summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorMats O Jansson <maja@cvs.openbsd.org>1998-03-11 17:48:09 +0000
committerMats O Jansson <maja@cvs.openbsd.org>1998-03-11 17:48:09 +0000
commit69de3a9e357327c17caa3b7bb058035e263573bc (patch)
treef6260f228c4d949b174128d017a7e323c7122f32 /gnu
parentb81973f175db7d3f4c763069b191dd57f4bd83d3 (diff)
Lynx 2.8
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/lynx/COPYHEADER20
-rw-r--r--gnu/usr.bin/lynx/COPYING339
-rw-r--r--gnu/usr.bin/lynx/INSTALLATION780
-rw-r--r--gnu/usr.bin/lynx/LYMessages_en.h657
-rw-r--r--gnu/usr.bin/lynx/MAKEFILE.W32737
-rw-r--r--gnu/usr.bin/lynx/PROBLEMS164
-rw-r--r--gnu/usr.bin/lynx/README139
-rw-r--r--gnu/usr.bin/lynx/VMSPrint.com15
-rw-r--r--gnu/usr.bin/lynx/WWW/BUILD42
-rw-r--r--gnu/usr.bin/lynx/WWW/Copyright.txt22
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/BSDI_Makefile405
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/CommonMakefile373
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.c1309
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.h150
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.c210
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.h126
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.c598
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.h231
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.c686
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.h148
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.c621
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.h361
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.c221
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.h109
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.c1370
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.h325
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.c126
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.h128
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.c1325
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.h447
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.c87
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.h44
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.c169
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.h49
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.c210
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.h66
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.c720
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.h104
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTCJK.h110
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.c204
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.h171
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.c94
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.h32
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.c3399
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.h77
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.c358
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.h37
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c2426
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.h210
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c441
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.h24
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.c1093
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.h441
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.c2004
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.h27
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.c772
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.h189
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.c157
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.h112
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.c176
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.h23
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.c142
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.h64
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.c314
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.h146
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.c2599
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.h87
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.c1674
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.h1006
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.c544
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.h32
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.c2824
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.h46
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.c901
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.h167
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.c301
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.h129
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.c665
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.h21
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.c418
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.h165
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTStream.h61
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c344
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.h63
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.c363
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.h182
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.c1142
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.h120
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.c1854
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.h33
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.c590
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.h24
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.c207
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.h29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTUtils.h447
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.c1264
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.h116
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.c2501
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.h376
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.c2448
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.h674
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.c1093
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.h44
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.c473
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.h48
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.c189
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.h28
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/HText.h265
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/LYLeaks.h183
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/LYexit.h58
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.c3576
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.h272
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/UCAux.h70
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/UCDefs.h86
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/UCMap.h48
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/Version.make1
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/crypt.c129
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/crypt_util.c981
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/entities.h1084
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/getline.c74
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/getpass.c64
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/patchlevel.h24
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/tcp.h681
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/Implementation/ufc-crypt.h108
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/apollo_m68k/Makefile38
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/clix/Makefile30
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/convex/Makefile32
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/decstation/Makefile23
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/djgpp/CommonMakefile371
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/djgpp/makefile30
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/duns/Makefile489
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/freebsd/Makefile27
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/isc/Makefile30
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/mips/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/netbsd/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/next/Makefile40
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/osf/Makefile23
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/ptx/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/rs6000/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/sco/Makefile33
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/sgi/Makefile30
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/snake/Makefile33
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/solaris2/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/sun3/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/sun4/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/svr4/Makefile29
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/umaxv-m88k/Makefile30
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/unix/makefile.in62
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/unix_x/Makefile491
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/vax_ultrix/Makefile33
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/vms/COPYING.LIB481
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/vms/descrip.mms255
-rw-r--r--gnu/usr.bin/lynx/WWW/Library/vms/libmake.com201
-rw-r--r--gnu/usr.bin/lynx/WWW/Makefile9
-rw-r--r--gnu/usr.bin/lynx/WWW/README.txt208
-rw-r--r--gnu/usr.bin/lynx/aclocal.m41513
-rw-r--r--gnu/usr.bin/lynx/build-slang.com359
-rw-r--r--gnu/usr.bin/lynx/build.com337
-rw-r--r--gnu/usr.bin/lynx/config.guess696
-rw-r--r--gnu/usr.bin/lynx/config.hin144
-rw-r--r--gnu/usr.bin/lynx/config.sub927
-rw-r--r--gnu/usr.bin/lynx/configure8185
-rw-r--r--gnu/usr.bin/lynx/configure.in599
-rw-r--r--gnu/usr.bin/lynx/descrip.mms132
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.3458
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.4891
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.51696
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.6732
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.7831
-rw-r--r--gnu/usr.bin/lynx/docs/CHANGES2.83403
-rw-r--r--gnu/usr.bin/lynx/docs/CMU.announce31
-rw-r--r--gnu/usr.bin/lynx/docs/CRAWL.announce131
-rw-r--r--gnu/usr.bin/lynx/docs/FM.announce72
-rw-r--r--gnu/usr.bin/lynx/docs/IBMPC-charsets.announce73
-rw-r--r--gnu/usr.bin/lynx/docs/README.chartrans169
-rw-r--r--gnu/usr.bin/lynx/docs/README.defines113
-rw-r--r--gnu/usr.bin/lynx/docs/SOCKETSHR.announce67
-rw-r--r--gnu/usr.bin/lynx/docs/TCPWARE.announce30
-rw-r--r--gnu/usr.bin/lynx/docs/VMSWAIS.announce28
-rw-r--r--gnu/usr.bin/lynx/docs/win-386.announce28
-rw-r--r--gnu/usr.bin/lynx/fixed512.com54
-rw-r--r--gnu/usr.bin/lynx/install.sh238
-rw-r--r--gnu/usr.bin/lynx/lynx.cfg1759
-rw-r--r--gnu/usr.bin/lynx/lynx.hlp463
-rw-r--r--gnu/usr.bin/lynx/lynx.man554
-rw-r--r--gnu/usr.bin/lynx/lynx_help/Lynx_users_guide.html2303
-rw-r--r--gnu/usr.bin/lynx/lynx_help/about_lynx.html97
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/bookmark_help.html21
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/cookie_help.html51
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/dired_help.html51
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/edit_help.html40
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/follow_help.html132
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/gopher_types_help.html59
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/history_help.html37
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/keystroke_help.html104
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/movement_help.html49
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/option_help.html262
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/other_help.html171
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/print_help.html37
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/scrolling_help.html58
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/visited_help.html31
-rw-r--r--gnu/usr.bin/lynx/lynx_help/keystrokes/xterm_help.html32
-rw-r--r--gnu/usr.bin/lynx/lynx_help/lynx-dev.html70
-rw-r--r--gnu/usr.bin/lynx/lynx_help/lynx_help_main.html84
-rw-r--r--gnu/usr.bin/lynx/lynx_help/lynx_url_support.html586
-rw-r--r--gnu/usr.bin/lynx/makefile.in289
-rw-r--r--gnu/usr.bin/lynx/mkdirs.sh34
-rw-r--r--gnu/usr.bin/lynx/samples/jumpsUnix.html47
-rw-r--r--gnu/usr.bin/lynx/samples/jumpsVMS.html28
-rw-r--r--gnu/usr.bin/lynx/samples/lynx.cfg1734
-rw-r--r--gnu/usr.bin/lynx/samples/lynx.com59
-rw-r--r--gnu/usr.bin/lynx/samples/lynx.lss60
-rw-r--r--gnu/usr.bin/lynx/samples/mailcap99
-rw-r--r--gnu/usr.bin/lynx/samples/mime.types24
-rw-r--r--gnu/usr.bin/lynx/src/AttrList.h68
-rw-r--r--gnu/usr.bin/lynx/src/DefaultStyle.c401
-rw-r--r--gnu/usr.bin/lynx/src/GridText.c8267
-rw-r--r--gnu/usr.bin/lynx/src/GridText.h206
-rw-r--r--gnu/usr.bin/lynx/src/HTAlert.c573
-rw-r--r--gnu/usr.bin/lynx/src/HTAlert.h133
-rw-r--r--gnu/usr.bin/lynx/src/HTFWriter.c1294
-rw-r--r--gnu/usr.bin/lynx/src/HTFont.h29
-rw-r--r--gnu/usr.bin/lynx/src/HTForms.h140
-rw-r--r--gnu/usr.bin/lynx/src/HTInit.c1063
-rw-r--r--gnu/usr.bin/lynx/src/HTML.c7491
-rw-r--r--gnu/usr.bin/lynx/src/HTML.h281
-rw-r--r--gnu/usr.bin/lynx/src/HTNestedList.h40
-rw-r--r--gnu/usr.bin/lynx/src/HTSaveToFile.h19
-rw-r--r--gnu/usr.bin/lynx/src/LYBookmark.c918
-rw-r--r--gnu/usr.bin/lynx/src/LYBookmark.h18
-rw-r--r--gnu/usr.bin/lynx/src/LYCgi.c660
-rw-r--r--gnu/usr.bin/lynx/src/LYCgi.h7
-rw-r--r--gnu/usr.bin/lynx/src/LYCharSets.c937
-rw-r--r--gnu/usr.bin/lynx/src/LYCharSets.h47
-rw-r--r--gnu/usr.bin/lynx/src/LYCharUtils.c3710
-rw-r--r--gnu/usr.bin/lynx/src/LYCharUtils.h106
-rw-r--r--gnu/usr.bin/lynx/src/LYClean.c210
-rw-r--r--gnu/usr.bin/lynx/src/LYClean.h18
-rw-r--r--gnu/usr.bin/lynx/src/LYCookie.c2345
-rw-r--r--gnu/usr.bin/lynx/src/LYCookie.h24
-rw-r--r--gnu/usr.bin/lynx/src/LYCurses.c1825
-rw-r--r--gnu/usr.bin/lynx/src/LYCurses.h381
-rw-r--r--gnu/usr.bin/lynx/src/LYDownload.c698
-rw-r--r--gnu/usr.bin/lynx/src/LYDownload.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYEdit.c189
-rw-r--r--gnu/usr.bin/lynx/src/LYEdit.h7
-rw-r--r--gnu/usr.bin/lynx/src/LYEditmap.c150
-rw-r--r--gnu/usr.bin/lynx/src/LYExtern.c97
-rw-r--r--gnu/usr.bin/lynx/src/LYExtern.h10
-rw-r--r--gnu/usr.bin/lynx/src/LYForms.c1503
-rw-r--r--gnu/usr.bin/lynx/src/LYGCurses.h251
-rw-r--r--gnu/usr.bin/lynx/src/LYGetFile.c1389
-rw-r--r--gnu/usr.bin/lynx/src/LYGetFile.h30
-rw-r--r--gnu/usr.bin/lynx/src/LYGlobalDefs.h340
-rw-r--r--gnu/usr.bin/lynx/src/LYHash.c51
-rw-r--r--gnu/usr.bin/lynx/src/LYHash.h39
-rw-r--r--gnu/usr.bin/lynx/src/LYHistory.c647
-rw-r--r--gnu/usr.bin/lynx/src/LYHistory.h20
-rw-r--r--gnu/usr.bin/lynx/src/LYJump.c498
-rw-r--r--gnu/usr.bin/lynx/src/LYJump.h29
-rw-r--r--gnu/usr.bin/lynx/src/LYKeymap.c817
-rw-r--r--gnu/usr.bin/lynx/src/LYKeymap.h125
-rw-r--r--gnu/usr.bin/lynx/src/LYLeaks.c607
-rw-r--r--gnu/usr.bin/lynx/src/LYList.c360
-rw-r--r--gnu/usr.bin/lynx/src/LYList.h11
-rw-r--r--gnu/usr.bin/lynx/src/LYLocal.c2287
-rw-r--r--gnu/usr.bin/lynx/src/LYLocal.h75
-rw-r--r--gnu/usr.bin/lynx/src/LYMail.c1914
-rw-r--r--gnu/usr.bin/lynx/src/LYMail.h26
-rw-r--r--gnu/usr.bin/lynx/src/LYMain.c2908
-rw-r--r--gnu/usr.bin/lynx/src/LYMainLoop.c5807
-rw-r--r--gnu/usr.bin/lynx/src/LYMainLoop.h7
-rw-r--r--gnu/usr.bin/lynx/src/LYMap.c590
-rw-r--r--gnu/usr.bin/lynx/src/LYMap.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYNews.c433
-rw-r--r--gnu/usr.bin/lynx/src/LYNews.h13
-rw-r--r--gnu/usr.bin/lynx/src/LYOptions.c3107
-rw-r--r--gnu/usr.bin/lynx/src/LYOptions.h65
-rw-r--r--gnu/usr.bin/lynx/src/LYPrint.c1365
-rw-r--r--gnu/usr.bin/lynx/src/LYPrint.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYReadCFG.c1321
-rw-r--r--gnu/usr.bin/lynx/src/LYReadCFG.h49
-rw-r--r--gnu/usr.bin/lynx/src/LYSearch.c385
-rw-r--r--gnu/usr.bin/lynx/src/LYSearch.h20
-rw-r--r--gnu/usr.bin/lynx/src/LYShowInfo.c365
-rw-r--r--gnu/usr.bin/lynx/src/LYShowInfo.h16
-rw-r--r--gnu/usr.bin/lynx/src/LYSignal.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYStrings.c1680
-rw-r--r--gnu/usr.bin/lynx/src/LYStrings.h175
-rw-r--r--gnu/usr.bin/lynx/src/LYStructs.h112
-rw-r--r--gnu/usr.bin/lynx/src/LYStyle.c406
-rw-r--r--gnu/usr.bin/lynx/src/LYStyle.h32
-rw-r--r--gnu/usr.bin/lynx/src/LYSystem.h10
-rw-r--r--gnu/usr.bin/lynx/src/LYTraversal.c194
-rw-r--r--gnu/usr.bin/lynx/src/LYTraversal.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYUpload.c316
-rw-r--r--gnu/usr.bin/lynx/src/LYUpload.h15
-rw-r--r--gnu/usr.bin/lynx/src/LYUtils.c5691
-rw-r--r--gnu/usr.bin/lynx/src/LYUtils.h145
-rw-r--r--gnu/usr.bin/lynx/src/LYVMSdef.h18
-rw-r--r--gnu/usr.bin/lynx/src/LYexit.c177
-rw-r--r--gnu/usr.bin/lynx/src/LYrcFile.c924
-rw-r--r--gnu/usr.bin/lynx/src/LYrcFile.h13
-rw-r--r--gnu/usr.bin/lynx/src/UCAuto.c362
-rw-r--r--gnu/usr.bin/lynx/src/UCAuto.h7
-rw-r--r--gnu/usr.bin/lynx/src/UCAux.c451
-rw-r--r--gnu/usr.bin/lynx/src/UCdomap.c2068
-rw-r--r--gnu/usr.bin/lynx/src/UCdomap.h55
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/MAKEFILE.W32129
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/MAKEW32.BAT40
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/README.format130
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/README.tables59
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/UCkd.h65
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/build-chrtrans.com159
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/build-header.com37
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1250_uni.tbl281
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1251_uni.tbl154
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1252_uni.tbl285
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1253_uni.tbl154
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1255_uni.tbl154
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1256_uni.tbl154
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp1257_uni.tbl278
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp437_uni.tbl168
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp737_uni.tbl155
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp775_uni.tbl278
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp850_uni.tbl286
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp852_uni.tbl280
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp862_uni.tbl155
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp864_uni.tbl155
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp866_uni.tbl154
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/cp869_uni.tbl155
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/def7_uni.tbl2217
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/dmcs_uni.tbl226
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso01_uni.tbl250
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso02_uni.tbl242
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso03_uni.tbl242
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso04_uni.tbl241
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso05_uni.tbl239
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso06_uni.tbl195
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso07_uni.tbl233
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso08_uni.tbl212
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso09_uni.tbl239
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/iso10_uni.tbl123
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/koi8r_uni.tbl141
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/mac_uni.tbl340
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/makefile.dos116
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/makefile.in146
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/makeuctb.c764
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/mnem2_suni.tbl1865
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/mnem_suni.tbl1861
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/next_uni.tbl177
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/rfc_suni.tbl1958
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/utf8_uni.tbl35
-rw-r--r--gnu/usr.bin/lynx/src/chrtrans/viscii_uni.tbl300
-rw-r--r--gnu/usr.bin/lynx/src/cmu_tcp.opt1
-rw-r--r--gnu/usr.bin/lynx/src/decc.opt2
-rw-r--r--gnu/usr.bin/lynx/src/descrip.mms170
-rw-r--r--gnu/usr.bin/lynx/src/gnuc.opt3
-rw-r--r--gnu/usr.bin/lynx/src/makefile.dos63
-rw-r--r--gnu/usr.bin/lynx/src/makefile.in168
-rw-r--r--gnu/usr.bin/lynx/src/mktime.c77
-rw-r--r--gnu/usr.bin/lynx/src/multinet.opt1
-rw-r--r--gnu/usr.bin/lynx/src/socketshr_tcp.opt1
-rw-r--r--gnu/usr.bin/lynx/src/strstr.c64
-rw-r--r--gnu/usr.bin/lynx/src/tcpwareolb.opt1
-rw-r--r--gnu/usr.bin/lynx/src/tcpwareshr.opt1
-rw-r--r--gnu/usr.bin/lynx/src/ucxolb.opt1
-rw-r--r--gnu/usr.bin/lynx/src/ucxshr.opt1
-rw-r--r--gnu/usr.bin/lynx/src/vaxc.opt2
-rw-r--r--gnu/usr.bin/lynx/src/win_tcp.opt1
-rw-r--r--gnu/usr.bin/lynx/test/ALT88592.html170
-rw-r--r--gnu/usr.bin/lynx/test/ISO_LATIN1_test.html83
-rw-r--r--gnu/usr.bin/lynx/test/README.txt8
-rw-r--r--gnu/usr.bin/lynx/test/TestComment.html50
-rw-r--r--gnu/usr.bin/lynx/test/iso8859-1.html239
-rw-r--r--gnu/usr.bin/lynx/test/iso88592.html173
-rw-r--r--gnu/usr.bin/lynx/test/sgml.html1070
-rw-r--r--gnu/usr.bin/lynx/test/tabtest.html39
-rw-r--r--gnu/usr.bin/lynx/test/unicode.html1053
-rw-r--r--gnu/usr.bin/lynx/userdefs.h1464
-rw-r--r--gnu/usr.bin/lynx/utils/lpansi/Makefile24
-rw-r--r--gnu/usr.bin/lynx/utils/lpansi/README82
-rw-r--r--gnu/usr.bin/lynx/utils/lpansi/lpansi.177
-rw-r--r--gnu/usr.bin/lynx/utils/lpansi/lpansi.c160
-rw-r--r--gnu/usr.bin/lynx/utils/lpansi/vmsbuild.com73
385 files changed, 189772 insertions, 0 deletions
diff --git a/gnu/usr.bin/lynx/COPYHEADER b/gnu/usr.bin/lynx/COPYHEADER
new file mode 100644
index 00000000000..b441aee7bc3
--- /dev/null
+++ b/gnu/usr.bin/lynx/COPYHEADER
@@ -0,0 +1,20 @@
+/* Copyright (C) 1995 University of Kansas.
+
+ This file is part of Lynx, a text-based, WWW browser.
+
+ Lynx is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ Lynx is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Lynx; see the file COPYING. If not, write to the Free
+ Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Any licensing or usage questions should be directed to Michael
+ Grobe <grobe@ukans.edu>.
+*/
diff --git a/gnu/usr.bin/lynx/COPYING b/gnu/usr.bin/lynx/COPYING
new file mode 100644
index 00000000000..a43ea2126fb
--- /dev/null
+++ b/gnu/usr.bin/lynx/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/gnu/usr.bin/lynx/INSTALLATION b/gnu/usr.bin/lynx/INSTALLATION
new file mode 100644
index 00000000000..61efdf8d8dd
--- /dev/null
+++ b/gnu/usr.bin/lynx/INSTALLATION
@@ -0,0 +1,780 @@
+
+ Lynx Installation Guide
+
+This file describes how to compile and install Lynx. A description of
+Lynx can be found in the README file. Lynx has been ported to UN*X, VMS,
+Win32 and 386DOS. The procedures for compiling these ports are quite
+divergent, and are detailed respectively in Sections II, III, IV and V.
+
+First, however, you must configure Lynx for your system regardless of the
+port you will be using. Follow the instructions given immediately below to
+configure for your system, and then go to the respective section concerning
+the port you wish to compile. General installation, problem solving, and
+environment variables are covered in Sections VI and VII.
+
+
+I. General configuration instructions (all ports).
+
+Step 1. (define compile-time variables -- See the userdefs.h file.)
+ There are a few variables that MUST be defined, or Lynx will not build.
+ There are a few more that you will probably want to change. The variables
+ that must be changed are marked as such in the userdefs.h file. Just edit
+ this file, and the changes should be straight forward. Many of the
+ variables in "userdefs.h" are now configurable in the lynx.cfg file, so
+ you may set them at run-time if you wish. If you compile using auto-
+ configure, you would not absolutely need to edit "userdefs.h". Check
+ LYMessages_en.h for tailoring the Lynx statusline prompts, messages and
+ warnings to the requirements of your site. The strings in LYMessages_en.h
+ may be translated into a language of your choice. If you rename the file,
+ be sure to change the definition in "userdefs.h".
+
+Step 2. (define run-time variables -- See the lynx.cfg file for details.)
+ Set up local printers, downloaders, assumed character set, key mapping,
+ and colors in the lynx.cfg file. Please read "lynx.cfg" thoroughly as
+ many of the features of Lynx, and how to use them, are explained. Also
+ see the example mime.types, mailcap and jumps files in the samples
+ subdirectory. Lynx must be able to find the lynx.cfg file at start-up.
+ The location of the lynx.cfg file may be compiled in with the LYNX_CFG_FILE
+ defined in userdefs.h (or with the configure option explained in the Unix
+ section below), specified with an environment variable, LYNX_CFG, or
+ specified with the "-cfg" command line option.
+
+Step 3. (You may skip this step if you only use English and are not
+ interested in any special characters, or if your display and local files
+ will all use the ISO-8859-1 "ISO Latin 1" Western European character set.)
+ People who will be running Lynx in an environment with different and
+ incompatible character sets should configure CHARACTER_SET (the Display
+ character set) and ASSUME_LOCAL_CHARSET to work correctly for them before
+ creating bookmark files et cetera. Please read "lynx.cfg" for detailed
+ instructions. Additional character sets and their properties may be
+ defined with tables in the src/chrtrans directory, see the README.* files
+ therein.
+
+Step 4. (optional -- news for UNIX and VMS)
+ Set NNTPSERVER in "lynx.cfg" to your site's NNTP server, or set the
+ environment variable externally. (See "VII. Setting environment
+ variables before running Lynx" for help on setting this and other
+ environment variables which affect Lynx.) For news posting ability
+ to be enabled in Lynx, in userdefs.h (and optionally in lynx.cfg) the
+ NEWS_POSTING symbol must be defined to TRUE. Also define LYNX_SIG_FILE
+ in userdefs.h or lynx.cfg so that it points to users' signature files
+ for appending to posted messages.
+
+Step 5. (optional -- UNIX only)
+ To add direct WAIS support, get the freeWAIS distribution from
+ "ftp://ftp.cnidr.org/pub/NIDR.tools/freewais", and compile it. The compile
+ process will create the libraries you will need, wais.a and client.a. Edit
+ the Makefile in the top level directory and add the library locations under
+ the DIRECT WAIS ACCESS heading. Edit the Makefile for the WWW Library in
+ "WWW/Library/Implementation/CommonMakefile" to point to the include
+ directory for the freewais distribution. Precompiled libraries are
+ available for many platforms if you don't wish to compile one yourself.
+
+Step 6. (Anonymous account -- VERY IMPORTANT!!!!! -- )
+ If you are building Lynx for your personal use only you may skip this
+ step. If you are setting up an anonymous account with Lynx, you are
+ STRONGLY advised to use the -anonymous command line option. If you do
+ not use this option, users may be able to gain access to all readable
+ files on your machine! ALSO NOTE that many implementations of telnetd
+ allow passing of environment variables, which might be used by
+ unscrupulous people to modify the environment in anonymous accounts.
+ When making Lynx and Web access publicly available via anonymous
+ accounts intended to run Lynx captively, be sure the wrapper uses the
+ -cfg switch to specify the startfile, rather than relying on the
+ LYNX_CFG, LYNX_CFG_FILE, or WWW_HOME variables.
+
+
+II. Compile instructions -- UNIX
+
+1a. Auto-configure. The auto-configure script uses autoconf2.12 to generate a
+ Bourne shell script, configure, which creates "makefile" and "lynx_cfg.h".
+
+ If you are on a UNIX platform, the easiest way to build Lynx is to type:
+
+ ./configure
+ and
+ make
+
+ NOTE: Configure has a number of useful options. Please see below.
+
+ NOTE: The 'configure' script generates auxiliary files "config.status"
+ "config.cache" and "config.log". Normally you will not notice these;
+ they are created automatically and removed by a "make distclean".
+
+ + If you wish to rebuild Lynx with a new host, or change ANY of the
+ parameters which are stored in config.cache, you MUST first remove
+ the config.cache file before running configure; its options do NOT
+ override the settings in that file.
+
+ + The config.status file is a script which creates (or regenerates)
+ the files created by the configure script.
+
+ Please report problems in the configure/make process by including a copy
+ of config.status, config.cache and config.log, as well as the pertinent
+ compiler diagnostics.
+
+ NOTE: Lynx is a curses-based application, so you must have a curses
+ library available to link to. Native curses (on the system when it was
+ installed) are often broken, so you may get superior performance if you
+ have either "ncurses" ("ftp://ftp.clark.net/pub/dickey/ncurses") or "slang"
+ ("ftp://space.mit.edu/pub/davis/slang"). If you install these libraries
+ in your home directory or a non-default location, you may need to set the
+ CPPFLAGS (full path to include files) and LIBS (full path to library files)
+ environment variables BEFORE running configure. See "1d. Environment".
+ Use the "--with-screen=ncurses" or "--with-screen=slang" option.
+
+1b. Platforms. Configure should work properly on any Unix-style system.
+ It has been tested on the following platforms.
+
+ AIX 3.2.5 (cc w/ curses) CLIX (cc w/ curses & ncurses)
+ DGUX
+ Digital Unix 3.2C and 4.0 (gcc & cc w/ curses, ncurses & slang)
+ FreeBSD 2.1.5 (gcc 2.6.3 w/ curses & ncurses)
+ HP-UX (K&R and ANSI cc, gcc w/ curses, ncurses & slang)
+ IRIX 5.2 and 6.2 (cc & gcc w/ curses, ncurses & slang)
+ Linux 2.0.0 (gcc 2.7.2 w/ curses, ncurses & slang)
+ MkLinux 2.1.5 (gcc 2.7.2.1) NetBSD
+ OS/2 EMX 0.9b SCO (cc w/ curses)
+ Solaris 2.5 & 2.6 (cc & gcc w/ curses, ncurses & slang)
+ SunOS 4.1 (cc w/ curses, gcc w/ ncurses & slang)
+
+ NOTE: SunOS and HP-UX come with a bundled K&R compiler, which is only
+ useful for compiling with the bundled curses. Both ncurses and slang
+ require a compiler that recognizes prototypes.
+
+1c. Options
+ To get a list of the configure script's options, type "./configure --help".
+ Below is an alphabetical listing of the Lynx-specific options. The actual
+ order shown by the -help option is different. See "docs/README.defines"
+ for information on defines for which there are no option switches.
+
+ --disable-dired (defines DIRED_SUPPORT)
+ Use this option to disable the optional directory-editor.
+
+ Lynx supports directory editing (DirEd) for local directories.
+ This allows users to do things like view, copy and remove files
+ using a tabular display of the directory and single-keystroke
+ commands instead of using the command line. From inside Lynx, the
+ keystroke sequence "g.<enter>" switches Lynx to DirEd mode on the
+ current directory. If you're building a Lynx that is to be used as
+ a kind of restricted shell for users who do not have access to the
+ command line and should not have access to equivalent capabilities,
+ you must disable DirEd with this option. You can also disable some
+ DirEd functions while allowing others. If you have disabled DirEd
+ completely, you can ignore all the other DirEd options.
+
+ All DirEd functions that were enabled on compilation can be disabled
+ or modified at run time via DIRED_MENU symbols in lynx.cfg.
+
+ --disable-dired-archive (define ARCHIVE_ONLY)
+ Use this option to prevent DirEd from extracting files from an
+ archive file.
+
+ --disable-dired-gzip (prevent defining OK_GZIP)
+ Use this option to prevent DirEd from using gzip and gunzip.
+
+ --disable-dired-override (prevent defining OK_OVERRIDE)
+ Lynx users can customize their keymaps by creating private
+ versions of lynx.cfg and modifying them to override the default
+ keymap. Use this option to prevent DirEd keymap overriding.
+
+ --disable-dired-permit (prevent defining OK_PERMIT)
+ Use this option to prevent DirEd from changing the permissions
+ on directories or files (i.e., from doing what the Unix chmod
+ command or the DOS attrib command does).
+
+ --disable-dired-tar (prevent defining OK_TAR)
+ Use this option to prevent DirEd from using the tar program.
+
+ --disable-dired-uudecode (prevent defining OK_UUDECODE)
+ Use this option to prevent DirEd from using uudecode.
+
+ --disable-dired-xpermit (define NO_CHANGE_EXECUTE_PERMS)
+ Use this option if you do not disable out the dired-permit
+ option, but want to restrict changes of the eXecute permission
+ to directories (i.e., not allow it to be changed for files). If
+ you don't do this, you can still block changes of the eXecute
+ permission for files but not directories via the
+ "change_exec_perms" command line restriction.
+
+ --disable-dired-zip (prevent defining OK_ZIP)
+ Use this option to prevent DirEd from using zip and unzip.
+
+ --disable-echo
+ Use this option to suppress the "compiling" commands during a build.
+ Doing this makes it easier to find and read warning messages.
+
+ --disable-extended-dtd (define NO_EXTENDED_HTMLDTD)
+ disable extended HTML DTD logic. This should revert to old-style
+ (2.7.1/2.7.2) behavior, but is not well-tested.
+
+ --disable-full-paths
+ Use this option to control whether full utility pathnames are used.
+ By default, configure substitutes full pathnames.
+
+ --disable-long-list (prevent defining LONG_LIST)
+ Use this option to disable long "ls -l" directory listings.
+
+ --disable-parent-dir-refs (define NO_PARENT_DIR_REFERENCE)
+ Use this option to disable "Up-to" parent-links in directory listings.
+
+ --enable-8bit-toupper (define EXP_8BIT_TOUPPER)
+ use experimental 8-bit case-conversion, e.g., for case-insensitive
+ searches in non-ASCII character set.
+
+ --enable-color-style (define USE_COLOR_STYLE)
+ Use this option to enable optional and *experimental* color style.
+ (Also defines USE_HASH, LINKEDSTYLES)
+
+ --enable-debug (The symbol DEBUG is always defined.)
+ Use this option to compile-in support for debugging.
+
+ --enable-default-colors (define USE_DEFAULT_COLORS)
+ enable use of default-color background (ncurses/slang). Either
+ configuration supports the use of 'default' for colors even without
+ this option.
+
+ --enable-externs (define USE_EXTERNALS)
+ Use this option to enable external application support. (See lynx.cfg.)
+
+ --enable-find-leaks (define LY_FIND_LEAKS)
+ Use this option to compile-in logic for testing memory leaks.
+
+ --enable-font-switch (define EXP_CHARTRANS_AUTOSWITCH)
+ Allow Lynx to automatically change the Linux console state (switch
+ fonts) according to the current Display Character Set. (Linux console
+ only. *Use with discretion.* See docs/README.chartrans.)
+
+ --enable-internal-links (define DONT_TRACK_INTERNAL_LINKS)
+ Disabled by default, this option allows tracking of internal links,
+ a feature which could, however, compromise a secure transaction by
+ forcing inappropriate resubmission of form content.
+
+ --enable-nsl-fork (define NSL_FORK)
+ Use this option to allow NSL requests to be aborted at will.
+
+ --enable-underlines (define UNDERLINE_LINKS)
+ Use this option underline links rather than using boldface.
+
+ --enable-warnings
+ Use this option to turn on GCC compiler warnings.
+
+ --libdir (affect LYNX_CFG_FILE)
+ Defines the location where you want the lynx.cfg file installed.
+ The configure script defines the symbol LYNX_CFG_FILE to correspond
+ with the $libdir environment variable. (For platforms which do not
+ support a configure script, such as MS-DOS, Win32 and VMS, you must
+ edit userdefs.h if you wish to specify the location of lynx.cfg).
+
+ --with-screen=XXX
+ Use this option to select the screen type. The option value,
+ XXX must be one of curses (the default), ncurses or slang.
+ Specifying a screen type causes the configure script to look in
+ standard locations for the associated header and library files,
+ unless you have preset the $CFLAGS and $LIBS variables.
+
+ --with-screen=ncurses (define NCURSES)
+ --with-screen=slang (define USE_SLANG)
+
+ --with-zlib (define USE_ZLIB)
+ Use zlib for decompression of some gzip files.
+
+1d. Environment variables
+ The configure script looks for programs and libraries in known/standard
+ locations. You can override the behavior of the script by presetting
+ environment variables. If they are set, the script will try to use these
+ values rather than computing new ones. Useful variables include:
+
+ CC - the C compiler. If you do not override this, configure
+ will try to use gcc.
+
+ CFLAGS - the C compiler options. These also include C
+ preprocessor options (such as -I), since the $CFLAGS and
+ $CPPFLAGS variables are maintained separately.
+
+ CPPFLAGS - the C preprocessor options. For some configuration
+ tests, you may need to set both $CFLAGS and $CPPFLAGS if
+ you are compiling against header files in nonstandard
+ locations.
+
+ LDFLAGS - linker/loader options.
+
+ LIBS - the libraries to be linked, with -L and -l options. If
+ you are linking against libraries in nonstandard locations
+ unrelated to the install prefix (that you can specify in
+ the configure script) you may have to specify these via
+ the $LIBS variable.
+
+-- 1997/7/27 - T. Dickey <dickey@clark.net>
+
+1e. Examples
+ If you are compiling Lynx for your personal use and are restricted to your
+ home directory, a simple method for building would be to choose some
+ directory, say ".lynx", and then type:
+
+ ./configure --prefix=~/.lynx --exec-prefix=~/.lynx
+ and
+ make install
+
+ Now you only need to add "~/.lynx/bin" to your PATH and edit "~/.lynx/lib/
+ lynx.cfg" as described above.
+
+ I personally use the following csh shell script to set environment
+ variables and configure options rather than type them each time.
+ setenv RESOLVLIB -lbind
+
+ #!/bin/csh -f
+ setenv CPPFLAGS "-SYSLOG_REQUESTED_URLS -I$HOME/slang \
+ -I$HOME/.usr/include"
+ setenv LIBS "-L$HOME/.slang/lib -L$HOME/.usr/lib"
+ ./configure --exec-prefix=$HOME --bindir=$HOME/.lynx \
+ --mandir=$HOME/.usr/man --libdir=$HOME/.usr/lib \
+ --with-screen=slang --with-zlib
+
+ The syntax for setting environment variables depends upon your shell. I
+ use the libbind.a resolver library, not libresolv.a. Setting RESOLVLIB to
+ -lbind defines this environment variable for `make', and thus must be set
+ in the same shell that `make' will be run. CPPFLAGS in this example
+ predefines SYSLOG_REQUESTED_URLS for the configure script, since it is not
+ defined by default, and has no option switch (see "docs/README.defines").
+ CPPFLAGS also defines the full path to the slang and zlib header files,
+ which are not kept in standard directories. Likewise, LIBS defines the
+ nonstandard locations of libslang.a and libz.a. Setting the option
+ --bindir tells the configure script where I want to install the lynx
+ binary; setting --mandir tells it where to put the lynx.1 man page, and
+ setting --libdir tells it (while at the same time defining LYNX_CFG_FILE)
+ where to put the configuration file "lynx.cfg", when I type "make install".
+ The --with-screen=slang and --with-zlib options are explained above.
+
+2. Manual compile
+ If auto-configure does not work for you, or you prefer to compile
+ Lynx manually, "docs/Makefile.old" will serve as a template for the
+ top-level Makefile, and instructions on how to compile are given in
+ "docs/INSTALLATION.old".
+
+
+III. Compile instructions -- VMS
+
+Step 1. Downloading binary files.
+ Lynx must handle all IO as streams, and on VMS, output files are always
+ created with Stream_LF format via the C RTL's fopen(). The file headers
+ indicate Implied Carriage Control, even when the transfer was in binary
+ mode, which can confuse downloading software and cause corruption of
+ the file contents. To deal with this, you should define the symbol
+ USE_FIXED_RECORDS as TRUE in userdefs.h and/or lynx.cfg. This will
+ instruct Lynx to correct the header information to indicate FIXED 512
+ records, with No Implied Carriage Control. If Lynx fails to do the
+ conversion (because the file wasn't mapped to a binary MIME type) you can
+ execute FIXED512.COM externally to correct the header information. The
+ command file uses Joe Meadow's FILE utility, or the SET FILE/ATTRIBUTES
+ command on current versions of VMS, to modify the headers. See the
+ comments in FIXED512.COM, userdefs.h and lynx.cfg for more information.
+
+Step 2. Passive FTP
+ If your system requires the PASV FTP code instead of the standard
+ PORT FTP code (e.g., to deal with a firewall) then edit "WWW/Library/
+ Implementation/HTFTP.c" and comment out line 43 like so:
+ /* #define LISTEN /* @@@@ Test LJM */.
+
+Step 3a.
+ Lynx uses the VMS port of gzip for uncompressing streams which have
+ Content-Encoding headers indicated compression with gzip or the
+ Unix compress. If you do not have gzip installed on your system
+ you can get it from "ftp://ftp.wku.edu/" in the fileserv directory.
+ The command Lynx uses to uncompress on VMS is "gzip -d".
+
+ If you are using the SOCKETSHR library, read SOCKETSHR.announce and
+ make sure you have defined SOCKETSHR and SOCKETSHR_LIBRARY as explained
+ therein.
+
+ A "build.com" and "build-slang.com" script for building Lynx with curses
+ or slang is in the top level directory. All you have to do is type
+ "@build" or "@build-slang" and answer its prompt for your system's TCP-IP
+ software. Current choices are:
+ MULTINET (default)
+ UCX
+ WIN_TCP
+ CMU_TCP
+ SOCKETSHR_TCP
+ TCPWARE
+ It will autosense whether you have VAXC, DECC or GNUC on VAX or AXP and
+ build appropriately. If a WWWLib already exists for that TCP-IP software,
+ it will prompt you for whether you want to rebuild it. If you want to
+ build a WWWLib separately, you can type "@libmake.com" with your default
+ directory set to [.WWW.Library.vms] instead doing it via "build.com" in
+ the top directory. You may need to modify "build-slang.com", as described
+ in its header, so that it can find slang.olb on your system. If you have
+ both DECC and VAXC, it will use DECC to benefit from the newer and more
+ efficient memory management functions.
+
+Step 3b. (optional compilation method)
+ If you have and want to use MMS, read the header of descrip.mms in the
+ top directory and be sure you include the appropriate macro definitions
+ when you invoke it:
+
+ $ MMS /Macro = (MULTINET=1) for VAXC - MultiNet
+ $ MMS /Macro = (WIN_TCP=1) for VAXC - Wollongong TCP/IP
+ $ MMS /Macro = (UCX=1) for VAXC - UCX
+ $ MMS /Macro = (CMU_TCP=1) for VAXC - OpenCMU TCP/IP
+ $ MMS /Macro = (SOCKETSHR_TCP=1) for VAXC - SOCKETSHR/NETLIB
+ $ MMS /Macro = (TCPWARE=1) for VAXC - TCPWare TCP/IP
+
+ $ MMS /Macro = (MULTINET=1, DEC_C=1) for DECC - MultiNet
+ $ MMS /Macro = (WIN_TCP=1, DEC_C=1) for DECC - Wollongong TCP/IP
+ $ MMS /Macro = (UCX=1, DEC_C=1) for DECC - UCX
+ $ MMS /Macro = (CMU_TCP=1, DEC_C=1) for DECC - OpenCMU TCP/IP
+ $ MMS /Macro = (SOCKETSHR_TCP=1,DEC_C=1) for DECC - SOCKETSHR/NETLIB
+ $ MMS /Macro = (TCPWARE=1, DEC_C=1) for DECC - TCPWare TCP/IP
+
+ $ MMS /Macro = (MULTINET=1, GNU_C=1) for GNUC - MultiNet
+ $ MMS /Macro = (WIN_TCP=1, GNU_C=1) for GNUC - Wollongong TCP/IP
+ $ MMS /Macro = (UCX=1, GNU_C=1) for GNUC - UCX
+ $ MMS /Macro = (CMU_TCP=1, GNU_C=1) for GNUC - OpenCMU TCP/IP
+ $ MMS /Macro = (SOCKETSHR_TCP=1,GNU_C=1) for GNUC - SOCKETSHR/NETLIB
+ $ MMS /Macro = (TCPWARE=1, GNU_C=1) for GNUC - TCPWare TCP/IP
+
+ If you just type "MMS" it will default to the MULTINET and VAXC
+ configuration. MMS will build the WWW library and Lynx sources, and
+ link the executable. However, not all of the header dependencies are
+ specified. If you are not a developer, and need a clean build, you
+ should use build.com instead of the MMS utility.
+
+ If you want SOCKS support on VMS, you must add SOCKS as a compilation
+ definition, and the SOCKS library to the link command. However, instead
+ of SOCKSifying Lynx for use behind a firewall, you are better off if you
+ build Lynx normally, and set up Lynx to use a proxy server (see below).
+ You instead can SOCKSify the proxy server, and it will handle all clients,
+ not just Lynx.
+
+
+IV. Compile instructions -- Win32 (Windows95/NT)
+
+ The original Win32 port was built with Borland C++ 4.52, but later
+ versions reportedly can be used. Before compiling the Lynx sources, you
+ need a curses library, and it is recommended that you have the zlib
+ library. Get pdcurses2.3 from "http://www.lightlink.com/hessling/". I
+ have modified it so that mouse support is no longer broken for Lynx (see
+ "http://www.fdisk.com/doslynx/"). You will want to get zlib from
+ "http://www.cdrom.com/pub/infozip/zlib/". Compile these libraries, and
+ put them in a convenient place (pdcurses inside the Lynx directory).
+
+ Unpack the latest Lynx source distribution, and make an obj directory
+ under the source root to contain the compile output. Copy in your
+ IDE file. A sample IDE file and helper libraries are available at
+ "http://www.fdisk.com/doslynx/wlynx/source/".
+
+ First build the .h files in src\chrtrans using "MAKEW32.BAT". Double
+ check for new .tbl files; hand edit in any new ones, and then do "makew32".
+ Jump into Borland C++, load the project (IDE file) and compile Lynx.
+ Alternately, after compiling the chartrans tables, you can come back to
+ the top directory and compile manually, i.e., do "make -f makefile.w32".
+
+ I also have a binary available at "http://www.fdisk.com/doslynx/". This
+ binary was compiled with pdcurses 2.3, hacked so win32 mouse support works,
+ and with zlib, so Lynx can do gzip routines internally. More hints and
+ information can be found in "http://www.fdisk.com/doslynx/lynxport.htm".
+
+-- 1997/10/12 - W. Buttles <lynx-port@fdisk.com>
+
+ It is possible to compile under the cygwin32 system, which will allow you
+ to use the configure script described above for Unix. Type, for example,
+ "./configure --with-screen=slang --with-libz" in a Dos window running the
+ cygwin bash$ shell. You also have the choice of using either pdcurses or
+ slang. See "http://www.flora.org/lynx-dev/html/month1097/msg00559.html"
+ and "http://www.flora.org/lynx-dev/html/month1097/msg00186.html", and other
+ messages along those threads. You will have to make a minor alteration to
+ HTTCP.c (change delay to 30 seconds) and modify HTFILE.c (concerning
+ getgroups). You will need a launch program to call helper applications.
+
+
+V. Compile instructions -- 386 DOS
+
+ Compiling for DOS with DJGPP is a multistep procedure. First install
+ the c compiler and its libraries. DJGPP, as distributed from the
+ usual DJGPP archives, will not successfully compile lynx. You need to
+ "stubedit" your "cc1.exe" file. The following parameters have worked
+ successfully: minstack=800k, bufsize=64k. To accomplish this, move to
+ the djgpp\bin directory and type the command:
+ "stubedit cc1.exe bufsize=64k minstack=800k".
+ Or do it interactively with the command: "stubedit cc1.exe".
+ (see "http://www.flora.org/lynx-dev/html/month0897/msg00145.html").
+
+ Unpack the source code using a DOS program like UNZIP386. If you are
+ using PKUNZIP to unpack the .zip archive, you must use the -d command
+ line switch to restore the directory structure contained in the archive,
+ i.e., do "pkunzip -d lynx-cur.zip". No switch is required if you use
+ unzip386 or unzip. If you are trying to compile the 386DOS port under a
+ Win95/NT DOS shell, be sure to unpack the source with a DOS program so
+ that all directories will be adjusted to the DOS 8.3 file format necessary
+ for compiling with DJGPP. Do NOT use Winzip, because that will create
+ long filenames that will not be recognized by DJGPP tools.
+
+ If you wish to compile with "USE_ZLIB" (recommended), you must have the
+ zlib library. Get the source from "http://www.cdrom.com/pub/infozip/zlib/"
+ and compile it. Put libz.a in the lib subdirectory of DJGPP, and put
+ zlib.h and zconf.h in the include subdirectory.
+
+ In addition to the files in the Lynx distribution, you will need a
+ curses package and a TCP package. You can use PDCurses (available at
+ "http://www.lightlink.com/hessling/") and the DJGPP port of WATTCP
+ (available in two different versions at "ftp://neonatal.sm.ic.ac.uk/"
+ and in "http://www.fdisk.com/doslynx/wlynx/source/djgpp.zip").
+ You can also use slang ("ftp://space.mit.edu/pub/davis/slang") as your
+ curses library. It has not been fully ported to DOS yet, however.
+ See "http://www.flora.org/lynx-dev/html/month1097/msg00390.html". You
+ need to compile these before you go any further. If you wish to use the
+ beta version of PDCurses 2.3, you need to first apply a patch (available at
+ "http://www.flora.org/lynx-dev/html/month0997/msg00441.html"). If you have
+ trouble applying the patch, we recommend that you use the "patch" program,
+ ("http://www.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/pat25b.zip"). To
+ read the Unix man style documentation, use, for example, "less"
+ ("http://www.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/lss332b.zip").
+ Compile or place your compiled PDCurses library in lynx2-*/curses, and
+ compile or place your compiled WATTCP library in lynx2-*/djgpp/tcplib.
+
+ Move to the "lynx2-*/WWW/Library/djgpp" directory and do "make". This
+ should compile libwww.a. Next move to the "lynx2-*/src/chrtrans"
+ directory and do "make -f makefile.dos" to compile the character tables.
+ Then move to the "lynx2-*/src" directory and do "make -f makefile.dos".
+ If all goes well, you will have a lynx.exe file. If you have trouble,
+ check to be sure djgpp.env is the way it came in the original package.
+
+ To test Lynx_386 you must have a packet driver installed. The simplest
+ method is to use a null packet driver that just allows Lynx to start up,
+ but doesn't do anything else. One such executable driver has been posted,
+ uuencoded, to the lynx-dev mailing list: "msg00031.html", "msg00057.html",
+ and "msg00066.html" under "http://www.flora.org/lynx-dev/html/month0198/".
+ Start the dummy packet driver with "nullpkt 0x60", and take it out of
+ memory with "nullpkt -u". You can also use slip8250.com. See the CRYNWR
+ package "http://www.simtel.net/pub/simtelnet/msdos/pktdrvr/pktd11.zip".
+ Usage is "slip8250 0x60", but you may have to invoke it as, for example,
+ "slip8250 0x60 6 3 0x2F8" so that it uses COM2 and IRQ 3, in order to
+ avoid an IRQ conflict with a mouse or some other device. Another packet
+ driver is slipper.exe, which is available from many sites, including
+ "ftp://jazz.trumpet.com.au/slipper". To remove it from memory use
+ termin.com (usage "termin 0x60"), available in the CRYNWR package. To
+ connect over a dialup PPP connection you need dosppp or klos' pppshare.
+ (Find at "http://www.simtel.net/pub/simtelnet/msdos/pktdrvr/dosppp05.zip"
+ and "ftp://ftp.klos.com/demo/pppshare.exe".)
+
+ See "http://www.fdisk.com/doslynx/lynxport.htm" for more hints and some
+ precompiled libraries. One problem you can run into is when editing
+ userdefs.h and lynx.cfg, which have unix-style end of lines. You would be
+ well advised to use an editor that can handle end of lines terminated with
+ a single LF character. You can also unpack the source code using unzip386
+ or unzip with the -a switch to convert unix LF to dos CRLF. That will make
+ texts more readable under DOS. If you compile lynx regularly, you may
+ automate the procedure by creating a batch file such as the following.
+
+ cd djgpp\tcplib\obj
+ make
+ cd ..\..\www\library\djgpp
+ make
+ cd ..\..\..\src\chrtrans
+ make -f makefile.dos
+ cd ..\..\..\src
+ make -f makefile.dos
+ strip lynx.exe
+ cd ..
+
+ This batch file expects the DJGPP port of WATTCP to be installed in the
+ lynx2-* directory. Place a copy of this batch file, named "djgpp.bat",
+ in the lynx2-* directory, move to that directory and type "djgpp". A more
+ complete batch file with error checking and annotation can be found at:
+ "http://www.flora.org/lynx-dev/html/month1197/msg00250.html".
+
+-- 1997/9/29 - D. Kaufman <dkaufman@rahul.net>
+-- 1997/10/3 - B. Schiavo <Wschiavo@concentric.net>
+
+
+VI. General installation instructions
+
+ Once you have compiled Lynx, test it out on "lynx_help/about_lynx.html".
+ You shouldn't need to install Lynx to test it. Once you are satisfied
+ that it works, go ahead and install Lynx. For Unix, type "make install".
+
+ For VMS, you need to have the executable in a public place, make it
+ accessible, define it as a foreign command, and copy lynx.cfg to
+ "Lynx_Dir". Look at lynx.com in the samples directory as a model for
+ installing Lynx. To include lynx.hlp in the system HELP library, use
+ the command: "$ library/replace sys$help:helplib.hlb lynx.hlp".
+
+ Local copies of the Lynx online help should be made accessible in response
+ to the Lynx 'h'elp command by defining HELPFILE in userdefs.h and/or
+ lynx.cfg to an appropriate file://localhost/path URL. On Unix, all you
+ need to do is type "make install-help." If you are installing manually,
+ copy the files "COPYHEADER" and "COPYING" into the lynx_help directory
+ BEFORE moving the lynx_help tree to its final location. These files are
+ referenced hypertextually from help documents. Find tips for installing
+ the help files at "http://www.irm.nara.kindai.ac.jp/lynxdev/README.help".
+
+ If you have old, pre-existing bookmark files from earlier versions of
+ Lynx, those files may have to be updated. Conversion may just consist
+ of adding one META line near the top, or may require creating new book-
+ mark files and editing in bookmarks from outdated files.
+
+ IMPORTANT! Be sure you have read the warnings about setting up an
+ anonymous account with Lynx if you plan to give public access to Lynx.
+
+ After applying patches or editing files to correct for an unsuccessful
+ build, be certain to do a "make clean" (or "make distclean" for those
+ using auto-configure) before attempting to compile again.
+
+ If something doesn't work, or you can't get Lynx to even compile, or you
+ don't understand what one of the defines means, read the PROBLEMS file,
+ and the README.defines and *.announce files in the docs subdirectory.
+ The docs/CHANGES* files record the entire development history of Lynx
+ and are an invaluable resource for understanding how Lynx should perform.
+
+ If you still have difficulties, send an email message to the Lynx-Dev
+ mailing list (see the README file). Try to include pertinent information
+ about your system, the OS you are using, the name and version of your
+ compiler, which curses library you are using and the compile-time errors.
+ Be sure to say what version and image-number (alternately the top date
+ of the CHANGES file) of Lynx you are trying to build.
+
+
+VII. Setting environment variables before running Lynx (optional)
+
+1. Unix and VMS
+ To set your site's NTTP server as the default host for news reading
+ and posting via Lynx, set the environment variable NNTPSERVER so that
+ it points to its Internet address. The variable "NNTPSERVER" is used
+ to specify the host which will be used as the default for news URLs.
+
+ UNIX
+ setenv NNTPSERVER "news.server.dom"
+
+ VMS
+ define/system NNTPSERVER "news.server.dom"
+
+ The environment variables "ORGANIZATION" or "NEWS_ORGANIZATION", if set,
+ will be used for the Organization: header in news postings. (On Unix,
+ Lynx also checks for an /etc/organization file.)
+
+ The environment variable "LYNX_CFG", if set, will override the default
+ location and name of the global configuration file (lynx.cfg) that was
+ defined via the constant "LYNX_CFG_FILE" in userdefs.h. See userdefs.h
+ for more information.
+
+ The environment variable "LYNX_TEMP_SPACE", if set, will override the
+ default path prefix for temporary files that was defined via the constant
+ "TEMP_SPACE" in userdefs.h. See userdefs.h for more information.
+
+ The environment variable "LYNX_SAVE_SPACE", if set, will override the
+ default path prefix for files saved to disk that was defined via the
+ constant "SAVE_SPACE" in lynx.cfg. See lynx.cfg for more information.
+
+ The variable "WWW_HOME", if set, will override the default startup
+ URL specified in any of the configuration files.
+
+ Lynx still supports use of gateway servers, with the servers specified
+ via the variables "WWW_access_GATEWAY", where "access" is lower case
+ and can be "http", "ftp", "gopher" or "wais". Most of the gateway
+ servers have been discontinued, but "http://www.w3.org:8001" is
+ available for wais searches (note that you do not include a terminal
+ '/' for gateways, but do for proxies; see below).
+
+ Lynx version 2.2 and beyond supports the use of proxy servers that can
+ act as firewall gateways and caching servers. They are preferable to
+ the older gateway servers. Each protocol used by Lynx can be mapped
+ separately using PROTOCOL_proxy environment variables of the form:
+
+ UNIX
+ setenv http_proxy "http://some.server.dom:port/"
+ setenv https_proxy "http://some.server.dom:port/"
+ setenv ftp_proxy "http://some.server.dom:port/"
+ setenv gopher_proxy "http://some.server.dom:port/"
+ setenv news_proxy "http://some.server.dom:port/"
+ setenv newspost_proxy "http://some.server.dom:port/"
+ setenv newsreply_proxy "http://some.server.dom:port/"
+ setenv snews_proxy "http://some.server.dom:port/"
+ setenv snewspost_proxy "http://some.server.dom:port/"
+ setenv snewsreply_proxy "http://some.server.dom:port/"
+ setenv nntp_proxy "http://some.server.dom:port/"
+ setenv wais_proxy "http://some.server.dom:port/"
+ setenv finger_proxy "http://some.server.dom:port/"
+ setenv cso_proxy "http://some.server.dom:port/"
+
+ VMS
+ define "http_proxy" "http://some.server.dom:port/"
+ define "https_proxy" "http://some.server.dom:port/"
+ define "ftp_proxy" "http://some.server.dom:port/"
+ define "gopher_proxy" "http://some.server.dom:port/"
+ define "news_proxy" "http://some.server.dom:port/"
+ define "newspost_proxy" "http://some.server.dom:port/"
+ define "newsreply_proxy" "http://some.server.dom:port/"
+ define "snews_proxy" "http://some.server.dom:port/"
+ define "snewspost_proxy" "http://some.server.dom:port/"
+ define "snewsreply_proxy" "http://some.server.dom:port/"
+ define "nntp_proxy" "http://some.server.dom:port/"
+ define "wais_proxy" "http://some.server.dom:port/"
+ define "finger_proxy" "http://some.server.dom:port/"
+ define "cso_proxy" "http://some.server.dom:port/"
+ (Encase *BOTH* strings in double-quotes to maintain
+ lower case for the PROTOCOL_proxy variable and for
+ the http access type; include /system if you want
+ proxying for all clients on your system.)
+
+ If you wish to override the use of a proxy server for specific hosts or
+ entire domains you may use the "no_proxy" environment variable. Here is
+ an example use of "no_proxy":
+
+ UNIX
+ setenv no_proxy "host.domain.dom, domain1.dom, domain2"
+
+ VMS
+ define "no_proxy" "host.domain.dom, domain1.dom, domain2"
+
+ You can include a port number in the no_proxy list to override use
+ of a proxy server for the host accessed via that port, but not via
+ other ports. For example, if you use "host.domain.dom:119" and/or
+ "host.domain.dom:210", then news (port 119) URLs and/or any wais
+ (port 210) searches on that host would be excluded, but http, ftp,
+ and gopher services (if normally proxied) would still be included,
+ as would any news or wais services on other hosts.
+
+ If you wish to override the use of a proxy server completely (i.e.,
+ globally override any existing proxy variables), set the value of
+ "no_proxy" to "*".
+
+ Note that Lynx treats file URLs on the local host as requests for
+ direct access to the file, and does not attempt ftp if that fails.
+ It treats both ftp URLs and file URLs on remote hosts as ftp URLs,
+ and does not attempt direct file access for either. If ftp URLs are
+ being proxied, file URLs on a remote host will be converted to ftp
+ URLs before submission by Lynx to the proxy server, so no special
+ procedure for inducing the proxy server to handle them is required.
+ Other WWW clients may require that the http server's configuration
+ file have "Map file:* ftp:*" in it to perform that conversion.
+
+ The proxy and no_proxy variables also can be set at run time via
+ lynx.cfg.
+
+2. Win32 (95/NT) and 386 DOS (adapted from "readme.txt" by Wayne Buttles)
+
+ HOME Where to keep the bookmark file and personal config files.
+ LYNX_CFG The full path and filename for lynx.cfg
+ TEMP or TMP Bookmarks are kept here with no HOME. Temp files here.
+ TERM Set TERM=vt100 to stop that annoying terminal type message.
+ USER Tells Lynx you are real instead of an anonymous user(?)
+
+ 386 version only:
+ WATTCP.CFG Where to find the wattcp.cfg file.
+ (Depending on how you compiled libtcp.a, you may have to use WATCONF.)
+
+ Define these in your batch file for running Lynx. For example, if your
+ application line is "D:\win32\lynx.bat", lynx.bat may look like:
+ @ECHO OFF
+ set home=d:\win32
+ set temp=d:\tmp
+ set lynx_cfg=d:\win32\lynx.cfg
+ d:\win32\lynx.exe %1 %2 %3 %4 %5
+
+
+VIII. Acknowledgment
+
+ Thanks to the many volunteers who offered suggestions for making this
+ installation manual as accurate and complete as possible.
+
+-- 1998/01/22 - H. Nelson <lynx-admin@irm.nara.kindai.ac.jp>
diff --git a/gnu/usr.bin/lynx/LYMessages_en.h b/gnu/usr.bin/lynx/LYMessages_en.h
new file mode 100644
index 00000000000..0ceb12734f6
--- /dev/null
+++ b/gnu/usr.bin/lynx/LYMessages_en.h
@@ -0,0 +1,657 @@
+/*
+ * Lynx - Hypertext navigation system
+ *
+ * (c) Copyright 1992, 1993, 1994 University of Kansas
+ * 1995, 1996: GNU General Public License
+ */
+#ifndef LYMESSAGES_EN_H
+#define LYMESSAGES_EN_H
+
+/*******************************************************************
+ * The following definitions are for statusline prompts, messages,
+ * or warnings issued by Lynx during program execution. You can
+ * modify them to make them more appropriate for you site, and/or
+ * to use other languages. Links to collections of alternate
+ * definitions, developed by the Lynx User Community, are maintained
+ * in Lynx links:
+ *
+ * http://www.crl.com/~subir/lynx.html
+ *
+ * You can substitute one of those as LYMessages_en.h, or modify
+ * the header inclusion statement in your userdefs.h to include
+ * one of those with a different name.
+ */
+#define REALLY_QUIT_Y "Are you sure you want to quit? [Y] "
+#ifdef VMS
+#define REALLY_EXIT_Y "Really exit from Lynx? [Y] "
+#endif /* VMS */
+#define REALLY_QUIT_N "Are you sure you want to quit? [N] "
+#ifdef VMS
+#define REALLY_EXIT_N "Really exit from Lynx? [N] "
+#endif /* VMS */
+#define CANCELLED "Cancelled!!!"
+#define CANCELLING "Cancelling!"
+#define NO_CANCEL "Excellent!!!"
+#define OPERATION_DONE "Done!"
+#define BAD_REQUEST "Bad request!"
+#define PREVIOUS "previous"
+#define NEXT_SCREEN "next screen"
+#define HELP \
+ "Commands: Use arrow keys to move, '?' for help, 'q' to quit, '<-' to go back."
+#define MOREHELP \
+ "-- press space for more, use arrow keys to move, '?' for help, 'q' to quit."
+#define MORE "-- press space for next page --"
+#define FORM_LINK_TEXT_MESSAGE \
+ "(Text entry field) Enter text. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_TEXT_UNM_MSG \
+ "UNMODIFIABLE form text field. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_TEXT_SUBMIT_MESSAGE \
+ "(Form field) Enter text. Use <return> to submit ('x' for no cache)."
+#define FORM_LINK_TEXT_RESUBMIT_MESSAGE \
+ "(Form field) Enter text. Use <return> to submit, arrows or tab to move off."
+#define FORM_LINK_TEXT_SUBMIT_UNM_MSG \
+ "UNMODIFIABLE form field. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_TEXT_SUBMIT_MAILTO_MSG \
+ "(mailto form field) Enter text. Use <return> to submit, arrows to move off."
+#define FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG \
+ "(mailto form field) Mail is disallowed so you cannot submit."
+#define FORM_LINK_PASSWORD_MESSAGE \
+ "(Password entry field) Enter text. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_PASSWORD_UNM_MSG \
+ "UNMODIFIABLE form password. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_CHECKBOX_MESSAGE \
+ "(Checkbox Field) Use right-arrow or <return> to toggle."
+#define FORM_LINK_CHECKBOX_UNM_MSG \
+ "UNMODIFIABLE form checkbox. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_RADIO_MESSAGE \
+ "(Radio Button) Use right-arrow or <return> to toggle."
+#define FORM_LINK_RADIO_UNM_MSG \
+ "UNMODIFIABLE form radio button. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_SUBMIT_MESSAGE \
+ "(Form submit button) Use right-arrow or <return> to submit ('x' for no cache)."
+#define FORM_LINK_RESUBMIT_MESSAGE \
+ "(Form submit button) Use right-arrow or <return> to submit."
+#define FORM_LINK_SUBMIT_DIS_MSG \
+ "DISABLED form submit button. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_SUBMIT_MAILTO_MSG \
+ "(mailto form submit button) Use right-arrow or <return> to submit."
+#define FORM_LINK_SUBMIT_MAILTO_DIS_MSG \
+ "(mailto form submit button) Mail is disallowed so you cannot submit."
+#define FORM_LINK_RESET_MESSAGE \
+ "(Form reset button) Use right-arrow or <return> to reset form to defaults."
+#define FORM_LINK_RESET_DIS_MSG \
+ "DISABLED form reset button. Use UP or DOWN arrows or tab to move off."
+#define FORM_LINK_OPTION_LIST_MESSAGE \
+ "(Option list) Hit return and use arrow keys and return to select option."
+#define CHOICE_LIST_MESSAGE \
+ "(Choice list) Hit return and use arrow keys and return to select option."
+#define FORM_LINK_OPTION_LIST_UNM_MSG \
+ "UNMODIFIABLE option list. Use return or arrow keys to review or leave."
+#define CHOICE_LIST_UNM_MSG \
+ "UNMODIFIABLE choice list. Use return or arrow keys to review or leave."
+#define NORMAL_LINK_MESSAGE \
+ "(NORMAL LINK) Use right-arrow or <return> to activate."
+#define LINK_NOT_FOUND "The resource requested is not available at this time."
+#define ENTER_LYNX_COMMAND "Enter Lynx keystroke command: "
+#define WWW_WAIT_MESSAGE "Getting %s"
+#define WWW_SKIP_MESSAGE "Skipping %s"
+#define WWW_USING_MESSAGE "Using %s"
+#define WWW_ILLEGAL_URL_MESSAGE "Illegal URL: %s"
+#define WWW_BAD_ADDR_MESSAGE "Badly formed address %s"
+#define ADVANCED_URL_MESSAGE "URL: %s"
+#define WWW_FAIL_MESSAGE "Unable to access WWW file!!!"
+#define WWW_INDEX_MESSAGE "This is a searchable index. Use %s to search."
+#define WWW_INDEX_MORE_MESSAGE \
+ "--More-- This is a searchable index. Use %s to search."
+#define BAD_LINK_NUM_ENTERED "You have entered an invalid link number."
+#define SOURCE_HELP \
+ "Currently viewing document source. Press '\\' to return to rendered version."
+#define NOVICE_LINE_ONE \
+ " Arrow keys: Up and Down to move. Right to follow a link; Left to go back. \n"
+#define NOVICE_LINE_TWO \
+ " H)elp O)ptions P)rint G)o M)ain screen Q)uit /=search [delete]=history list \n"
+#define NOVICE_LINE_TWO_A \
+ " O)ther cmds H)elp K)eymap G)oto P)rint M)ain screen o)ptions Q)uit \n"
+#define NOVICE_LINE_TWO_B \
+ " O)ther cmds B)ack E)dit D)ownload ^R)eload ^W)ipe screen search doc: / \n"
+#define NOVICE_LINE_TWO_C \
+ " O)ther cmds C)omment History: <delete> Bookmarks: V)iew, A)dd, R)emove \n"
+#define FORM_NOVICELINE_ONE \
+ " Enter text into the field by typing on the keyboard "
+#define FORM_NOVICELINE_TWO \
+" Ctrl-U to delete all text in field, [Backspace] to delete a character "
+#define SUBMITTING_FORM "Submitting form..."
+#define RESETTING_FORM "Resetting form..."
+#define RELOADING_FORM \
+ "Reloading document. Any form entries will be lost!"
+#define CANNOT_TRANSCODE_FORM "Warning: Cannot transcode form data to charset %s!"
+#define BAD_FORM_MAILTO "Malformed mailto form submission! Cancelled!"
+#define FORM_MAILTO_DISALLOWED "Mail disallowed! Cannot submit."
+#define FORM_MAILTO_FAILED "Mailto form submission failed!"
+#define FORM_MAILTO_CANCELLED "Mailto form submission Cancelled!!!"
+#define SENDING_FORM_CONTENT "Sending form content..."
+#define NO_ADDRESS_IN_MAILTO_URL "No email address is present in mailto URL!"
+#define MAILTO_URL_TEMPOPEN_FAILED \
+ "Unable to open temporary file for mailto URL!"
+#define COMMENT_REQUEST_CANCELLED "Comment request cancelled!!!"
+#define INC_ORIG_MSG_PROMPT \
+ "Do you wish to include the original message? (y/n) "
+#define INC_PREPARSED_MSG_PROMPT \
+ "Do you wish to include the preparsed source? (y/n) "
+#define SPAWNING_EDITOR_FOR_MAIL \
+ "Spawning your selected editor to edit mail message"
+#define ERROR_SPAWNING_EDITOR \
+ "Error spawning editor, check your editor definition in the options menu"
+#define SEND_COMMENT_PROMPT "Send this comment? (y/n) "
+#define SEND_MESSAGE_PROMPT "Send this message? (y/n) "
+#define SENDING_YOUR_MSG "Sending your message..."
+#define FILE_ACTIONS_DISALLOWED "file: ACTIONs are disallowed!"
+#define FILE_SERVED_LINKS_DISALLOWED \
+ "file: URLs via served links are disallowed!"
+#define FILE_BOOKMARKS_DISALLOWED "file: URLs via bookmarks are disallowed!"
+#define SPECIAL_VIA_EXTERNAL_DISALLOWED \
+ "This special URL is not allowed in external documents!"
+#define RETURN_TO_LYNX "Press <return> to return to Lynx."
+#ifdef VMS
+#define SPAWNING_MSG \
+ "Spawning DCL subprocess. Use 'logout' to return to Lynx.\n"
+#else
+#ifdef DOSPATH
+#define SPAWNING_MSG \
+ "Type EXIT to return to Lynx.\r\n"
+#else /* UNIX */
+#define SPAWNING_MSG \
+ "Spawning your default shell. Use 'exit' to return to Lynx.\n"
+#endif
+#endif /* VMS */
+#define SPAWNING_DISABLED "Spawning is currently disabled."
+#define DOWNLOAD_DISABLED "The 'd'ownload command is currently disabled."
+#define NO_DOWNLOAD_INPUT "You cannot download a input field."
+#define NO_DOWNLOAD_MAILTO_ACTION "Form has a mailto action! Cannot download."
+#define NO_DOWNLOAD_COOKIES "You cannot download cookies."
+#define NO_DOWNLOAD_PRINT_OP "You cannot download a printing option."
+#define NO_DOWNLOAD_UPLOAD_OP "You cannot download an upload option."
+#define NO_DOWNLOAD_PERMIT_OP "You cannot download an permit option."
+#define NO_DOWNLOAD_SPECIAL "This special URL cannot be downloaded!"
+#define NO_DOWNLOAD_CHOICE "Nothing to download."
+#define TRACE_ON "Trace ON!"
+#define TRACE_OFF "Trace OFF!"
+#define CLICKABLE_IMAGES_ON \
+ "Links will be included for all images! Reloading..."
+#define CLICKABLE_IMAGES_OFF \
+ "Standard image handling restored! Reloading..."
+#define PSEUDO_INLINE_ALTS_ON \
+ "Pseudo_ALTs will be inserted for inlines without ALT strings! Reloading..."
+#define PSEUDO_INLINE_ALTS_OFF \
+ "Inlines without an ALT string specified will be ignored! Reloading..."
+#define RAWMODE_OFF "Raw 8-bit or CJK mode toggled OFF! Reloading..."
+#define RAWMODE_ON "Raw 8-bit or CJK mode toggled ON! Reloading..."
+#define HEAD_D_L_OR_CANCEL \
+ "Send HEAD request for D)ocument or L)ink, or C)ancel? (d,l,c): "
+#define HEAD_D_OR_CANCEL \
+ "Send HEAD request for D)ocument, or C)ancel? (d,c): "
+#define DOC_NOT_HTTP_URL "Sorry, the document is not an http URL."
+#define LINK_NOT_HTTP_URL "Sorry, the link is not an http URL."
+#define FORM_ACTION_DISABLED "Sorry, the ACTION for this form is disabled."
+#define FORM_ACTION_NOT_HTTP_URL \
+ "Sorry, the ACTION for this form is not an http URL."
+#define NOT_HTTP_URL_OR_ACTION "Not an http URL or form ACTION!"
+#define SPECIAL_ACTION_DISALLOWED "This special URL cannot be a form ACTION!"
+#define NOT_IN_STARTING_REALM "URL is not in starting realm!"
+#define NEWSPOSTING_DISABLED "News posting is disabled!"
+#define DIRED_DISABLED "File management support is disabled!"
+#define NO_JUMPFILE "No jump file is currently available."
+#define JUMP_PROMPT "Jump to (use '?' for list): "
+#define JUMP_DISALLOWED "Jumping to a shortcut URL is disallowed!"
+#define RANDOM_URL_DISALLOWED "Random URL is disallowed! Use a shortcut."
+#define NO_RANDOM_URLS_YET "No random URLs have been used thus far."
+#define BOOKMARKS_DISABLED "Bookmark features are currently disabled."
+#define BOOKMARK_EXEC_DISABLED "Execution via bookmarks is disabled."
+#define BOOKMARK_FILE_NOT_DEFINED \
+ "Bookmark file is not defined. Use %s to see options."
+#define NO_TEMP_FOR_HOTLIST \
+ "Unable to open tempfile for X Mosaic hotlist conversion."
+#define BOOKMARK_OPEN_FAILED "ERROR - unable to open bookmark file."
+#define BOOKMARK_OPEN_FAILED_FOR_DEL \
+ "Unable to open bookmark file for deletion of link."
+#ifdef VMS
+#define BOOKSCRA_OPEN_FAILED_FOR_DEL \
+ "Unable to open scratch file for deletion of link."
+#define ERROR_RENAMING_SCRA "Error renaming scratch file."
+#else
+#define BOOKTEMP_OPEN_FAILED_FOR_DEL \
+ "Unable to open temporary file for deletion of link."
+#define ERROR_RENAMING_TEMP "Error renaming temporary file."
+#define BOOKTEMP_REOPEN_FAIL_FOR_DEL \
+ "Unable to reopen temporary file for deletion of link."
+#endif /* VMS */
+#define BOOKMARK_LINK_NOT_ONE_LINE \
+ "Link is not by itself all on one line in bookmark file."
+#define BOOKMARK_DEL_FAILED "Bookmark deletion failed."
+#define BOOKMARKS_NOT_TRAVERSED \
+ "Bookmark files cannot be traversed (only http URLs)."
+#define BOOKMARKS_NOT_OPEN \
+ "Unable to open bookmark file, use 'a' to save a link first"
+#define BOOKMARKS_NOLINKS "There are no links in this bookmark file!"
+#define BOOK_D_L_OR_CANCEL \
+ "Save D)ocument or L)ink to bookmark file or C)ancel? (d,l,c): "
+#define BOOK_D_OR_CANCEL "Save D)ocument to bookmark file or C)ancel? (d,c): "
+#define BOOK_L_OR_CANCEL "Save L)ink to bookmark file or C)ancel? (l,c): "
+#define NOBOOK_POST_FORM \
+ "Documents from forms with POST content cannot be saved as bookmarks."
+#define NOBOOK_FORM_FIELD "Cannot save form fields/links"
+#define NOBOOK_HSML \
+ "History, showinfo, menu and list files cannot be saved as bookmarks."
+#define CONFIRM_BOOKMARK_DELETE \
+ "Do you really want to delete this link from your bookmark file? (y/n)"
+#define MALFORMED_ADDRESS "Malformed address."
+#define HISTORICAL_ON_MINIMAL_OFF \
+ "Historical comment parsing ON (Minimal is overridden)!"
+#define HISTORICAL_OFF_MINIMAL_ON \
+ "Historical comment parsing OFF (Minimal is in effect)!"
+#define HISTORICAL_ON_VALID_OFF \
+ "Historical comment parsing ON (Valid is overridden)!"
+#define HISTORICAL_OFF_VALID_ON \
+ "Historical comment parsing OFF (Valid is in effect)!"
+#define MINIMAL_ON_IN_EFFECT \
+ "Minimal comment parsing ON (and in effect)!"
+#define MINIMAL_OFF_VALID_ON \
+ "Minimal comment parsing OFF (Valid is in effect)!"
+#define MINIMAL_ON_BUT_HISTORICAL \
+ "Minimal comment parsing ON (but Historical is in effect)!"
+#define MINIMAL_OFF_HISTORICAL_ON \
+ "Minimal comment parsing OFF (Historical is in effect)!"
+#define SOFT_DOUBLE_QUOTE_ON "Soft double-quote parsing ON!"
+#define SOFT_DOUBLE_QUOTE_OFF "Soft double-quote parsing OFF!"
+#define USING_DTD_0 "Now using TagSoup parsing of HTML."
+#define USING_DTD_1 "Now using SortaSGML parsing of HTML!"
+#define ALREADY_AT_END "You are already at the end of this document."
+#define ALREADY_AT_BEGIN "You are already at the beginning of this document."
+#define ALREADY_AT_PAGE "You are already at page %d of this document."
+#define LINK_ALREADY_CURRENT "Link number %d already is current."
+#define ALREADY_AT_FIRST "You are already at the first document"
+#define NO_LINKS_ABOVE "There are no links above this line of the document."
+#define NO_LINKS_BELOW "There are no links below this line of the document."
+#define MAXLEN_REACHED_DEL_OR_MOV \
+ "Maximum length reached! Delete text or move off field."
+#define NOT_ON_SUBMIT_OR_LINK \
+ "You are not on a form submission button or normal link."
+#define NEED_CHECKED_RADIO_BUTTON \
+ "One radio button must be checked at all times!"
+#define PREV_DOC_QUERY "Do you want to go back to the previous document? [N]"
+#define ARROWS_OR_TAB_TO_MOVE "Use arrows or tab to move off of field."
+#define ENTER_TEXT_ARROWS_OR_TAB \
+ "Enter text. Use arrows or tab to move off of field."
+#define NO_FORM_ACTION "** Bad HTML!! No form action defined. **"
+#define BAD_HTML_NO_POPUP "Bad HTML!! Unable to create popup window!"
+#define POPUP_FAILED "Unable to create popup window!"
+#define GOTO_DISALLOWED "Goto a random URL is disallowed!"
+#define GOTO_NON_HTTP_DISALLOWED "Goto a non-http URL is disallowed!"
+#define GOTO_CSO_DISALLOWED "You are not allowed to goto \"cso:\" URLs"
+#define GOTO_FILE_DISALLOWED "You are not allowed to goto \"file:\" URLs"
+#define GOTO_FINGER_DISALLOWED "You are not allowed to goto \"finger:\" URLs"
+#define GOTO_FTP_DISALLOWED "You are not allowed to goto \"ftp:\" URLs"
+#define GOTO_GOPHER_DISALLOWED "You are not allowed to goto \"gopher:\" URLs"
+#define GOTO_HTTP_DISALLOWED "You are not allowed to goto \"http:\" URLs"
+#define GOTO_HTTPS_DISALLOWED "You are not allowed to goto \"https:\" URLs"
+#define GOTO_CGI_DISALLOWED "You are not allowed to goto \"lynxcgi:\" URLs"
+#define GOTO_EXEC_DISALLOWED "You are not allowed to goto \"lynxexec:\" URLs"
+#define GOTO_PROG_DISALLOWED "You are not allowed to goto \"lynxprog:\" URLs"
+#define GOTO_MAILTO_DISALLOWED "You are not allowed to goto \"mailto:\" URLs"
+#define GOTO_NEWS_DISALLOWED "You are not allowed to goto \"news:\" URLs"
+#define GOTO_NNTP_DISALLOWED "You are not allowed to goto \"nntp:\" URLs"
+#define GOTO_RLOGIN_DISALLOWED "You are not allowed to goto \"rlogin:\" URLs"
+#define GOTO_SNEWS_DISALLOWED "You are not allowed to goto \"snews:\" URLs"
+#define GOTO_TELNET_DISALLOWED "You are not allowed to goto \"telnet:\" URLs"
+#define GOTO_TN3270_DISALLOWED "You are not allowed to goto \"tn3270:\" URLs"
+#define GOTO_WAIS_DISALLOWED "You are not allowed to goto \"wais:\" URLs"
+#define GOTO_SPECIAL_DISALLOWED "This special URL is not allowed as a goto!"
+#define URL_TO_OPEN "URL to open: "
+#define EDIT_CURRENT_GOTO "Edit the current Goto URL: "
+#define EDIT_THE_PREV_GOTO "Edit the previous Goto URL: "
+#define EDIT_A_PREV_GOTO "Edit a previous Goto URL: "
+#define CURRENT_DOC_HAS_POST_DATA "Current document has POST data."
+#define EDIT_CURDOC_URL "Edit this document's URL: "
+#define EDIT_CURLINK_URL "Edit the current link's URL: "
+#define EDIT_FM_MENU_URLS_DISALLOWED "You cannot edit File Management URLs"
+#define ENTER_DATABASE_QUERY "Enter a database query: "
+#define ENTER_WHEREIS_QUERY "Enter a whereis query: "
+#define EDIT_CURRENT_QUERY "Edit the current query: "
+#define EDIT_THE_PREV_QUERY "Edit the previous query: "
+#define EDIT_A_PREV_QUERY "Edit a previous query: "
+#define USE_C_R_TO_RESUB_CUR_QUERY \
+ "Use Control-R to resubmit the current query."
+#define EDIT_CURRENT_SHORTCUT "Edit the current shortcut: "
+#define EDIT_THE_PREV_SHORTCUT "Edit the previous shortcut: "
+#define EDIT_A_PREV_SHORTCUT "Edit a previous shortcut: "
+#define KEY_NOT_MAPPED_TO_JUMP_FILE "Key '%c' is not mapped to a jump file!"
+#define CANNOT_LOCATE_JUMP_FILE "Cannot locate jump file!"
+#define CANNOT_OPEN_JUMP_FILE "Cannot open jump file!"
+#define ERROR_READING_JUMP_FILE "Error reading jump file!"
+#define OUTOF_MEM_FOR_JUMP_FILE "Out of memory reading jump file!"
+#define OUTOF_MEM_FOR_JUMP_TABLE "Out of memory reading jump table!"
+#define NO_INDEX_FILE "No index is currently available."
+#define CONFIRM_MAIN_SCREEN \
+ "Do you really want to go to the Main screen? (y/n) [n] "
+#define IN_MAIN_SCREEN "You are already at main screen!"
+#define NOT_ISINDEX \
+ "Not a searchable indexed document -- press '/' to search for a text string"
+#define NO_OWNER \
+ "No owner is defined for this file so you cannot send a comment"
+#define NO_OWNER_USE "No owner is defined. Use %s? [N] "
+#define CONFIRM_COMMENT "Do you wish to send a comment? [N]"
+#define MAIL_DISALLOWED "Mail is disallowed so you cannot send a comment"
+#define EDIT_DISABLED "The 'e'dit command is currently disabled."
+#define NO_STATUS "System error - failure to get status."
+#define NO_EDITOR "No editor is defined!"
+#define PRINT_DISABLED "The 'p'rint command is currently disabled."
+#define NO_TOOLBAR "Document has no Toolbar links or Banner."
+#define NOOPEN_TRAV_ERR_FILE "Unable to open traversal errors output file"
+#define FOLLOW_LINK_NUMBER "Follow link (or goto link or page) number: "
+#define SELECT_OPTION_NUMBER "Select option (or page) number: "
+#define OPTION_CHOICE_NUMBER "Option choice (or page) number: "
+#define OPTION_ALREADY_CURRENT "Option number %d already is current."
+#define CHOICE_ALREADY_CURRENT "Choice number %d already is current."
+#define ALREADY_AT_OPTION_END \
+ "You are already at the end of this option list."
+#define ALREADY_AT_CHOICE_END \
+ "You are already at the end of this choice list."
+#define ALREADY_AT_OPTION_BEGIN \
+ "You are already at the beginning of this option list."
+#define ALREADY_AT_CHOICE_BEGIN \
+ "You are already at the beginning of this choice list."
+#define ALREADY_AT_OPTION_PAGE \
+ "You are already at page %d of this option list."
+#define ALREADY_AT_CHOICE_PAGE \
+ "You are already at page %d of this choice list."
+#define BAD_OPTION_NUM_ENTERED "You have entered an invalid option number."
+#define BAD_CHOICE_NUM_ENTERED "You have entered an invalid choice number."
+#define BAD_HTML_USE_TRACE "** Bad HTML!! Use -trace to diagnose. **"
+#define CANNOT_OPEN_TEMP "Can't open temporary file!"
+#define CANNOT_OPEN_OUTPUT "Can't open output file! Cancelling!"
+#define EXECUTION_DISABLED "Execution is disabled."
+#define EXECUTION_DISABLED_FOR_FILE \
+ "Execution is not enabled for this file. See the Options menu (use %s)."
+#define EXECUTION_NOT_COMPILED \
+ "Execution capabilities are not compiled into this version."
+#define CANNOT_DISPLAY_FILE "This file cannot be displayed on this terminal."
+#define CANNOT_DISPLAY_FILE_D_OR_C \
+ "This file cannot be displayed on this terminal: D)ownload, or C)ancel"
+#define WRONG_CHARSET_D_OR_C "%s D)ownload, or C)ancel"
+#define UNMAPPED_TYPE_D_OR_C "%s D)ownload, or C)ancel"
+#define CANCELLING_FILE "Cancelling file."
+#define RETRIEVING_FILE "Retrieving file. - PLEASE WAIT -"
+#define FILENAME_PROMPT "Enter a filename: "
+#define EDIT_THE_PREV_FILENAME "Edit the previous filename: "
+#define EDIT_A_PREV_FILENAME "Edit a previous filename: "
+#define NEW_FILENAME_PROMPT "Enter a new filename: "
+#define FILENAME_CANNOT_BE_DOT "File name may not begin with a dot."
+#ifdef VMS
+#define FILE_EXISTS_HPROMPT "File exists. Create higher version? (y/n)"
+#else
+#define FILE_EXISTS_OPROMPT "File exists. Overwrite? (y/n)"
+#endif /* VMS */
+#define CANNOT_WRITE_TO_FILE "Cannot write to file."
+#define MISCONF_DOWNLOAD_COMMAND "ERROR! - download command is misconfigured."
+#define CANNOT_DOWNLOAD_FILE "Unable to download file."
+#define SAVING "Saving..."
+#define COULD_NOT_ACCESS_FILE "Could not access file."
+#define CANNOT_EDIT_REMOTE_FILES \
+ "Lynx cannot currently (E)dit remote WWW files"
+#define NOAUTH_TO_EDIT_FILE "You are not authorized to edit this file."
+#define TITLE_PROMPT "Title: "
+#define SUBJECT_PROMPT "Subject: "
+#define USERNAME_PROMPT "Username: "
+#define PASSWORD_PROMPT "Password: "
+#define USERNAME_PASSWORD_REQUIRED "lynx: Username and Password required!!!"
+#define PASSWORD_REQUIRED "lynx: Password required!!!"
+#define CLEAR_ALL_AUTH_INFO "Clear all authorization info for this session?"
+#define AUTH_INFO_CLEARED "Authorization info cleared."
+#define CGI_DISABLED "cgi support has been disabled by system administrator."
+#define CGI_NOT_COMPILED \
+ "Lynxcgi capabilities are not compiled into this version."
+#define CANNOT_CONVERT_I_TO_O "Sorry, no known way of converting %s to %s."
+#define CONNECT_SET_FAILED "Unable to set up connection."
+#define CONNECT_FAILED "Unable to make connection"
+#define MALFORMED_EXEC_REQUEST \
+ "Executable link rejected due to malformed request."
+#define BADCHAR_IN_EXEC_LINK \
+ "Executable link rejected due to `%c' character."
+#define RELPATH_IN_EXEC_LINK \
+ "Executable link rejected due to relative path string ('../')."
+#define BADLOCPATH_IN_EXEC_LINK \
+ "Executable link rejected due to location or path."
+#define MAIL_DISABLED "Mail access is disabled!"
+#define ACCESS_ONLY_LOCALHOST \
+ "Only files and servers on the local host can be accessed."
+#define TELNET_DISABLED "Telnet access is disabled!"
+#define TELNET_PORT_SPECS_DISABLED \
+ "Telnet port specifications are disabled."
+#define NEWS_DISABLED "USENET news access is disabled!"
+#define RLOGIN_DISABLED "Rlogin access is disabled!"
+#define FTP_DISABLED "Ftp access is disabled!"
+#define NO_REFS_FROM_DOC "There are no references from this document."
+#define NO_VISIBLE_REFS_FROM_DOC "There are only hidden links from this document."
+#ifdef VMS
+#define CANNOT_OPEN_COMFILE "Unable to open command file."
+#endif /* VMS */
+#define NEWS_POST_CANCELLED "News Post Cancelled!!!"
+#define SPAWNING_EDITOR_FOR_NEWS \
+ "Spawning your selected editor to edit news message"
+#define POST_MSG_PROMPT "Post this message? (y/n) "
+#define APPEND_SIG_FILE "Append '%s'? (y/n) "
+#define POSTING_TO_NEWS "Posting to newsgroup(s)..."
+#ifdef VMS
+#define HAVE_UNREAD_MAIL_MSG "*** You have unread mail. ***"
+#else
+#define HAVE_MAIL_MSG "*** You have mail. ***"
+#endif /* VMS */
+#define HAVE_NEW_MAIL_MSG "*** You have new mail. ***"
+#define SAVE_REQUEST_CANCELLED "Save request cancelled!!!"
+#define MAIL_REQUEST_CANCELLED "Mail request cancelled!!!"
+#define CONFIRM_MAIL_SOURCE_PREPARSED \
+ "Viewing preparsed source. Are you sure you want to mail it? [y]"
+#define MAILING_FILE "Mailing file. Please wait..."
+#define MAIL_REQUEST_FAILED "ERROR - Unable to mail file"
+#define CONFIRM_LONG_SCREEN_PRINT \
+ "File is %d screens long. Are you sure you want to print? [y]"
+#define PRINT_REQUEST_CANCELLED "Print request cancelled!!!"
+#define PRESS_RETURN_TO_BEGIN "Press <return> to begin: "
+#define PRESS_RETURN_TO_FINISH "Press <return> to finish: "
+#define CONFIRM_LONG_PAGE_PRINT \
+ "File is %d pages long. Are you sure you want to print? [y]"
+#define FILE_ALLOC_FAILED "ERROR - Unable to allocate file space!!!"
+#define UNABLE_TO_OPEN_TEMPFILE "Unable to open tempfile"
+#define UNABLE_TO_OPEN_PRINTOP_FILE "Unable to open print options file"
+#define PRINTING_FILE "Printing file. Please wait..."
+#define MAIL_ADDRESS_PROMPT "Please enter a valid internet mail address: "
+#define PRINTER_MISCONF_ERROR "ERROR! - printer is misconfigured!"
+#define MISDIRECTED_MAP_REQUEST "Misdirected client-side image MAP request!"
+#define MAP_NOT_ACCESSIBLE "Client-side image MAP is not accessible!"
+#define MAPS_NOT_AVAILABLE "No client-side image MAPs are available!"
+#define MAP_NOT_AVAILABLE "Client-side image MAP is not available!"
+#define OPTION_SCREEN_NEEDS_24 \
+ "Screen height must be at least 24 lines for the Options menu!"
+#define OPTION_SCREEN_NEEDS_23 \
+ "Screen height must be at least 23 lines for the Options menu!"
+#define OPTION_SCREEN_NEEDS_22 \
+ "Screen height must be at least 22 lines for the Options menu!"
+#define NEED_ADVANCED_USER_MODE "That key requires Advanced User mode."
+#define COMMAND_PROMPT "Command: "
+#define SELECT_SEGMENT "Select "
+#define CAP_LETT_SEGMENT "capital letter"
+#define OF_OPT_LINE_SEGMENT " of option line,"
+#define TO_SAVE_SEGMENT " to save,"
+#define OR_SEGMENT " or "
+#define TO_RETURN_SEGMENT " to return to Lynx."
+#define ACCEPT_DATA "Hit RETURN to accept entered data."
+#define ACCEPT_DATA_OR_DEFAULT \
+"Hit RETURN to accept entered data. Delete data to invoke the default."
+#define VALUE_ACCEPTED "Value accepted!"
+#define VALUE_ACCEPTED_WARNING_X \
+ "Value accepted! -- WARNING: Lynx is configured for XWINDOWS!"
+#define VALUE_ACCEPTED_WARNING_NONX \
+ "Value accepted! -- WARNING: Lynx is NOT configured for XWINDOWS!"
+#define EDITOR_LOCKED "You are not allowed to change which editor to use!"
+#define FAILED_TO_SET_DISPLAY "Failed to set DISPLAY variable!"
+#define FAILED_CLEAR_SET_DISPLAY "Failed to clear DISPLAY variable!"
+#define BOOKMARK_CHANGE_DISALLOWED \
+ "You are not allowed to change the bookmark file!"
+#define COLOR_TOGGLE_DISABLED "Terminal does not support color"
+#define COLOR_TOGGLE_DISABLED_FOR_TERM "Your '%s' terminal does not support color."
+#define DOTFILE_ACCESS_DISABLED "Access to dot files is disabled!"
+#define UA_COPYRIGHT_WARNING \
+ "WARNING: Misrepresentation of the User-Agent may be a copyright violation!"
+#define CHANGE_OF_SETTING_DISALLOWED \
+ "You are not allowed to change this setting."
+#define SAVING_OPTIONS "Saving Options..."
+#define OPTIONS_SAVED "Options saved!"
+#define OPTIONS_NOT_SAVED "Unable to save Options!"
+#define R_TO_RETURN_TO_LYNX " 'r' to return to Lynx "
+#define SAVE_OR_R_TO_RETURN_TO_LYNX " '>' to save, or 'r' to return to Lynx "
+#define ANY_KEY_CHANGE_RET_ACCEPT \
+ "Hit any key to change value; RETURN to accept."
+#define ERROR_UNCOMPRESSING_TEMP "Error uncompressing temporary file!"
+#define UNSUPPORTED_URL_SCHEME "Unsupported URL scheme!"
+#define UNSUPPORTED_DATA_URL "Unsupported data: URL! Use SHOWINFO, for now."
+#define ILLEGAL_REDIRECTION_URL "Illegal redirection URL received from server!"
+#define SERVER_ASKED_FOR_REDIRECTION \
+ "Server asked for %d redirection of POST content to"
+#define PROCEED_GET_CANCEL "P)roceed, use G)ET or C)ancel "
+#define PROCEED_OR_CANCEL "P)roceed, or C)ancel "
+#define ADVANCED_POST_GET_REDIRECT \
+ "Redirection of POST content. P)roceed, see U)RL, use G)ET or C)ancel"
+#define ADVANCED_POST_REDIRECT \
+ "Redirection of POST content. P)roceed, see U)RL, or C)ancel"
+#define CONFIRM_POST_RESUBMISSION \
+ "Document from Form with POST content. Resubmit?"
+#define CONFIRM_POST_RESUBMISSION_TO \
+ "Resubmit POST content to %s ?"
+#define CONFIRM_POST_LIST_RELOAD \
+ "List from document with POST data. Reload %s ?"
+#define CONFIRM_POST_DOC_HEAD \
+ "Document from POST action, HEAD may not be understood. Proceed?"
+#define CONFIRM_POST_LINK_HEAD \
+ "Form submit action is POST, HEAD may not be understood. Proceed?"
+#define DISCARDING_POST_DATA "Discarding POST data..."
+#define WILL_NOT_RELOAD_DOC "Document will not be reloaded!"
+#define LOCATION_HEADER "Location: "
+#define STRING_NOT_FOUND "'%s' not found!"
+#define MULTIBOOKMARKS_DEFAULT "Default Bookmark File"
+#define MULTIBOOKMARKS_SMALL "Screen too small! (8x35 min)"
+#define MULTIBOOKMARKS_SAVE "Select destination or ^G to Cancel: "
+#define MULTIBOOKMARKS_SELECT \
+ "Select subbookmark, '=' for menu, or ^G to cancel: "
+#define MULTIBOOKMARKS_SELF \
+ "Reproduce L)ink in this bookmark file or C)ancel? (l,c): "
+#define MULTIBOOKMARKS_DISALLOWED "Multiple bookmark support is not available."
+#define MULTIBOOKMARKS_SHEAD_MASK " Select Bookmark (screen %d of %d)"
+#define MULTIBOOKMARKS_SHEAD " Select Bookmark"
+#define MULTIBOOKMARKS_EHEAD_MASK \
+ "Editing Bookmark DESCRIPTION and FILEPATH (%d of 2)"
+#define MULTIBOOKMARKS_EHEAD \
+ " Editing Bookmark DESCRIPTION and FILEPATH"
+#define MULTIBOOKMARKS_LETTER "Letter: "
+#ifdef VMS
+#define USE_PATH_OFF_HOME \
+ "Use a filepath off your login directory in SHELL syntax!"
+#else
+#define USE_PATH_OFF_HOME "Use a filepath off your home directory!"
+#endif /* VMS */
+#define MAXLINKS_REACHED \
+ "Maximum links per page exceeded! Use half-page or two-line scrolling."
+#define MAXHIST_REACHED \
+ "History List maximum reached! Document not pushed."
+#define VISITED_LINKS_EMPTY "No previously visited links available!"
+#define MEMORY_EXHAUSTED_ABORT "Memory exhausted! Program aborted!"
+#define DFM_NOT_AVAILABLE "Directory/File Manager not available"
+#define BASE_NOT_ABSOLUTE "HREF in BASE tag is not an absolute URL."
+#define LOCATION_NOT_ABSOLUTE "Location URL is not absolute."
+#define REFRESH_URL_NOT_ABSOLUTE "Refresh URL is not absolute."
+#define SENDING_MESSAGE_WITH_BODY_TO \
+ "You are sending a message with body to:\n "
+#define SENDING_COMMENT_TO "You are sending a comment to:\n "
+#define WITH_COPY_TO "\n With copy to:\n "
+#define WITH_COPIES_TO "\n With copies to:\n "
+#define CTRL_G_TO_CANCEL_SEND \
+ "\n\nUse Ctrl-G to cancel if you do not want to send a message\n"
+#define ENTER_NAME_OR_BLANK \
+ "\n Please enter your name, or leave it blank to remain anonymous\n"
+#define ENTER_MAIL_ADDRESS_OR_OTHER \
+ "\n Please enter a mail address or some other\n"
+#define MEANS_TO_CONTACT_FOR_RESPONSE \
+ " means to contact you, if you desire a response.\n"
+#define ENTER_SUBJECT_LINE "\n Please enter a subject line.\n"
+#define ENTER_ADDRESS_FOR_CC \
+ "\n Enter a mail address for a CC of your message.\n"
+#define BLANK_FOR_NO_COPY " (Leave blank if you don't want a copy.)\n"
+#define REVIEW_MESSAGE_BODY "\n Please review the message body:\n\n"
+#define RETURN_TO_CONTINUE "\nPress RETURN to continue: "
+#define CTRL_U_TO_ERASE " Use Control-U to erase the default.\n"
+#define ENTER_MESSAGE_BELOW "\n Please enter your message below."
+#define ENTER_PERIOD_WHEN_DONE_A \
+ "\n When you are done, press enter and put a single period (.)"
+#define ENTER_PERIOD_WHEN_DONE_B \
+ "\n on a line and press enter again."
+#define ADVANCED_COOKIE_CONFIRMATION \
+ "%s cookie: %.*s=%.*s Allow? (Y/N/Always/neVer)"
+#define INVALID_COOKIE_DOMAIN_CONFIRMATION \
+ "Accept invalid cookie domain=%s for '%s'?"
+#define ALLOWING_COOKIE "Allowing this cookie."
+#define REJECTING_COOKIE "Rejecting this cookie."
+#define COOKIE_JAR_IS_EMPTY "The Cookie Jar is empty."
+#define COOKIE_JAR_TITLE "Lynx Cookie Jar"
+#define REACHED_COOKIE_JAR_PAGE "You have reached the Lynx Cookie Jar Page"
+#define ACTIVATE_TO_GOBBLE \
+ "Activate links to gobble up cookies or entire domains,"
+#define OR_CHANGE_ALLOW "or to change a domain's 'allow' setting."
+#define COOKIES_NEVER_ALLOWED "(Cookies never allowed.)"
+#define COOKIES_ALWAYS_ALLOWED "(Cookies always allowed.)"
+#define COOKIES_ALLOWED_VIA_PROMPT "(Cookies allowed via prompt.)"
+#define NO_NAME "(No name.)"
+#define NO_VALUE "(No value.)"
+#define END_OF_SESSION "(End of session.)"
+#define DELETE_COOKIE_CONFIRMATION "Delete this cookie?"
+#define COOKIE_EATEN "The cookie has been eaten!"
+#define DELETE_EMPTY_DOMAIN_CONFIRMATION "Delete this empty domain?"
+#define DOMAIN_EATEN "The domain has been eaten!"
+#define DELETE_COOKIES_SET_ALLOW_OR_CANCEL \
+ "D)elete domain's cookies, set allow A)lways/P)rompt/neV)er, or C)ancel? "
+#define DELETE_DOMAIN_SET_ALLOW_OR_CANCEL \
+ "D)elete domain, set allow A)lways/P)rompt/neV)er, or C)ancel? "
+#define DOMAIN_COOKIES_EATEN "All cookies in the domain have been eaten!"
+#define ALWAYS_ALLOWING_COOKIES "'A'lways allowing from domain '%s'."
+#define NEVER_ALLOWING_COOKIES "ne'V'er allowing from domain '%s'."
+#define PROMTING_TO_ALLOW_COOKIES "'P'rompting to allow from domain '%s'."
+#define DELETE_ALL_COOKIES_IN_DOMAIN "Delete all cookies in this domain?"
+#define ALL_COOKIES_EATEN "All of the cookies in the jar have been eaten!"
+#define PORT_NINETEEN_INVALID "Port 19 not permitted in URLs."
+#define PORT_TWENTYFIVE_INVALID "Port 25 not permitted in URLs."
+#define PORT_INVALID "Port %lu not permitted in URLs."
+#define URL_PORT_BAD "URL has a bad port field."
+#define HTML_STACK_OVERRUN "Maximum nesting of HTML elements exceeded."
+#define BAD_PARTIAL_REFERENCE "Bad partial reference! Stripping lead dots."
+#define TRACELOG_OPEN_FAILED "Trace Log open failed. Trace off!."
+#define LYNX_TRACELOG_TITLE "Lynx Trace Log"
+#define NO_TRACELOG_STARTED "No trace log has been started for this session."
+#define MAX_TEMPCOUNT_REACHED \
+ "The maximum temporary file count has been reached!"
+#define FORM_VALUE_TOO_LONG \
+ "Form field value exceeds buffer length! Trim the tail."
+#define FORM_TAIL_COMBINED_WITH_HEAD \
+ "Modified tail combined with head of form field value."
+
+#ifdef DIRED_SUPPORT
+#define DIRED_NOVICELINE \
+ " C)reate D)ownload E)dit F)ull menu M)odify R)emove T)ag U)pload \n"
+#define CURRENT_LINK_STATUS_FAILED "Failed to obtain status of current link!"
+
+#define INVALID_PERMIT_URL \
+ "Special URL only valid from current File Permission menu!"
+#endif /* DIRED_SUPPORT */
+
+#ifdef USE_EXTERNALS
+#define EXTERNALS_DISABLED "External support is currently disabled."
+#endif /* USE_EXTERNALS */
+
+#endif /* LYMESSAGES_EN_H */
diff --git a/gnu/usr.bin/lynx/MAKEFILE.W32 b/gnu/usr.bin/lynx/MAKEFILE.W32
new file mode 100644
index 00000000000..2c8000e9138
--- /dev/null
+++ b/gnu/usr.bin/lynx/MAKEFILE.W32
@@ -0,0 +1,737 @@
+#
+# Borland C++ IDE generated makefile
+#
+.AUTODEPEND
+
+
+#
+# Borland C++ tools
+#
+IMPLIB = Implib
+BCC32 = Bcc32 +BccW32.cfg
+TLINK32 = TLink32
+TLIB = TLib
+BRC32 = Brc32
+TASM32 = Tasm32
+#
+# IDE macros
+#
+
+
+#
+# Options
+#
+IDE_LFLAGS32 = -LD:\BC45\LIB
+LLATC32_lynxdexe = -LCURSES;D:\BC45\LIB -wdpl -wdup -Tpe -ap -c
+RLATC32_lynxdexe = -k -w32
+BLATC32_lynxdexe =
+CNIEAT_lynxdexe = -I.\;CURSES;SRC;WWW\LIBRARY\IMPLEMENTATION;D:\BC45\INCLUDE;SRC\CHRTRANS -DNO_UNISTD_H;_WINDOWS;XMOSAIC_HACK;ACCESS_AUTH;NO_UTMP;NO_CUSERID;NO_TTYTYPE;NOSIGHUP;DOSPATH;NOUSERS;NCURSES;FANCY_CURSES;COLOR_CURSES;HAVE_KEYPAD;VC="2.14FM";NCURSES_VERSION
+LNIEAT_lynxdexe = -x
+LEAT_lynxdexe = $(LLATC32_lynxdexe)
+REAT_lynxdexe = $(RLATC32_lynxdexe)
+BEAT_lynxdexe = $(BLATC32_lynxdexe)
+CLATW16_cursesbpdcursesdlib =
+LLATW16_cursesbpdcursesdlib =
+RLATW16_cursesbpdcursesdlib =
+BLATW16_cursesbpdcursesdlib =
+CEAT_cursesbpdcursesdlib = $(CEAT_lynxdexe) $(CLATW16_cursesbpdcursesdlib)
+CNIEAT_cursesbpdcursesdlib = -I.\;CURSES;SRC;WWW\LIBRARY\IMPLEMENTATION;D:\BC45\INCLUDE;SRC\CHRTRANS -DNO_UNISTD_H;_WINDOWS;XMOSAIC_HACK;ACCESS_AUTH;NO_UTMP;NO_CUSERID;NO_TTYTYPE;NOSIGHUP;DOSPATH;NOUSERS;NCURSES;FANCY_CURSES;COLOR_CURSES;HAVE_KEYPAD;VC="2.14FM";NCURSES_VERSION
+LNIEAT_cursesbpdcursesdlib = -x
+LEAT_cursesbpdcursesdlib = $(LEAT_lynxdexe) $(LLATW16_cursesbpdcursesdlib)
+REAT_cursesbpdcursesdlib = $(REAT_lynxdexe) $(RLATW16_cursesbpdcursesdlib)
+BEAT_cursesbpdcursesdlib = $(BEAT_lynxdexe) $(BLATW16_cursesbpdcursesdlib)
+
+#
+# Dependency List
+#
+Dep_lynx = \
+ lynx.exe
+
+lynx : BccW32.cfg $(Dep_lynx)
+ echo MakeNode
+
+Dep_lynxdexe = \
+ OBJ\htdos.obj\
+ curses\pdcurses.lib\
+ OBJ\ucauto.obj\
+ OBJ\ucaux.obj\
+ OBJ\ucdomap.obj\
+ OBJ\htalert.obj\
+ OBJ\htfwrite.obj\
+ OBJ\htinit.obj\
+ OBJ\httcp.obj\
+ OBJ\crypt.obj\
+ OBJ\crypt_ut.obj\
+ OBJ\getline.obj\
+ OBJ\htaabrow.obj\
+ OBJ\htaafile.obj\
+ OBJ\htaaprot.obj\
+ OBJ\htaaserv.obj\
+ OBJ\htaautil.obj\
+ OBJ\htaccess.obj\
+ OBJ\htacl.obj\
+ OBJ\htanchor.obj\
+ OBJ\htassoc.obj\
+ OBJ\htatom.obj\
+ OBJ\htauth.obj\
+ OBJ\htbtree.obj\
+ OBJ\htchunk.obj\
+ OBJ\htfile.obj\
+ OBJ\htfinger.obj\
+ OBJ\htformat.obj\
+ OBJ\htftp.obj\
+ OBJ\htgopher.obj\
+ OBJ\htgroup.obj\
+ OBJ\hthistor.obj\
+ OBJ\htlex.obj\
+ OBJ\htlist.obj\
+ OBJ\htmime.obj\
+ OBJ\htmldtd.obj\
+ OBJ\htmlgen.obj\
+ OBJ\htnews.obj\
+ OBJ\htparse.obj\
+ OBJ\htpasswd.obj\
+ OBJ\htplain.obj\
+ OBJ\htrules.obj\
+ OBJ\htstring.obj\
+ OBJ\htstyle.obj\
+ OBJ\httelnet.obj\
+ OBJ\http.obj\
+ OBJ\htuu.obj\
+ OBJ\htwriter.obj\
+ OBJ\htwsrc.obj\
+ OBJ\sgml.obj\
+ OBJ\defaults.obj\
+ OBJ\gridtext.obj\
+ OBJ\html.obj\
+ OBJ\lybookma.obj\
+ OBJ\lycgi.obj\
+ OBJ\lycharse.obj\
+ OBJ\lycharut.obj\
+ OBJ\lyclean.obj\
+ OBJ\lycookie.obj\
+ OBJ\lycurses.obj\
+ OBJ\lydownlo.obj\
+ OBJ\lyedit.obj\
+ OBJ\lyeditma.obj\
+ OBJ\lyexit.obj\
+ OBJ\lyforms.obj\
+ OBJ\lygetfil.obj\
+ OBJ\lyhistor.obj\
+ OBJ\lyjump.obj\
+ OBJ\lykeymap.obj\
+ OBJ\lyleaks.obj\
+ OBJ\lylist.obj\
+ OBJ\lylocal.obj\
+ OBJ\lymail.obj\
+ OBJ\lymain.obj\
+ OBJ\lymainlo.obj\
+ OBJ\lymap.obj\
+ OBJ\lynews.obj\
+ OBJ\lyoption.obj\
+ OBJ\lyprint.obj\
+ OBJ\lyrcfile.obj\
+ OBJ\lyreadcf.obj\
+ OBJ\lysearch.obj\
+ OBJ\lyshowin.obj\
+ OBJ\lystring.obj\
+ OBJ\lytraver.obj\
+ OBJ\lyupload.obj\
+ OBJ\lyutils.obj
+
+lynx.exe : $(Dep_lynxdexe)
+ $(TLINK32) @&&|
+ /v $(IDE_LFLAGS32) $(LEAT_lynxdexe) $(LNIEAT_lynxdexe) +
+D:\BC45\LIB\c0x32.obj+
+OBJ\htdos.obj+
+OBJ\ucauto.obj+
+OBJ\ucaux.obj+
+OBJ\ucdomap.obj+
+OBJ\htalert.obj+
+OBJ\htfwrite.obj+
+OBJ\htinit.obj+
+OBJ\httcp.obj+
+OBJ\crypt.obj+
+OBJ\crypt_ut.obj+
+OBJ\getline.obj+
+OBJ\htaabrow.obj+
+OBJ\htaafile.obj+
+OBJ\htaaprot.obj+
+OBJ\htaaserv.obj+
+OBJ\htaautil.obj+
+OBJ\htaccess.obj+
+OBJ\htacl.obj+
+OBJ\htanchor.obj+
+OBJ\htassoc.obj+
+OBJ\htatom.obj+
+OBJ\htauth.obj+
+OBJ\htbtree.obj+
+OBJ\htchunk.obj+
+OBJ\htfile.obj+
+OBJ\htfinger.obj+
+OBJ\htformat.obj+
+OBJ\htftp.obj+
+OBJ\htgopher.obj+
+OBJ\htgroup.obj+
+OBJ\hthistor.obj+
+OBJ\htlex.obj+
+OBJ\htlist.obj+
+OBJ\htmime.obj+
+OBJ\htmldtd.obj+
+OBJ\htmlgen.obj+
+OBJ\htnews.obj+
+OBJ\htparse.obj+
+OBJ\htpasswd.obj+
+OBJ\htplain.obj+
+OBJ\htrules.obj+
+OBJ\htstring.obj+
+OBJ\htstyle.obj+
+OBJ\httelnet.obj+
+OBJ\http.obj+
+OBJ\htuu.obj+
+OBJ\htwriter.obj+
+OBJ\htwsrc.obj+
+OBJ\sgml.obj+
+OBJ\defaults.obj+
+OBJ\gridtext.obj+
+OBJ\html.obj+
+OBJ\lybookma.obj+
+OBJ\lycgi.obj+
+OBJ\lycharse.obj+
+OBJ\lycharut.obj+
+OBJ\lyclean.obj+
+OBJ\lycookie.obj+
+OBJ\lycurses.obj+
+OBJ\lydownlo.obj+
+OBJ\lyedit.obj+
+OBJ\lyeditma.obj+
+OBJ\lyexit.obj+
+OBJ\lyforms.obj+
+OBJ\lygetfil.obj+
+OBJ\lyhistor.obj+
+OBJ\lyjump.obj+
+OBJ\lykeymap.obj+
+OBJ\lyleaks.obj+
+OBJ\lylist.obj+
+OBJ\lylocal.obj+
+OBJ\lymail.obj+
+OBJ\lymain.obj+
+OBJ\lymainlo.obj+
+OBJ\lymap.obj+
+OBJ\lynews.obj+
+OBJ\lyoption.obj+
+OBJ\lyprint.obj+
+OBJ\lyrcfile.obj+
+OBJ\lyreadcf.obj+
+OBJ\lysearch.obj+
+OBJ\lyshowin.obj+
+OBJ\lystring.obj+
+OBJ\lytraver.obj+
+OBJ\lyupload.obj+
+OBJ\lyutils.obj
+$<,$*
+curses\pdcurses.lib+
+D:\BC45\LIB\bidsf.lib+
+D:\BC45\LIB\import32.lib+
+D:\BC45\LIB\cw32.lib
+
+|
+
+OBJ\htdos.obj : www\library\implemen\htdos.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htdos.c
+|
+
+OBJ\ucauto.obj : src\ucauto.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\ucauto.c
+|
+
+OBJ\ucaux.obj : src\ucaux.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\ucaux.c
+|
+
+OBJ\ucdomap.obj : src\ucdomap.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\ucdomap.c
+|
+
+OBJ\htalert.obj : src\htalert.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\htalert.c
+|
+
+OBJ\htfwrite.obj : src\htfwrite.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\htfwrite.c
+|
+
+OBJ\htinit.obj : src\htinit.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\htinit.c
+|
+
+OBJ\httcp.obj : www\library\implemen\httcp.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\httcp.c
+|
+
+OBJ\crypt.obj : www\library\implemen\crypt.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\crypt.c
+|
+
+OBJ\crypt_ut.obj : www\library\implemen\crypt_ut.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\crypt_ut.c
+|
+
+OBJ\getline.obj : www\library\implemen\getline.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\getline.c
+|
+
+OBJ\htaabrow.obj : www\library\implemen\htaabrow.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaabrow.c
+|
+
+OBJ\htaafile.obj : www\library\implemen\htaafile.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaafile.c
+|
+
+OBJ\htaaprot.obj : www\library\implemen\htaaprot.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaaprot.c
+|
+
+OBJ\htaaserv.obj : www\library\implemen\htaaserv.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaaserv.c
+|
+
+OBJ\htaautil.obj : www\library\implemen\htaautil.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaautil.c
+|
+
+OBJ\htaccess.obj : www\library\implemen\htaccess.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htaccess.c
+|
+
+OBJ\htacl.obj : www\library\implemen\htacl.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htacl.c
+|
+
+OBJ\htanchor.obj : www\library\implemen\htanchor.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htanchor.c
+|
+
+OBJ\htassoc.obj : www\library\implemen\htassoc.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htassoc.c
+|
+
+OBJ\htatom.obj : www\library\implemen\htatom.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htatom.c
+|
+
+OBJ\htauth.obj : www\library\implemen\htauth.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htauth.c
+|
+
+OBJ\htbtree.obj : www\library\implemen\htbtree.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htbtree.c
+|
+
+OBJ\htchunk.obj : www\library\implemen\htchunk.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htchunk.c
+|
+
+OBJ\htfile.obj : www\library\implemen\htfile.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htfile.c
+|
+
+OBJ\htfinger.obj : www\library\implemen\htfinger.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htfinger.c
+|
+
+OBJ\htformat.obj : www\library\implemen\htformat.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htformat.c
+|
+
+OBJ\htftp.obj : www\library\implemen\htftp.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htftp.c
+|
+
+OBJ\htgopher.obj : www\library\implemen\htgopher.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htgopher.c
+|
+
+OBJ\htgroup.obj : www\library\implemen\htgroup.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htgroup.c
+|
+
+OBJ\hthistor.obj : www\library\implemen\hthistor.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\hthistor.c
+|
+
+OBJ\htlex.obj : www\library\implemen\htlex.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htlex.c
+|
+
+OBJ\htlist.obj : www\library\implemen\htlist.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htlist.c
+|
+
+OBJ\htmime.obj : www\library\implemen\htmime.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htmime.c
+|
+
+OBJ\htmldtd.obj : www\library\implemen\htmldtd.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htmldtd.c
+|
+
+OBJ\htmlgen.obj : www\library\implemen\htmlgen.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htmlgen.c
+|
+
+OBJ\htnews.obj : www\library\implemen\htnews.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htnews.c
+|
+
+OBJ\htparse.obj : www\library\implemen\htparse.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htparse.c
+|
+
+OBJ\htpasswd.obj : www\library\implemen\htpasswd.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htpasswd.c
+|
+
+OBJ\htplain.obj : www\library\implemen\htplain.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htplain.c
+|
+
+OBJ\htrules.obj : www\library\implemen\htrules.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htrules.c
+|
+
+OBJ\htstring.obj : www\library\implemen\htstring.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htstring.c
+|
+
+OBJ\htstyle.obj : www\library\implemen\htstyle.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htstyle.c
+|
+
+OBJ\httelnet.obj : www\library\implemen\httelnet.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\httelnet.c
+|
+
+OBJ\http.obj : www\library\implemen\http.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\http.c
+|
+
+OBJ\htuu.obj : www\library\implemen\htuu.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htuu.c
+|
+
+OBJ\htwriter.obj : www\library\implemen\htwriter.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htwriter.c
+|
+
+OBJ\htwsrc.obj : www\library\implemen\htwsrc.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\htwsrc.c
+|
+
+OBJ\sgml.obj : www\library\implemen\sgml.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ www\library\implemen\sgml.c
+|
+
+OBJ\defaults.obj : src\defaults.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\defaults.c
+|
+
+OBJ\gridtext.obj : src\gridtext.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\gridtext.c
+|
+
+OBJ\html.obj : src\html.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\html.c
+|
+
+OBJ\lybookma.obj : src\lybookma.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lybookma.c
+|
+
+OBJ\lycgi.obj : src\lycgi.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lycgi.c
+|
+
+OBJ\lycharse.obj : src\lycharse.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lycharse.c
+|
+
+OBJ\lycharut.obj : src\lycharut.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lycharut.c
+|
+
+OBJ\lyclean.obj : src\lyclean.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyclean.c
+|
+
+OBJ\lycookie.obj : src\lycookie.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lycookie.c
+|
+
+OBJ\lycurses.obj : src\lycurses.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lycurses.c
+|
+
+OBJ\lydownlo.obj : src\lydownlo.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lydownlo.c
+|
+
+OBJ\lyedit.obj : src\lyedit.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyedit.c
+|
+
+OBJ\lyeditma.obj : src\lyeditma.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyeditma.c
+|
+
+OBJ\lyexit.obj : src\lyexit.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyexit.c
+|
+
+OBJ\lyforms.obj : src\lyforms.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyforms.c
+|
+
+OBJ\lygetfil.obj : src\lygetfil.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lygetfil.c
+|
+
+OBJ\lyhistor.obj : src\lyhistor.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyhistor.c
+|
+
+OBJ\lyjump.obj : src\lyjump.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyjump.c
+|
+
+OBJ\lykeymap.obj : src\lykeymap.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lykeymap.c
+|
+
+OBJ\lyleaks.obj : src\lyleaks.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyleaks.c
+|
+
+OBJ\lylist.obj : src\lylist.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lylist.c
+|
+
+OBJ\lylocal.obj : src\lylocal.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lylocal.c
+|
+
+OBJ\lymail.obj : src\lymail.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lymail.c
+|
+
+OBJ\lymain.obj : src\lymain.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lymain.c
+|
+
+OBJ\lymainlo.obj : src\lymainlo.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lymainlo.c
+|
+
+OBJ\lymap.obj : src\lymap.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lymap.c
+|
+
+OBJ\lynews.obj : src\lynews.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lynews.c
+|
+
+OBJ\lyoption.obj : src\lyoption.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyoption.c
+|
+
+OBJ\lyprint.obj : src\lyprint.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyprint.c
+|
+
+OBJ\lyrcfile.obj : src\lyrcfile.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyrcfile.c
+|
+
+OBJ\lyreadcf.obj : src\lyreadcf.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyreadcf.c
+|
+
+OBJ\lysearch.obj : src\lysearch.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lysearch.c
+|
+
+OBJ\lyshowin.obj : src\lyshowin.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyshowin.c
+|
+
+OBJ\lystring.obj : src\lystring.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lystring.c
+|
+
+OBJ\lytraver.obj : src\lytraver.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lytraver.c
+|
+
+OBJ\lyupload.obj : src\lyupload.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyupload.c
+|
+
+OBJ\lyutils.obj : src\lyutils.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_lynxdexe) $(CNIEAT_lynxdexe) -o$@ src\lyutils.c
+|
+
+# Compiler configuration file
+BccW32.cfg :
+ Copy &&|
+-R
+-v
+-vi
+-H
+-H=lynx.csm
+-w-
+-A-
+-wcpt
+-wrpt
+-wrng
+-w-voi
+-w-ret
+-w-sus
+-w-dup
+-w-big
+-w-ext
+-w-zdi
+-w-bei
+-w-obi
+-w-ofp
+-w-eas
+-w-hid
+-w-ncf
+-w-ibc
+-w-dsz
+-w-nst
+-w-mpc
+-w-mpd
+-w-ntd
+-w-nvf
+-w-hch
+-w-inl
+-w-lin
+-w-lvc
+-wpia
+-w-def
+-w-nod
+-w-pro
+-w-rvl
+-wccc
+-w-aus
+-w-par
+-w-rch
+-w-eff
+-w-ill
+-w-ias
+-w-msg
+-Ot
+-d-
+-K
+-a-
+-w-stu
+-wbbf
+-w-dpu
+-wcln
+-wsig
+-wucp
+-g255
+-H-
+-v-
+-WC
+-wamb
+| $@
+
+
diff --git a/gnu/usr.bin/lynx/PROBLEMS b/gnu/usr.bin/lynx/PROBLEMS
new file mode 100644
index 00000000000..4815d2ba179
--- /dev/null
+++ b/gnu/usr.bin/lynx/PROBLEMS
@@ -0,0 +1,164 @@
+Lynx PROBLEMS file.
+
+Ideally you would never have to read this, but inevitably problems
+do arise. As implementation and installation problems become known
+they will be outlined in this file.
+
+ Control-Z on Unix can cause aberrant behavior. If you encounter
+ problems, use -restrictions=suspend to disable it, and only '!'
+ for escapes to shell (on VMS control-Z is unconditional 'Q'uit,
+ with no attempt to suspend the Lynx process only temporarily).
+ Control-Z on Unix often works better with slang.
+
+ Screen resizing can be a bit funny. If you resize the screen,
+ documents that have been cached will be out of whack. Any further
+ documents will look fine. You can reload documents to the current
+ window size with CTRL-R
+
+ On a Sun system, the message:
+ "Alert!: Unable to connect to remote host"
+ will be displayed every time an attempt is made to access a host
+ other than localhost if Lynx has been built without the resolv
+ library and needed it, or with it and shouldn't have been.
+ Unfortunately, there's no way to check in the Makefile whether
+ -lresolv should be included in the LIBS="" list. What's necessary
+ depends on how that Sun is configured. To get the build right for
+ your SUN 3 or 4 OS, if you didn't have RESOLVLIB defined in the
+ Makefile define it and build Lynx again, or vice versa. Also, if
+ you have upgraded to the bind-8.1 or later library, you should try
+ changing -lresolv to -lbind.
+
+ The Sun `shelltool' and `cmdtool' terminals are stupid by default.
+ In order to get bold text to appear differently than inverse video,
+ the user should put this line in ~/.Xdefaults:
+
+ Term*boldStyle: Offset_X
+
+ From the `shelltool' man page, it seems that an analogous line
+ in ~/.defaults
+
+ /Tty/Bold_style "Offset_X"
+
+ ought to work just as well, but you may not get the desired
+ behavior until you modify your .Xdefaults file (and run `xrdb
+ ~/.Xdefaults'). Note also that there are other supported values
+ for the boldStyle resource/Bold_style default, all of which begin
+ with "Offset_". (helpful hint from kevin@traffic.den.mmc.com)
+
+ Directory browsing has been implemented for VMS, but there are no
+ plans to port additional DIRED support, because Lynx must handle files
+ as streams, and this precludes "serious" Directory/File Management on
+ VMS. Use a jumps file link to CSwing (sources or executables are
+ available from ftp://narnia.memst.edu), or define CSWING_PATH in
+ userdefs.h or lynx.cfg to invoke CSwing via the DIRED_MENU command.
+
+ If one switches between K)eypad "Numbers act as arrows" versus "Links
+ are numbered" in the 'o'ptions menu when the current document is a
+ DIRED menu in which links have been tagged, the tagging can be trashed
+ (so don't switch at such times 8-).
+
+ When "Links are numbered" is on, if a line is split on an anchor (to
+ obey right margin restrictions), and there is no space in the bolded
+ string such that the entire "[#]string" must be moved down, the "[#]"
+ becomes bolded, instead on only "string".
+
+ The Mosaic v2.5 hostlist uses HTML similar to that of Lynx's bookmark
+ file, but with </UL></HTML> at the bottom, such that it is not fully
+ compatible with Lynx's file. If you try to use the Mosaic file as if
+ it were a Lynx bookmark file, the </UL></HTML> will not be taken into
+ account and new links will be added below rather than above those end
+ tags. Instead, add a link to the Mosaic file in your Lynx file, and
+ to the Lynx file in your Mosaic file, so that you can access both files
+ with both clients.
+
+ SOCKSification and the -socks switch have not yet been integrated with
+ the slang library support.
+
+ There is an apparently broken version of select() in libcurses.a
+ of HP/UX 10.10. It also breaks tn3270, ncftp, emacs, and xemacs.
+ Using:
+ LIBS="-lc -lcurses -ltermcap \
+ ^^^
+ (i.e, adding -lc *before* the -lcurses) in the snake3 and snake3-slang
+ targets of the top level Makefile yields a useable image, but with
+ inappropriate video attributes on the Lynx displays (reverse video and
+ underscores on everything). Using "-lc -lHcurses" instead fixes the
+ ^^^^^^^^^
+ video attributes but then the arrow keys are messed up. - Donald S.
+ Teiser (dsteis01@homer.louisville.edu)
+ NOTE: If HP fixes the problem or you come up with a better workaround,
+ notify the lynx-dev@sig.net list.
+ Updated NOTE (1996-09-02): A patch reportedly is available from HP to
+ fix the select() problem, so that "-lc" is no longer needed, but
+ the curses glitch is not yet fixed, and you should still include
+ "-lHcurses".
+ Updated NOTE (1997-02-03): The problems reportedly are fixed with
+ patches PHCO_8086 and PHCO_8947 from HP.
+ Updated NOTE (1997-12-15): PHCO_8086 & PHCO_8947 are very old and are
+ no longer available. The current patch to install if running
+ under HP-UX 10.20 is PHCO_11342.
+
+ Lynx juggles variable abilities of curses packages or emulations to
+ display bolding and underlining simultaneously. This may fail if
+ Lynx thinks that your terminal, in connection with the curses package,
+ supports a capability which the terminal hardware or emulation does not
+ in fact support. Setting the right TERM environment variable, tweaking
+ terminfo or termcap files, or compiling with a newer version of ncurses
+ or slang may solve problems with missing highlighting or strange
+ characters appearing on the screen. Also, for a mono terminal, make sure
+ that there is no "show color (&) : ON" on the Options screen.
+
+ The Wyse 50 and older TeleVideo terminals, among others, are
+ "magic cookie" terminals. This means that display attributes like
+ reverse, blink, underline, etc. work in a bizarre way that makes them
+ difficult to program. You may see extra spaces scattered around your
+ screen (separating different sorts of highlight); or sections of the
+ screen may be unexpectedly highlighted.
+ There is a workaround which works by restricting the terminal to a
+ single standout attribute (e.g. normal and reverse, but no others).
+ Implementing the workaround is specific to your curses implementation.
+ Most versions of curses use one of two terminal databases, called
+ "termcap" and "terminfo". Updating these databases is system-specific.
+ New databases should be available from the vendor or other sources.
+ For the Wyse 50, try
+ <URL: http://www.wyse.com/text/custserv/faq/wy50faq.htm>;
+ extract the "wy50" (NOT "wy50-mc") entry and use that in place of the
+ existing one. See `terminfo', `infocmp', `tic' etc. man pages if
+ necessary.
+ Alternatively, compiling Lynx with the slang library may avoid problems
+ with theses terminals.
+
+ On VMS, Lynx, and other TCP-IP software, have been experiencing chronic
+ problems of incompatibilities between DECC and MultiNet headers whenever
+ new versions of either DECC or MultiNet are released. The Lynx build
+ procedure for VMS and a maze of spaghetti #ifdef-ing in tcp.h of the
+ libwww-FM had previously been successful in dealing with this problem
+ across all versions of MultiNet and of DECC, VAXC, and Pat Rankin's
+ VMS port of GNUC, but are now not 100% successful. If you get compiler
+ messages about "struct timeval timeout" having no linkage, add that
+ declaration immediately below the inclusion of ioctl.h for MultiNet in
+ tcp.h (by deleting the "#ifdef NOT_DEFINED" and "#endif /* NOT_DEFINED */"
+ lines):
+ [...]
+ #include "multinet_root:[multinet.include.sys]ioctl.h"
+ struct timeval {
+ long tv_sec; /* seconds since Jan. 1, 1970 */
+ long tv_usec; /* microseconds */
+ };
+ [...]
+ If you get compiler warnings about incompatible multinet_foo()
+ declarations, delete those where indicated in tcp.h. For the most
+ current versions of MultiNet, you can modify tcp.h to use the DECC
+ socket and related headers.
+
+ On VMS, the ftp function does not work with SOCKETSHR 0.9D and NETLIB
+ 2 (NETLIB 1 may work). This is because the functions getsockname()
+ and getpeername() within SOCKETSHR make incorrect calls to the NETLIB
+ functions. This results in zeroes being returned for part of the local
+ IP address. Since ftp sends this IP address to the remote end, the
+ remote server ends up sending a file back to a non-existent address.
+ Andy Harper (A.HARPER@kcl.ac.uk) has fixed these problems in the
+ SOCKETSHR 0.9D sources and offers the fixes as:
+ http://alder.cc.kcl.ac.uk/fileserv/zip/socketshr_src_09d-2.zip
+ ftp://ftp2.kcl.ac.uk/zip/socketshr_src_09d-2.zip
+
diff --git a/gnu/usr.bin/lynx/README b/gnu/usr.bin/lynx/README
new file mode 100644
index 00000000000..acb937de19d
--- /dev/null
+++ b/gnu/usr.bin/lynx/README
@@ -0,0 +1,139 @@
+
+ Lynx README file
+
+Lynx Version 2.8 is the latest "official" release. This release is based on
+the lynx2.7.1ac-0.118 development code set, and includes bug fixes through
+March 8, 1998. See the CHANGES2.8 file in the docs subdirectory for a complete
+record of all changes and bug fixes in this release. New releases are
+announced on the lynx-dev mailing list (see below).
+
+
+WHAT IS LYNX?
+
+ Lynx is a fully-featured World Wide Web (WWW) client for users running
+ cursor-addressable, character-cell display devices such as vt100
+ terminals, vt100 emulators running on PCs or Macs, or any other
+ character-cell display. It will display Hypertext Markup Language
+ (HTML) documents containing links to files on the local system, as
+ well as files on remote systems running http, gopher, ftp, wais, nntp,
+ finger, or cso/ph/qi servers, and services accessible via logins to
+ telnet, tn3270 or rlogin accounts. Current versions of Lynx run on
+ Unix, VMS, Windows95/NT, 386DOS and OS/2 EMX.
+
+ Lynx can be used to access information on the WWW, or to establish
+ information systems intended primarily for local access. Lynx has been
+ used to build several Campus Wide Information Systems (CWIS). Lynx can
+ also be used to build systems isolated within a single LAN.
+
+ Links to the current sources and support materials for Lynx are
+ maintained at:
+ "Lynx links"
+ <URL:http://www.crl.com/~subir/lynx.html>
+ and at the Lynx homepage:
+ "Lynx Information"
+ <URL:http://lynx.browser.org/>.
+ View these pages for information about Lynx, including new updates.
+
+ Lynx is distributed under the GNU General Public License (GPL) without
+ restrictions on usage or redistribution. The Lynx copyright statement,
+ "COPYHEADER", and GNU GPL, "COPYING", are included in the top-level
+ directory of the distribution. Lynx is supported by the Lynx user
+ community, an entirely volunteer (and unofficial) organization.
+
+ Certain portions of the Lynx source distribution were originally
+ created by CERN and have been modified during the development of
+ Lynx. See WWW/Copyright.txt for copyright info regarding CERN
+ products used in Lynx.
+
+YEAR 2000 COMPLIANCE
+
+ We believe Lynx works properly for the Year 2000 issues, since it does
+ not store dates in 2-digit form. Since it must communicate with a wide
+ range of web servers, it interprets dates in a variety of formats. In
+ particular, if Lynx receives a date with a 2-digit year, it assumes that
+ values less than 70 are in the range 2000-2069.
+
+DOCUMENTATION
+
+ A users guide is included in this distribution along with a man page
+ for Unix systems and a help file for VMS systems. All documentation is
+ contained in the top directory and the docs, samples and lynx_help
+ subdirectories.
+
+ While running Lynx, type 'h', 'H', or '?' to invoke the help menu
+ system. From the help menu you may access several useful documents
+ pertaining to Lynx and the World Wide Web. The most important of
+ these is the Lynx Users Guide. By default, Lynx will use the Lynx
+ Enhanced Pages, which includes http links for help and FAQs concerning
+ Lynx. It is recommended that you install your own help menu system at
+ your site in order to lessen the load on http servers. This also will
+ allow you to customize the help menu system for your site and greatly
+ speed up access for those using Lynx over a slow connection.
+
+ For Unix and related systems which support the autoconf configure script,
+ the help menu system is installed by the "make install-help" command.
+
+ For other systems (such as VMS), copy COPYHEADER and COPYING into the
+ lynx_help/ subdirectory. Then copy the lynx_help subdirectory to a public
+ place on your system, or into your $HOME directory if you are a single
+ user. Finally, edit the lynx.cfg file so that the HELPFILE line is
+ defined as follows:
+
+ HELPFILE:file://localhost/[public_path]/lynx_help/lynx_help_main.html
+
+ where [public_path] is the absolute path to the lynx_help directory.
+ Customizing the help menu system is just a matter of editing a set of
+ HTML files. Additional information about installing and customizing
+ the help file set is available at <URL:http://www.irm.nara.kindai.ac.jp/
+ lynxdev/README.help>.
+
+INSTALLING LYNX
+
+ To install Lynx, follow the steps in the INSTALLATION file, which is
+ located in the top directory of the source distribution.
+
+PROBLEMS
+
+ If you experience problems configuring, compiling or installing Lynx,
+ please read Section VI. "General installation instructions" in the
+ INSTALLATION file. Instructions are given there for reporting your
+ problem to the "lynx-dev" mailing list, which is frequented by experienced
+ Lynx users.
+
+LYNX-DEV MAILING LIST
+
+ To subscribe to lynx-dev, send email to majordomo@sig.net with only the
+ following message in the body:
+
+ SUBSCRIBE LYNX-DEV address
+
+ where inclusion of your email address is optional if it can be obtained,
+ correctly, from the mail headers of your subscription request.
+
+ If you wish to unsubscribe from lynx-dev, send email to majordomo@sig.net
+ with only the following message in the body:
+
+ UNSUBSCRIBE LYNX-DEV address
+
+ where inclusion of your email address is optional if it can be obtained,
+ correctly, from the mail headers of your request.
+
+ Also, to get a list of useful majordomo commands, send email to
+ majordomo@sig.net with the following command:
+ ^^^^^^^^^
+ HELP
+
+ PLEASE!!! do not send commands to the lynx-dev mailing list itself.
+
+ Any messages you wish to post should be sent to lynx-dev@sig.net.
+ PLEASE use the lynx-dev list, NOT private email to the developers,
+ for questions or discussion about Lynx, or contributions of patches.
+ Patches should use the context diff format (diff -c).
+
+ You need not be subscribed to the lynx-dev list in order to post. If
+ you post without subscribing, though, you should read replies to your
+ questions or comments in the archive since more often than not nobody
+ will send a carbon copy to you. View the archives at:
+
+ "lynx-dev Mailing list archives"
+ <URL:http://www.flora.org/lynx-dev/html/>
diff --git a/gnu/usr.bin/lynx/VMSPrint.com b/gnu/usr.bin/lynx/VMSPrint.com
new file mode 100644
index 00000000000..d1e2c936a87
--- /dev/null
+++ b/gnu/usr.bin/lynx/VMSPrint.com
@@ -0,0 +1,15 @@
+$!
+$! Lynx_Dir:VMSPrint.com - Alan J. Hirsh (hirsh@atuk.aspentec.com)
+$! ---------------------
+$! Lynx deletes temporary files on exit. If your printer queue
+$! is very busy such that Lynx is deleting the files before they
+$! have been queued for printing, use PRINTER commands in lynx.cfg
+$! which invoke this script.
+$!
+$! PRINTER:description for menu:@Lynx_Dir\:VMSPrint queue_name %s:FALSE:58
+$!
+$! P1 = queue_name (e.g., sys$print) P2 = temporary Lynx file (%s)
+$! --------------------------------- -----------------------------
+$ copy 'P2' 'P2'_temp_print
+$ print/queue='P1'/delete 'P2'_temp_print
+$ exit
diff --git a/gnu/usr.bin/lynx/WWW/BUILD b/gnu/usr.bin/lynx/WWW/BUILD
new file mode 100644
index 00000000000..5fda9e0e7c0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/BUILD
@@ -0,0 +1,42 @@
+#! /bin/csh
+# Build all WWW Code for this platform
+#
+# Figure out what sort of unix this is
+# (NeXT machines don't have uname!)
+
+set UNAME=NeXT
+if (-e /usr/bin/uname) set UNAME=`/usr/bin/uname`
+if (-e /bin/uname) set UNAME=`/bin/uname`
+if (-e /usr/apollo/bin) set UNAME=`ver sys5.3 /bin/uname`
+if ( $UNAME == "" ) then
+ if (-r /NextApps ) set UNAME=next
+endif
+#
+setenv UNAME $UNAME
+# For apollo, must use bsd mode. Also, WWW_MACH not inherited through make!
+if ($UNAME == "DomainOS") setenv WWW_MACH apollo_m68k
+if ($UNAME == next) setenv WWW_MACH next
+if ($UNAME == "HP-UX") setenv WWW_MACH snake
+if ($UNAME == "IRIX") setenv WWW_MACH sgi
+if ($UNAME == "SunOS") setenv WWW_MACH sun4
+if ($UNAME == "ULTRIX") setenv WWW_MACH decstation
+if ($UNAME == "AIX") setenv WWW_MACH rs6000
+if ($UNAME == "OSF1") setenv WWW_MACH osf1
+
+if ($WWW_MACH == "") then
+ echo "Please edit BUILD file to include your machine OS"
+ echo "and mail differences back to www-bug@info.cern.ch
+ exit -99
+endif
+echo "________________________________________________________________"
+echo "WWW build for machine type: " $WWW_MACH
+
+# Now go do build
+
+# We don't want SHELL set to something funny to screw up make
+
+(cd All/Implementation; unsetenv SHELL; make)
+set stat = $status
+echo
+echo "WWW build for " $WWW_MACH " done. status = " $stat
+exit $stat
diff --git a/gnu/usr.bin/lynx/WWW/Copyright.txt b/gnu/usr.bin/lynx/WWW/Copyright.txt
new file mode 100644
index 00000000000..3d7397bba61
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Copyright.txt
@@ -0,0 +1,22 @@
+ Copyright -- /hypertext
+ COPYRIGHT CERN 1990-1993
+
+ Except where specifically placed in the public domain, the information (of
+ all forms) in these directories is the intellectual property of the European
+ Laboratory for Particle Physics (known as CERN). No guarantee whatsoever is
+ provided by CERN. No liability whatsoever is accepted for any loss or damage
+ of any kind resulting from any defect or inaccuracy in this information or
+ code.
+
+ The conditions for public domain and other access to the code are defined in
+ distribution conditions of WWW code[1]
+
+ Tim Berners-Lee[2]
+
+ CERN
+
+ 1211 Geneva 23, Switzerland
+
+ Tel +41(22)767 3755, Fax +41(22)767 7155, Email: tbl@cernvax.cern.ch
+
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/BSDI_Makefile b/gnu/usr.bin/lynx/WWW/Library/Implementation/BSDI_Makefile
new file mode 100644
index 00000000000..21ff1c02d8e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/BSDI_Makefile
@@ -0,0 +1,405 @@
+# Make WWW under unix
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = unix
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = generic/unix
+
+
+CFLAGS = -O -DDEBUG -DUSE_DIRENT -DSVR4 -DNO_FILIO_H
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+# Common Makefile for W3 Library Code
+# -----------------------------------
+#
+# (c) CERN 1990, 1991 -- see Copyright.html for conditions
+#
+# This file should be invariant between systems.
+# DEPENDENCIES NOT COMPLETE @@
+#
+# make Compile and link the software (private version)
+# make install Copy it into the system (implies make)
+# make update Copy installed version into installed version
+# make uninstall Unlink installed version from the system
+# make clean Remove intermediate files
+# make cleanall Remove intremediate files and products
+#
+# Macros required to be defined already for make:
+#
+# CC The C compiler
+# CFLAGS Flags for $(CC) -- except the -I which are below
+# LFLAGS Flags for ld
+# LYFLAGS Flags for Lynx
+#
+# WWW The WWW source tree directory
+#
+# Macros needed for make install:
+#
+# LIBDIR Directory for installed library
+#______________________________________________________________________
+
+# If this env var is set to something else Some makes will use that instead
+SHELL = /bin/sh
+
+# .h files are distributed but originally are made from the
+# self-documenting hypertext files.
+
+.SUFFIXES: .h .html
+.html.h:
+# - chmod +w $*.h
+ www -w90 -na -to text/x-c $*.html > $*.h
+# chmod -w $*.h
+
+# If this is actually run in a subdirectory,
+#
+# WWW = ../../..
+# WWW = ../.. For [cernlib] build in this directory
+
+WC = $(WWW)/Library
+CMN = $(WWW)/Library/Implementation/
+VMS = $(CMN)vms
+# Where shall we put the objects and built library?
+
+LOB = $(WTMP)/Library/$(WWW_MACH)
+
+# Only needed if HTWAIS.c is to be compiled. Put into your Makefile.include
+# uncomment these and fill in WAISINC for adding direct wais access
+# to Lynx.
+#HTWAIS = $(LOB)/HTWAIS.o
+#WAIS = YES
+#WAISINC = -I../../../../freeWAIS-0.202/ir
+#WAISCFLAGS = -DDIRECT_WAIS
+#
+
+# This path, if relative, is taken relative to the directory
+# in which this makefile is, not the pwd. This screws up the
+# recursive invocation
+# include $(CMN)Version.make
+VC = 2.14
+
+# XMOsAIC hack is only for server to cope with xmosaic kludge for mmedia
+#
+# add -DNEW_GATEWAY here for the new gateway config stuff
+CFLAGS2 = $(CFLAGS) $(LYFLAGS) $(WAISCFLAGS) -I$(CMN) -DXMOSAIC_HACK -DACCESS_AUTH
+
+CERNLIBBIN = $(WWW)/bin
+
+COMMON = $(LOB)/HTParse.o $(LOB)/HTAccess.o $(LOB)/HTTP.o \
+ $(LOB)/HTFile.o $(LOB)/HTBTree.o $(LOB)/HTFTP.o $(LOB)/HTTCP.o \
+ $(LOB)/SGML.o $(LOB)/HTMLDTD.o $(LOB)/HTChunk.o \
+ $(LOB)/HTPlain.o $(LOB)/HTWriter.o \
+ $(LOB)/HTMLGen.o \
+ $(LOB)/HTAtom.o $(LOB)/HTAnchor.o $(LOB)/HTStyle.o \
+ $(LOB)/HTList.o $(LOB)/HTString.o \
+ $(LOB)/HTRules.o $(LOB)/HTFormat.o $(LOB)/HTMIME.o \
+ $(LOB)/HTHistory.o $(LOB)/HTNews.o $(LOB)/HTGopher.o \
+ $(LOB)/HTTelnet.o $(LOB)/HTFinger.o $(LOB)/HTWSRC.o $(HTWAIS) \
+ $(LOB)/HTAAUtil.o $(LOB)/HTAAServ.o $(LOB)/HTAABrow.o \
+ $(LOB)/HTAAFile.o $(LOB)/HTPasswd.o $(LOB)/HTGroup.o \
+ $(LOB)/HTACL.o $(LOB)/HTAuth.o $(LOB)/HTAAProt.o \
+ $(LOB)/HTAssoc.o $(LOB)/HTLex.o $(LOB)/HTUU.o
+
+CFILES = $(CMN)HTParse.c $(CMN)HTAccess.c $(CMN)HTTP.c $(CMN)HTFile.c \
+ $(CMN)HTBTree.c \
+ $(CMN)HTFTP.c $(CMN)HTTCP.c $(CMN)SGML.c \
+ $(CMN)HTMLDTD.c \
+ $(CMN)HTPlain.c $(CMN)HTWriter.c \
+ $(CMN)HTMLGen.c \
+ $(CMN)HTChunk.c $(CMN)HTAtom.c $(CMN)HTAnchor.c $(CMN)HTStyle.c \
+ $(CMN)HTList.c $(CMN)HTString.c $(CMN)HTRules.c \
+ $(CMN)HTFormat.c $(CMN)HTMIME.c $(CMN)HTHistory.c \
+ $(CMN)HTNews.c $(CMN)HTGopher.c $(CMN)HTTelnet.c \
+ $(CMN)HTFinger.c $(CMN)HTWAIS.c $(CMN)HTWSRC.c \
+ $(CMN)HTAAUtil.c $(CMN)HTAAServ.c $(CMN)HTAABrow.c \
+ $(CMN)HTAAFile.c $(CMN)HTPasswd.c $(CMN)HTGroup.c \
+ $(CMN)HTACL.c $(CMN)HTAuth.c $(CMN)HTAAProt.c \
+ $(CMN)HTAssoc.c $(CMN)HTLex.c $(CMN)HTUU.c
+
+HFILES = $(CMN)HTParse.h $(CMN)HTAccess.h $(CMN)HTTP.h $(CMN)HTFile.h \
+ $(CMN)HTBTree.h $(CMN)HTFTP.h $(CMN)HTTCP.h \
+ $(CMN)SGML.h $(CMN)HTML.h $(CMN)HTMLDTD.h $(CMN)HTChunk.h \
+ $(CMN)HTPlain.h $(CMN)HTWriter.h \
+ $(CMN)HTFWriter.h $(CMN)HTMLGen.h \
+ $(CMN)HTStream.h \
+ $(CMN)HTAtom.h $(CMN)HTAnchor.h $(CMN)HTStyle.h \
+ $(CMN)HTList.h \
+ $(CMN)HTString.h $(CMN)HTAlert.h $(CMN)HTRules.h \
+ $(CMN)HTFormat.h $(CMN)HTInit.h \
+ $(CMN)HTMIME.h $(CMN)HTHistory.h $(CMN)HTNews.h \
+ $(CMN)HTGopher.h \
+ $(CMN)HTUtils.h $(CMN)tcp.h $(CMN)HText.h \
+ $(CMN)HTTelnet.h $(CMN)HTFinger.h \
+ $(CMN)HTWAIS.h $(CMN)HTWSRC.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAServ.h $(CMN)HTAABrow.h \
+ $(CMN)HTAAFile.h $(CMN)HTPasswd.h $(CMN)HTGroup.h \
+ $(CMN)HTACL.h $(CMN)HTAuth.h $(CMN)HTAAProt.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h $(CMN)HTUU.h
+
+SOURCES = $(CFILES) $(HFILES) $(CMN)Version.make \
+ $(CMN)CommonMakefile $(CMN)Makefile \
+ $(WWW)/README.txt $(WWW)/Copyright.txt $(WWW)/BUILD $(WWW)/Makefile
+SPECIFIC = $(WWW)/All/*/Makefile.include $(WWW)/All/Implementation/Makefile* \
+ $(VMS)/descrip.mms $(VMS)/build_multinet.com \
+ $(VMS)/COPYING.LIB $(VMS)/setup.com $(VMS)/multinet.opt \
+ $(VMS)/patchlevel.h $(VMS)/ufc-crypt.h \
+ $(VMS)/crypt.c $(VMS)/crypt_util.c \
+ $(VMS)/getline.c $(VMS)/getpass.c \
+ $(VMS)/HTVMSUtils.h $(VMS)/HTVMSUtils.c
+
+
+# Library
+#
+# On SGI, ranlib is unnecessary and does not exist so we ignore errors
+# for that step
+$(LOB)/libwww.a : $(COMMON)
+ ar r $(LOB)/libwww.a $(COMMON)
+ -ranlib $(LOB)/libwww.a
+
+# Clean up everything generatable except final products
+clean :
+ rm $(LOB)/*.o $(LOB)/.created
+ -rmdir $(LOB)
+
+# Clean up everything generatable including final products
+
+cleanall : clean
+ rm $(LOB)/libwww.a
+
+# Install W3 library into system space (not normally necessary)
+
+install : libwww.a
+ if [ ! -r $(LIBDIR) ] mkdir $(LIBDIR)
+ cp libwww.a $(LIBDIR)/libwww.a
+
+uninstall :
+ rm $(LIBDIR)/libwww.a
+
+# Distribution use only:
+# ----------------------
+
+# Needs www version 2.4 or later to do this
+inc : $(HFILES)
+ echo Include files generated from hypertext.
+
+binary : /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+ echo FTP archive binary Libray $(VC) for $(WWW_MACH) up to date.
+
+
+/pub/www/bin/$(WWW_MACH)/libwww_$(VC).a : libwww.a
+ -mkdir /pub/www/bin/$(WWW_MACH)
+ cp libwww.a /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+
+# Source Distribution:
+
+distribute : /pub/www/README.txt /pub/www/Copyright.txt
+ (cd $(WWW)/..; WWW=WWW ABS=`pwd`/ make $(MFLAGS) \
+ -f WWW/Library/Implementation/CommonMakefile \
+ /pub/www/src/WWWLibrary_$(VC).tar.Z)
+ (cd ../Implementation; cvs tag \
+ `sed -e 's/VC = /v/' Version.make | sed -e 's?\.?/?'` )
+ echo Distribution of Library version $(VC) up to date.
+
+/pub/www/src/WWWLibrary_$(VC).tar.Z : $(SOURCES)
+ tar cf /pub/www/src/WWWLibrary_$(VC).tar \
+ $(SOURCES) $(SPECIFIC) $(WC)/*/Makefile
+ compress /pub/www/src/WWWLibrary_$(VC).tar
+
+
+# Hypertext supplied in text format
+# ---------------------------------
+
+$(WWW)/README.txt : $(WWW)/../README.html
+ www -n -p66 http://www.w3.org/hypertext/README.html \
+ > $(WWW)/README.txt
+/pub/www/README.txt : $(WWW)/README.txt
+ cp $(WWW)/README.txt /pub/www/README.txt
+
+$(WWW)/Copyright.txt : $(WWW)/../Copyright.html
+ www -n -p66 http://www.w3.org/hypertext/Copyright.html \
+ > $(WWW)/Copyright.txt
+/pub/www/Copyright.txt : $(WWW)/Copyright.txt
+ cp $(WWW)/Copyright.txt /pub/www/Copyright.txt
+
+# Common code
+# -----------
+
+# Directory for object files - .created checks it exists
+
+OE = $(LOB)/.created
+$(OE) :
+ if [ ! -r $(WTMP) ] ; then mkdir $(WTMP); else echo OK ; fi
+ if [ ! -r $(WTMP)/Library ] ; then mkdir $(WTMP)/Library; else echo OK ; fi
+ if [ ! -r $(WTMP)/Library/$(WWW_MACH) ] ; \
+ then mkdir $(WTMP)/Library/$(WWW_MACH); else echo OK ; fi
+ touch $@
+
+$(LOB)/HTList.o : $(OE) $(CMN)HTList.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTList.c
+
+$(LOB)/HTAnchor.o : $(OE) $(CMN)HTAnchor.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAnchor.c
+
+$(LOB)/HTFormat.o : $(OE) $(CMN)HTFormat.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFormat.c
+
+$(LOB)/HTMIME.o : $(OE) $(CMN)HTMIME.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMIME.c
+
+$(LOB)/HTHistory.o : $(OE) $(CMN)HTHistory.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTHistory.c
+
+$(LOB)/HTNews.o : $(OE) $(CMN)HTNews.c $(CMN)HTUtils.h $(CMN)HTList.h\
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTNews.c
+
+$(LOB)/HTGopher.o : $(OE) $(CMN)HTGopher.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGopher.c
+
+$(LOB)/HTTelnet.o : $(OE) $(CMN)HTTelnet.c $(CMN)HTUtils.h $(CMN)HTTelnet.h $(CMN)../../../userdefs.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTelnet.c
+
+$(LOB)/HTFinger.o : $(OE) $(CMN)HTFinger.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFinger.c
+
+$(LOB)/HTStyle.o : $(OE) $(CMN)HTStyle.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTStyle.c
+
+$(LOB)/HTAtom.o : $(OE) $(CMN)HTAtom.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAtom.c
+
+$(LOB)/HTChunk.o : $(OE) $(CMN)HTChunk.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTChunk.c
+
+$(LOB)/HTString.o : $(OE) $(CMN)HTString.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTString.c
+
+$(LOB)/HTRules.o : $(OE) $(CMN)HTRules.c $(CMN)HTUtils.h $(CMN)Version.make \
+ $(CMN)HTAAServ.h $(CMN)HTAAProt.h
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTRules.c
+
+$(LOB)/SGML.o : $(OE) $(CMN)SGML.c $(CMN)HTUtils.h $(CMN)UCAux.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)SGML.c
+
+$(LOB)/HTMLGen.o : $(OE) $(CMN)HTMLGen.c $(CMN)HTUtils.h $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLGen.c
+
+$(LOB)/HTMLDTD.o : $(OE) $(CMN)HTMLDTD.c $(CMN)SGML.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLDTD.c
+
+$(LOB)/HTPlain.o : $(OE) $(CMN)HTPlain.c $(CMN)HTPlain.h $(CMN)HTStream.h \
+ $(CMN)UCAux.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPlain.c
+
+$(LOB)/HTWAIS.o : $(OE) $(CMN)HTWAIS.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(WAISINC) $(CMN)HTWAIS.c
+
+$(LOB)/HTWSRC.o : $(OE) $(CMN)HTWSRC.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWSRC.c
+
+$(LOB)/HTWriter.o : $(OE) $(CMN)HTWriter.c $(CMN)HTWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWriter.c
+
+
+# Access Authorization
+
+$(LOB)/HTAAUtil.o : $(OE) $(CMN)HTAAUtil.c $(CMN)HTAAUtil.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAUtil.c
+
+$(LOB)/HTAAFile.o : $(OE) $(CMN)HTAAFile.c $(CMN)HTAAFile.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAFile.c
+
+$(LOB)/HTPasswd.o : $(OE) $(CMN)HTPasswd.c $(CMN)HTPasswd.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPasswd.c
+
+$(LOB)/HTGroup.o : $(OE) $(CMN)HTGroup.c $(CMN)HTGroup.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGroup.c
+
+$(LOB)/HTACL.o : $(OE) $(CMN)HTACL.c $(CMN)HTACL.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTGroup.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTACL.c
+
+$(LOB)/HTAuth.o : $(OE) $(CMN)HTAuth.c $(CMN)HTAuth.h \
+ $(CMN)HTAAUtil.h $(CMN)HTPasswd.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAuth.c
+
+$(LOB)/HTAAServ.o : $(OE) $(CMN)HTAAServ.c $(CMN)HTAAServ.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTPasswd.h \
+ $(CMN)HTGroup.h $(CMN)HTACL.h $(CMN)HTAuth.h \
+ $(CMN)HTUU.h $(CMN)HTParse.h $(CMN)HTList.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTRules.h \
+ $(CMN)HTAAProt.h $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAServ.c
+
+$(LOB)/HTAABrow.o : $(OE) $(CMN)HTAABrow.c $(CMN)HTAABrow.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUU.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h \
+ $(CMN)HTParse.h $(CMN)HTList.h $(CMN)HTAlert.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAABrow.c
+
+$(LOB)/HTAAProt.o : $(OE) $(CMN)HTAAProt.c $(CMN)HTAAProt.h \
+ $(CMN)HTUtils.h $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAProt.c
+
+$(LOB)/HTAssoc.o : $(OE) $(CMN)HTAssoc.c $(CMN)HTAssoc.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAssoc.c
+
+$(LOB)/HTLex.o : $(OE) $(CMN)HTLex.c $(CMN)HTLex.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTLex.c
+
+$(LOB)/HTUU.o : $(OE) $(CMN)HTUU.c $(CMN)HTUU.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTUU.c
+
+
+# Communications & Files
+
+$(LOB)/HTTP.o : $(OE) $(CMN)HTTP.c $(CMN)HTUtils.h $(CMN)HTAABrow.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTP.c
+
+$(LOB)/HTTCP.o : $(OE) $(CMN)HTTCP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTCP.c
+
+$(LOB)/HTFile.o : $(OE) $(CMN)HTFile.c $(CMN)HTUtils.h \
+ $(CMN)HTMLDTD.h $(CMN)HTAAServ.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFile.c
+
+$(LOB)/HTBTree.o : $(OE) $(CMN)HTBTree.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTBTree.c
+
+$(LOB)/HTFTP.o : $(OE) $(CMN)HTFTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFTP.c
+
+$(LOB)/HTAccess.o : $(OE) $(CMN)HTAccess.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAccess.c
+
+$(LOB)/HTParse.o : $(OE) $(CMN)HTParse.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTParse.c
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/CommonMakefile b/gnu/usr.bin/lynx/WWW/Library/Implementation/CommonMakefile
new file mode 100644
index 00000000000..b7d32576ec9
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/CommonMakefile
@@ -0,0 +1,373 @@
+# Common Makefile for W3 Library Code
+# -----------------------------------
+#
+# (c) CERN 1990, 1991 -- see Copyright.html for conditions
+#
+# This file should be invariant between systems.
+# DEPENDENCIES NOT COMPLETE @@
+#
+# make Compile and link the software (private version)
+# make install Copy it into the system (implies make)
+# make update Copy installed version into installed version
+# make uninstall Unlink installed version from the system
+# make clean Remove intermediate files
+# make cleanall Remove intremediate files and products
+#
+# Macros required to be defined already for make:
+#
+# CC The C compiler
+# CFLAGS Flags for $(CC) -- except the -I which are below
+# LFLAGS Flags for ld
+# LYFLAGS Flags for Lynx
+#
+# WWW The WWW source tree directory
+#
+# Macros needed for make install:
+#
+# LIBDIR Directory for installed library
+#______________________________________________________________________
+
+# If this env var is set to something else Some makes will use that instead
+SHELL = /bin/sh
+
+RANLIB = ranlib
+
+# .h files are distributed but originally are made from the
+# self-documenting hypertext files.
+
+.SUFFIXES: .h .html
+.html.h:
+# - chmod +w $*.h
+ www -w90 -na -to text/x-c $*.html > $*.h
+# chmod -w $*.h
+
+# If this is actually run in a subdirectory,
+#
+# WWW = ../../..
+# WWW = ../.. For [cernlib] build in this directory
+
+WC = $(WWW)/Library
+CMN = $(WWW)/Library/Implementation/
+VMS = $(CMN)vms
+# Where shall we put the objects and built library?
+
+LOB = $(WTMP)/Library/$(WWW_MACH)
+
+# Only needed if HTWAIS.c is to be compiled. Put into your Makefile.include
+# uncomment these and fill in WAISINC for adding direct wais access
+# to Lynx.
+#HTWAIS = $(LOB)/HTWAIS.o
+#WAIS = YES
+#WAISINC = -I../../../../freeWAIS-0.202/ir
+#WAISCFLAGS = -DDIRECT_WAIS
+#
+
+# XMOsAIC hack is only for server to cope with xmosaic kludge for mmedia
+#
+# add -DNEW_GATEWAY here for the new gateway config stuff
+CFLAGS2 = $(CFLAGS) $(LYFLAGS) $(WAISCFLAGS) -I$(CMN) -DXMOSAIC_HACK -DACCESS_AUTH
+
+CERNLIBBIN = $(WWW)/bin
+
+COMMON = $(LOB)/HTParse.o $(LOB)/HTAccess.o $(LOB)/HTTP.o \
+ $(LOB)/HTFile.o $(LOB)/HTBTree.o $(LOB)/HTFTP.o $(LOB)/HTTCP.o \
+ $(LOB)/SGML.o $(LOB)/HTMLDTD.o $(LOB)/HTChunk.o \
+ $(LOB)/HTPlain.o $(LOB)/HTWriter.o \
+ $(LOB)/HTMLGen.o \
+ $(LOB)/HTAtom.o $(LOB)/HTAnchor.o $(LOB)/HTStyle.o \
+ $(LOB)/HTList.o $(LOB)/HTString.o \
+ $(LOB)/HTRules.o $(LOB)/HTFormat.o $(LOB)/HTMIME.o \
+ $(LOB)/HTHistory.o $(LOB)/HTNews.o $(LOB)/HTGopher.o \
+ $(LOB)/HTTelnet.o $(LOB)/HTFinger.o $(LOB)/HTWSRC.o $(HTWAIS) \
+ $(LOB)/HTAAUtil.o $(LOB)/HTAAServ.o $(LOB)/HTAABrow.o \
+ $(LOB)/HTAAFile.o $(LOB)/HTPasswd.o $(LOB)/HTGroup.o \
+ $(LOB)/HTACL.o $(LOB)/HTAuth.o $(LOB)/HTAAProt.o \
+ $(LOB)/HTAssoc.o $(LOB)/HTLex.o $(LOB)/HTUU.o
+
+CFILES = $(CMN)HTParse.c $(CMN)HTAccess.c $(CMN)HTTP.c $(CMN)HTFile.c \
+ $(CMN)HTBTree.c \
+ $(CMN)HTFTP.c $(CMN)HTTCP.c $(CMN)SGML.c \
+ $(CMN)HTMLDTD.c \
+ $(CMN)HTPlain.c $(CMN)HTWriter.c \
+ $(CMN)HTMLGen.c \
+ $(CMN)HTChunk.c $(CMN)HTAtom.c $(CMN)HTAnchor.c $(CMN)HTStyle.c \
+ $(CMN)HTList.c $(CMN)HTString.c $(CMN)HTRules.c \
+ $(CMN)HTFormat.c $(CMN)HTMIME.c $(CMN)HTHistory.c \
+ $(CMN)HTNews.c $(CMN)HTGopher.c $(CMN)HTTelnet.c \
+ $(CMN)HTFinger.c $(CMN)HTWAIS.c $(CMN)HTWSRC.c \
+ $(CMN)HTAAUtil.c $(CMN)HTAAServ.c $(CMN)HTAABrow.c \
+ $(CMN)HTAAFile.c $(CMN)HTPasswd.c $(CMN)HTGroup.c \
+ $(CMN)HTACL.c $(CMN)HTAuth.c $(CMN)HTAAProt.c \
+ $(CMN)HTAssoc.c $(CMN)HTLex.c $(CMN)HTUU.c
+
+HFILES = $(CMN)HTParse.h $(CMN)HTAccess.h $(CMN)HTTP.h $(CMN)HTFile.h \
+ $(CMN)HTBTree.h $(CMN)HTFTP.h $(CMN)HTTCP.h \
+ $(CMN)SGML.h $(CMN)HTML.h $(CMN)HTMLDTD.h $(CMN)HTChunk.h \
+ $(CMN)HTPlain.h $(CMN)HTWriter.h \
+ $(CMN)HTFWriter.h $(CMN)HTMLGen.h \
+ $(CMN)HTStream.h \
+ $(CMN)HTAtom.h $(CMN)HTAnchor.h $(CMN)HTStyle.h \
+ $(CMN)HTList.h \
+ $(CMN)HTString.h $(CMN)HTAlert.h $(CMN)HTRules.h \
+ $(CMN)HTFormat.h $(CMN)HTInit.h \
+ $(CMN)HTMIME.h $(CMN)HTHistory.h $(CMN)HTNews.h \
+ $(CMN)HTGopher.h \
+ $(CMN)HTUtils.h $(CMN)tcp.h $(CMN)HText.h \
+ $(CMN)HTTelnet.h $(CMN)HTFinger.h \
+ $(CMN)HTWAIS.h $(CMN)HTWSRC.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAServ.h $(CMN)HTAABrow.h \
+ $(CMN)HTAAFile.h $(CMN)HTPasswd.h $(CMN)HTGroup.h \
+ $(CMN)HTACL.h $(CMN)HTAuth.h $(CMN)HTAAProt.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h $(CMN)HTUU.h
+
+SOURCES = $(CFILES) $(HFILES) $(CMN)Version.make \
+ $(CMN)CommonMakefile $(CMN)Makefile \
+ $(WWW)/README.txt $(WWW)/Copyright.txt $(WWW)/BUILD $(WWW)/Makefile
+SPECIFIC = $(WWW)/All/*/Makefile.include $(WWW)/All/Implementation/Makefile* \
+ $(VMS)/descrip.mms $(VMS)/build_multinet.com \
+ $(VMS)/COPYING.LIB $(VMS)/setup.com $(VMS)/multinet.opt \
+ $(VMS)/patchlevel.h $(VMS)/ufc-crypt.h \
+ $(VMS)/crypt.c $(VMS)/crypt_util.c \
+ $(VMS)/getline.c $(VMS)/getpass.c \
+ $(VMS)/HTVMSUtils.h $(VMS)/HTVMSUtils.c
+
+
+# Library
+#
+# On SGI, ranlib is unnecessary and does not exist so we ignore errors
+# for that step
+$(LOB)/libwww.a : $(COMMON)
+ ar r $(LOB)/libwww.a $(COMMON)
+ -$(RANLIB) $(LOB)/libwww.a
+
+# Clean up everything generatable except final products
+clean :
+ rm $(LOB)/*.o $(LOB)/.created
+ -rmdir $(LOB)
+
+# Clean up everything generatable including final products
+
+cleanall : clean
+ rm $(LOB)/libwww.a
+
+# Install W3 library into system space (not normally necessary)
+
+install : libwww.a
+ if [ ! -r $(LIBDIR) ] mkdir $(LIBDIR)
+ cp libwww.a $(LIBDIR)/libwww.a
+
+uninstall :
+ rm $(LIBDIR)/libwww.a
+
+# Distribution use only:
+# ----------------------
+
+# Needs www version 2.4 or later to do this
+inc : $(HFILES)
+ echo Include files generated from hypertext.
+
+binary : /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+ echo FTP archive binary Libray $(VC) for $(WWW_MACH) up to date.
+
+
+/pub/www/bin/$(WWW_MACH)/libwww_$(VC).a : libwww.a
+ -mkdir /pub/www/bin/$(WWW_MACH)
+ cp libwww.a /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+
+# Source Distribution:
+
+distribute : /pub/www/README.txt /pub/www/Copyright.txt
+ (cd $(WWW)/..; WWW=WWW ABS=`pwd`/ make $(MFLAGS) \
+ -f WWW/Library/Implementation/CommonMakefile \
+ /pub/www/src/WWWLibrary_$(VC).tar.Z)
+ (cd ../Implementation; cvs tag \
+ `sed -e 's/VC = /v/' Version.make | sed -e 's?\.?/?'` )
+ echo Distribution of Library version $(VC) up to date.
+
+/pub/www/src/WWWLibrary_$(VC).tar.Z : $(SOURCES)
+ tar cf /pub/www/src/WWWLibrary_$(VC).tar \
+ $(SOURCES) $(SPECIFIC) $(WC)/*/Makefile
+ compress /pub/www/src/WWWLibrary_$(VC).tar
+
+
+# Hypertext supplied in text format
+# ---------------------------------
+
+$(WWW)/README.txt : $(WWW)/../README.html
+ www -n -p66 http://www.w3.org/hypertext/README.html \
+ > $(WWW)/README.txt
+/pub/www/README.txt : $(WWW)/README.txt
+ cp $(WWW)/README.txt /pub/www/README.txt
+
+$(WWW)/Copyright.txt : $(WWW)/../Copyright.html
+ www -n -p66 http://www.w3.org/hypertext/Copyright.html \
+ > $(WWW)/Copyright.txt
+/pub/www/Copyright.txt : $(WWW)/Copyright.txt
+ cp $(WWW)/Copyright.txt /pub/www/Copyright.txt
+
+# Common code
+# -----------
+
+# Directory for object files - .created checks it exists
+
+OE = $(LOB)/.created
+$(OE) :
+ if [ ! -r $(WTMP) ] ; then mkdir $(WTMP); else echo OK ; fi
+ if [ ! -r $(WTMP)/Library ] ; then mkdir $(WTMP)/Library; else echo OK ; fi
+ if [ ! -r $(WTMP)/Library/$(WWW_MACH) ] ; \
+ then mkdir $(WTMP)/Library/$(WWW_MACH); else echo OK ; fi
+ touch $@
+
+$(LOB)/HTList.o : $(OE) $(CMN)HTList.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTList.c
+
+$(LOB)/HTAnchor.o : $(OE) $(CMN)HTAnchor.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAnchor.c
+
+$(LOB)/HTFormat.o : $(OE) $(CMN)HTFormat.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFormat.c
+
+$(LOB)/HTMIME.o : $(OE) $(CMN)HTMIME.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMIME.c
+
+$(LOB)/HTHistory.o : $(OE) $(CMN)HTHistory.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTHistory.c
+
+$(LOB)/HTNews.o : $(OE) $(CMN)HTNews.c $(CMN)HTUtils.h $(CMN)HTList.h\
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTNews.c
+
+$(LOB)/HTGopher.o : $(OE) $(CMN)HTGopher.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGopher.c
+
+$(LOB)/HTTelnet.o : $(OE) $(CMN)HTTelnet.c $(CMN)HTUtils.h $(CMN)HTTelnet.h $(CMN)../../../userdefs.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTelnet.c
+
+$(LOB)/HTFinger.o : $(OE) $(CMN)HTFinger.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFinger.c
+
+$(LOB)/HTStyle.o : $(OE) $(CMN)HTStyle.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTStyle.c
+
+$(LOB)/HTAtom.o : $(OE) $(CMN)HTAtom.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAtom.c
+
+$(LOB)/HTChunk.o : $(OE) $(CMN)HTChunk.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTChunk.c
+
+$(LOB)/HTString.o : $(OE) $(CMN)HTString.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTString.c
+
+$(LOB)/HTRules.o : $(OE) $(CMN)HTRules.c $(CMN)HTUtils.h $(CMN)Version.make \
+ $(CMN)HTAAServ.h $(CMN)HTAAProt.h
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTRules.c
+
+$(LOB)/SGML.o : $(OE) $(CMN)SGML.c $(CMN)HTUtils.h $(CMN)UCAux.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)SGML.c
+
+$(LOB)/HTMLGen.o : $(OE) $(CMN)HTMLGen.c $(CMN)HTUtils.h $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLGen.c
+
+$(LOB)/HTMLDTD.o : $(OE) $(CMN)HTMLDTD.c $(CMN)SGML.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLDTD.c
+
+$(LOB)/HTPlain.o : $(OE) $(CMN)HTPlain.c $(CMN)HTPlain.h $(CMN)HTStream.h \
+ $(CMN)UCAux.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPlain.c
+
+$(LOB)/HTWAIS.o : $(OE) $(CMN)HTWAIS.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(WAISINC) $(CMN)HTWAIS.c
+
+$(LOB)/HTWSRC.o : $(OE) $(CMN)HTWSRC.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWSRC.c
+
+$(LOB)/HTWriter.o : $(OE) $(CMN)HTWriter.c $(CMN)HTWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWriter.c
+
+
+# Access Authorization
+
+$(LOB)/HTAAUtil.o : $(OE) $(CMN)HTAAUtil.c $(CMN)HTAAUtil.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAUtil.c
+
+$(LOB)/HTAAFile.o : $(OE) $(CMN)HTAAFile.c $(CMN)HTAAFile.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAFile.c
+
+$(LOB)/HTPasswd.o : $(OE) $(CMN)HTPasswd.c $(CMN)HTPasswd.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPasswd.c
+
+$(LOB)/HTGroup.o : $(OE) $(CMN)HTGroup.c $(CMN)HTGroup.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGroup.c
+
+$(LOB)/HTACL.o : $(OE) $(CMN)HTACL.c $(CMN)HTACL.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTGroup.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTACL.c
+
+$(LOB)/HTAuth.o : $(OE) $(CMN)HTAuth.c $(CMN)HTAuth.h \
+ $(CMN)HTAAUtil.h $(CMN)HTPasswd.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAuth.c
+
+$(LOB)/HTAAServ.o : $(OE) $(CMN)HTAAServ.c $(CMN)HTAAServ.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTPasswd.h \
+ $(CMN)HTGroup.h $(CMN)HTACL.h $(CMN)HTAuth.h \
+ $(CMN)HTUU.h $(CMN)HTParse.h $(CMN)HTList.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTRules.h \
+ $(CMN)HTAAProt.h $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAServ.c
+
+$(LOB)/HTAABrow.o : $(OE) $(CMN)HTAABrow.c $(CMN)HTAABrow.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUU.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h \
+ $(CMN)HTParse.h $(CMN)HTList.h $(CMN)HTAlert.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAABrow.c
+
+$(LOB)/HTAAProt.o : $(OE) $(CMN)HTAAProt.c $(CMN)HTAAProt.h \
+ $(CMN)HTUtils.h $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAProt.c
+
+$(LOB)/HTAssoc.o : $(OE) $(CMN)HTAssoc.c $(CMN)HTAssoc.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAssoc.c
+
+$(LOB)/HTLex.o : $(OE) $(CMN)HTLex.c $(CMN)HTLex.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTLex.c
+
+$(LOB)/HTUU.o : $(OE) $(CMN)HTUU.c $(CMN)HTUU.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTUU.c
+
+
+# Communications & Files
+
+$(LOB)/HTTP.o : $(OE) $(CMN)HTTP.c $(CMN)HTUtils.h $(CMN)HTAABrow.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTP.c
+
+$(LOB)/HTTCP.o : $(OE) $(CMN)HTTCP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTCP.c
+
+$(LOB)/HTFile.o : $(OE) $(CMN)HTFile.c $(CMN)HTUtils.h \
+ $(CMN)HTMLDTD.h $(CMN)HTAAServ.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFile.c
+
+$(LOB)/HTBTree.o : $(OE) $(CMN)HTBTree.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTBTree.c
+
+$(LOB)/HTFTP.o : $(OE) $(CMN)HTFTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFTP.c
+
+$(LOB)/HTAccess.o : $(OE) $(CMN)HTAccess.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAccess.c
+
+$(LOB)/HTParse.o : $(OE) $(CMN)HTParse.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTParse.c
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.c
new file mode 100644
index 00000000000..0ebe5309e7d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.c
@@ -0,0 +1,1309 @@
+
+/* MODULE HTAABrow.c
+** BROWSER SIDE ACCESS AUTHORIZATION MODULE
+**
+** Containts the code for keeping track on server hostnames,
+** port numbers, scheme names, usernames, passwords
+** (and servers' public keys).
+**
+** IMPORTANT:
+** Routines in this module use dynamic allocation, but free
+** automatically all the memory reserved by them.
+**
+** Therefore the caller never has to (and never should)
+** free() any object returned by these functions.
+**
+** Therefore also all the strings returned by this package
+** are only valid until the next call to the same function
+** is made. This approach is selected, because of the nature
+** of access authorization: no string returned by the package
+** needs to be valid longer than until the next call.
+**
+** This also makes it easy to plug the AA package in:
+** you don't have to ponder whether to free() something
+** here or is it done somewhere else (because it is always
+** done somewhere else).
+**
+** The strings that the package needs to store are copied
+** so the original strings given as parameters to AA
+** functions may be freed or modified with no side effects.
+**
+** The AA package does not free() anything else than what
+** it has itself allocated.
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+** Oct 17 AL Made corrections suggested by marca:
+** Added if (!realm->username) return NULL;
+** Changed some ""s to NULLs.
+** Now doing calloc() to init uuencode source;
+** otherwise HTUU_encode() reads uninitialized memory
+** every now and then (not a real bug but not pretty).
+** Corrected the formula for uuencode destination size.
+**
+** 28 Apr 1997 AJL Do Proxy Authorisation.
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include <string.h> /* strchr() */
+#include "HTString.h"
+#include "HTParse.h" /* URL parsing function */
+#include "HTList.h" /* HTList object */
+#include "HTAlert.h" /* HTConfirm(), HTPrompt() */
+#include "HTAAUtil.h" /* AA common to both sides */
+#include "HTAssoc.h" /* Assoc list */
+#include "HTAABrow.h" /* Implemented here */
+#include "HTUU.h" /* Uuencoding and uudecoding */
+
+#include "LYLeaks.h"
+
+extern BOOL using_proxy; /* Are we using an HTTP gateway? */
+
+/*
+** Local datatype definitions
+**
+** HTAAServer contains all the information about one server.
+*/
+typedef struct {
+
+ char * hostname; /* Host's name */
+ int portnumber; /* Port number */
+ BOOL IsProxy; /* Is it a proxy? */
+ HTList * setups; /* List of protection setups */
+ /* on this server; i.e. valid */
+ /* authentication schemes and */
+ /* templates when to use them. */
+ /* This is actually a list of */
+ /* HTAASetup objects. */
+ HTList * realms; /* Information about passwords */
+} HTAAServer;
+
+/*
+** HTAASetup contains information about one server's one
+** protected tree of documents.
+*/
+typedef struct {
+ HTAAServer *server; /* Which server serves this tree */
+ char * template; /* Template for this tree */
+ HTList * valid_schemes; /* Valid authentic.schemes */
+ HTAssocList**scheme_specifics;/* Scheme specific params */
+ BOOL retry; /* Failed last time -- reprompt (or whatever)*/
+} HTAASetup;
+
+/*
+** Information about usernames and passwords in
+** Basic and Pubkey authentication schemes;
+*/
+typedef struct {
+ char * realmname; /* Password domain name */
+ char * username; /* Username in that domain */
+ char * password; /* Corresponding password */
+} HTAARealm;
+
+/*
+** To free off all globals. - FM
+*/
+PRIVATE void free_HTAAGlobals NOPARAMS;
+PRIVATE BOOL free_HTAAGlobalsSet = FALSE;
+PRIVATE char *HTAA_composeAuthResult = NULL;
+PRIVATE char *compose_auth_stringResult = NULL; /* Uuencoded presentation */
+
+/*
+** Module-wide global variables
+*/
+PRIVATE HTList *server_table = NULL; /* Browser's info about servers */
+PRIVATE char *secret_key = NULL; /* Browser's latest secret key */
+PRIVATE HTAASetup *current_setup= NULL; /* The server setup we are currently */
+ /* talking to */
+PRIVATE char *current_hostname = NULL; /* The server's name and portnumber */
+PRIVATE int current_portnumber = 80; /* where we are currently trying to */
+ /* connect. */
+PRIVATE char *current_docname = NULL; /* The document's name we are */
+ /* trying to access. */
+PRIVATE char *HTAAForwardAuth = NULL; /* Authorization: line to forward */
+ /* (used by gateway httpds) */
+PRIVATE HTAASetup *proxy_setup = NULL; /* Same as above, but for Proxy -AJL */
+PRIVATE char *proxy_hostname = NULL;
+PRIVATE char *proxy_docname = NULL;
+PRIVATE int proxy_portnumber = 80;
+
+
+/*** HTAAForwardAuth for enabling gateway-httpds to forward Authorization ***/
+
+PUBLIC void HTAAForwardAuth_set ARGS2(
+ CONST char *, scheme_name,
+ CONST char *, scheme_specifics)
+{
+ int len = 20 + (scheme_name ? strlen(scheme_name) : 0)
+ + (scheme_specifics ? strlen(scheme_specifics) : 0);
+
+ FREE(HTAAForwardAuth);
+ if (!(HTAAForwardAuth = (char*)calloc(1, sizeof(char) * len)))
+ outofmem(__FILE__, "HTAAForwardAuth_set");
+
+ strcpy(HTAAForwardAuth, "Authorization: ");
+ if (scheme_name) {
+ strcat(HTAAForwardAuth, scheme_name);
+ strcat(HTAAForwardAuth, " ");
+ if (scheme_specifics) {
+ strcat(HTAAForwardAuth, scheme_specifics);
+ }
+ }
+}
+
+PUBLIC void HTAAForwardAuth_reset NOARGS
+{
+ FREE(HTAAForwardAuth);
+}
+
+
+/**************************** HTAAServer ***********************************/
+
+PRIVATE void HTAASetup_delete PARAMS((HTAASetup * killme)); /* Forward */
+
+/* PRIVATE HTAAServer_new()
+** ALLOCATE A NEW NODE TO HOLD SERVER INFO
+** AND ADD IT TO THE LIST OF SERVERS
+** ON ENTRY:
+** hostname is the name of the host that the server
+** is running in.
+** portnumber is the portnumber which the server listens.
+** IsProxy should be TRUE if this is a proxy.
+**
+** ON EXIT:
+** returns the newly-allocated node with all the strings
+** duplicated.
+** Strings will be automatically freed by
+** the function HTAAServer_delete(), which also
+** frees the node itself.
+*/
+PRIVATE HTAAServer *HTAAServer_new ARGS3(
+ CONST char*, hostname,
+ int, portnumber,
+ BOOL, IsProxy)
+{
+ HTAAServer *server;
+
+ if (!(server = (HTAAServer *)calloc(1, sizeof(HTAAServer))))
+ outofmem(__FILE__, "HTAAServer_new");
+
+ server->hostname = NULL;
+ server->portnumber = (portnumber > 0 ? portnumber : 80);
+ server->IsProxy = IsProxy;
+ server->setups = HTList_new();
+ server->realms = HTList_new();
+
+ if (hostname)
+ StrAllocCopy(server->hostname, hostname);
+
+ if (!server_table)
+ server_table = HTList_new();
+
+ HTList_addObject(server_table, (void*)server);
+
+ return server;
+}
+
+
+/* PRIVATE HTAAServer_delete()
+**
+** DELETE THE ENTRY FOR THE SERVER FROM THE HOST TABLE,
+** AND FREE THE MEMORY USED BY IT.
+**
+** ON ENTRY:
+** killme points to the HTAAServer to be freed.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PRIVATE void HTAAServer_delete ARGS1(
+ HTAAServer *, killme)
+{
+ int n, i;
+ HTAASetup *setup;
+ HTAARealm *realm;
+ HTList *cur;
+
+ if (killme) {
+ if (killme->setups != NULL) {
+ n = HTList_count(killme->setups);
+ for (i = (n - 1); i >= 0; i--) {
+ if ((setup = (HTAASetup*)HTList_objectAt(killme->setups,
+ i)) != NULL) {
+ HTAASetup_delete(setup);
+ setup = NULL;
+ }
+ }
+ HTList_delete(killme->setups);
+ killme->setups = NULL;
+ }
+
+ cur = killme->realms;
+ while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur))) {
+ FREE(realm->realmname);
+ FREE(realm->username);
+ FREE(realm->password);
+ FREE(realm);
+ }
+ HTList_delete(killme->realms);
+ killme->realms = NULL;
+
+ FREE(killme->hostname);
+
+ HTList_removeObject(server_table, (void*)killme);
+ FREE(killme);
+ }
+}
+
+/* PRIVATE HTAAServer_lookup()
+** LOOK UP SERVER BY HOSTNAME AND PORTNUMBER
+** ON ENTRY:
+** hostname obvious.
+** portnumber if non-positive defaults to 80.
+** IsProxy should be TRUE if this is a proxy.
+**
+** Looks up the server in the module-global server_table.
+**
+** ON EXIT:
+** returns pointer to a HTAAServer structure
+** representing the looked-up server.
+** NULL, if not found.
+*/
+PRIVATE HTAAServer *HTAAServer_lookup ARGS3(
+ CONST char *, hostname,
+ int, portnumber,
+ BOOL, IsProxy)
+{
+ if (hostname) {
+ HTList *cur = server_table;
+ HTAAServer *server;
+
+ if (portnumber <= 0)
+ portnumber = 80;
+
+ while (NULL != (server = (HTAAServer*)HTList_nextObject(cur))) {
+ if (server->portnumber == portnumber &&
+ 0==strcmp(server->hostname, hostname) &&
+ server->IsProxy == IsProxy)
+ return server;
+ }
+ }
+ return NULL; /* NULL parameter, or not found */
+}
+
+
+/*************************** HTAASetup *******************************/
+
+/* PRIVATE HTAASetup_lookup()
+** FIGURE OUT WHICH AUTHENTICATION SETUP THE SERVER
+** IS USING FOR A GIVEN FILE ON A GIVEN HOST AND PORT
+**
+** ON ENTRY:
+** hostname is the name of the server host machine.
+** portnumber is the port that the server is running in.
+** docname is the (URL-)pathname of the document we
+** are trying to access.
+** IsProxy should be TRUE if this is a proxy.
+**
+** This function goes through the information known about
+** all the setups of the server, and finds out if the given
+** filename resides in one of the protected directories.
+**
+** ON EXIT:
+** returns NULL if no match.
+** Otherwise, a HTAASetup structure representing
+** the protected server setup on the corresponding
+** document tree.
+**
+*/
+PRIVATE HTAASetup *HTAASetup_lookup ARGS4(
+ CONST char *, hostname,
+ int, portnumber,
+ CONST char *, docname,
+ BOOL, IsProxy)
+{
+ HTAAServer *server;
+ HTAASetup *setup;
+
+ if (portnumber <= 0)
+ portnumber = 80;
+
+ if (hostname && docname && *hostname && *docname &&
+ NULL != (server = HTAAServer_lookup(hostname,
+ portnumber,
+ IsProxy))) {
+
+ HTList *cur = server->setups;
+
+ if (TRACE)
+ fprintf(stderr, "%s %s (%s:%d:%s)\n",
+ "HTAASetup_lookup: resolving setup for",
+ (IsProxy ? "proxy" : "server"),
+ hostname, portnumber, docname);
+
+ while (NULL != (setup = (HTAASetup*)HTList_nextObject(cur))) {
+ if (HTAA_templateMatch(setup->template, docname)) {
+ if (TRACE)
+ fprintf(stderr, "%s `%s' %s `%s'\n",
+ "HTAASetup_lookup:", docname,
+ "matched template", setup->template);
+ return setup;
+ }
+ else if (TRACE)
+ fprintf(stderr, "%s `%s' %s `%s'\n",
+ "HTAASetup_lookup:", docname,
+ "did NOT match template", setup->template);
+ } /* while setups remain */
+ } /* if valid parameters and server found */
+
+ if (TRACE)
+ fprintf(stderr, "%s `%s' %s\n",
+ "HTAASetup_lookup: No template matched",
+ (docname ? docname : "(null)"),
+ "(so probably not protected)");
+
+ return NULL; /* NULL in parameters, or not found */
+}
+
+/* PRIVATE HTAASetup_new()
+** CREATE A NEW SETUP NODE
+** ON ENTRY:
+** server is a pointer to a HTAAServer structure
+** to which this setup belongs.
+** template documents matching this template
+** are protected according to this setup.
+** valid_schemes a list containing all valid authentication
+** schemes for this setup.
+** If NULL, all schemes are disallowed.
+** scheme_specifics is an array of assoc lists, which
+** contain scheme specific parameters given
+** by server in Authenticate: fields.
+** If NULL, all scheme specifics are
+** set to NULL.
+** ON EXIT:
+** returns a new HTAASetup node, and also adds it as
+** part of the HTAAServer given as parameter.
+*/
+PRIVATE HTAASetup *HTAASetup_new ARGS4(
+ HTAAServer *, server,
+ char *, template,
+ HTList *, valid_schemes,
+ HTAssocList **, scheme_specifics)
+{
+ HTAASetup *setup;
+
+ if (!server || !template || !*template)
+ return NULL;
+
+ if (!(setup = (HTAASetup*)calloc(1, sizeof(HTAASetup))))
+ outofmem(__FILE__, "HTAASetup_new");
+
+ setup->retry = NO;
+ setup->server = server;
+ setup->template = NULL;
+ if (template)
+ StrAllocCopy(setup->template, template);
+ setup->valid_schemes = valid_schemes;
+ setup->scheme_specifics = scheme_specifics;
+
+ HTList_addObject(server->setups, (void*)setup);
+
+ return setup;
+}
+
+/* PRIVATE HTAASetup_delete()
+** FREE A HTAASetup STRUCTURE
+** ON ENTRY:
+** killme is a pointer to the structure to free().
+**
+** ON EXIT:
+** returns nothing.
+*/
+PRIVATE void HTAASetup_delete ARGS1(
+ HTAASetup *, killme)
+{
+ int scheme;
+
+ if (killme) {
+ FREE(killme->template);
+ if (killme->valid_schemes)
+ HTList_delete(killme->valid_schemes);
+ killme->valid_schemes = NULL;
+ for (scheme = 0; scheme < HTAA_MAX_SCHEMES; scheme++)
+ if (killme->scheme_specifics[scheme])
+ HTAssocList_delete(killme->scheme_specifics[scheme]);
+ FREE(killme->scheme_specifics);
+ FREE(killme);
+ }
+}
+
+/* PRIVATE HTAASetup_updateSpecifics()
+* COPY SCHEME SPECIFIC PARAMETERS
+** TO HTAASetup STRUCTURE
+** ON ENTRY:
+** setup destination setup structure.
+** specifics string array containing scheme
+** specific parameters for each scheme.
+** If NULL, all the scheme specific
+** parameters are set to NULL.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PRIVATE void HTAASetup_updateSpecifics ARGS2(
+ HTAASetup *, setup,
+ HTAssocList **, specifics)
+{
+ int scheme;
+
+ if (setup) {
+ if (setup->scheme_specifics) {
+ for (scheme = 0; scheme < HTAA_MAX_SCHEMES; scheme++) {
+ if (setup->scheme_specifics[scheme])
+ HTAssocList_delete(setup->scheme_specifics[scheme]);
+ }
+ FREE(setup->scheme_specifics);
+ }
+ setup->scheme_specifics = specifics;
+ }
+}
+
+
+/*************************** HTAARealm **********************************/
+
+/* PRIVATE HTAARealm_lookup()
+** LOOKUP HTAARealm STRUCTURE BY REALM NAME
+** ON ENTRY:
+** realm_table a list of realm objects.
+** realmname is the name of realm to look for.
+**
+** ON EXIT:
+** returns the realm. NULL, if not found.
+*/
+PRIVATE HTAARealm *HTAARealm_lookup ARGS2(
+ HTList *, realm_table,
+ CONST char *, realmname)
+{
+ if (realm_table && realmname) {
+ HTList *cur = realm_table;
+ HTAARealm *realm;
+
+ while (NULL != (realm = (HTAARealm*)HTList_nextObject(cur))) {
+ if (0==strcmp(realm->realmname, realmname))
+ return realm;
+ }
+ }
+ return NULL; /* No table, NULL param, or not found */
+}
+
+/* PRIVATE HTAARealm_new()
+** CREATE A NODE CONTAINING USERNAME AND
+** PASSWORD USED FOR THE GIVEN REALM.
+** IF REALM ALREADY EXISTS, CHANGE
+** USERNAME/PASSWORD.
+** ON ENTRY:
+** realm_table a list of realms to where to add
+** the new one, too.
+** realmname is the name of the password domain.
+** username and
+** password are what you can expect them to be.
+**
+** ON EXIT:
+** returns the created realm.
+*/
+PRIVATE HTAARealm *HTAARealm_new ARGS4(
+ HTList *, realm_table,
+ CONST char *, realmname,
+ CONST char *, username,
+ CONST char *, password)
+{
+ HTAARealm *realm;
+
+ realm = HTAARealm_lookup(realm_table, realmname);
+
+ if (!realm) {
+ if (!(realm = (HTAARealm*)calloc(1, sizeof(HTAARealm))))
+ outofmem(__FILE__, "HTAARealm_new");
+ realm->realmname = NULL;
+ realm->username = NULL;
+ realm->password = NULL;
+ StrAllocCopy(realm->realmname, realmname);
+ if (realm_table)
+ HTList_addObject(realm_table, (void*)realm);
+ }
+ if (username)
+ StrAllocCopy(realm->username, username);
+ if (password)
+ StrAllocCopy(realm->password, password);
+
+ return realm;
+}
+
+
+/***************** Basic and Pubkey Authentication ************************/
+
+/* PRIVATE compose_auth_string()
+**
+** COMPOSE Basic OR Pubkey AUTHENTICATION STRING;
+** PROMPTS FOR USERNAME AND PASSWORD IF NEEDED
+**
+** ON ENTRY:
+** scheme is either HTAA_BASIC or HTAA_PUBKEY.
+** setup is the current server setup.
+** IsProxy should be TRUE if this is a proxy.
+**
+** ON EXIT:
+** returns a newly composed authorization string,
+** (with, of course, a newly generated secret
+** key and fresh timestamp, if Pubkey-scheme
+** is being used).
+** NULL, if something fails.
+** NOTE:
+** Like throughout the entire AA package, no string or structure
+** returned by AA package needs to (or should) be freed.
+**
+*/
+PRIVATE char *compose_auth_string ARGS3(
+ HTAAScheme, scheme,
+ HTAASetup *, setup,
+ BOOL, IsProxy)
+{
+ char *cleartext = NULL; /* Cleartext presentation */
+ char *ciphertext = NULL; /* Encrypted presentation */
+ int len;
+ char *msg = NULL;
+ char *username = NULL;
+ char *password = NULL;
+ char *realmname = NULL;
+ char *theHost = NULL;
+ char *proxiedHost = NULL;
+ char *thePort = NULL;
+ HTAARealm *realm;
+ char *i_net_addr = "0.0.0.0"; /* Change... @@@@ */
+ char *timestamp = "42"; /* ... these @@@@ */
+
+
+ FREE(compose_auth_stringResult); /* From previous call */
+
+ if ((scheme != HTAA_BASIC && scheme != HTAA_PUBKEY) || !setup ||
+ !setup->scheme_specifics || !setup->scheme_specifics[scheme] ||
+ !setup->server || !setup->server->realms)
+ return NULL;
+
+ realmname = HTAssocList_lookup(setup->scheme_specifics[scheme], "realm");
+ if (!realmname)
+ return NULL;
+
+ realm = HTAARealm_lookup(setup->server->realms, realmname);
+ if (!(realm &&
+ realm->username && *realm->username &&
+ realm->password && *realm->password) || setup->retry) {
+ if (!realm) {
+ if (TRACE)
+ fprintf(stderr, "%s `%s' %s\n",
+ "compose_auth_string: realm:", realmname,
+ "not found -- creating");
+ realm = HTAARealm_new(setup->server->realms,
+ realmname, NULL, NULL);
+ }
+ /*
+ * The template should be either the '*' global
+ * for everthing on the server (always true for
+ * proxy authorization setups), or a path for
+ * the start of a protected limb, with no host
+ * field, but we'll check for a host anyway in
+ * case a WWW-Protection-Template header set an
+ * absolute URL instead of a path. If we do get
+ * a host from this, it will include the port. - FM
+ */
+ if ((!IsProxy) && using_proxy && setup->template) {
+ proxiedHost = HTParse(setup->template, "", PARSE_HOST);
+ if (proxiedHost && *proxiedHost != '\0') {
+ theHost = proxiedHost;
+ }
+ }
+ /*
+ * If we didn't get a host field from the
+ * template, set up the host name and port
+ * from the setup->server elements. - FM
+ */
+ if (!theHost)
+ theHost = setup->server->hostname;
+ if (setup->server->portnumber > 0 &&
+ setup->server->portnumber != 80) {
+ if (!(thePort = (char *)calloc(1, sizeof(char) * 40)))
+ outofmem(__FILE__, "compose_auth_string");
+ sprintf(thePort, ":%d", setup->server->portnumber);
+ }
+ /*
+ * Set up the message for the username prompt,
+ * and then issue the prompt. The default
+ * username is included in the call to the
+ * prompting function, but the password is
+ * NULL-ed and always replaced. - FM
+ */
+ len = strlen(realm->realmname) +
+ strlen(theHost ?
+ theHost : "??") + 50;
+ if (!(msg = (char *)calloc(1, sizeof(char) * len)))
+ outofmem(__FILE__, "compose_auth_string");
+ sprintf(msg, "Username for '%s' at %s '%s%s':",
+ realm->realmname,
+ (IsProxy ? "proxy" : "server"),
+ (theHost ? theHost : "??"),
+ (thePort ? thePort : ""));
+ FREE(proxiedHost);
+ FREE(thePort);
+ username = realm->username;
+ password = NULL;
+ HTPromptUsernameAndPassword(msg, &username, &password, IsProxy);
+
+ FREE(msg);
+ FREE(realm->username);
+ FREE(realm->password);
+ realm->username = username;
+ realm->password = password;
+
+ if (!realm->username || !realm->password) {
+ /*
+ * Signals to retry. - FM
+ */
+ return NULL;
+ } else if (*realm->username == '\0' || *realm->password == '\0') {
+ /*
+ * Signals to abort. - FM
+ */
+ StrAllocCopy(compose_auth_stringResult, "");
+ return compose_auth_stringResult;
+ }
+ }
+
+ len = strlen(realm->username ? realm->username : "") +
+ strlen(realm->password ? realm->password : "") + 3;
+
+ if (scheme == HTAA_PUBKEY) {
+#ifdef PUBKEY
+ /* Generate new secret key */
+ StrAllocCopy(secret_key, HTAA_generateRandomKey());
+#endif /* PUBKEY */
+ /* Room for secret key, timestamp and inet address */
+ len += strlen(secret_key ? secret_key : "") + 30;
+ } else {
+ FREE(secret_key);
+ }
+
+ if (!(cleartext = (char*)calloc(1, sizeof(char) * len)))
+ outofmem(__FILE__, "compose_auth_string");
+
+ if (realm->username)
+ strcpy(cleartext, realm->username);
+ else
+ *cleartext = '\0';
+
+ strcat(cleartext, ":");
+
+ if (realm->password)
+ strcat(cleartext, realm->password);
+
+ if (scheme == HTAA_PUBKEY) {
+ strcat(cleartext, ":");
+ strcat(cleartext, i_net_addr);
+ strcat(cleartext, ":");
+ strcat(cleartext, timestamp);
+ strcat(cleartext, ":");
+ if (secret_key)
+ strcat(cleartext, secret_key);
+
+ if (!((ciphertext = (char *)calloc(1, (sizeof(char) * 2) * len)) &&
+ (compose_auth_stringResult =
+ (char *)calloc(1, (sizeof(char) * 3) * len))))
+ outofmem(__FILE__, "compose_auth_string");
+#ifdef PUBKEY
+ HTPK_encrypt(cleartext, ciphertext, server->public_key);
+ HTUU_encode((unsigned char *)ciphertext, strlen(ciphertext),
+ compose_auth_stringResult);
+#endif /* PUBKEY */
+ FREE(cleartext);
+ FREE(ciphertext);
+ }
+ else { /* scheme == HTAA_BASIC */
+ if (!(compose_auth_stringResult =
+ (char*)calloc(1, (4 * ((len+2)/3)) + 1)))
+ outofmem(__FILE__, "compose_auth_string");
+ HTUU_encode((unsigned char *)cleartext, strlen(cleartext),
+ compose_auth_stringResult);
+ FREE(cleartext);
+ }
+ return compose_auth_stringResult;
+}
+
+/* BROWSER PRIVATE HTAA_selectScheme()
+** SELECT THE AUTHENTICATION SCHEME TO USE
+** ON ENTRY:
+** setup is the server setup structure which can
+** be used to make the decision about the
+** used scheme.
+**
+** When new authentication methods are added to library
+** this function makes the decision about which one to
+** use at a given time. This can be done by inspecting
+** environment variables etc.
+**
+** Currently only searches for the first valid scheme,
+** and if nothing found suggests Basic scheme;
+**
+** ON EXIT:
+** returns the authentication scheme to use.
+*/
+PRIVATE HTAAScheme HTAA_selectScheme ARGS1(
+ HTAASetup *, setup)
+{
+ HTAAScheme scheme;
+
+ if (setup && setup->valid_schemes) {
+ for (scheme = HTAA_BASIC; scheme < HTAA_MAX_SCHEMES; scheme++)
+ if (-1 < HTList_indexOf(setup->valid_schemes, (void*)scheme))
+ return scheme;
+ }
+ return HTAA_BASIC;
+}
+
+/*
+** Purpose: Free off all module globals.
+** Arguments: void
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** To be used at program exit.
+** Revision History:
+** 06-19-96 created - FM
+*/
+PRIVATE void free_HTAAGlobals NOARGS
+{
+ HTAAServer * server;
+ int n, i;
+
+ if (server_table != NULL) {
+ n = HTList_count(server_table);
+ for (i = (n - 1); i >= 0; i--) {
+ if ((server = (HTAAServer*)HTList_objectAt(server_table,
+ i)) != NULL) {
+ HTAAServer_delete(server);
+ server = NULL;
+ }
+ }
+ HTList_delete(server_table);
+ server_table = NULL;
+ }
+
+ HTAAForwardAuth_reset();
+ FREE(HTAA_composeAuthResult);
+ FREE(current_hostname);
+ FREE(current_docname);
+ FREE(proxy_hostname);
+ FREE(proxy_docname);
+ FREE(compose_auth_stringResult);
+ FREE(secret_key);
+}
+
+/* BROWSER PUBLIC HTAA_composeAuth()
+**
+** SELECT THE AUTHENTICATION SCHEME AND
+** COMPOSE THE ENTIRE AUTHORIZATION HEADER LINE
+** IF WE ALREADY KNOW THAT THE HOST REQUIRES AUTHENTICATION
+**
+** ON ENTRY:
+** hostname is the hostname of the server.
+** portnumber is the portnumber in which the server runs.
+** docname is the pathname of the document (as in URL)
+** IsProxy should be TRUE if this is a proxy.
+**
+** ON EXIT:
+** returns NULL, if no authorization seems to be needed, or
+** if it is the entire Authorization: line, e.g.
+**
+** "Authorization: Basic username:password"
+**
+** As usual, this string is automatically freed.
+*/
+PUBLIC char *HTAA_composeAuth ARGS4(
+ CONST char *, hostname,
+ CONST int, portnumber,
+ CONST char *, docname,
+ BOOL, IsProxy)
+{
+ char *auth_string;
+ BOOL retry;
+ HTAAScheme scheme;
+ int len;
+
+ /*
+ ** Setup atexit() freeing if not done already. - FM
+ */
+ if (!free_HTAAGlobalsSet) {
+ atexit(free_HTAAGlobals);
+ free_HTAAGlobalsSet = TRUE;
+ }
+
+ /*
+ ** Make gateway httpds pass authorization field as it was received.
+ ** (This still doesn't really work because Authenticate: headers
+ ** from remote server are not forwarded to client yet so it cannot
+ ** really know that it should send authorization; I will not
+ ** implement it yet because I feel we will soon change radically
+ ** the way requests are represented to allow multithreading
+ ** on server-side. Life is hard.)
+ */
+ if (HTAAForwardAuth) {
+ if (TRACE)
+ fprintf(stderr, "HTAA_composeAuth: %s\n",
+ "Forwarding received authorization");
+ StrAllocCopy(HTAA_composeAuthResult, HTAAForwardAuth);
+ HTAAForwardAuth_reset(); /* Just a precaution */
+ return HTAA_composeAuthResult;
+ }
+
+ FREE(HTAA_composeAuthResult); /* From previous call */
+
+ if (IsProxy) {
+ /*
+ ** Proxy Authorization required. - AJL
+ */
+
+ if (TRACE)
+ fprintf(stderr,
+ "Composing Proxy Authorization for %s:%d/%s\n",
+ hostname, portnumber, docname);
+
+ if (proxy_portnumber != portnumber ||
+ !proxy_hostname || !proxy_docname ||
+ !hostname || !docname ||
+ 0 != strcmp(proxy_hostname, hostname) ||
+ 0 != strcmp(proxy_docname, docname)) {
+
+ retry = NO;
+
+ proxy_portnumber = portnumber;
+
+ if (hostname)
+ StrAllocCopy(proxy_hostname, hostname);
+ else
+ FREE(proxy_hostname);
+
+ if (docname)
+ StrAllocCopy(proxy_docname, docname);
+ else
+ FREE(proxy_docname);
+ } else {
+ retry = YES;
+ }
+
+ if (!proxy_setup || !retry)
+ proxy_setup = HTAASetup_lookup(hostname, portnumber,
+ docname, IsProxy);
+
+ if (!proxy_setup)
+ return NULL;
+
+ switch (scheme = HTAA_selectScheme(proxy_setup)) {
+ case HTAA_BASIC:
+ case HTAA_PUBKEY:
+ auth_string = compose_auth_string(scheme, proxy_setup, IsProxy);
+ break;
+ case HTAA_KERBEROS_V4:
+ /* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
+ default:
+ {
+ char msg[100];
+ sprintf(msg, "%s %s `%s'",
+ "This client doesn't know how to compose proxy",
+ "authorization information for scheme",
+ HTAAScheme_name(scheme));
+ HTAlert(msg);
+ auth_string = NULL;
+ }
+ } /* switch scheme */
+
+ proxy_setup->retry = NO;
+
+ if (!auth_string)
+ /*
+ ** Signal a failure. - FM
+ */
+ return NULL; /* Added by marca. */
+ if (*auth_string == '\0') {
+ /*
+ ** Signal an abort. - FM
+ */
+ StrAllocCopy(HTAA_composeAuthResult, "");
+ return(HTAA_composeAuthResult);
+ }
+ len = strlen(auth_string) + strlen((char *)HTAAScheme_name(scheme)) + 26;
+ if (!(HTAA_composeAuthResult = (char*)calloc(1, sizeof(char) * len)))
+ outofmem(__FILE__, "HTAA_composeAuth");
+ strcpy(HTAA_composeAuthResult, "Proxy-Authorization: ");
+
+ } else {
+ /*
+ ** Normal WWW authorization.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "Composing Authorization for %s:%d/%s\n",
+ hostname, portnumber, docname);
+
+ if (current_portnumber != portnumber ||
+ !current_hostname || !current_docname ||
+ !hostname || !docname ||
+ 0 != strcmp(current_hostname, hostname) ||
+ 0 != strcmp(current_docname, docname)) {
+
+ retry = NO;
+
+ current_portnumber = portnumber;
+
+ if (hostname)
+ StrAllocCopy(current_hostname, hostname);
+ else
+ FREE(current_hostname);
+
+ if (docname)
+ StrAllocCopy(current_docname, docname);
+ else
+ FREE(current_docname);
+ } else {
+ retry = YES;
+ }
+
+ if (!current_setup || !retry)
+ current_setup = HTAASetup_lookup(hostname, portnumber,
+ docname, IsProxy);
+
+ if (!current_setup)
+ return NULL;
+
+ switch (scheme = HTAA_selectScheme(current_setup)) {
+ case HTAA_BASIC:
+ case HTAA_PUBKEY:
+ auth_string = compose_auth_string(scheme, current_setup, IsProxy);
+ break;
+ case HTAA_KERBEROS_V4:
+ /* OTHER AUTHENTICATION ROUTINES ARE CALLED HERE */
+ default:
+ {
+ char msg[100];
+ sprintf(msg, "%s %s `%s'",
+ "This client doesn't know how to compose",
+ "authoritzation information for scheme",
+ HTAAScheme_name(scheme));
+ HTAlert(msg);
+ auth_string = NULL;
+ }
+ } /* switch scheme */
+
+ current_setup->retry = NO;
+
+ if (!auth_string)
+ /*
+ ** Signal a failure. - FM
+ */
+ return NULL; /* Added by marca. */
+ if (*auth_string == '\0') {
+ /*
+ ** Signal an abort. - FM
+ */
+ StrAllocCopy(HTAA_composeAuthResult, "");
+ return(HTAA_composeAuthResult);
+ }
+
+ len = strlen(auth_string) + strlen((char *)HTAAScheme_name(scheme)) + 20;
+ if (!(HTAA_composeAuthResult = (char*)calloc(1, sizeof(char) * len)))
+ outofmem(__FILE__, "HTAA_composeAuth");
+ strcpy(HTAA_composeAuthResult, "Authorization: ");
+ }
+
+ strcat(HTAA_composeAuthResult, HTAAScheme_name(scheme));
+ strcat(HTAA_composeAuthResult, " ");
+ strcat(HTAA_composeAuthResult, auth_string);
+ return HTAA_composeAuthResult;
+}
+
+/* BROWSER PUBLIC HTAA_shouldRetryWithAuth()
+**
+** DETERMINES IF WE SHOULD RETRY THE SERVER
+** WITH AUTHORIZATION
+** (OR IF ALREADY RETRIED, WITH A DIFFERENT
+** USERNAME AND/OR PASSWORD (IF MISSPELLED))
+** ON ENTRY:
+** start_of_headers is the first block already read from socket,
+** but status line skipped; i.e. points to the
+** start of the header section.
+** length is the remaining length of the first block.
+** soc is the socket to read the rest of server reply.
+** IsProxy should be TRUE if this is a proxy.
+**
+** This function should only be called when
+** server has replied with a 401 (Unauthorized)
+** status code.
+** ON EXIT:
+** returns YES, if connection should be retried.
+** The node containing all the necessary
+** information is
+** * either constructed if it does not exist
+** * or password is reset to NULL to indicate
+** that username and password should be
+** reprompted when composing Authorization:
+** field (in function HTAA_composeAuth()).
+** NO, otherwise.
+*/
+PUBLIC BOOL HTAA_shouldRetryWithAuth ARGS5(
+ char *, start_of_headers,
+ int, length,
+ void *, handle,
+ int, soc,
+ BOOL, IsProxy)
+{
+ HTAAScheme scheme;
+ char *line = NULL;
+ int num_schemes = 0;
+ HTList *valid_schemes = HTList_new();
+ HTAssocList **scheme_specifics = NULL;
+ char *template = NULL;
+ char *temp = NULL;
+
+ /*
+ ** Setup atexit() freeing if not done already. - FM
+ */
+ if (!free_HTAAGlobalsSet) {
+ atexit(free_HTAAGlobals);
+ free_HTAAGlobalsSet = TRUE;
+ }
+
+ /*
+ ** Read server reply header lines
+ */
+ if (TRACE)
+ fprintf(stderr, "Server reply header lines:\n");
+
+ HTAA_setupReader(start_of_headers, length, handle, soc);
+ while (NULL != (line = HTAA_getUnfoldedLine()) && *line != '\0') {
+ if (TRACE)
+ fprintf(stderr, "%s\n", line);
+
+ if (strchr(line, ':')) { /* Valid header line */
+
+ char *p = line;
+ char *fieldname = HTNextField(&p);
+ char *arg1 = HTNextField(&p);
+ char *args = p;
+
+ if ((IsProxy &&
+ 0==strcasecomp(fieldname, "Proxy-Authenticate:")) ||
+ (!IsProxy &&
+ 0==strcasecomp(fieldname, "WWW-Authenticate:"))) {
+ if (!(arg1 && *arg1 && args && *args)) {
+ temp = (char *)calloc(1, strlen(line) +
+ (arg1 ? strlen(arg1) : 0) +
+ (args ? strlen(args) : 0) + 24);
+ if (!temp)
+ outofmem(__FILE__, "HTAA_shouldRetryWithAuth");
+ sprintf(temp, "Invalid header '%s%s%s%s%s'", line,
+ ((arg1 && *arg1) ? " " : ""),
+ ((arg1 && *arg1) ? arg1 : ""),
+ ((args && *args) ? " " : ""),
+ ((args && *args) ? args : ""));
+ HTAlert(temp);
+ FREE(temp);
+ }
+ else if (HTAA_UNKNOWN != (scheme = HTAAScheme_enum(arg1))) {
+ HTList_addObject(valid_schemes, (void*)scheme);
+ if (!scheme_specifics) {
+ int i;
+ scheme_specifics = (HTAssocList**)
+ calloc(1, HTAA_MAX_SCHEMES * sizeof(HTAssocList*));
+ if (!scheme_specifics)
+ outofmem(__FILE__, "HTAA_shouldRetryWithAuth");
+ for (i=0; i < HTAA_MAX_SCHEMES; i++)
+ scheme_specifics[i] = NULL;
+ }
+ scheme_specifics[scheme] = HTAA_parseArgList(args);
+ num_schemes++;
+ }
+ else if (TRACE) {
+ fprintf(stderr, "Unknown scheme `%s' %s\n",
+ (arg1 ? arg1 : "(null)"),
+ (IsProxy ?
+ "in Proxy-Authenticate: field" :
+ "in WWW-Authenticate: field"));
+ }
+ }
+
+ else if (!IsProxy &&
+ 0==strcasecomp(fieldname, "WWW-Protection-Template:")) {
+ if (TRACE)
+ fprintf(stderr, "Protection template set to `%s'\n", arg1);
+ StrAllocCopy(template, arg1);
+ }
+
+ } /* if a valid header line */
+ else if (TRACE) {
+ fprintf(stderr, "Invalid header line `%s' ignored\n", line);
+ } /* else invalid header line */
+
+ FREE(line);
+ } /* while header lines remain */
+ FREE(line);
+
+
+ /*
+ ** So should we retry with authorization?
+ */
+ if (IsProxy) {
+ if (num_schemes == 0) {
+ /*
+ ** No proxy authorization valid
+ */
+ proxy_setup = NULL;
+ return NO;
+ }
+ /*
+ ** Doing it for proxy. -AJL
+ */
+ if (proxy_setup && proxy_setup->server) {
+ /*
+ ** We have already tried with proxy authorization.
+ ** Either we don't have access or username or
+ ** password was misspelled.
+ **
+ ** Update scheme-specific parameters
+ ** (in case they have expired by chance).
+ */
+ HTAASetup_updateSpecifics(proxy_setup, scheme_specifics);
+
+ if (NO == HTConfirm("Authorization failed. Retry?")) {
+ proxy_setup = NULL;
+ return NO;
+ } else {
+ /*
+ ** Re-ask username+password (if misspelled).
+ */
+ proxy_setup->retry = YES;
+ return YES;
+ }
+ } else {
+ /*
+ ** proxy_setup == NULL, i.e. we have a
+ ** first connection to a protected server or
+ ** the server serves a wider set of documents
+ ** than we expected so far.
+ */
+ HTAAServer *server = HTAAServer_lookup(proxy_hostname,
+ proxy_portnumber,
+ IsProxy);
+ if (!server) {
+ server = HTAAServer_new(proxy_hostname,
+ proxy_portnumber,
+ IsProxy);
+ }
+ if (!template) /* Proxy matches everything -AJL */
+ StrAllocCopy(template, "*");
+ proxy_setup = HTAASetup_new(server,
+ template,
+ valid_schemes,
+ scheme_specifics);
+ FREE(template);
+
+ HTAlert("Proxy authorization required -- retrying");
+ return YES;
+ }
+ /* Never reached */
+ }
+ /*
+ ** Normal WWW authorization.
+ */
+ if (num_schemes == 0) {
+ /*
+ ** No authorization valid.
+ */
+ current_setup = NULL;
+ return NO;
+ }
+ if (current_setup && current_setup->server) {
+ /*
+ ** So we have already tried with WWW authorization.
+ ** Either we don't have access or username or
+ ** password was misspelled.
+ **
+ ** Update scheme-specific parameters
+ ** (in case they have expired by chance).
+ */
+ HTAASetup_updateSpecifics(current_setup, scheme_specifics);
+
+ if (NO == HTConfirm("Authorization failed. Retry?")) {
+ current_setup = NULL;
+ return NO;
+ } else {
+ /*
+ ** Re-ask username+password (if misspelled).
+ */
+ current_setup->retry = YES;
+ return YES;
+ }
+ } else {
+ /*
+ ** current_setup == NULL, i.e. we have a
+ ** first connection to a protected server or
+ ** the server serves a wider set of documents
+ ** than we expected so far.
+ */
+ HTAAServer *server = HTAAServer_lookup(current_hostname,
+ current_portnumber,
+ IsProxy);
+ if (!server) {
+ server = HTAAServer_new(current_hostname,
+ current_portnumber,
+ IsProxy);
+ }
+ if (!template)
+ template = HTAA_makeProtectionTemplate(current_docname);
+ current_setup = HTAASetup_new(server,
+ template,
+ valid_schemes,
+ scheme_specifics);
+ FREE(template);
+
+ HTAlert("Access without authorization denied -- retrying");
+ return YES;
+ }
+ /* Never reached */
+}
+
+/*
+** This function clears all authorization information by
+** invoking the free_HTAAGlobals() function, which normally
+** is invoked at exit. It allows a browser command to do
+** this at any time, for example, if the user is leaving
+** the terminal for a period of time, but does not want
+** to end the current session. - FM
+*/
+PUBLIC void HTClearHTTPAuthInfo NOARGS
+{
+ /*
+ ** Need code to check cached documents against the
+ ** protention templates, and do something to ensure
+ ** that any protected documents no longer can be
+ ** accessed without a new retrieval. - FM
+ */
+
+ /*
+ ** Now free all of the authorization info, and
+ ** reset the free_HTAAGlobalsSet flag. - FM
+ */
+ free_HTAAGlobals();
+ free_HTAAGlobalsSet = FALSE;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.h
new file mode 100644
index 00000000000..80da3e6e330
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAABrow.h
@@ -0,0 +1,150 @@
+/* BROWSER SIDE ACCESS AUTHORIZATION MODULE
+
+ This module is the browser side interface to Access Authorization (AA) package. It
+ contains code only for browser.
+
+ Important to know about memory allocation:
+
+ Routines in this module use dynamic allocation, but free automatically all the memory
+ reserved by them.
+
+ Therefore the caller never has to (and never should) free() any object returned by
+ these functions.
+
+ Therefore also all the strings returned by this package are only valid until the next
+ call to the same function is made. This approach is selected, because of the nature of
+ access authorization: no string returned by the package needs to be valid longer than
+ until the next call.
+
+ This also makes it easy to plug the AA package in: you don't have to ponder whether to
+ free()something here or is it done somewhere else (because it is always done somewhere
+ else).
+
+ The strings that the package needs to store are copied so the original strings given as
+ parameters to AA functions may be freed or modified with no side effects.
+
+ Also note:The AA package does not free() anything else than what it has itself
+ allocated.
+
+ */
+
+#ifndef HTAABROW_H
+#define HTAABROW_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h" /* BOOL, PARAMS, ARGS */
+#endif /* HTUTILS_H */
+#include "HTAAUtil.h" /* Common parts of AA */
+
+
+#ifdef SHORT_NAMES
+#define HTAAcoAu HTAA_composeAuth
+#define HTAAsRWA HTAA_shouldRetryWithAuth
+#endif /*SHORT_NAMES*/
+
+/*
+
+Routines for Browser Side Recording of AA Info
+
+ Most of the browser-side AA is done by the following two functions (which are called
+ from file HTTP.c so the browsers using libwww only need to be linked with the new
+ library and not be changed at all):
+
+ HTAA_composeAuth() composes the Authorization: line contents, if the AA package
+ thinks that the given document is protected. Otherwise this function returns NULL.
+ This function also calls the functions HTPrompt(),HTPromptPassword() and HTConfirm()
+ to get the username, password and some confirmation from the user.
+
+ HTAA_shouldRetryWithAuth() determines whether to retry the request with AA or with a
+ new AA (in case username or password was misspelled).
+
+ */
+
+/* PUBLIC HTAA_composeAuth()
+**
+** COMPOSE THE ENTIRE AUTHORIZATION HEADER LINE IF WE
+** ALREADY KNOW, THAT THE HOST MIGHT REQUIRE AUTHORIZATION
+**
+** ON ENTRY:
+** hostname is the hostname of the server.
+** portnumber is the portnumber in which the server runs.
+** docname is the pathname of the document (as in URL)
+**
+** ON EXIT:
+** returns NULL, if no authorization seems to be needed, or
+** if it is the entire Authorization: line, e.g.
+**
+** "Authorization: basic username:password"
+**
+** As usual, this string is automatically freed.
+*/
+extern char *HTAA_composeAuth PARAMS((
+ CONST char * hostname,
+ CONST int portnumber,
+ CONST char * docname,
+ BOOL IsProxy));
+
+
+/* BROWSER PUBLIC HTAA_shouldRetryWithAuth()
+**
+** DETERMINES IF WE SHOULD RETRY THE SERVER
+** WITH AUTHORIZATION
+** (OR IF ALREADY RETRIED, WITH A DIFFERENT
+** USERNAME AND/OR PASSWORD (IF MISSPELLED))
+** ON ENTRY:
+** start_of_headers is the first block already read from socket,
+** but status line skipped; i.e. points to the
+** start of the header section.
+** length is the remaining length of the first block.
+** soc is the socket to read the rest of server reply.
+**
+** This function should only be called when
+** server has replied with a 401 (Unauthorized)
+** status code.
+** ON EXIT:
+** returns YES, if connection should be retried.
+** The node containing all the necessary
+** information is
+** * either constructed if it does not exist
+** * or password is reset to NULL to indicate
+** that username and password should be
+** reprompted when composing Authorization:
+** field (in function HTAA_composeAuth()).
+** NO, otherwise.
+*/
+extern BOOL HTAA_shouldRetryWithAuth PARAMS((
+ char * start_of_headers,
+ int length,
+ void * handle,
+ int soc,
+ BOOL IsProxy));
+
+/*
+** Function to allow clearing of all Authorization info
+** via a browser command. - FM
+*/
+extern void HTClearHTTPAuthInfo NOPARAMS;
+
+/*
+
+Enabling Gateway httpds to Forward Authorization
+
+ These functions should only be called from daemon code, and HTAAForwardAuth_reset()
+ must be called before the next request is handled to make sure that authorization
+ string isn't cached in daemon so that other people can access private files using
+ somebody elses previous authorization information.
+
+ */
+
+extern void HTAAForwardAuth_set PARAMS((
+ CONST char * scheme_name,
+ CONST char * scheme_specifics));
+extern void HTAAForwardAuth_reset NOPARAMS;
+/*
+
+ */
+
+#endif /* NOT HTAABROW_H */
+/*
+
+ End of file HTAABrow.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.c
new file mode 100644
index 00000000000..a55b2f899c4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.c
@@ -0,0 +1,210 @@
+
+/* MODULE HTAAFile.c
+** FILE ROUTINES FOR AUTHENTICATION
+** (PASSWD AND GROUP FILES) AND
+** ACCESS CONTROL LIST (.www_acl)
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+**
+**
+** BUGS:
+**
+**
+*/
+
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+#include "tcp.h" /* Macro FROMASCII() */
+/*#include <stdio.h> included by HTUtils.h -- FM *//* FILE */
+#include <string.h>
+#include "HTAAUtil.h" /* Common utilities used in AA */
+#include "HTAAFile.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+#define SPACE ' '
+#define TAB '\t'
+
+
+
+/* PUBLIC HTAAFile_nextRec()
+** GO TO THE BEGINNING OF THE NEXT RECORD
+** ON ENTRY:
+** fp is the file from which records are read from.
+**
+** ON EXIT:
+** returns nothing. File read pointer is located at the beginning
+** of the next record. Handles continuation lines
+** (lines ending in comma indicate a following
+** continuation line).
+**
+*/
+PUBLIC void HTAAFile_nextRec ARGS1(FILE *, fp)
+{
+ int ch = getc(fp);
+ int last = (char)0;
+
+ do {
+ while (ch != EOF && ch != CR && ch != LF) {
+ if (ch != ' ' && ch != '\t')
+ last = ch; /* Last non-whitespace */
+ ch = getc(fp); /* Skip until end-of-line */
+ }
+ while (ch != EOF &&
+ (ch == CR || ch == LF))/*Skip carriage returns and linefeeds*/
+ ch = getc(fp);
+ if (ch != EOF)
+ ungetc(ch, fp);
+ } while (last == ',' && ch != EOF); /* Skip also continuation lines */
+}
+
+
+/* PRIVATE read_item()
+** READ AN ITEM FROM A PASSWORD, GROUP
+** OR ACCESS CONTROL LIST FILE
+** i.e. either a field, or a list item.
+** ON ENTRY:
+** fp is the file to read the characters from
+** contents is the character array to put the characters
+** reading_list if TRUE, read a list item (ends either in
+** acomma or acolon),
+** if FALSE, read a field (ends in acolon).
+** max_len is the maximum number of characters that may
+** be read (i.e. the size of dest minus one for
+** terminating null).
+** ON EXIT:
+** returns the terminating character
+** (i.e. either separator or CR or LF or EOF).
+** contents contains a null-terminated string representing
+** the read field.
+** NOTE 1:
+** Ignores leading and trailing blanks and tabs.
+** NOTE 2:
+** If the item is more than max_len characters
+** long, the rest of the characters in that item
+** are ignored. However, contents is always
+** null-terminated!
+*/
+PRIVATE int read_item ARGS4(FILE *, fp,
+ char *, contents,
+ BOOL, reading_list,
+ int, max_len)
+{
+ char * dest = contents;
+ char * end = contents;
+ int cnt = 0;
+ int ch = getc(fp);
+
+ while (SPACE == ch || TAB == ch) /* Skip spaces and tabs */
+ ch = getc(fp);
+
+ while (ch != FIELD_SEPARATOR &&
+ (!reading_list || ch != LIST_SEPARATOR) &&
+ ch != CR && ch != LF && ch != EOF && cnt < max_len) {
+ *(dest++) = ch;
+ cnt++;
+ if (ch != SPACE && ch != TAB)
+ end = dest;
+ ch = getc(fp);
+ } /* while not eol or eof or too many read */
+
+ if (cnt == max_len) {
+ /* If the field was too long (or exactly maximum) ignore the rest */
+ while (ch != FIELD_SEPARATOR &&
+ (!reading_list || ch != LIST_SEPARATOR) &&
+ ch != CR && ch != LF && ch != EOF)
+ ch = getc(fp);
+ }
+
+ if (ch == CR || ch == LF)
+ ungetc(ch, fp); /* Push back the record separator (NL or LF) */
+
+ /* Terminate the string, truncating trailing whitespace off.
+ ** Otherwise (if whitespace would be included), here would
+ ** be *dest='\0'; and cnt -= ... would be left out.
+ */
+ *end = '\0';
+ cnt -= dest-end;
+
+ return ch; /* Return the terminating character */
+}
+
+
+
+/* PUBLIC HTAAFile_readField()
+** READ A FIELD FROM A PASSWORD, GROUP
+** OR ACCESS CONTROL LIST FILE
+** i.e. an item terminated by colon,
+** end-of-line, or end-of-file.
+** ON ENTRY:
+** fp is the file to read the characters from
+** contents is the character array to put the characters
+** max_len is the maximum number of characters that may
+** be read (i.e. the size of dest minus one for
+** terminating null).
+** ON EXIT:
+** returns the terminating character
+** (i.e. either separator or CR or LF or EOF).
+** contents contains a null-terminated string representing
+** the read field.
+** NOTE 1:
+** Ignores leading and trailing blanks and tabs.
+** NOTE 2:
+** If the field is more than max_len characters
+** long, the rest of the characters in that item
+** are ignored. However, contents is always
+** null-terminated!
+*/
+PUBLIC int HTAAFile_readField ARGS3(FILE *, fp,
+ char *, contents,
+ int, max_len)
+{
+ return read_item(fp, contents, NO, max_len);
+}
+
+
+
+
+/* PUBLIC HTAAFile_readList()
+**
+** READ A LIST OF STRINGS SEPARATED BY COMMAS
+** (FROM A GROUP OR ACCESS CONTROL LIST FILE)
+** ON ENTRY:
+** fp is a pointer to the input file.
+** result is the list to which append the read items.
+** max_len is the maximum number of characters in each
+** list entry (extra characters are ignored).
+** ON EXIT:
+** returns the number of items read.
+**
+*/
+PUBLIC int HTAAFile_readList ARGS3(FILE *, fp,
+ HTList *, result,
+ int, max_len)
+{
+ char *item = NULL;
+ int terminator;
+ int cnt = 0;
+
+ do {
+ if (!item && !(item = (char*)malloc(max_len+1)))
+ outofmem(__FILE__, "HTAAFile_readList");
+ terminator = read_item(fp, item, YES, max_len);
+ if (strlen(item) > 0) {
+ cnt++;
+ HTList_addObject(result, (void*)item);
+ item = NULL;
+ }
+ } while (terminator != FIELD_SEPARATOR &&
+ terminator != CR && terminator != LF &&
+ terminator != EOF);
+
+ FREE(item); /* This was not needed */
+ return cnt;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.h
new file mode 100644
index 00000000000..f6f8ac5053e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAFile.h
@@ -0,0 +1,126 @@
+/* FILE ROUTINES FOR ACCESS AUTHORIZATION PACKAGE
+
+ This module implements the routines used for accessing (and parsing) the files used in
+ the access authorization:
+
+ password file
+
+ group file
+
+ access control list (ACL) file
+
+ */
+
+
+#ifndef HTAAFILE_H
+#define HTAAFILE_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h" /* BOOL, PARAMS, ARGS */
+#endif /* HTUTILS_H */
+/*#include <stdio.h> included by HTUtils.h -- FM *//* FILE */
+#include "HTList.h" /* HTList */
+
+#ifdef SHORT_NAMES
+#define HTAAFnRe HTAAFile_nextRec
+#define HTAAFrFi HTAAFile_readField
+#define HTAAFrLi HTAAFile_readList
+#endif /*SHORT_NAMES*/
+
+
+/* Used field separators */
+
+#define FIELD_SEPARATOR ':' /* Used to separate fields */
+#define LIST_SEPARATOR ',' /* Used to separate items in a list */
+ /* in group and ALC files. */
+
+/*
+
+Naming conventions
+
+ Record is an entire line in file.
+
+ Field is an entity separated by colons and/or by end-of-line.
+
+ List is a field in which there are items separated by commas.
+
+Record-oriented Read Routines
+
+ Password, group and ACL are internally read in by the following functions:
+
+ HTAAFile_nextRec() skips to the beginning of the next record (must be called even
+ after the last field of a record is read to proceed to the next
+ record).
+
+ HTAAFile_readField() reads a field (separated by colons).
+
+ HTAAFile_readList() reads a field containing a comma-separated list of items.
+
+ */
+
+/* PUBLIC HTAAFile_nextRec()
+** GO TO THE BEGINNING OF THE NEXT RECORD
+** ON ENTRY:
+** fp is the file from which records are read from.
+**
+** ON EXIT:
+** returns nothing. File read pointer is located at the beginning
+** of the next record.
+**
+*/
+PUBLIC void HTAAFile_nextRec PARAMS((FILE * fp));
+
+
+/* PUBLIC HTAAFile_readField()
+** READ A FIELD FROM A PASSWORD, GROUP
+** OR ACCESS CONTROL LIST FILE
+** i.e. an item terminated by colon,
+** end-of-line, or end-of-file.
+** ON ENTRY:
+** fp is the file to read the characters from
+** contents is the character array to put the characters
+** max_len is the maximum number of characters that may
+** be read (i.e. the size of dest minus one for
+** terminating null).
+** ON EXIT:
+** returns the terminating character
+** (i.e. either separator or CR or LF or EOF).
+** contents contains a null-terminated string representing
+** the read field.
+** NOTE 1:
+** Ignores leading and trailing blanks and tabs.
+** NOTE 2:
+** If the field is more than max_len characters
+** long, the rest of the characters in that item
+** are ignored. However, contents is always
+** null-terminated!
+*/
+PUBLIC int HTAAFile_readField PARAMS((FILE * fp,
+ char * contents,
+ int max_len));
+
+
+/* PUBLIC HTAAFile_readList()
+**
+** READ A LIST OF STRINGS SEPARATED BY COMMAS
+** (FROM A GROUP OR ACCESS CONTROL LIST FILE)
+** ON ENTRY:
+** fp is a pointer to the input file.
+** result is the list to which append the read items.
+** max_len is the maximum number of characters in each
+** list entry (extra characters are ignored).
+** ON EXIT:
+** returns the number of items read.
+**
+*/
+PUBLIC int HTAAFile_readList PARAMS((FILE * fp,
+ HTList * result,
+ int max_len));
+/*
+
+ */
+
+#endif /* not HTAAFILE_H */
+/*
+
+ End of file HTAAFile.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.c
new file mode 100644
index 00000000000..9b40c3beee3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.c
@@ -0,0 +1,598 @@
+
+/* MODULE HTAAProt.c
+** PROTECTION FILE PARSING MODULE
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+** MD Mark Donszelmann duns@vxdeop.cern.ch
+**
+** HISTORY:
+** 20 Oct 93 AL Now finds uid/gid for nobody/nogroup by name
+** (doesn't use default 65534 right away).
+** Also understands negative uids/gids.
+** 14 Nov 93 MD Added VMS compatibility
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+
+#include <string.h>
+#ifndef VMS
+#ifndef NOUSERS
+#include <pwd.h> /* Unix password file routine: getpwnam() */
+#include <grp.h> /* Unix group file routine: getgrnam() */
+#endif /* NOUSERS */
+#endif /* not VMS */
+
+#include "HTAAUtil.h"
+#include "HTAAFile.h"
+#include "HTLex.h" /* Lexical analysor */
+#include "HTAssoc.h" /* Association list */
+#include "HTAAProt.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+/*
+** Protection setup caching
+*/
+typedef struct {
+ char * prot_filename;
+ HTAAProt * prot;
+} HTAAProtCache;
+
+PRIVATE HTList * prot_cache = NULL; /* Protection setup cache. */
+PRIVATE HTAAProt *default_prot = NULL; /* Default protection. */
+PRIVATE HTAAProt *current_prot = NULL; /* Current protection mode */
+ /* which is set up by callbacks */
+ /* from the rule system when */
+ /* a "protect" rule is matched. */
+
+
+/* PRIVATE isNumber()
+** DOES A CHARACTER STRING REPRESENT A NUMBER
+*/
+PRIVATE BOOL isNumber ARGS1(CONST char *, s)
+{
+ CONST char *cur = s;
+
+ if (!s || !*s) return NO;
+
+ if (*cur == '-')
+ cur++; /* Allow initial minus sign in a number */
+
+ while (*cur) {
+ if (*cur < '0' || *cur > '9')
+ return NO;
+ cur++;
+ }
+ return YES;
+}
+
+
+#if defined (VMS) || defined (NOUSERS)
+/* PUBLIC HTAA_getUidName()
+** GET THE USER ID NAME (VMS ONLY)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the user name
+** Default is "" (nobody).
+*/
+PUBLIC char * HTAA_getUidName NOARGS
+{
+ if (current_prot && current_prot->uid_name
+ && (0 != strcmp(current_prot->uid_name,"nobody")) )
+ return(current_prot->uid_name);
+ else
+ return("");
+}
+
+/* PUBLIC HTAA_getFileName
+** GET THE FILENAME (VMS ONLY)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the filename
+*/
+PUBLIC char * HTAA_getFileName NOARGS
+{
+ if (current_prot && current_prot->filename)
+ return(current_prot->filename);
+ else
+ return("");
+}
+
+#else /* not VMS */
+
+/* PUBLIC HTAA_getUid()
+** GET THE USER ID TO CHANGE THE PROCESS UID TO
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the uid number to give to setuid() system call.
+** Default is 65534 (nobody).
+*/
+PUBLIC int HTAA_getUid NOARGS
+{
+ struct passwd *pw = NULL;
+
+ if (current_prot && current_prot->uid_name) {
+ if (isNumber(current_prot->uid_name)) {
+ if (NULL != (pw = getpwuid(atoi(current_prot->uid_name)))) {
+ if (TRACE) fprintf(stderr,
+ "%s(%s) returned (%s:%s:%d:%d:...)\n",
+ "HTAA_getUid: getpwuid",
+ current_prot->uid_name,
+ pw->pw_name, pw->pw_passwd,
+ pw->pw_uid, pw->pw_gid);
+ return pw->pw_uid;
+ }
+ }
+ else { /* User name (not a number) */
+ if (NULL != (pw = getpwnam(current_prot->uid_name))) {
+ if (TRACE) fprintf(stderr, "%s(\"%s\") %s (%s:%s:%d:%d:...)\n",
+ "HTAA_getUid: getpwnam",
+ current_prot->uid_name, "returned",
+ pw->pw_name, pw->pw_passwd,
+ pw->pw_uid, pw->pw_gid);
+ return pw->pw_uid;
+ }
+ }
+ }
+ /*
+ ** Ok, then let's get uid for nobody.
+ */
+ if (NULL != (pw = getpwnam("nobody"))) {
+ if (TRACE) fprintf(stderr, "HTAA_getUid: Uid for `nobody' is %d\n",
+ pw->pw_uid);
+ return pw->pw_uid;
+ }
+ /*
+ ** Ok, then use default.
+ */
+ return 65534; /* nobody */
+}
+
+
+/* PUBLIC HTAA_getGid()
+** GET THE GROUP ID TO CHANGE THE PROCESS GID TO
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the uid number to give to setgid() system call.
+** Default is 65534 (nogroup).
+*/
+PUBLIC int HTAA_getGid NOARGS
+{
+ struct group *gr = NULL;
+
+ if (current_prot && current_prot->gid_name) {
+ if (isNumber(current_prot->gid_name)) {
+ if (NULL != (gr = getgrgid(atoi(current_prot->gid_name)))) {
+#ifndef __EMX__ /* no gr_passwd */
+ if (TRACE) fprintf(stderr,
+ "%s(%s) returned (%s:%s:%d:...)\n",
+ "HTAA_getGid: getgrgid",
+ current_prot->gid_name,
+ gr->gr_name, gr->gr_passwd, gr->gr_gid);
+#endif
+ return gr->gr_gid;
+ }
+ }
+ else { /* Group name (not number) */
+ if (NULL != (gr = getgrnam(current_prot->gid_name))) {
+#ifndef __EMX__ /* no gr_passwd */
+ if (TRACE) fprintf(stderr,
+ "%s(\"%s\") returned (%s:%s:%d:...)\n",
+ "HTAA_getGid: getgrnam",
+ current_prot->gid_name,
+ gr->gr_name, gr->gr_passwd, gr->gr_gid);
+#endif
+ return gr->gr_gid;
+ }
+ }
+ }
+ /*
+ ** Ok, then let's get gid for nogroup.
+ */
+ if (NULL != (gr = getgrnam("nogroup"))) {
+ if (TRACE) fprintf(stderr, "HTAA_getGid: Gid for `nogroup' is %d\n",
+ gr->gr_gid);
+ return gr->gr_gid;
+ }
+ /*
+ ** Ok, then use default.
+ */
+ return 65534; /* nogroup */
+}
+#endif /* not VMS */
+
+
+/* PRIVATE HTAA_setIds()
+** SET UID AND GID (AS NAMES OR NUMBERS)
+** TO HTAAProt STRUCTURE
+** ON ENTRY:
+** prot destination.
+** ids is a string like "james.www" or "1422.69" etc.
+** giving uid and gid.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PRIVATE void HTAA_setIds ARGS2(HTAAProt *, prot,
+ CONST char *, ids)
+{
+ if (ids) {
+ char *local_copy = NULL;
+ char *point;
+
+ StrAllocCopy(local_copy, ids);
+ point = strchr(local_copy, '.');
+ if (point) {
+ *(point++) = (char)0;
+ StrAllocCopy(prot->gid_name, point);
+ }
+ else {
+ StrAllocCopy(prot->gid_name, "nogroup");
+ }
+ StrAllocCopy(prot->uid_name, local_copy);
+ FREE(local_copy);
+ }
+ else {
+ StrAllocCopy(prot->uid_name, "nobody");
+ StrAllocCopy(prot->gid_name, "nogroup");
+ }
+}
+
+
+/* PRIVATE HTAA_parseProtFile()
+** PARSE A PROTECTION SETUP FILE AND
+** PUT THE RESULT IN A HTAAProt STRUCTURE
+** ON ENTRY:
+** prot destination structure.
+** fp open protection file.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PRIVATE void HTAA_parseProtFile ARGS2(HTAAProt *, prot,
+ FILE *, fp)
+{
+ if (prot && fp) {
+ LexItem lex_item;
+ char *fieldname = NULL;
+
+ while (LEX_EOF != (lex_item = lex(fp))) {
+
+ while (lex_item == LEX_REC_SEP) /* Ignore empty lines */
+ lex_item = lex(fp);
+
+ if (lex_item == LEX_EOF) /* End of file */
+ break;
+
+ if (lex_item == LEX_ALPH_STR) { /* Valid setup record */
+
+ StrAllocCopy(fieldname, HTlex_buffer);
+
+ if (LEX_FIELD_SEP != (lex_item = lex(fp)))
+ unlex(lex_item); /* If someone wants to use colon */
+ /* after field name it's ok, but */
+ /* not required. Here we read it.*/
+
+ if (0==strncasecomp(fieldname, "Auth", 4)) {
+ lex_item = lex(fp);
+ while (lex_item == LEX_ALPH_STR) {
+ HTAAScheme scheme = HTAAScheme_enum(HTlex_buffer);
+ if (scheme != HTAA_UNKNOWN) {
+ if (!prot->valid_schemes)
+ prot->valid_schemes = HTList_new();
+ HTList_addObject(prot->valid_schemes,(void*)scheme);
+ if (TRACE) fprintf(stderr, "%s %s `%s'\n",
+ "HTAA_parseProtFile: valid",
+ "authentication scheme:",
+ HTAAScheme_name(scheme));
+ }
+ else if (TRACE) fprintf(stderr, "%s %s `%s'\n",
+ "HTAA_parseProtFile: unknown",
+ "authentication scheme:",
+ HTlex_buffer);
+
+ if (LEX_ITEM_SEP != (lex_item = lex(fp)))
+ break;
+ /*
+ ** Here lex_item == LEX_ITEM_SEP; after item separator
+ ** it is ok to have one or more newlines (LEX_REC_SEP)
+ ** and they are ignored (continuation line).
+ */
+ do {
+ lex_item = lex(fp);
+ } while (lex_item == LEX_REC_SEP);
+ } /* while items in list */
+ } /* if "Authenticate" */
+
+ else if (0==strncasecomp(fieldname, "mask", 4)) {
+ prot->mask_group = HTAA_parseGroupDef(fp);
+ lex_item=LEX_REC_SEP; /*groupdef parser read this already*/
+ if (TRACE) {
+ if (prot->mask_group) {
+ fprintf(stderr,
+ "HTAA_parseProtFile: Mask group:\n");
+ HTAA_printGroupDef(prot->mask_group);
+ } else fprintf(stderr, "HTAA_parseProtFile: %s\n",
+ "Mask group syntax error");
+ }
+ } /* if "Mask" */
+
+ else { /* Just a name-value pair, put it to assoclist */
+
+ if (LEX_ALPH_STR == (lex_item = lex(fp))) {
+ if (!prot->values)
+ prot->values = HTAssocList_new();
+ HTAssocList_add(prot->values, fieldname, HTlex_buffer);
+ lex_item = lex(fp); /* Read record separator */
+ if (TRACE) fprintf(stderr,
+ "%s `%s' bound to value `%s'\n",
+ "HTAA_parseProtFile: Name",
+ fieldname, HTlex_buffer);
+ }
+ } /* else name-value pair */
+
+ } /* if valid field */
+
+ if (lex_item != LEX_EOF && lex_item != LEX_REC_SEP) {
+ if (TRACE) fprintf(stderr, "%s %s %d (that line ignored)\n",
+ "HTAA_parseProtFile: Syntax error",
+ "in protection setup file at line",
+ HTlex_line);
+ do {
+ lex_item = lex(fp);
+ } while (lex_item != LEX_EOF && lex_item != LEX_REC_SEP);
+ } /* if syntax error */
+ } /* while not end-of-file */
+ FREE(fieldname);
+ } /* if valid parameters */
+}
+
+
+/* PRIVATE HTAAProt_new()
+** ALLOCATE A NEW HTAAProt STRUCTURE AND
+** INITIALIZE IT FROM PROTECTION SETUP FILE
+** ON ENTRY:
+** cur_docname current filename after rule translations.
+** prot_filename protection setup file name.
+** If NULL, not an error.
+** ids Uid and gid names or numbers,
+** examples:
+** james ( <=> james.nogroup)
+** .www ( <=> nobody.www)
+** james.www
+** james.69
+** 1422.69
+** 1422.www
+**
+** May be NULL, defaults to nobody.nogroup.
+** Should be NULL, if prot_file is NULL.
+**
+** ON EXIT:
+** returns returns a new and initialized protection
+** setup structure.
+** If setup file is already read in (found
+** in cache), only sets uid_name and gid
+** fields, and returns that.
+*/
+PRIVATE HTAAProt *HTAAProt_new ARGS3(CONST char *, cur_docname,
+ CONST char *, prot_filename,
+ CONST char *, ids)
+{
+ HTList *cur = prot_cache;
+ HTAAProtCache *cache_item = NULL;
+ HTAAProt *prot;
+ FILE *fp;
+
+ if (!prot_cache)
+ prot_cache = HTList_new();
+
+ while (NULL != (cache_item = (HTAAProtCache*)HTList_nextObject(cur))) {
+ if (!strcmp(cache_item->prot_filename, prot_filename))
+ break;
+ }
+ if (cache_item) {
+ prot = cache_item->prot;
+ if (TRACE) fprintf(stderr, "%s `%s' already in cache\n",
+ "HTAAProt_new: Protection file", prot_filename);
+ } else {
+ if (TRACE) fprintf(stderr,
+ "HTAAProt_new: Loading protection file `%s'\n",
+ prot_filename);
+
+ if (!(prot = (HTAAProt*)calloc(1, sizeof(HTAAProt))))
+ outofmem(__FILE__, "HTAAProt_new");
+
+ prot->template = NULL;
+ prot->filename = NULL;
+ prot->uid_name = NULL;
+ prot->gid_name = NULL;
+ prot->valid_schemes = HTList_new();
+ prot->mask_group= NULL; /* Masking disabled by defaults */
+ prot->values = HTAssocList_new();
+
+ if (prot_filename && NULL != (fp = fopen(prot_filename, "r"))) {
+ HTAA_parseProtFile(prot, fp);
+ fclose(fp);
+ if (!(cache_item =
+ (HTAAProtCache*)calloc(1, sizeof(HTAAProtCache))))
+ outofmem(__FILE__, "HTAAProt_new");
+ cache_item->prot = prot;
+ cache_item->prot_filename = NULL;
+ StrAllocCopy(cache_item->prot_filename, prot_filename);
+ HTList_addObject(prot_cache, (void*)cache_item);
+ }
+ else if (TRACE) fprintf(stderr, "HTAAProt_new: %s `%s'\n",
+ "Unable to open protection setup file",
+ (prot_filename ? prot_filename : "(null)"));
+ }
+
+ if (cur_docname)
+ StrAllocCopy(prot->filename, cur_docname);
+ HTAA_setIds(prot, ids);
+
+ return prot;
+}
+
+
+/* PUBLIC HTAA_setDefaultProtection()
+** SET THE DEFAULT PROTECTION MODE
+** (called by rule system when a
+** "defprot" rule is matched)
+** ON ENTRY:
+** cur_docname is the current result of rule translations.
+** prot_filename is the protection setup file (second argument
+** for "defprot" rule, optional)
+** ids contains user and group names separated by
+** a dot, corresponding to the uid
+** gid under which the server should run,
+** default is "nobody.nogroup" (third argument
+** for "defprot" rule, optional; can be given
+** only if protection setup file is also given).
+**
+** ON EXIT:
+** returns nothing.
+** Sets the module-wide variable default_prot.
+*/
+PUBLIC void HTAA_setDefaultProtection ARGS3(CONST char *, cur_docname,
+ CONST char *, prot_filename,
+ CONST char *, ids)
+{
+ default_prot = NULL; /* Not free()'d because this is in cache */
+
+ if (prot_filename) {
+ default_prot = HTAAProt_new(cur_docname, prot_filename, ids);
+ } else {
+ if (TRACE) fprintf(stderr, "%s %s\n",
+ "HTAA_setDefaultProtection: ERROR: Protection file",
+ "not specified (obligatory for DefProt rule)!!\n");
+ }
+}
+
+
+/* PUBLIC HTAA_setCurrentProtection()
+** SET THE CURRENT PROTECTION MODE
+** (called by rule system when a
+** "protect" rule is matched)
+** ON ENTRY:
+** cur_docname is the current result of rule translations.
+** prot_filename is the protection setup file (second argument
+** for "protect" rule, optional)
+** ids contains user and group names separated by
+** a dot, corresponding to the uid
+** gid under which the server should run,
+** default is "nobody.nogroup" (third argument
+** for "protect" rule, optional; can be given
+** only if protection setup file is also given).
+**
+** ON EXIT:
+** returns nothing.
+** Sets the module-wide variable current_prot.
+*/
+PUBLIC void HTAA_setCurrentProtection ARGS3(CONST char *, cur_docname,
+ CONST char *, prot_filename,
+ CONST char *, ids)
+{
+ current_prot = NULL; /* Not free()'d because this is in cache */
+
+ if (prot_filename) {
+ current_prot = HTAAProt_new(cur_docname, prot_filename, ids);
+ } else {
+ if (default_prot) {
+ current_prot = default_prot;
+ HTAA_setIds(current_prot, ids);
+ if (TRACE) fprintf(stderr, "%s %s %s\n",
+ "HTAA_setCurrentProtection: Protection file",
+ "not specified for Protect rule",
+ "-- using default protection");
+ } else {
+ if (TRACE) fprintf(stderr, "%s %s %s\n",
+ "HTAA_setCurrentProtection: ERROR: Protection",
+ "file not specified for Protect rule, and",
+ "default protection is not set!!");
+ }
+ }
+}
+
+
+/* PUBLIC HTAA_getCurrentProtection()
+** GET CURRENT PROTECTION SETUP STRUCTURE
+** (this is set up by callbacks made from
+** the rule system when matching "protect"
+** (and "defprot") rules)
+** ON ENTRY:
+** HTTranslate() must have been called before calling
+** this function.
+**
+** ON EXIT:
+** returns a HTAAProt structure representing the
+** protection setup of the HTTranslate()'d file.
+** This must not be free()'d.
+*/
+PUBLIC HTAAProt *HTAA_getCurrentProtection NOARGS
+{
+ return current_prot;
+}
+
+
+/* PUBLIC HTAA_getDefaultProtection()
+** GET DEFAULT PROTECTION SETUP STRUCTURE
+** AND SET IT TO CURRENT PROTECTION
+** (this is set up by callbacks made from
+** the rule system when matching "defprot"
+** rules)
+** ON ENTRY:
+** HTTranslate() must have been called before calling
+** this function.
+**
+** ON EXIT:
+** returns a HTAAProt structure representing the
+** default protection setup of the HTTranslate()'d
+** file (if HTAA_getCurrentProtection() returned
+** NULL, i.e. if there is no "protect" rule
+** but ACL exists, and we need to know default
+** protection settings).
+** This must not be free()'d.
+** IMPORTANT:
+** As a side-effect this tells the protection system that
+** the file is in fact protected and sets the current
+** protection mode to default.
+*/
+PUBLIC HTAAProt *HTAA_getDefaultProtection NOARGS
+{
+ if (!current_prot) {
+ current_prot = default_prot;
+ default_prot = NULL;
+ }
+ return current_prot;
+}
+
+
+/* SERVER INTERNAL HTAA_clearProtections()
+** CLEAR DOCUMENT PROTECTION MODE
+** (ALSO DEFAULT PROTECTION)
+** (called by the rule system)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns nothing.
+** Frees the memory used by protection information.
+*/
+PUBLIC void HTAA_clearProtections NOARGS
+{
+ current_prot = NULL; /* These are not freed because */
+ default_prot = NULL; /* they are actually in cache. */
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.h
new file mode 100644
index 00000000000..73bb7c454d3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAProt.h
@@ -0,0 +1,231 @@
+/* PROTECTION SETUP FILE
+
+ */
+
+#ifndef HTAAPROT_H
+#define HTAAPROT_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTGroup.h"
+#include "HTAssoc.h"
+
+#ifdef SHORT_NAMES
+#define HTAAgUid HTAA_getUid
+#define HTAAgGid HTAA_getGid
+#define HTAAgDPr HTAA_setDefaultProtection
+#define HTAAsCPr HTAA_setCurrentProtection
+#define HTAAgCPr HTAA_getCurrentProtection
+#define HTAAgDPr HTAA_getDefaultProtection
+#define HTAAclPr HTAA_clearProtections
+#endif /*SHORT_NAMES*/
+/*
+
+Server's Representation of Document (Tree) Protections
+
+ */
+
+typedef struct {
+ char * template; /* Template for this protection */
+ char * filename; /* Current document file */
+ char * uid_name; /* Effective uid (name of it) */
+ char * gid_name; /* Effective gid (name of it) */
+ GroupDef * mask_group; /* Allowed users and IP addresses */
+ HTList * valid_schemes;/* Valid authentication schemes */
+ HTAssocList * values; /* Association list for scheme specific */
+ /* parameters. */
+} HTAAProt;
+/*
+
+Callbacks for rule system
+
+ The following three functioncs are called by the rule system:
+
+ HTAA_clearProtections() when starting to translate a filename
+
+ HTAA_setDefaultProtection() when "defprot" rule is matched
+
+ HTAA_setCurrentProtection() when "protect" rule is matched
+
+ Protection setup files are cached by these functions.
+
+ */
+
+/* PUBLIC HTAA_setDefaultProtection()
+** SET THE DEFAULT PROTECTION MODE
+** (called by rule system when a
+** "defprot" rule is matched)
+** ON ENTRY:
+** cur_docname is the current result of rule translations.
+** prot_filename is the protection setup file (second argument
+** for "defprot" rule, optional)
+** eff_ids contains user and group names separated by
+** a dot, corresponding to the effective uid
+** gid under which the server should run,
+** default is "nobody.nogroup" (third argument
+** for "defprot" rule, optional; can be given
+** only if protection setup file is also given).
+**
+** ON EXIT:
+** returns nothing.
+** Sets the module-wide variable default_prot.
+*/
+PUBLIC void HTAA_setDefaultProtection PARAMS((CONST char * cur_docname,
+ CONST char * prot_filename,
+ CONST char * eff_ids));
+
+
+
+/* PUBLIC HTAA_setCurrentProtection()
+** SET THE CURRENT PROTECTION MODE
+** (called by rule system when a
+** "protect" rule is matched)
+** ON ENTRY:
+** cur_docname is the current result of rule translations.
+** prot_filename is the protection setup file (second argument
+** for "protect" rule, optional)
+** eff_ids contains user and group names separated by
+** a dot, corresponding to the effective uid
+** gid under which the server should run,
+** default is "nobody.nogroup" (third argument
+** for "protect" rule, optional; can be given
+** only if protection setup file is also given).
+**
+** ON EXIT:
+** returns nothing.
+** Sets the module-wide variable current_prot.
+*/
+PUBLIC void HTAA_setCurrentProtection PARAMS((CONST char * cur_docname,
+ CONST char * prot_filename,
+ CONST char * eff_ids));
+
+
+/* SERVER INTERNAL HTAA_clearProtections()
+** CLEAR DOCUMENT PROTECTION MODE
+** (ALSO DEFAULT PROTECTION)
+** (called by the rule system)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns nothing.
+** Frees the memory used by protection information.
+*/
+PUBLIC void HTAA_clearProtections NOPARAMS;
+/*
+
+Getting Protection Settings
+
+ HTAA_getCurrentProtection() returns the current protection mode (if there was a
+ "protect" rule). NULL, if no "protect" rule has been matched.
+
+ HTAA_getDefaultProtection() sets the current protection mode to what it was set to
+ by "defprot" rule and also returns it (therefore after this call also
+ HTAA_getCurrentProtection() returns the same structure.
+
+ */
+
+/* PUBLIC HTAA_getCurrentProtection()
+** GET CURRENT PROTECTION SETUP STRUCTURE
+** (this is set up by callbacks made from
+** the rule system when matching "protect"
+** (and "defprot") rules)
+** ON ENTRY:
+** HTTranslate() must have been called before calling
+** this function.
+**
+** ON EXIT:
+** returns a HTAAProt structure representing the
+** protection setup of the HTTranslate()'d file.
+** This must not be free()'d.
+*/
+PUBLIC HTAAProt *HTAA_getCurrentProtection NOPARAMS;
+
+
+
+/* PUBLIC HTAA_getDefaultProtection()
+** GET DEFAULT PROTECTION SETUP STRUCTURE
+** (this is set up by callbacks made from
+** the rule system when matching "defprot"
+** rules)
+** ON ENTRY:
+** HTTranslate() must have been called before calling
+** this function.
+**
+** ON EXIT:
+** returns a HTAAProt structure representing the
+** default protection setup of the HTTranslate()'d
+** file (if HTAA_getCurrentProtection() returned
+** NULL, i.e. if there is no "protect" rule
+** but ACL exists, and we need to know default
+** protection settings).
+** This must not be free()'d.
+*/
+PUBLIC HTAAProt *HTAA_getDefaultProtection NOPARAMS;
+/*
+
+Get User and Group IDs to Which Set to
+
+ */
+
+#ifndef VMS
+/* PUBLIC HTAA_getUid()
+** GET THE USER ID TO CHANGE THE PROCESS UID TO
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the uid number to give to setuid() system call.
+** Default is 65534 (nobody).
+*/
+PUBLIC int HTAA_getUid NOPARAMS;
+
+
+/* PUBLIC HTAA_getGid()
+** GET THE GROUP ID TO CHANGE THE PROCESS GID TO
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the uid number to give to setgid() system call.
+** Default is 65534 (nogroup).
+*/
+PUBLIC int HTAA_getGid NOPARAMS;
+#endif /* not VMS */
+/*
+
+ For VMS:
+
+ */
+
+#ifdef VMS
+/* PUBLIC HTAA_getUidName()
+** GET THE USER ID NAME (VMS ONLY)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the user name
+** Default is "" (nobody).
+*/
+PUBLIC char * HTAA_getUidName NOPARAMS;
+
+/* PUBLIC HTAA_getFileName
+** GET THE FILENAME (VMS ONLY)
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns the filename
+*/
+PUBLIC char * HTAA_getFileName NOPARAMS;
+#endif /* VMS */
+/*
+
+ */
+
+#endif /* not HTAAPROT_H */
+/*
+
+ End of file HTAAProt.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.c
new file mode 100644
index 00000000000..cb8623d7fd7
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.c
@@ -0,0 +1,686 @@
+
+/* MODULE HTAAServ.c
+** SERVER SIDE ACCESS AUTHORIZATION MODULE
+**
+** Contains the means for checking the user access
+** authorization for a file.
+**
+** IMPORTANT:
+** Routines in this module use dynamic allocation, but free
+** automatically all the memory reserved by them.
+**
+** Therefore the caller never has to (and never should)
+** free() any object returned by these functions.
+**
+** Therefore also all the strings returned by this package
+** are only valid until the next call to the same function
+** is made. This approach is selected, because of the nature
+** of access authorization: no string returned by the package
+** needs to be valid longer than until the next call.
+**
+** This also makes it easy to plug the AA package in:
+** you don't have to ponder whether to free() something
+** here or is it done somewhere else (because it is always
+** done somewhere else).
+**
+** The strings that the package needs to store are copied
+** so the original strings given as parameters to AA
+** functions may be freed or modified with no side effects.
+**
+** The AA package does not free() anything else than what
+** it has itself allocated.
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+**
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+
+/*#include <stdio.h> included by HTUtils.h -- FM *//* FILE */
+#include <string.h> /* strchr() */
+
+#include "HTString.h"
+#include "HTAccess.h" /* HTSecure */
+#include "HTFile.h" /* HTLocalName */
+#include "HTRules.h" /* */
+#include "HTParse.h" /* URL parsing function */
+#include "HTList.h" /* HTList object */
+
+#include "HTAAUtil.h" /* AA common parts */
+#include "HTAuth.h" /* Authentication */
+#include "HTACL.h" /* Access Control List */
+#include "HTGroup.h" /* Group handling */
+#include "HTAAProt.h" /* Protection file parsing */
+#include "HTAAServ.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+/*
+** Global variables
+*/
+PUBLIC time_t theTime;
+
+
+/*
+** Module-wide global variables
+*/
+PRIVATE FILE * htaa_logfile = NULL; /* Log file */
+PRIVATE HTAAUser *htaa_user = NULL; /* Authenticated user */
+PRIVATE HTAAFailReasonType HTAAFailReason = HTAA_OK; /* AA fail reason */
+
+
+/* SERVER PUBLIC HTAA_statusMessage()
+** RETURN A STRING EXPLAINING ACCESS
+** AUTHORIZATION FAILURE
+** (Can be used in server reply status line
+** with 401/403 replies.)
+** ON EXIT:
+** returns a string containing the error message
+** corresponding to internal HTAAFailReason.
+*/
+PUBLIC char *HTAA_statusMessage NOARGS
+{
+ switch (HTAAFailReason) {
+
+ /* 401 cases */
+ case HTAA_NO_AUTH:
+ return "Unauthorized -- authentication failed";
+ break;
+ case HTAA_NOT_MEMBER:
+ return "Unauthorized to access the document";
+ break;
+
+ /* 403 cases */
+ case HTAA_BY_RULE:
+ return "Forbidden -- by rule";
+ break;
+ case HTAA_IP_MASK:
+ return "Forbidden -- server refuses to serve to your IP address";
+ break;
+ case HTAA_NO_ACL:
+ case HTAA_NO_ENTRY:
+ return "Forbidden -- access to file is never allowed";
+ break;
+ case HTAA_SETUP_ERROR:
+ return "Forbidden -- server protection setup error";
+ break;
+ case HTAA_DOTDOT:
+ return "Forbidden -- URL containing /../ disallowed";
+ break;
+ case HTAA_HTBIN:
+ return "Forbidden -- /htbin feature not enabled on this server";
+ break;
+
+ /* 404 cases */
+ case HTAA_NOT_FOUND:
+ return "Not found -- file doesn't exist or is read protected";
+ break;
+
+ /* Success */
+ case HTAA_OK:
+ return "AA: Access should be ok but something went wrong";
+ break;
+
+ case HTAA_OK_GATEWAY:
+ return "AA check bypassed (gatewaying) but something went wrong";
+ break;
+
+ /* Others */
+ default:
+ return "Access denied -- unable to specify reason (bug)";
+
+ } /* switch */
+}
+
+
+PRIVATE char *status_name ARGS1(HTAAFailReasonType, reason)
+{
+ switch (reason) {
+
+ /* 401 cases */
+ case HTAA_NO_AUTH:
+ return "NO-AUTHENTICATION";
+ break;
+ case HTAA_NOT_MEMBER:
+ return "NOT-AUTHORIZED";
+ break;
+
+ /* 403 cases */
+ case HTAA_BY_RULE:
+ return "FORB-RULE";
+ break;
+ case HTAA_IP_MASK:
+ return "FORB-IP";
+ break;
+ case HTAA_NO_ACL:
+ return "NO-ACL-FILE";
+ break;
+ case HTAA_NO_ENTRY:
+ return "NO-ACL-ENTRY";
+ break;
+ case HTAA_SETUP_ERROR:
+ return "SETUP-ERROR";
+ break;
+ case HTAA_DOTDOT:
+ return "SLASH-DOT-DOT";
+ break;
+ case HTAA_HTBIN:
+ return "HTBIN-OFF";
+ break;
+
+ /* 404 cases */
+ case HTAA_NOT_FOUND:
+ return "NOT-FOUND";
+ break;
+
+ /* Success */
+ case HTAA_OK:
+ return "OK";
+ break;
+ case HTAA_OK_GATEWAY:
+ return "OK-GATEWAY";
+ break;
+
+ /* Others */
+ default:
+ return "SERVER-BUG";
+ } /* switch */
+}
+
+
+/* PRIVATE check_uthorization()
+** CHECK IF USER IS AUTHORIZED TO ACCESS A FILE
+** ON ENTRY:
+** pathname is the physical file pathname
+** to access.
+** method method, e.g. METHOD_GET, METHOD_PUT, ...
+** scheme authentication scheme.
+** scheme_specifics authentication string (or other
+** scheme specific parameters, like
+** Kerberos-ticket).
+**
+** ON EXIT:
+** returns HTAA_OK on success.
+** Otherwise the reason for failing.
+** NOTE:
+** This function does not check whether the file
+** exists or not -- so the status 404 Not found
+** must be returned from somewhere else (this is
+** to avoid unnecessary overhead of opening the
+** file twice).
+*/
+PRIVATE HTAAFailReasonType check_authorization ARGS4(CONST char *, pathname,
+ HTAAMethod, method,
+ HTAAScheme, scheme,
+ char *, scheme_specifics)
+{
+ HTAAFailReasonType reason;
+ GroupDef *allowed_groups;
+ FILE *acl_file = NULL;
+ HTAAProt *prot = NULL; /* Protection mode */
+
+ htaa_user = NULL;
+
+ if (!pathname) {
+ if (TRACE)
+ fprintf(stderr, "HTAA_checkAuthorization: Forbidden by rule\n");
+ return HTAA_BY_RULE;
+ }
+ if (TRACE)
+ fprintf(stderr, "%s `%s' %s %s\n",
+ "HTAA_checkAuthorization: translated path:",
+ pathname, "method:", HTAAMethod_name(method));
+
+ /*
+ ** Get protection setting (set up by callbacks from rule system)
+ ** NULL, if not protected by a "protect" rule.
+ */
+ prot = HTAA_getCurrentProtection();
+
+ /*
+ ** Check ACL existence
+ */
+ if (!(acl_file = HTAA_openAcl(pathname))) {
+ if (prot) { /* protect rule, but no ACL */
+ if (prot->mask_group) {
+ /*
+ ** Only mask enabled, check that
+ */
+ GroupDefList *group_def_list =
+ HTAA_readGroupFile(HTAssocList_lookup(prot->values,
+ "group"));
+ /*
+ ** Authenticate if authentication info given
+ */
+ if (scheme != HTAA_UNKNOWN && scheme != HTAA_NONE) {
+ htaa_user = HTAA_authenticate(scheme,
+ scheme_specifics,
+ prot);
+ if (TRACE)
+ fprintf(stderr, "Authentication returned: %s\n",
+ (htaa_user ? htaa_user->username
+ : "NOT-AUTHENTICATED"));
+ }
+ HTAA_resolveGroupReferences(prot->mask_group, group_def_list);
+ reason = HTAA_userAndInetInGroup(prot->mask_group,
+ htaa_user
+ ? htaa_user->username : "",
+ HTClientHost,
+ NULL);
+ if (TRACE) {
+ if (reason != HTAA_OK)
+ fprintf(stderr, "%s %s %s %s\n",
+ "HTAA_checkAuthorization: access denied",
+ "by mask (no ACL, only Protect rule)",
+ "host", HTClientHost);
+ else
+ fprintf(stderr, "%s %s %s %s\n",
+ "HTAA_checkAuthorization: request from",
+ HTClientHost,
+ "accepted by only mask match (no ACL, only",
+ "Protect rule, and only mask enabled)");
+ }
+ return reason;
+ }
+ else { /* 403 Forbidden */
+ if (TRACE)
+ fprintf(stderr, "%s %s\n",
+ "HTAA_checkAuthorization: Protected, but",
+ "no mask group nor ACL -- forbidden");
+ return HTAA_NO_ACL;
+ }
+ }
+ else { /* No protect rule and no ACL => OK 200 */
+ if (TRACE)
+ fprintf(stderr, "HTAA_checkAuthorization: %s\n",
+ "no protect rule nor ACL -- ok\n");
+ return HTAA_OK;
+ }
+ }
+
+ /*
+ ** Now we know that ACL exists
+ */
+ if (!prot) { /* Not protected by "protect" rule */
+ if (TRACE)
+ fprintf(stderr, "HTAA_checkAuthorization: default protection\n");
+ prot = HTAA_getDefaultProtection(); /* Also sets current protection */
+
+ if (!prot) { /* @@ Default protection not set ?? */
+ if (TRACE)
+ fprintf(stderr, "%s %s\n",
+ "HTAA_checkAuthorization: default protection",
+ "not set (internal server error)!!");
+ return HTAA_SETUP_ERROR;
+ }
+ }
+
+ /*
+ ** Now we know that document is protected and ACL exists.
+ ** Check against ACL entry.
+ */
+ {
+ GroupDefList *group_def_list =
+ HTAA_readGroupFile(HTAssocList_lookup(prot->values, "group"));
+
+ /*
+ ** Authenticate now that we know protection mode
+ */
+ if (scheme != HTAA_UNKNOWN && scheme != HTAA_NONE) {
+ htaa_user = HTAA_authenticate(scheme,
+ scheme_specifics,
+ prot);
+ if (TRACE)
+ fprintf(stderr, "Authentication returned: %s\n",
+ (htaa_user
+ ? htaa_user->username : "NOT-AUTHENTICATED"));
+ }
+ /*
+ ** Check mask group
+ */
+ if (prot->mask_group) {
+ HTAA_resolveGroupReferences(prot->mask_group, group_def_list);
+ reason=HTAA_userAndInetInGroup(prot->mask_group,
+ htaa_user ? htaa_user->username : "",
+ HTClientHost,
+ NULL);
+ if (reason != HTAA_OK) {
+ if (TRACE)
+ fprintf(stderr, "%s %s %s\n",
+ "HTAA_checkAuthorization: access denied",
+ "by mask, host:", HTClientHost);
+ return reason;
+ }
+ else {
+ if (TRACE)
+ fprintf(stderr, "%s %s %s %s %s\n",
+ "HTAA_checkAuthorization: request from",
+ HTClientHost,
+ "accepted by just mask group match",
+ "(no ACL, only Protect rule, and only",
+ "mask enabled)");
+ /* And continue authorization checking */
+ }
+ }
+ /*
+ ** Get ACL entries; get first one first, the loop others
+ ** Remember, allowed_groups is automatically freed by
+ ** HTAA_getAclEntry().
+ */
+ allowed_groups = HTAA_getAclEntry(acl_file, pathname, method);
+ if (!allowed_groups) {
+ if (TRACE)
+ fprintf(stderr, "%s `%s' %s\n",
+ "No entry for file", pathname, "in ACL");
+ HTAA_closeAcl(acl_file);
+ return HTAA_NO_ENTRY; /* Forbidden -- no entry in the ACL */
+ }
+ else {
+ do {
+ HTAA_resolveGroupReferences(allowed_groups, group_def_list);
+ reason = HTAA_userAndInetInGroup(allowed_groups,
+ htaa_user
+ ? htaa_user->username : "",
+ HTClientHost,
+ NULL);
+ if (reason == HTAA_OK) {
+ HTAA_closeAcl(acl_file);
+ return HTAA_OK; /* OK */
+ }
+ allowed_groups = HTAA_getAclEntry(acl_file, pathname, method);
+ } while (allowed_groups);
+ HTAA_closeAcl(acl_file);
+ return HTAA_NOT_MEMBER; /* Unauthorized */
+ }
+ }
+}
+
+
+/* PUBLIC HTAA_checkAuthorization()
+** CHECK IF USER IS AUTHORIZED TO ACCESS A FILE
+** ON ENTRY:
+** url is the document to be accessed.
+** method_name name of the method, e.g. "GET"
+** scheme_name authentication scheme name.
+** scheme_specifics authentication string (or other
+** scheme specific parameters, like
+** Kerberos-ticket).
+**
+** ON EXIT:
+** returns status codes uniform with those of HTTP:
+** 200 OK if file access is ok.
+** 401 Unauthorized if user is not authorized to
+** access the file.
+** 403 Forbidden if there is no entry for the
+** requested file in the ACL.
+**
+** NOTE:
+** This function does not check whether the file
+** exists or not -- so the status 404 Not found
+** must be returned from somewhere else (this is
+** to avoid unnecessary overhead of opening the
+** file twice).
+**
+*/
+PUBLIC int HTAA_checkAuthorization ARGS4(CONST char *, url,
+ CONST char *, method_name,
+ CONST char *, scheme_name,
+ char *, scheme_specifics)
+{
+ static char *pathname = NULL;
+ char *local_copy = NULL;
+ HTAAMethod method = HTAAMethod_enum(method_name);
+ HTAAScheme scheme = HTAAScheme_enum(scheme_name);
+
+ HTAAFailReason = HTAA_OK;
+
+ /*
+ ** Translate into absolute pathname, and
+ ** check for "protect" and "defprot" rules.
+ */
+ FREE(pathname); /* From previous call */
+ StrAllocCopy(local_copy, url);
+ {
+ char *keywords = strchr(local_copy, '?');
+ if (keywords)
+ *keywords = '\0'; /* Chop off keywords */
+ }
+ HTSimplify(local_copy); /* Remove ".." etc. */
+
+ /* HTSimplify will leave in a "/../" at the top, which can
+ ** be a security hole.
+ */
+ if (strstr(local_copy, "/../")) {
+ if (TRACE)
+ fprintf(stderr, "HTAA_checkAuthorization: %s (`%s')\n",
+ "Illegal attempt to use /../", url);
+ HTAAFailReason = HTAA_DOTDOT;
+ }
+ else {
+ pathname = HTTranslate(local_copy); /* Translate rules even if */
+ /* a /htbin call to set up */
+ /* protections. */
+ if (0 == strncmp(local_copy, "/htbin/", 7)) {
+ if (!HTBinDir)
+ HTAAFailReason = HTAA_HTBIN;
+ else {
+ char *end = strchr(local_copy+7, '/');
+ if (end)
+ *end = '\0';
+ FREE(pathname);
+ pathname=(char*)malloc(strlen(HTBinDir)+strlen(local_copy)+1);
+ strcpy(pathname, HTBinDir);
+ strcat(pathname, local_copy+6);
+ }
+ }
+
+ if (!pathname) { /* Forbidden by rule */
+ if (TRACE)
+ fprintf(stderr, "HTAA_checkAuthorization: Forbidden by rule\n");
+ HTAAFailReason = HTAA_BY_RULE;
+ }
+ else if (HTAAFailReason != HTAA_HTBIN) {
+ /* pathname != NULL */
+ char *acc_method = HTParse(pathname, "", PARSE_ACCESS);
+ if (!*acc_method || 0 == strcmp(acc_method,"file")) { /*Local file, do AA*/
+ if (!HTSecure && 0 != strncmp(local_copy, "/htbin/", 7)) {
+ char *localname = HTLocalName(pathname);
+ FREE(pathname);
+ pathname = localname;
+ }
+ HTAAFailReason = check_authorization(pathname, method,
+ scheme, scheme_specifics);
+ }
+ else { /* Not local access */
+ HTAAFailReason = HTAA_OK_GATEWAY;
+ if (TRACE)
+ fprintf(stderr,
+ "HTAA_checkAuthorization: %s (%s access)\n",
+ "Gatewaying -- skipping authorization check",
+ acc_method);
+ }
+ } /* pathname */
+ }
+ FREE(local_copy);
+
+ if (htaa_logfile) {
+ time(&theTime);
+ fprintf(htaa_logfile, "%24.24s %s %s %s %s %s\n",
+ ctime(&theTime),
+ HTClientHost ? HTClientHost : "local",
+ method_name,
+ url,
+ status_name(HTAAFailReason),
+ htaa_user && htaa_user->username
+ ? htaa_user->username : "");
+ fflush(htaa_logfile); /* Actually update it on disk */
+ if (TRACE)
+ fprintf(stderr, "Log: %24.24s %s %s %s %s %s\n",
+ ctime(&theTime),
+ HTClientHost ? HTClientHost : "local",
+ method_name,
+ url,
+ status_name(HTAAFailReason),
+ htaa_user && htaa_user->username
+ ? htaa_user->username : "");
+ }
+
+ switch (HTAAFailReason) {
+
+ case HTAA_NO_AUTH:
+ case HTAA_NOT_MEMBER:
+ return 401;
+ break;
+
+ case HTAA_BY_RULE:
+ case HTAA_IP_MASK:
+ case HTAA_NO_ACL:
+ case HTAA_NO_ENTRY:
+ case HTAA_SETUP_ERROR:
+ case HTAA_DOTDOT:
+ case HTAA_HTBIN:
+ return 403;
+ break;
+
+ case HTAA_NOT_FOUND:
+ return 404;
+ break;
+
+ case HTAA_OK:
+ case HTAA_OK_GATEWAY:
+ return 200;
+ break;
+
+ default:
+ return 500;
+ } /* switch */
+}
+
+
+/* PRIVATE compose_scheme_specifics()
+** COMPOSE SCHEME-SPECIFIC PARAMETERS
+** TO BE SENT ALONG WITH SERVER REPLY
+** IN THE WWW-Authenticate: FIELD.
+** ON ENTRY:
+** scheme is the authentication scheme for which
+** parameters are asked for.
+** prot protection setup structure.
+**
+** ON EXIT:
+** returns scheme specific parameters in an
+** auto-freed string.
+*/
+PRIVATE char *compose_scheme_specifics ARGS2(HTAAScheme, scheme,
+ HTAAProt *, prot)
+{
+ static char *result = NULL;
+
+ FREE(result); /* From previous call */
+
+ switch (scheme) {
+ case HTAA_BASIC:
+ {
+ char *realm = HTAssocList_lookup(prot->values, "server");
+ result = (char*)malloc(60);
+ sprintf(result, "realm=\"%s\"",
+ (realm ? realm : "UNKNOWN"));
+ return result;
+ }
+ break;
+
+ case HTAA_PUBKEY:
+ {
+ char *realm = HTAssocList_lookup(prot->values, "server");
+ result = (char*)malloc(200);
+ sprintf(result, "realm=\"%s\", key=\"%s\"",
+ (realm ? realm : "UNKNOWN"),
+ "PUBKEY-NOT-IMPLEMENTED");
+ return result;
+ }
+ break;
+ default:
+ return NULL;
+ }
+}
+
+
+/* SERVER PUBLIC HTAA_composeAuthHeaders()
+** COMPOSE WWW-Authenticate: HEADER LINES
+** INDICATING VALID AUTHENTICATION SCHEMES
+** FOR THE REQUESTED DOCUMENT
+** ON ENTRY:
+** No parameters, but HTAA_checkAuthorization() must
+** just before have failed because a wrong (or none)
+** authentication scheme was used.
+**
+** ON EXIT:
+** returns a buffer containing all the WWW-Authenticate:
+** fields including CRLFs (this buffer is auto-freed).
+** NULL, if authentication won't help in accessing
+** the requested document.
+**
+*/
+PUBLIC char *HTAA_composeAuthHeaders NOARGS
+{
+ static char *result = NULL;
+ HTAAScheme scheme;
+ char *scheme_name;
+ char *scheme_params;
+ HTAAProt *prot = HTAA_getCurrentProtection();
+
+ if (!prot) {
+ if (TRACE)
+ fprintf(stderr, "%s %s\n",
+ "HTAA_composeAuthHeaders: Document not protected",
+ "-- why was this function called??");
+ return NULL;
+ }
+ else if (TRACE)
+ fprintf(stderr, "HTAA_composeAuthHeaders: for file `%s'\n",
+ prot->filename);
+
+ FREE(result); /* From previous call */
+ if (!(result = (char*)malloc(4096))) /* @@ */
+ outofmem(__FILE__, "HTAA_composeAuthHeaders");
+ *result = '\0';
+
+ for (scheme=0; scheme < HTAA_MAX_SCHEMES; scheme++) {
+ if (-1 < HTList_indexOf(prot->valid_schemes, (void*)scheme)) {
+ if ((scheme_name = HTAAScheme_name(scheme))) {
+ scheme_params = compose_scheme_specifics(scheme,prot);
+ strcat(result, "WWW-Authenticate: ");
+ strcat(result, scheme_name);
+ if (scheme_params) {
+ strcat(result, " ");
+ strcat(result, scheme_params);
+ }
+ strcat(result, "\r\n");
+ } /* scheme name found */
+ else if (TRACE)
+ fprintf(stderr, "HTAA_composeAuthHeaders: %s %d\n",
+ "No name found for scheme number", scheme);
+ } /* scheme valid for requested document */
+ } /* for every scheme */
+
+ return result;
+}
+
+
+/* PUBLIC HTAA_startLogging()
+** START UP ACCESS AUTHORIZATION LOGGING
+** ON ENTRY:
+** fp is the open log file.
+**
+*/
+PUBLIC void HTAA_startLogging ARGS1(FILE *, fp)
+{
+ htaa_logfile = fp;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.h
new file mode 100644
index 00000000000..dc03c7dd1ae
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAServ.h
@@ -0,0 +1,148 @@
+/* SERVER SIDE ACCESS AUTHORIZATION MODULE
+
+ This module is the server side interface to Access Authorization (AA) package. It
+ contains code only for server.
+
+ Important to know about memory allocation:
+
+ Routines in this module use dynamic allocation, but free automatically all the memory
+ reserved by them.
+
+ Therefore the caller never has to (and never should) free() any object returned by
+ these functions.
+
+ Therefore also all the strings returned by this package are only valid until the next
+ call to the same function is made. This approach is selected, because of the nature of
+ access authorization: no string returned by the package needs to be valid longer than
+ until the next call.
+
+ This also makes it easy to plug the AA package in: you don't have to ponder whether to
+ free()something here or is it done somewhere else (because it is always done somewhere
+ else).
+
+ The strings that the package needs to store are copied so the original strings given as
+ parameters to AA functions may be freed or modified with no side effects.
+
+ Also note:The AA package does not free() anything else than what it has itself
+ allocated.
+
+ */
+
+#ifndef HTAASERV_H
+#define HTAASERV_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h" /* BOOL, PARAMS, ARGS */
+#endif /* HTUTILS_H */
+/*#include <stdio.h> included by HTUtils.h -- FM *//* FILE */
+#include "HTRules.h" /* This module interacts with rule system */
+#include "HTAAUtil.h" /* Common parts of AA */
+#include "HTAuth.h" /* Authentication */
+
+
+#ifdef SHORT_NAMES
+#define HTAAstMs HTAA_statusMessage
+#define HTAAchAu HTAA_checkAuthorization
+#define HTAAcoAH HTAA_composeAuthHeaders
+#define HTAAsLog HTAA_startLogging
+#endif /*SHORT_NAMES*/
+
+extern time_t theTime;
+
+/*
+
+Check Access Authorization
+
+ HTAA_checkAuthorization() is the main access authorization function.
+
+ */
+
+/* PUBLIC HTAA_checkAuthorization()
+** CHECK IF USER IS AUTHORIZED TO ACCESS A FILE
+** ON ENTRY:
+** url is the document to be accessed.
+** method_name name of the method, e.g. "GET"
+** scheme_name authentication scheme name.
+** scheme_specifics authentication string (or other
+** scheme specific parameters, like
+** Kerberos-ticket).
+**
+** ON EXIT:
+** returns status codes uniform with those of HTTP:
+** 200 OK if file access is ok.
+** 401 Unauthorized if user is not authorized to
+** access the file.
+** 403 Forbidden if there is no entry for the
+** requested file in the ACL.
+**
+** NOTE:
+** This function does not check whether the file
+** exists or not -- so the status 404 Not found
+** must be returned from somewhere else (this is
+** to avoid unnecessary overhead of opening the
+** file twice).
+**
+*/
+PUBLIC int HTAA_checkAuthorization PARAMS((CONST char * url,
+ CONST char * method_name,
+ CONST char * scheme_name,
+ char * scheme_specifics));
+/*
+
+Compose Status Line Message
+
+ */
+
+/* SERVER PUBLIC HTAA_statusMessage()
+** RETURN A STRING EXPLAINING ACCESS
+** AUTHORIZATION FAILURE
+** (Can be used in server reply status line
+** with 401/403 replies.)
+** ON EXIT:
+** returns a string containing the error message
+** corresponding to internal HTAAFailReason.
+*/
+PUBLIC char *HTAA_statusMessage NOPARAMS;
+/*
+
+Compose "Authenticate:" Header Lines for Server Reply
+
+ */
+
+/* SERVER PUBLIC HTAA_composeAuthHeaders()
+** COMPOSE WWW-Authenticate: HEADER LINES
+** INDICATING VALID AUTHENTICATION SCHEMES
+** FOR THE REQUESTED DOCUMENT
+** ON ENTRY:
+** No parameters, but HTAA_checkAuthorization() must
+** just before have failed because a wrong (or none)
+** authentication scheme was used.
+**
+** ON EXIT:
+** returns a buffer containing all the WWW-Authenticate:
+** fields including CRLFs (this buffer is auto-freed).
+** NULL, if authentication won't help in accessing
+** the requested document.
+*/
+PUBLIC char *HTAA_composeAuthHeaders NOPARAMS;
+/*
+
+Start Access Authorization Logging
+
+ */
+
+/* PUBLIC HTAA_startLogging()
+** START UP ACCESS AUTHORIZATION LOGGING
+** ON ENTRY:
+** fp is the open log file.
+**
+*/
+PUBLIC void HTAA_startLogging PARAMS((FILE * fp));
+/*
+
+ */
+
+#endif /* NOT HTAASERV_H */
+/*
+
+ End of file HTAAServ.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.c
new file mode 100644
index 00000000000..a7cad59b180
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.c
@@ -0,0 +1,621 @@
+
+/* MODULE HTAAUtil.c
+** COMMON PARTS OF ACCESS AUTHORIZATION MODULE
+** FOR BOTH SERVER AND BROWSER
+**
+** IMPORTANT:
+** Routines in this module use dynamic allocation, but free
+** automatically all the memory reserved by them.
+**
+** Therefore the caller never has to (and never should)
+** free() any object returned by these functions.
+**
+** Therefore also all the strings returned by this package
+** are only valid until the next call to the same function
+** is made. This approach is selected, because of the nature
+** of access authorization: no string returned by the package
+** needs to be valid longer than until the next call.
+**
+** This also makes it easy to plug the AA package in:
+** you don't have to ponder whether to free() something
+** here or is it done somewhere else (because it is always
+** done somewhere else).
+**
+** The strings that the package needs to store are copied
+** so the original strings given as parameters to AA
+** functions may be freed or modified with no side effects.
+**
+** The AA package does not free() anything else than what
+** it has itself allocated.
+**
+** AA (Access Authorization) package means modules which
+** names start with HTAA.
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+** MD Mark Donszelmann duns@vxdeop.cern.ch
+**
+** HISTORY:
+** 8 Nov 93 MD (VMS only) Added case insensitive comparison in HTAA_templateCaseMatch
+**
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h" /* NETREAD() etc. */
+#include <string.h>
+#include "HTAAUtil.h" /* Implemented here */
+#include "HTAssoc.h" /* Assoc list */
+#include "HTTCP.h"
+#include "HTAlert.h"
+
+#include "LYLeaks.h"
+
+/* PUBLIC HTAAScheme_enum()
+** TRANSLATE SCHEME NAME INTO
+** A SCHEME ENUMERATION
+**
+** ON ENTRY:
+** name is a string representing the scheme name.
+**
+** ON EXIT:
+** returns the enumerated constant for that scheme.
+*/
+PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
+{
+ char *upcased = NULL;
+ char *cur;
+
+ if (!name)
+ return HTAA_UNKNOWN;
+
+ StrAllocCopy(upcased, name);
+ cur = upcased;
+ while (*cur) {
+ *cur = TOUPPER(*cur);
+ cur++;
+ }
+
+ if (!strncmp(upcased, "NONE", 4)) {
+ FREE(upcased);
+ return HTAA_NONE;
+ } else if (!strncmp(upcased, "BASIC", 5)) {
+ FREE(upcased);
+ return HTAA_BASIC;
+ } else if (!strncmp(upcased, "PUBKEY", 6)) {
+ FREE(upcased);
+ return HTAA_PUBKEY;
+ } else if (!strncmp(upcased, "KERBEROSV4", 10)) {
+ FREE(upcased);
+ return HTAA_KERBEROS_V4;
+ } else if (!strncmp(upcased, "KERBEROSV5", 10)) {
+ FREE(upcased);
+ return HTAA_KERBEROS_V5;
+ } else {
+ FREE(upcased);
+ return HTAA_UNKNOWN;
+ }
+}
+
+
+/* PUBLIC HTAAScheme_name()
+** GET THE NAME OF A GIVEN SCHEME
+** ON ENTRY:
+** scheme is one of the scheme enum values:
+** HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
+**
+** ON EXIT:
+** returns the name of the scheme, i.e.
+** "None", "Basic", "Pubkey", ...
+*/
+PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
+{
+ switch (scheme) {
+ case HTAA_NONE:
+ return "None";
+ break;
+ case HTAA_BASIC:
+ return "Basic";
+ break;
+ case HTAA_PUBKEY:
+ return "Pubkey";
+ break;
+ case HTAA_KERBEROS_V4:
+ return "KerberosV4";
+ break;
+ case HTAA_KERBEROS_V5:
+ return "KerberosV5";
+ break;
+ case HTAA_UNKNOWN:
+ return "UNKNOWN";
+ break;
+ default:
+ return "THIS-IS-A-BUG";
+ }
+}
+
+
+/* PUBLIC HTAAMethod_enum()
+** TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
+** ON ENTRY:
+** name is the method name to translate.
+**
+** ON EXIT:
+** returns HTAAMethod enumerated value corresponding
+** to the given name.
+*/
+PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name)
+{
+ char tmp[MAX_METHODNAME_LEN+1];
+ CONST char *src = name;
+ char *dest = tmp;
+
+ if (!name)
+ return METHOD_UNKNOWN;
+
+ while (*src) {
+ *dest = TOUPPER(*src);
+ dest++;
+ src++;
+ }
+ *dest = 0;
+
+ if (0==strcmp(tmp, "GET"))
+ return METHOD_GET;
+ else if (0==strcmp(tmp, "PUT"))
+ return METHOD_PUT;
+ else
+ return METHOD_UNKNOWN;
+}
+
+
+/* PUBLIC HTAAMethod_name()
+** GET THE NAME OF A GIVEN METHOD
+** ON ENTRY:
+** method is one of the method enum values:
+** METHOD_GET, METHOD_PUT, ...
+**
+** ON EXIT:
+** returns the name of the scheme, i.e.
+** "GET", "PUT", ...
+*/
+PUBLIC char *HTAAMethod_name ARGS1(HTAAMethod, method)
+{
+ switch (method) {
+ case METHOD_GET:
+ return "GET";
+ break;
+ case METHOD_PUT:
+ return "PUT";
+ break;
+ case METHOD_UNKNOWN:
+ return "UNKNOWN";
+ break;
+ default:
+ return "THIS-IS-A-BUG";
+ }
+}
+
+
+/* PUBLIC HTAAMethod_inList()
+** IS A METHOD IN A LIST OF METHOD NAMES
+** ON ENTRY:
+** method is the method to look for.
+** list is a list of method names.
+**
+** ON EXIT:
+** returns YES, if method was found.
+** NO, if not found.
+*/
+PUBLIC BOOL HTAAMethod_inList ARGS2(HTAAMethod, method,
+ HTList *, list)
+{
+ HTList *cur = list;
+ char *item;
+
+ while (NULL != (item = (char*)HTList_nextObject(cur))) {
+ if (TRACE)
+ fprintf(stderr, " %s", item);
+ if (method == HTAAMethod_enum(item))
+ return YES;
+ }
+
+ return NO; /* Not found */
+}
+
+
+/* PUBLIC HTAA_templateMatch()
+** STRING COMPARISON FUNCTION FOR FILE NAMES
+** WITH ONE WILDCARD * IN THE TEMPLATE
+** NOTE:
+** This is essentially the same code as in HTRules.c, but it
+** cannot be used because it is embedded in between other code.
+** (In fact, HTRules.c should use this routine, but then this
+** routine would have to be more sophisticated... why is life
+** sometimes so hard...)
+**
+** ON ENTRY:
+** template is a template string to match the file name
+** agaist, may contain a single wildcard
+** character * which matches zero or more
+** arbitrary characters.
+** filename is the filename (or pathname) to be matched
+** agaist the template.
+**
+** ON EXIT:
+** returns YES, if filename matches the template.
+** NO, otherwise.
+*/
+PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template,
+ CONST char *, filename)
+{
+ CONST char *p = template;
+ CONST char *q = filename;
+ int m;
+
+ for (; *p && *q && *p == *q; p++, q++) /* Find first mismatch */
+ ; /* do nothing else */
+
+ if (!*p && !*q)
+ return YES; /* Equally long equal strings */
+ else if ('*' == *p) { /* Wildcard */
+ p++; /* Skip wildcard character */
+ m = strlen(q) - strlen(p); /* Amount to match to wildcard */
+ if (m < 0)
+ return NO; /* No match, filename too short */
+ else { /* Skip the matched characters and compare */
+ if (strcmp(p, q+m))
+ return NO; /* Tail mismatch */
+ else
+ return YES; /* Tail match */
+ }
+ } /* if wildcard */
+ else
+ return NO; /* Length or character mismatch */
+}
+
+
+/* PUBLIC HTAA_templateCaseMatch()
+** STRING COMPARISON FUNCTION FOR FILE NAMES
+** WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
+** NOTE:
+** This is essentially the same code as in HTAA_templateMatch, but
+** it compares case insensitive (for VMS). Reason for this routine
+** is that HTAA_templateMatch gets called from several places, also
+** there where a case sensitive match is needed, so one cannot just
+** change the HTAA_templateMatch routine for VMS.
+**
+** ON ENTRY:
+** template is a template string to match the file name
+** agaist, may contain a single wildcard
+** character * which matches zero or more
+** arbitrary characters.
+** filename is the filename (or pathname) to be matched
+** agaist the template.
+**
+** ON EXIT:
+** returns YES, if filename matches the template.
+** NO, otherwise.
+*/
+PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, template,
+ CONST char *, filename)
+{
+ CONST char *p = template;
+ CONST char *q = filename;
+ int m;
+
+ /* Find first mismatch */
+ for (; *p && *q && TOUPPER(*p) == TOUPPER(*q); p++, q++)
+ ; /* do nothing else */
+
+ if (!*p && !*q)
+ return YES; /* Equally long equal strings */
+ else if ('*' == *p) { /* Wildcard */
+ p++; /* Skip wildcard character */
+ m = strlen(q) - strlen(p); /* Amount to match to wildcard */
+ if (m < 0)
+ return NO; /* No match, filename too short */
+ else { /* Skip the matched characters and compare */
+ if (strcasecomp(p, q+m))
+ return NO; /* Tail mismatch */
+ else
+ return YES; /* Tail match */
+ }
+ } /* if wildcard */
+ else
+ return NO; /* Length or character mismatch */
+}
+
+
+/* PUBLIC HTAA_makeProtectionTemplate()
+** CREATE A PROTECTION TEMPLATE FOR THE FILES
+** IN THE SAME DIRECTORY AS THE GIVEN FILE
+** (Used by server if there is no fancier way for
+** it to tell the client, and by browser if server
+** didn't send WWW-ProtectionTemplate: field)
+** ON ENTRY:
+** docname is the document pathname (from URL).
+**
+** ON EXIT:
+** returns a template matching docname, and other files
+** files in that directory.
+**
+** E.g. /foo/bar/x.html => /foo/bar/ *
+** ^
+** Space only to prevent it from
+** being a comment marker here,
+** there really isn't any space.
+*/
+PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
+{
+ char *template = NULL;
+ char *slash = NULL;
+
+ if (docname) {
+ StrAllocCopy(template, docname);
+ slash = strrchr(template, '/');
+ if (slash)
+ slash++;
+ else
+ slash = template;
+ *slash = '\0';
+ StrAllocCat(template, "*");
+ }
+ else
+ StrAllocCopy(template, "*");
+
+ if (TRACE)
+ fprintf(stderr, "make_template: made template `%s' for file `%s'\n",
+ template, docname);
+
+ return template;
+}
+
+
+/*
+** Skip leading whitespace from *s forward
+*/
+#define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
+
+/*
+** Kill trailing whitespace starting from *(s-1) backwords
+*/
+#define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)='\0';}
+
+
+/* PUBLIC HTAA_parseArgList()
+** PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
+** ON ENTRY:
+** str is a comma-separated list:
+**
+** item, item, item
+** where
+** item ::= value
+** | name=value
+** | name="value"
+**
+** Leading and trailing whitespace is ignored
+** everywhere except inside quotes, so the following
+** examples are equal:
+**
+** name=value,foo=bar
+** name="value",foo="bar"
+** name = value , foo = bar
+** name = "value" , foo = "bar"
+**
+** ON EXIT:
+** returns a list of name-value pairs (actually HTAssocList*).
+** For items with no name, just value, the name is
+** the number of order number of that item. E.g.
+** "1" for the first, etc.
+*/
+PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
+{
+ HTAssocList *assoc_list = HTAssocList_new();
+ char *cur = NULL;
+ char *name = NULL;
+ int n = 0;
+
+ if (!str)
+ return assoc_list;
+
+ while (*str) {
+ SKIPWS(str); /* Skip leading whitespace */
+ cur = str;
+ n++;
+
+ while (*cur && *cur != '=' && *cur != ',')
+ cur++; /* Find end of name (or lonely value without a name) */
+ KILLWS(cur); /* Kill trailing whitespace */
+
+ if (*cur == '=') { /* Name followed by a value */
+ *(cur++) = '\0'; /* Terminate name */
+ StrAllocCopy(name, str);
+ SKIPWS(cur); /* Skip WS leading the value */
+ str = cur;
+ if (*str == '"') { /* Quoted value */
+ str++;
+ cur = str;
+ while (*cur && *cur != '"')
+ cur++;
+ if (*cur == '"')
+ *(cur++) = '\0'; /* Terminate value */
+ /* else it is lacking terminating quote */
+ SKIPWS(cur); /* Skip WS leading comma */
+ if (*cur == ',')
+ cur++; /* Skip separating colon */
+ }
+ else { /* Unquoted value */
+ while (*cur && *cur != ',')
+ cur++;
+ KILLWS(cur); /* Kill trailing whitespace */
+ if (*cur == ',')
+ *(cur++) = '\0';
+ /* else *cur already NULL */
+ }
+ }
+ else { /* No name, just a value */
+ if (*cur == ',')
+ *(cur++) = '\0'; /* Terminate value */
+ /* else last value on line (already terminated by NULL) */
+ StrAllocCopy(name, "nnn"); /* Room for item order number */
+ sprintf(name, "%d", n); /* Item order number for name */
+ }
+ HTAssocList_add(assoc_list, name, str);
+ str = cur;
+ } /* while *str */
+
+ FREE(name);
+ return assoc_list;
+}
+
+
+/************** HEADER LINE READER -- DOES UNFOLDING *************************/
+
+#define BUFFER_SIZE 1024
+
+PRIVATE char buffer[BUFFER_SIZE + 1];
+PRIVATE char *start_pointer = buffer;
+PRIVATE char *end_pointer = buffer;
+PRIVATE int in_soc = -1;
+
+/* PUBLIC HTAA_setupReader()
+** SET UP HEADER LINE READER, i.e. give
+** the already-read-but-not-yet-processed
+** buffer of text to be read before more
+** is read from the socket.
+** ON ENTRY:
+** start_of_headers is a pointer to a buffer containing
+** the beginning of the header lines
+** (rest will be read from a socket).
+** length is the number of valid characters in
+** 'start_of_headers' buffer.
+** soc is the socket to use when start_of_headers
+** buffer is used up.
+** ON EXIT:
+** returns nothing.
+** Subsequent calls to HTAA_getUnfoldedLine()
+** will use this buffer first and then
+** proceed to read from socket.
+*/
+PUBLIC void HTAA_setupReader ARGS4(char *, start_of_headers,
+ int, length,
+ void *, handle,
+ int, soc)
+{
+ start_pointer = buffer;
+ if (start_of_headers) {
+ strncpy(buffer, start_of_headers, length);
+ buffer[length] = '\0';
+ end_pointer = buffer + length;
+ }
+ else {
+ *start_pointer = '\0';
+ end_pointer = start_pointer;
+ }
+ in_soc = soc;
+}
+
+
+/* PUBLIC HTAA_getUnfoldedLine()
+** READ AN UNFOLDED HEADER LINE FROM SOCKET
+** ON ENTRY:
+** HTAA_setupReader must absolutely be called before
+** this function to set up internal buffer.
+**
+** ON EXIT:
+** returns a newly-allocated character string representing
+** the read line. The line is unfolded, i.e.
+** lines that begin with whitespace are appended
+** to current line. E.g.
+**
+** Field-Name: Blaa-Blaa
+** This-Is-A-Continuation-Line
+** Here-Is_Another
+**
+** is seen by the caller as:
+**
+** Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
+**
+*/
+PUBLIC char *HTAA_getUnfoldedLine NOARGS
+{
+ char *line = NULL;
+ char *cur;
+ int count;
+ BOOL peek_for_folding = NO;
+
+ if (in_soc < 0) {
+ if (TRACE)
+ fprintf(stderr, "%s %s\n",
+ "HTAA_getUnfoldedLine: buffer not initialized",
+ "with function HTAA_setupReader()");
+ return NULL;
+ }
+
+ for(;;) {
+
+ /* Reading from socket */
+
+ if (start_pointer >= end_pointer) {/*Read the next block and continue*/
+ count = NETREAD(in_soc, buffer, BUFFER_SIZE);
+ if (count <= 0) {
+ in_soc = -1;
+ return line;
+ }
+ start_pointer = buffer;
+ end_pointer = buffer + count;
+ *end_pointer = '\0';
+#ifdef NOT_ASCII
+ cur = start_pointer;
+ while (cur < end_pointer) {
+ *cur = TOASCII(*cur);
+ cur++;
+ }
+#endif /*NOT_ASCII*/
+ }
+ cur = start_pointer;
+
+
+ /* Unfolding */
+
+ if (peek_for_folding) {
+ if (*cur != ' ' && *cur != '\t')
+ return line; /* Ok, no continuation line */
+ else /* So this is a continuation line, continue */
+ peek_for_folding = NO;
+ }
+
+
+ /* Finding end-of-line */
+
+ while (cur < end_pointer && *cur != '\n') /* Find the end-of-line */
+ cur++; /* (or end-of-buffer). */
+
+
+ /* Terminating line */
+
+ if (cur < end_pointer) { /* So *cur==LF, terminate line */
+ *cur = '\0'; /* Overwrite LF */
+ if (*(cur-1) == '\r')
+ *(cur-1) = '\0'; /* Overwrite CR */
+ peek_for_folding = YES; /* Check for a continuation line */
+ }
+
+
+ /* Copying the result */
+
+ if (line)
+ StrAllocCat(line, start_pointer); /* Append */
+ else
+ StrAllocCopy(line, start_pointer); /* A new line */
+
+ start_pointer = cur+1; /* Skip the read line */
+
+ } /* forever */
+}
+
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.h
new file mode 100644
index 00000000000..226f1547035
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAAUtil.h
@@ -0,0 +1,361 @@
+/* Utilities for the Authorization parts of libwww
+ COMMON PARTS OF AUTHORIZATION MODULE TO BOTH SERVER AND BROWSER
+
+ This module is the interface to the common parts of Access Authorization (AA) package
+ for both server and browser. Important to know about memory allocation:
+
+ Routines in this module use dynamic allocation, but free automatically all the memory
+ reserved by them.
+
+ Therefore the caller never has to (and never should) free() any object returned by
+ these functions.
+
+ Therefore also all the strings returned by this package are only valid until the next
+ call to the same function is made. This approach is selected, because of the nature of
+ access authorization: no string returned by the package needs to be valid longer than
+ until the next call.
+
+ This also makes it easy to plug the AA package in: you don't have to ponder whether to
+ free() something here or is it done somewhere else (because it is always done somewhere
+ else).
+
+ The strings that the package needs to store are copied so the original strings given as
+ parameters to AA functions may be freed or modified with no side effects.
+
+ Also note: The AA package does not free() anything else than what it has itself
+ allocated.
+
+ */
+
+#ifndef HTAAUTIL_H
+#define HTAAUTIL_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h" /* BOOL, PARAMS, ARGS */
+#endif /* HTUTILS_H */
+#include "tcp.h"
+#include "HTList.h"
+
+#ifdef SHORT_NAMES
+#define HTAASenu HTAAScheme_enum
+#define HTAASnam HTAAScheme_name
+#define HTAAMenu HTAAMethod_enum
+#define HTAAMnam HTAAMethod_name
+#define HTAAMinL HTAAMethod_inList
+#define HTAAteMa HTAA_templateMatch
+#define HTAAmaPT HTAA_makeProtectionTemplate
+#define HTAApALi HTAA_parseArgList
+#define HTAAsuRe HTAA_setupReader
+#define HTAAgUfL HTAA_getUnfoldedLine
+#endif /*SHORT_NAMES*/
+
+
+/*
+
+Default filenames
+
+ */
+#ifndef PASSWD_FILE
+#define PASSWD_FILE "/home2/luotonen/passwd"
+#endif
+
+#ifndef GROUP_FILE
+#define GROUP_FILE "/home2/luotonen/group"
+#endif
+
+#define ACL_FILE_NAME ".www_acl"
+
+
+/*
+** Numeric constants
+*/
+#define MAX_USERNAME_LEN 16 /* @@ Longest allowed username */
+#define MAX_PASSWORD_LEN 3*13 /* @@ Longest allowed password */
+ /* (encrypted, so really only 3*8)*/
+#define MAX_METHODNAME_LEN 12 /* @@ Longest allowed method name */
+#define MAX_FIELDNAME_LEN 16 /* @@ Longest field name in */
+ /* protection setup file */
+#define MAX_PATHNAME_LEN 80 /* @@ Longest passwd/group file */
+ /* patname to allow */
+
+/*
+** Helpful macros
+*/
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+
+Datatype definitions
+
+ HTAASCHEME
+
+ The enumeration HTAAScheme represents the possible authentication schemes used by the
+ WWW Access Authorization.
+
+ */
+
+typedef enum {
+ HTAA_UNKNOWN,
+ HTAA_NONE,
+ HTAA_BASIC,
+ HTAA_PUBKEY,
+ HTAA_KERBEROS_V4,
+ HTAA_KERBEROS_V5,
+ HTAA_MAX_SCHEMES /* THIS MUST ALWAYS BE LAST! Number of schemes */
+} HTAAScheme;
+
+/*
+
+ ENUMERATION TO REPRESENT HTTP METHODS
+
+ */
+
+typedef enum {
+ METHOD_UNKNOWN,
+ METHOD_GET,
+ METHOD_PUT
+} HTAAMethod;
+
+/*
+
+Authentication Schemes
+
+ */
+
+/* PUBLIC HTAAScheme_enum()
+** TRANSLATE SCHEME NAME TO A SCHEME ENUMERATION
+** ON ENTRY:
+** name is a string representing the scheme name.
+**
+** ON EXIT:
+** returns the enumerated constant for that scheme.
+*/
+PUBLIC HTAAScheme HTAAScheme_enum PARAMS((CONST char* name));
+
+
+/* PUBLIC HTAAScheme_name()
+** GET THE NAME OF A GIVEN SCHEME
+** ON ENTRY:
+** scheme is one of the scheme enum values:
+** HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
+**
+** ON EXIT:
+** returns the name of the scheme, i.e.
+** "none", "basic", "pubkey", ...
+*/
+PUBLIC char *HTAAScheme_name PARAMS((HTAAScheme scheme));
+
+/*
+
+Methods
+
+ */
+
+/* PUBLIC HTAAMethod_enum()
+** TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
+** ON ENTRY:
+** name is the method name to translate.
+**
+** ON EXIT:
+** returns HTAAMethod enumerated value corresponding
+** to the given name.
+*/
+PUBLIC HTAAMethod HTAAMethod_enum PARAMS((CONST char * name));
+
+
+/* PUBLIC HTAAMethod_name()
+** GET THE NAME OF A GIVEN METHOD
+** ON ENTRY:
+** method is one of the method enum values:
+** METHOD_GET, METHOD_PUT, ...
+**
+** ON EXIT:
+** returns the name of the scheme, i.e.
+** "GET", "PUT", ...
+*/
+PUBLIC char *HTAAMethod_name PARAMS((HTAAMethod method));
+
+
+/* PUBLIC HTAAMethod_inList()
+** IS A METHOD IN A LIST OF METHOD NAMES
+** ON ENTRY:
+** method is the method to look for.
+** list is a list of method names.
+**
+** ON EXIT:
+** returns YES, if method was found.
+** NO, if not found.
+*/
+PUBLIC BOOL HTAAMethod_inList PARAMS((HTAAMethod method,
+ HTList * list));
+/*
+
+Match Template Against Filename
+
+ */
+
+/* PUBLIC HTAA_templateMatch()
+** STRING COMPARISON FUNCTION FOR FILE NAMES
+** WITH ONE WILDCARD * IN THE TEMPLATE
+** NOTE:
+** This is essentially the same code as in HTRules.c, but it
+** cannot be used because it is embedded in between other code.
+** (In fact, HTRules.c should use this routine, but then this
+** routine would have to be more sophisticated... why is life
+** sometimes so hard...)
+**
+** ON ENTRY:
+** template is a template string to match the file name
+** agaist, may contain a single wildcard
+** character * which matches zero or more
+** arbitrary characters.
+** filename is the filename (or pathname) to be matched
+** agaist the template.
+**
+** ON EXIT:
+** returns YES, if filename matches the template.
+** NO, otherwise.
+*/
+PUBLIC BOOL HTAA_templateMatch PARAMS((CONST char * template,
+ CONST char * filename));
+
+
+/* PUBLIC HTAA_templateCaseMatch()
+** STRING COMPARISON FUNCTION FOR FILE NAMES
+** WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
+** NOTE:
+** This is essentially the same code as in HTAA_templateMatch, but
+** it compares case insensitive (for VMS). Reason for this routine
+** is that HTAA_templateMatch gets called from several places, also
+** there where a case sensitive match is needed, so one cannot just
+** change the HTAA_templateMatch routine for VMS.
+**
+** ON ENTRY:
+** template is a template string to match the file name
+** agaist, may contain a single wildcard
+** character * which matches zero or more
+** arbitrary characters.
+** filename is the filename (or pathname) to be matched
+** agaist the template.
+**
+** ON EXIT:
+** returns YES, if filename matches the template.
+** NO, otherwise.
+*/
+PUBLIC BOOL HTAA_templateCaseMatch PARAMS((CONST char * template,
+ CONST char * filename));
+
+
+/* PUBLIC HTAA_makeProtectionTemplate()
+** CREATE A PROTECTION TEMPLATE FOR THE FILES
+** IN THE SAME DIRECTORY AS THE GIVEN FILE
+** (Used by server if there is no fancier way for
+** it to tell the client, and by browser if server
+** didn't send WWW-ProtectionTemplate: field)
+** ON ENTRY:
+** docname is the document pathname (from URL).
+**
+** ON EXIT:
+** returns a template matching docname, and other files
+** files in that directory.
+**
+** E.g. /foo/bar/x.html => /foo/bar/ *
+** ^
+** Space only to prevent it from
+** being a comment marker here,
+** there really isn't any space.
+*/
+PUBLIC char *HTAA_makeProtectionTemplate PARAMS((CONST char * docname));
+/*
+
+MIME Argument List Parser
+
+ */
+
+
+/* PUBLIC HTAA_parseArgList()
+** PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
+** ON ENTRY:
+** str is a comma-separated list:
+**
+** item, item, item
+** where
+** item ::= value
+** | name=value
+** | name="value"
+**
+** Leading and trailing whitespace is ignored
+** everywhere except inside quotes, so the following
+** examples are equal:
+**
+** name=value,foo=bar
+** name="value",foo="bar"
+** name = value , foo = bar
+** name = "value" , foo = "bar"
+**
+** ON EXIT:
+** returns a list of name-value pairs (actually HTAssocList*).
+** For items with no name, just value, the name is
+** the number of order number of that item. E.g.
+** "1" for the first, etc.
+*/
+PUBLIC HTList *HTAA_parseArgList PARAMS((char * str));
+
+/*
+
+Header Line Reader
+
+ */
+
+/* PUBLIC HTAA_setupReader()
+** SET UP HEADER LINE READER, i.e. give
+** the already-read-but-not-yet-processed
+** buffer of text to be read before more
+** is read from the socket.
+** ON ENTRY:
+** start_of_headers is a pointer to a buffer containing
+** the beginning of the header lines
+** (rest will be read from a socket).
+** length is the number of valid characters in
+** 'start_of_headers' buffer.
+** soc is the socket to use when start_of_headers
+** buffer is used up.
+** ON EXIT:
+** returns nothing.
+** Subsequent calls to HTAA_getUnfoldedLine()
+** will use this buffer first and then
+** proceed to read from socket.
+*/
+PUBLIC void HTAA_setupReader PARAMS((char * start_of_headers,
+ int length,
+ void * handle,
+ int soc));
+
+
+/* PUBLIC HTAA_getUnfoldedLine()
+** READ AN UNFOLDED HEADER LINE FROM SOCKET
+** ON ENTRY:
+** HTAA_setupReader must absolutely be called before
+** this function to set up internal buffer.
+**
+** ON EXIT:
+** returns a newly-allocated character string representing
+** the read line. The line is unfolded, i.e.
+** lines that begin with whitespace are appended
+** to current line. E.g.
+**
+** Field-Name: Blaa-Blaa
+** This-Is-A-Continuation-Line
+** Here-Is_Another
+**
+** is seen by the caller as:
+**
+** Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
+**
+*/
+PUBLIC char *HTAA_getUnfoldedLine NOPARAMS;
+
+#endif /* NOT HTAAUTIL_H */
+/*
+
+ End of file HTAAUtil.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.c
new file mode 100644
index 00000000000..2147e23f93e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.c
@@ -0,0 +1,221 @@
+
+/* MODULE HTACL.c
+** ACCESS CONTROL LIST ROUTINES
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+** MD Mark Donszelmann duns@vxdeop.cern.ch
+**
+** HISTORY:
+** 8 Nov 93 MD (VMS only) case insensitive compare reading acl entry, filename
+**
+**
+** BUGS:
+**
+**
+*/
+
+
+#include "HTUtils.h"
+
+/*#include <stdio.h> included by HTUtils.h -- FM *//* FILE */
+#include <string.h>
+
+#include "HTAAFile.h" /* File routines */
+#include "HTGroup.h" /* GroupDef */
+#include "HTACL.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+/* PRIVATE HTAA_getAclFilename()
+** RESOLVE THE FULL PATHNAME OF ACL FILE FOR A GIVEN FILE
+** ON ENTRY:
+** path is the pathname of the file for which to
+** ACL file should be found.
+**
+** ACL filename is computed by replacing
+** the filename by .www_acl in the pathname
+** (this is done to a local copy, of course).
+**
+** ON EXIT:
+** returns the absolute pathname of ACL file
+** (which is automatically freed next time
+** this fuction is called).
+*/
+PRIVATE char *HTAA_getAclFilename ARGS1(CONST char *, pathname)
+{
+ static char * local_copy = NULL;
+ static char * acl_path = NULL;
+ char * directory = NULL;
+ char * filename = NULL;
+
+ StrAllocCopy(local_copy, pathname); /* Also frees local_copy */
+ /* from previous call. */
+
+ directory = local_copy;
+ filename = strrchr(directory, '/');
+ if (!filename) { /* No path in front of filename */
+ directory = "."; /* So use current directory */
+ filename = local_copy; /* and the pathname itself is the filename */
+ }
+ else {
+ *filename = '\0'; /* Truncate filename off from directory path */
+ filename++; /* and the filename begins from the next character */
+ }
+
+ StrAllocCopy(acl_path, directory); /* Also frees acl_path */
+ /* from previous call. */
+ StrAllocCat(acl_path, "/");
+ StrAllocCat(acl_path, ACL_FILE_NAME);
+
+ return acl_path;
+}
+
+
+/* PUBLIC HTAA_openAcl()
+** OPEN THE ACL FILE FOR THE GIVEN DOCUMENT
+** ON ENTRY:
+** pathname is the absolute pathname of
+** the file to be accessed.
+**
+** ON EXIT:
+** returns the FILE* to open ACL.
+** NULL, if ACL not found.
+*/
+PUBLIC FILE *HTAA_openAcl ARGS1(CONST char *, pathname)
+{
+ return fopen(HTAA_getAclFilename(pathname), "r");
+}
+
+
+/* PUBLIC HTAA_closeAcl()
+** CLOSE ACL FILE
+** ON ENTRY:
+** acl_file is Access Control List file to close.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PUBLIC void HTAA_closeAcl ARGS1(FILE *, acl_file)
+{
+ if (acl_file) fclose(acl_file);
+}
+
+
+/* PUBLIC HTAA_getAclEntry()
+** CONSULT THE ACCESS CONTROL LIST AND
+** GIVE A LIST OF GROUPS (AND USERS)
+** AUTHORIZED TO ACCESS A GIVEN FILE
+** ON ENTRY:
+** acl_file is an open ACL file.
+** pathname is the absolute pathname of
+** the file to be accessed.
+** method is the method for which access is wanted.
+**
+** ALC FILE FORMAT:
+**
+** template : method, method, ... : group@addr, user, group, ...
+**
+** The last item is in fact in exactly the same format as
+** group definition in group file, i.e. everything that
+** follows the 'groupname:' part,
+** e.g.
+** user, group, user@address, group@address,
+** (user,group,...)@(address, address, ...)
+**
+** ON EXIT:
+** returns NULL, if there is no entry for the file in the ACL,
+** or ACL doesn't exist.
+** If there is, a GroupDef object containing the
+** group and user names allowed to access the file
+** is returned (this is automatically freed
+** next time this function is called).
+** IMPORTANT:
+** Returns the first entry with matching template and
+** method. This function should be called multiple times
+** to process all the valid entries (until it returns NULL).
+** This is because there can be multiple entries like:
+**
+** *.html : get,put : ari,timbl,robert
+** *.html : get : jim,james,jonathan,jojo
+**
+** NOTE:
+** The returned group definition may well contain references
+** to groups defined in group file. Therefore these references
+** must be resolved according to that rule file by function
+** HTAA_resolveGroupReferences() (group file is read in by
+** HTAA_readGroupFile()) and after that access authorization
+** can be checked with function HTAA_userAndInetGroup().
+*/
+PUBLIC GroupDef *HTAA_getAclEntry ARGS3(FILE *, acl_file,
+ CONST char *, pathname,
+ HTAAMethod, method)
+{
+ static GroupDef * group_def = NULL;
+ CONST char * filename;
+ int len;
+ char *buf;
+
+ if (!acl_file) return NULL; /* ACL doesn't exist */
+
+ if (group_def) {
+ GroupDef_delete(group_def); /* From previous call */
+ group_def = NULL;
+ }
+
+ if (!(filename = strrchr(pathname, '/')))
+ filename = pathname;
+ else filename++; /* Skip slash */
+
+ len = strlen(filename);
+
+ if (!(buf = (char*)malloc((strlen(filename)+2)*sizeof(char))))
+ outofmem(__FILE__, "HTAA_getAuthorizedGroups");
+
+ while (EOF != HTAAFile_readField(acl_file, buf, len+1)) {
+#ifdef VMS
+ if (HTAA_templateCaseMatch(buf, filename)) {
+#else /* not VMS */
+ if (HTAA_templateMatch(buf, filename)) {
+#endif /* not VMS */
+ HTList *methods = HTList_new();
+ HTAAFile_readList(acl_file, methods, MAX_METHODNAME_LEN);
+ if (TRACE) {
+ fprintf(stderr,
+ "Filename '%s' matched template '%s', allowed methods:",
+ filename, buf);
+ }
+ if (HTAAMethod_inList(method, methods)) { /* right method? */
+ if (TRACE)
+ fprintf(stderr, " METHOD OK\n");
+ HTList_delete(methods);
+ methods = NULL;
+ FREE(buf);
+ group_def = HTAA_parseGroupDef(acl_file);
+ /*
+ ** HTAA_parseGroupDef() already reads the record
+ ** separator so we don't call HTAAFile_nextRec().
+ */
+ return group_def;
+ } else if (TRACE) {
+ fprintf(stderr, " METHOD NOT FOUND\n");
+ }
+ HTList_delete(methods);
+ methods = NULL;
+ } /* if template match */
+ else {
+ if (TRACE) {
+ fprintf(stderr,
+ "Filename '%s' didn't match template '%s'\n",
+ filename, buf);
+ }
+ }
+
+ HTAAFile_nextRec(acl_file);
+ } /* while not eof */
+ FREE(buf);
+
+ return NULL; /* No entry for requested file */
+ /* (or an empty entry). */
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.h
new file mode 100644
index 00000000000..c0367c9d214
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTACL.h
@@ -0,0 +1,109 @@
+/* ACCESS CONTROL LIST ROUTINES
+
+ */
+
+#ifndef HTACL_H
+#define HTACL_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTAAUtil.h"
+#include "HTGroup.h"
+
+#ifdef SHORT_NAMES
+#define HTAAoACL HTAA_openAcl
+#define HTAAcACL HTAA_closeAcl
+#define HTAAgAEn HTAA_getAclEntry
+#endif /* SHORT_NAMES */
+
+/*
+
+Opening Access Control List File
+
+ */
+
+/* PUBLIC HTAA_openAcl()
+** OPEN THE ACL FILE FOR THE GIVEN DOCUMENT
+** ON ENTRY:
+** pathname is the absolute pathname of
+** the file to be accessed.
+**
+** ON EXIT:
+** returns the FILE* to open ACL.
+** NULL, if ACL not found.
+*/
+PUBLIC FILE *HTAA_openAcl PARAMS((CONST char * pathname));
+
+
+/* PUBLIC HTAA_closeAcl()
+** CLOSE ACL FILE
+** ON ENTRY:
+** acl_file is Access Control List file to close.
+**
+** ON EXIT:
+** returns nothing.
+*/
+PUBLIC void HTAA_closeAcl PARAMS((FILE * acl_file));
+/*
+
+Getting ACL Entry
+
+ */
+
+/* PUBLIC HTAA_getAclEntry()
+** CONSULT THE ACCESS CONTROL LIST AND
+** GIVE A LIST OF GROUPS (AND USERS)
+** AUTHORIZED TO ACCESS A GIVEN FILE
+** ON ENTRY:
+** acl_file is an open ACL file.
+** pathname is the absolute pathname of
+** the file to be accessed.
+** method is the method for which access is wanted.
+**
+** ALC FILE FORMAT:
+**
+** template : method, method, ... : group@addr, user, group, ...
+**
+** The last item is in fact in exactly the same format as
+** group definition in group file, i.e. everything that
+** follows the 'groupname:' part,
+** e.g.
+** user, group, user@address, group@address,
+** (user,group,...)@(address, address, ...)
+**
+** ON EXIT:
+** returns NULL, if there is no entry for the file in the ACL,
+** or ACL doesn't exist.
+** If there is, a GroupDef object containing the
+** group and user names allowed to access the file
+** is returned (this is automatically freed
+** next time this function is called).
+** IMPORTANT:
+** Returns the first entry with matching template and
+** method. This function should be called multiple times
+** to process all the valid entries (until it returns NULL).
+** This is because there can be multiple entries like:
+**
+** *.html : get,put : ari,timbl,robert
+** *.html : get : jim,james,jonathan,jojo
+**
+** NOTE:
+** The returned group definition may well contain references
+** to groups defined in group file. Therefore these references
+** must be resolved according to that rule file by function
+** HTAA_resolveGroupReferences() (group file is read in by
+** HTAA_readGroupFile()) and after that access authorization
+** can be checked with function HTAA_userAndInetGroup().
+*/
+PUBLIC GroupDef *HTAA_getAclEntry PARAMS((FILE * acl_file,
+ CONST char * pathname,
+ HTAAMethod method));
+/*
+
+ */
+
+#endif /* not HTACL_H */
+/*
+
+ End of file HTACL.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.c
new file mode 100644
index 00000000000..7d4def15269
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.c
@@ -0,0 +1,1370 @@
+/* Access Manager HTAccess.c
+** ==============
+**
+** Authors
+** TBL Tim Berners-Lee timbl@info.cern.ch
+** JFG Jean-Francois Groff jfg@dxcern.cern.ch
+** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
+** FM Foteos Macrides macrides@sci.wfeb.edu
+** PDM Danny Mayer mayer@ljo.dec.com
+**
+** History
+** 8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
+** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
+** 6 Oct 92 Moved HTClientHost and logfile into here. TBL
+** 17 Dec 92 Tn3270 added, bug fix. DD
+** 4 Feb 93 Access registration, Search escapes bad chars TBL
+** PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
+** 28 May 93 WAIS gateway explicit if no WAIS library linked in.
+** 31 May 94 Added DIRECT_WAIS support for VMS. FM
+** 27 Jan 95 Fixed proxy support to use NNTPSERVER for checking
+** whether or not to use the proxy server. PDM
+** 27 Jan 95 Ensured that proxy service will be overridden for files
+** on the local host (because HTLoadFile() doesn't try ftp
+** for those) and will substitute ftp for remote files. FM
+** 28 Jan 95 Tweeked PDM's proxy override mods to handle port info
+** for news and wais URL's. FM
+**
+** Bugs
+** This module assumes that that the graphic object is hypertext, as it
+** needs to select it when it has been loaded. A superclass needs to be
+** defined which accepts select and select_anchor.
+*/
+
+#ifdef VMS
+#define DIRECT_WAIS
+#endif /* VMS */
+
+#include "HTUtils.h"
+#include "HTTP.h"
+#include "HTAlert.h"
+/*
+** Implements:
+*/
+#include "HTAccess.h"
+
+/*
+** Uses:
+*/
+#include "HTParse.h"
+#include "HTML.h" /* SCW */
+
+#ifndef NO_RULES
+#include "HTRules.h"
+#endif
+
+#include "HTList.h"
+#include "HText.h" /* See bugs above */
+#include "HTAlert.h"
+#include "HTCJK.h"
+#include "UCMap.h"
+#include "GridText.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern HTCJKlang HTCJK;
+
+/*
+** These flags may be set to modify the operation of this module
+*/
+PUBLIC char * HTClientHost = NULL; /* Name of remote login host if any */
+PUBLIC FILE * HTlogfile = NULL; /* File to which to output one-liners */
+PUBLIC BOOL HTSecure = NO; /* Disable access for telnet users? */
+
+PUBLIC BOOL using_proxy = NO; /* are we using a proxy gateway? */
+
+/*
+** To generate other things, play with these:
+*/
+PUBLIC HTFormat HTOutputFormat = NULL;
+PUBLIC HTStream* HTOutputStream = NULL; /* For non-interactive, set this */
+
+PRIVATE HTList * protocols = NULL; /* List of registered protocol descriptors */
+
+PUBLIC char *use_this_url_instead = NULL;
+
+PRIVATE int pushed_assume_LYhndl = -1; /* see LYUC* functions below - kw */
+PRIVATE char * pushed_assume_MIMEname = NULL;
+
+PRIVATE void free_protocols NOARGS
+{
+ HTList_delete(protocols);
+ protocols = NULL;
+ FREE(pushed_assume_MIMEname); /* shouldn't happen, just in case - kw */
+}
+
+/* Register a Protocol. HTRegisterProtocol()
+** --------------------
+*/
+PUBLIC BOOL HTRegisterProtocol ARGS1(
+ HTProtocol *, protocol)
+{
+ if (!protocols) {
+ protocols = HTList_new();
+ atexit(free_protocols);
+ }
+ HTList_addObject(protocols, protocol);
+ return YES;
+}
+
+
+/* Register all known protocols. HTAccessInit()
+** -----------------------------
+**
+** Add to or subtract from this list if you add or remove protocol
+** modules. This routine is called the first time the protocol list
+** is needed, unless any protocols are already registered, in which
+** case it is not called. Therefore the application can override
+** this list.
+**
+** Compiling with NO_INIT prevents all known protocols from being
+** forced in at link time.
+*/
+#ifndef NO_INIT
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol, HTTP);
+extern GLOBALREF (HTProtocol, HTTPS);
+extern GLOBALREF (HTProtocol, HTFile);
+extern GLOBALREF (HTProtocol, HTTelnet);
+extern GLOBALREF (HTProtocol, HTTn3270);
+extern GLOBALREF (HTProtocol, HTRlogin);
+#ifndef DECNET
+extern GLOBALREF (HTProtocol, HTFTP);
+extern GLOBALREF (HTProtocol, HTNews);
+extern GLOBALREF (HTProtocol, HTNNTP);
+extern GLOBALREF (HTProtocol, HTNewsPost);
+extern GLOBALREF (HTProtocol, HTNewsReply);
+extern GLOBALREF (HTProtocol, HTSNews);
+extern GLOBALREF (HTProtocol, HTSNewsPost);
+extern GLOBALREF (HTProtocol, HTSNewsReply);
+extern GLOBALREF (HTProtocol, HTGopher);
+extern GLOBALREF (HTProtocol, HTCSO);
+extern GLOBALREF (HTProtocol, HTFinger);
+#ifdef DIRECT_WAIS
+extern GLOBALREF (HTProtocol, HTWAIS);
+#endif /* DIRECT_WAIS */
+#endif /* !DECNET */
+#else
+GLOBALREF HTProtocol HTTP, HTTPS, HTFile, HTTelnet, HTTn3270, HTRlogin;
+#ifndef DECNET
+GLOBALREF HTProtocol HTFTP, HTNews, HTNNTP, HTNewsPost, HTNewsReply;
+GLOBALREF HTProtocol HTSNews, HTSNewsPost, HTSNewsReply;
+GLOBALREF HTProtocol HTGopher, HTCSO, HTFinger;
+#ifdef DIRECT_WAIS
+GLOBALREF HTProtocol HTWAIS;
+#endif /* DIRECT_WAIS */
+#endif /* !DECNET */
+#endif /* GLOBALREF_IS_MACRO */
+
+PRIVATE void HTAccessInit NOARGS /* Call me once */
+{
+ HTRegisterProtocol(&HTTP);
+ HTRegisterProtocol(&HTTPS);
+ HTRegisterProtocol(&HTFile);
+ HTRegisterProtocol(&HTTelnet);
+ HTRegisterProtocol(&HTTn3270);
+ HTRegisterProtocol(&HTRlogin);
+#ifndef DECNET
+ HTRegisterProtocol(&HTFTP);
+ HTRegisterProtocol(&HTNews);
+ HTRegisterProtocol(&HTNNTP);
+ HTRegisterProtocol(&HTNewsPost);
+ HTRegisterProtocol(&HTNewsReply);
+ HTRegisterProtocol(&HTSNews);
+ HTRegisterProtocol(&HTSNewsPost);
+ HTRegisterProtocol(&HTSNewsReply);
+ HTRegisterProtocol(&HTGopher);
+ HTRegisterProtocol(&HTCSO);
+ HTRegisterProtocol(&HTFinger);
+#ifdef DIRECT_WAIS
+ HTRegisterProtocol(&HTWAIS);
+#endif /* DIRECT_WAIS */
+#endif /* !DECNET */
+ LYRegisterLynxProtocols();
+}
+#endif /* !NO_INIT */
+
+/* Check for proxy override. override_proxy()
+** -------------------------
+**
+** Check the no_proxy environment variable to get the list
+** of hosts for which proxy server is not consulted.
+**
+** no_proxy is a comma- or space-separated list of machine
+** or domain names, with optional :port part. If no :port
+** part is present, it applies to all ports on that domain.
+**
+** Example:
+** no_proxy="cern.ch,some.domain:8001"
+**
+** Use "*" to override all proxy service:
+** no_proxy="*"
+*/
+PUBLIC BOOL override_proxy ARGS1(
+ CONST char *, addr)
+{
+ CONST char * no_proxy = getenv("no_proxy");
+ char * p = NULL;
+ char * at = NULL;
+ char * host = NULL;
+ char * Host = NULL;
+ char * acc_method = NULL;
+ int port = 0;
+ int h_len = 0;
+
+ /*
+ * Check for global override.
+ */
+ if (no_proxy) {
+ if (!strcmp(no_proxy, "*"))
+ return YES;
+ }
+
+ /*
+ * Never proxy file:// URLs if they are on the local host.
+ * HTLoadFile() will not attempt ftp for those if direct
+ * access fails. We'll check that first, in case no_proxy
+ * hasn't been defined. - FM
+ */
+ if (!addr)
+ return NO;
+ if (!(host = HTParse(addr, "", PARSE_HOST)))
+ return NO;
+ if (!*host) {
+ FREE(host);
+ return NO;
+ }
+ Host = (((at = strchr(host, '@')) != NULL) ? (at+1) : host);
+
+ if ((acc_method = HTParse(addr, "", PARSE_ACCESS))) {
+ if (!strcmp("file", acc_method) &&
+ (!strcmp(Host, "localhost") ||
+#ifdef VMS
+ !strcasecomp(Host, HTHostName())
+#else
+ !strcmp(Host, HTHostName())
+#endif /* VMS */
+ )) {
+ FREE(host);
+ FREE(acc_method);
+ return YES;
+ }
+ FREE(acc_method);
+ }
+
+ if (!no_proxy) {
+ FREE(host);
+ return NO;
+ }
+
+ if (NULL != (p = strrchr(Host, ':'))) { /* Port specified */
+ *p++ = 0; /* Chop off port */
+ port = atoi(p);
+ } else { /* Use default port */
+ acc_method = HTParse(addr, "", PARSE_ACCESS);
+ if (acc_method != NULL) {
+ if (!strcmp(acc_method, "http")) port = 80;
+ else if (!strcmp(acc_method, "https")) port = 443;
+ else if (!strcmp(acc_method, "ftp")) port = 21;
+ else if (!strcmp(acc_method, "gopher")) port = 70;
+ else if (!strcmp(acc_method, "cso")) port = 105;
+ else if (!strcmp(acc_method, "news")) port = 119;
+ else if (!strcmp(acc_method, "nntp")) port = 119;
+ else if (!strcmp(acc_method, "newspost")) port = 119;
+ else if (!strcmp(acc_method, "newsreply")) port = 119;
+ else if (!strcmp(acc_method, "snews")) port = 563;
+ else if (!strcmp(acc_method, "snewspost")) port = 563;
+ else if (!strcmp(acc_method, "snewsreply")) port = 563;
+ else if (!strcmp(acc_method, "wais")) port = 210;
+ else if (!strcmp(acc_method, "finger")) port = 79;
+ FREE(acc_method);
+ }
+ }
+ if (!port)
+ port = 80; /* Default */
+ h_len = strlen(Host);
+
+ while (*no_proxy) {
+ CONST char * end;
+ CONST char * colon = NULL;
+ int templ_port = 0;
+ int t_len;
+
+ while (*no_proxy && (WHITE(*no_proxy) || *no_proxy == ','))
+ no_proxy++; /* Skip whitespace and separators */
+
+ end = no_proxy;
+ while (*end && !WHITE(*end) && *end != ',') { /* Find separator */
+ if (*end == ':') colon = end; /* Port number given */
+ end++;
+ }
+
+ if (colon) {
+ templ_port = atoi(colon+1);
+ t_len = colon - no_proxy;
+ }
+ else {
+ t_len = end - no_proxy;
+ }
+
+ if ((!templ_port || templ_port == port) &&
+ (t_len > 0 && t_len <= h_len &&
+ !strncasecomp(Host + h_len - t_len, no_proxy, t_len))) {
+ FREE(host);
+ return YES;
+ }
+ if (*end)
+ no_proxy = (end + 1);
+ else
+ break;
+ }
+
+ FREE(host);
+ return NO;
+}
+
+/* Find physical name and access protocol get_physical()
+** --------------------------------------
+**
+** On entry,
+** addr must point to the fully qualified hypertext reference.
+** anchor a pareent anchor with whose address is addr
+**
+** On exit,
+** returns HT_NO_ACCESS Error has occured.
+** HT_OK Success
+*/
+PRIVATE int get_physical ARGS2(
+ CONST char *, addr,
+ HTParentAnchor *, anchor)
+{
+ char * acc_method = NULL; /* Name of access method */
+ char * physical = NULL;
+ char * Server_addr = NULL;
+
+#ifndef NO_RULES
+ physical = HTTranslate(addr);
+ if (!physical) {
+ return HT_FORBIDDEN;
+ }
+ if (anchor->isISMAPScript == TRUE) {
+ StrAllocCat(physical, "?0,0");
+ if (TRACE)
+ fprintf(stderr, "HTAccess: Appending '?0,0' coordinate pair.\n");
+ }
+ HTAnchor_setPhysical(anchor, physical);
+ FREE(physical); /* free our copy */
+#else
+ if (anchor->isISMAPScript == TRUE) {
+ StrAllocCopy(physical, addr);
+ StrAllocCat(physical, "?0,0");
+ if (TRACE)
+ fprintf(stderr, "HTAccess: Appending '?0,0' coordinate pair.\n");
+ HTAnchor_setPhysical(anchor, physical);
+ FREE(physical); /* free our copy */
+ } else {
+ HTAnchor_setPhysical(anchor, addr);
+ }
+#endif /* NO_RULES */
+
+ acc_method = HTParse(HTAnchor_physical(anchor),
+ "file:", PARSE_ACCESS);
+
+ /*
+ ** Check whether gateway access has been set up for this.
+ **
+ ** This function can be replaced by the rule system above.
+ */
+#define USE_GATEWAYS
+#ifdef USE_GATEWAYS
+ /*
+ ** Make sure the using_proxy variable is FALSE.
+ */
+ using_proxy = NO;
+
+ if (!strcasecomp(acc_method, "news")) {
+ /*
+ ** News is different, so we need to check the name of the server,
+ ** as well as the default port for selective exclusions.
+ */
+ char *host = NULL;
+ if ((host = HTParse(addr, "", PARSE_HOST))) {
+ if (strchr(host, ':') == NULL) {
+ StrAllocCopy(Server_addr, "news://");
+ StrAllocCat(Server_addr, host);
+ StrAllocCat(Server_addr, ":119/");
+ }
+ FREE(host);
+ } else if (getenv("NNTPSERVER") != NULL) {
+ StrAllocCopy(Server_addr, "news://");
+ StrAllocCat(Server_addr, (char *)getenv("NNTPSERVER"));
+ StrAllocCat(Server_addr, ":119/");
+ }
+ } else if (!strcasecomp(acc_method, "wais")) {
+ /*
+ ** Wais also needs checking of the default port
+ ** for selective exclusions.
+ */
+ char *host = NULL;
+ if ((host = HTParse(addr, "", PARSE_HOST))) {
+ if (!(strchr(host, ':'))) {
+ StrAllocCopy(Server_addr, "wais://");
+ StrAllocCat(Server_addr, host);
+ StrAllocCat(Server_addr, ":210/");
+ }
+ FREE(host);
+ }
+ else
+ StrAllocCopy(Server_addr, addr);
+ } else {
+ StrAllocCopy(Server_addr, addr);
+ }
+
+ if (!override_proxy(Server_addr)) {
+ char * gateway_parameter, *gateway, *proxy;
+
+ /*
+ ** Search for gateways.
+ */
+ gateway_parameter = (char *)calloc(1, (strlen(acc_method) + 20));
+ if (gateway_parameter == NULL)
+ outofmem(__FILE__, "HTLoad");
+ strcpy(gateway_parameter, "WWW_");
+ strcat(gateway_parameter, acc_method);
+ strcat(gateway_parameter, "_GATEWAY");
+ gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
+
+ /*
+ ** Search for proxy servers.
+ */
+ if (!strcmp(acc_method, "file"))
+ /*
+ ** If we got to here, a file URL is for ftp on a remote host. - FM
+ */
+ strcpy(gateway_parameter, "ftp");
+ else
+ strcpy(gateway_parameter, acc_method);
+ strcat(gateway_parameter, "_proxy");
+ proxy = (char *)getenv(gateway_parameter);
+ FREE(gateway_parameter);
+
+ if (TRACE && gateway)
+ fprintf(stderr, "Gateway found: %s\n", gateway);
+ if (TRACE && proxy)
+ fprintf(stderr, "proxy server found: %s\n", proxy);
+
+ /*
+ ** Proxy servers have precedence over gateway servers.
+ */
+ if (proxy) {
+ char * gatewayed = NULL;
+ StrAllocCopy(gatewayed,proxy);
+ /*
+ ** Ensure that the proxy server uses ftp for file URLs. - FM
+ */
+ if (!strncmp(addr, "file", 4)) {
+ StrAllocCat(gatewayed, "ftp");
+ StrAllocCat(gatewayed, (addr + 4));
+ } else
+ StrAllocCat(gatewayed, addr);
+ using_proxy = YES;
+ if (anchor->isISMAPScript == TRUE)
+ StrAllocCat(gatewayed, "?0,0");
+ HTAnchor_setPhysical(anchor, gatewayed);
+ FREE(gatewayed);
+ FREE(acc_method);
+
+ acc_method = HTParse(HTAnchor_physical(anchor),
+ "http:", PARSE_ACCESS);
+
+ } else if (gateway) {
+ char * path = HTParse(addr, "",
+ PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
+ /* Chop leading / off to make host into part of path */
+ char * gatewayed = HTParse(path+1, gateway, PARSE_ALL);
+ FREE(path);
+ HTAnchor_setPhysical(anchor, gatewayed);
+ FREE(gatewayed);
+ FREE(acc_method);
+
+ acc_method = HTParse(HTAnchor_physical(anchor),
+ "http:", PARSE_ACCESS);
+ }
+ }
+ FREE(Server_addr);
+#endif /* use gateways */
+
+ /*
+ ** Search registered protocols to find suitable one.
+ */
+ {
+ int i, n;
+#ifndef NO_INIT
+ if (!protocols) HTAccessInit();
+#endif
+ n = HTList_count(protocols);
+ for (i = 0; i < n; i++) {
+ HTProtocol *p = (HTProtocol *)HTList_objectAt(protocols, i);
+ if (!strcmp(p->name, acc_method)) {
+ HTAnchor_setProtocol(anchor, p);
+ FREE(acc_method);
+ return (HT_OK);
+ }
+ }
+ }
+
+ FREE(acc_method);
+ return HT_NO_ACCESS;
+}
+
+/*
+ * Temporarily set the int UCLYhndl_for_unspec and string
+ * UCLYhndl_for_unspec used for charset "assuming" to the values
+ * implied by a HTParentAnchor's UCStages, after saving the current
+ * values for later restoration. - kw
+ * @@@ These functions may not really belong here, but where else?
+ * I want the "pop" to occur as soon as possible after loading
+ * has finished. - kw @@@
+ */
+
+extern char*UCAssume_MIMEcharset;
+
+PUBLIC void LYUCPushAssumed ARGS1(
+ HTParentAnchor *, anchor)
+{
+ int anchor_LYhndl = -1;
+ LYUCcharset * anchor_UCI = NULL;
+ if (anchor) {
+ anchor_LYhndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_PARSER);
+ if (anchor_LYhndl >= 0)
+ anchor_UCI = HTAnchor_getUCInfoStage(anchor,
+ UCT_STAGE_PARSER);
+ if (anchor_UCI && anchor_UCI->MIMEname) {
+ pushed_assume_MIMEname = UCAssume_MIMEcharset;
+ UCAssume_MIMEcharset = NULL;
+ StrAllocCopy(UCAssume_MIMEcharset, anchor_UCI->MIMEname);
+ pushed_assume_LYhndl = anchor_LYhndl;
+ UCLYhndl_for_unspec = anchor_LYhndl;
+ return;
+ }
+ }
+ pushed_assume_LYhndl = -1;
+ FREE(pushed_assume_MIMEname);
+}
+/*
+ * Restore the int UCLYhndl_for_unspec and string
+ * UCLYhndl_for_unspec used for charset "assuming" from the values
+ * saved by LYUCPushAssumed, if any. - kw
+ */
+PRIVATE int LYUCPopAssumed NOARGS
+{
+ if (pushed_assume_LYhndl >= 0) {
+ UCLYhndl_for_unspec = pushed_assume_LYhndl;
+ pushed_assume_LYhndl = -1;
+ FREE(UCAssume_MIMEcharset);
+ UCAssume_MIMEcharset = pushed_assume_MIMEname;
+ pushed_assume_MIMEname = NULL;
+ return UCLYhndl_for_unspec;
+ }
+ return -1;
+}
+
+/* Load a document HTLoad()
+** ---------------
+**
+** This is an internal routine, which has an address AND a matching
+** anchor. (The public routines are called with one OR the other.)
+**
+** On entry,
+** addr must point to the fully qualified hypertext reference.
+** anchor a pareent anchor with whose address is addr
+**
+** On exit,
+** returns <0 Error has occured.
+** HT_LOADED Success
+** HT_NO_DATA Success, but no document loaded.
+** (telnet sesssion started etc)
+*/
+PRIVATE int HTLoad ARGS4(
+ CONST char *, addr,
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream *, sink)
+{
+ HTProtocol *p;
+ int status = get_physical(addr, anchor);
+ if (status == HT_FORBIDDEN) {
+ return HTLoadError(sink, 500, "Access forbidden by rule");
+ }
+ if (status < 0)
+ return status; /* Can't resolve or forbidden */
+
+ p = (HTProtocol *)HTAnchor_protocol(anchor);
+ anchor->underway = TRUE; /* Hack to deal with caching */
+ status= (*(p->load))(HTAnchor_physical(anchor),
+ anchor, format_out, sink);
+ anchor->underway = FALSE;
+ LYUCPopAssumed();
+ return status;
+}
+
+/* Get a save stream for a document HTSaveStream()
+** --------------------------------
+*/
+PUBLIC HTStream *HTSaveStream ARGS1(
+ HTParentAnchor *, anchor)
+{
+ HTProtocol *p = (HTProtocol *)HTAnchor_protocol(anchor);
+ if (!p)
+ return NULL;
+
+ return (*p->saveStream)(anchor);
+}
+
+extern char LYinternal_flag; /* from LYMainLoop.c */
+
+/* Load a document - with logging etc HTLoadDocument()
+** ----------------------------------
+**
+** - Checks or documents already loaded
+** - Logs the access
+** - Allows stdin filter option
+** - Trace ouput and error messages
+**
+** On Entry,
+** anchor is the node_anchor for the document
+** full_address The address of the document to be accessed.
+** filter if YES, treat stdin as HTML
+**
+** On Exit,
+** returns YES Success in opening document
+** NO Failure
+*/
+
+extern char LYforce_no_cache; /* from GridText.c */
+extern char LYoverride_no_cache; /* from LYMainLoop.c */
+extern char * HTLoadedDocumentURL NOPARAMS; /* in GridText.c */
+extern BOOL HText_hasNoCacheSet PARAMS((HText *text)); /* in GridText.c */
+extern BOOL reloading;
+extern BOOL permanent_redirection;
+#ifdef DIRED_SUPPORT
+extern BOOLEAN lynx_edit_mode;
+#endif
+
+PRIVATE BOOL HTLoadDocument ARGS4(
+ CONST char *, full_address,
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ int status;
+ HText * text;
+ CONST char * address_to_load = full_address;
+ char *cp;
+ BOOL ForcingNoCache = LYforce_no_cache;
+ static int redirection_attempts = 0;
+
+ if (TRACE)
+ fprintf (stderr, "HTAccess: loading document %s\n", address_to_load);
+
+ /*
+ ** Free use_this_url_instead and reset permanent_redirection
+ ** if not done elsewhere. - FM
+ */
+ FREE(use_this_url_instead);
+ permanent_redirection = FALSE;
+
+ /*
+ ** Make sure some yoyo doesn't send us 'round in circles
+ ** with redirecting URLs that point back to themselves.
+ ** We'll set the original Lynx limit of 10 redirections
+ ** per requested URL from a user, because the HTTP/1.1
+ ** will no longer specify a restriction to 5, but will
+ ** leave it up to the browser's discretion, in deference
+ ** to Microsoft. - FM
+ */
+ if (redirection_attempts > 10) {
+ redirection_attempts = 0;
+ HTAlert("Redirection limit of 10 URL's reached.");
+ return NO;
+ }
+
+ /*
+ * If this is marked as an internal link but we don't have the
+ * document loaded any more, and we haven't explicitly flagged
+ * that we want to reload with LYforce_no_cache, then something
+ * has disappeared from the cache when we expected it to be still
+ * there. The user probably doesn't expect a new network access.
+ * So if we have POST data and safe is not set in the anchor,
+ * ask for confirmation, and fail if not granted. The exception
+ * are LYNXIMGMAP documents, for which we defer to LYLoadIMGmap
+ * for prompting if necessary. - kw
+ */
+ if (LYinternal_flag && !LYforce_no_cache &&
+ anchor->post_data && !anchor->safe &&
+ (text = (HText *)HTAnchor_document(anchor)) == NULL &&
+ strncmp(full_address, "LYNXIMGMAP:", 11) &&
+ HTConfirm("Document with POST content not found in cache. Resubmit?")
+ != TRUE) {
+ return NO;
+ }
+
+ /*
+ ** If we don't have POST content, check whether this is a previous
+ ** redirecting URL, and keep re-checking until we get to the final
+ ** destination or redirection limit. If we do have POST content,
+ ** we didn't allow permanent redirection, and an interactive user
+ ** will be deciding whether to keep redirecting. - FM
+ */
+ if (!anchor->post_data) {
+ while ((cp = HTAnchor_physical(anchor)) != NULL &&
+ !strncmp(cp, "Location=", 9)) {
+ DocAddress NewDoc;
+
+ if (TRACE) {
+ fprintf (stderr, "HTAccess: '%s' is a redirection URL.\n",
+ anchor->address);
+ fprintf (stderr, "HTAccess: Redirecting to '%s'\n", cp+9);
+ }
+
+ /*
+ ** Don't exceed the redirection_attempts limit. - FM
+ */
+ if (++redirection_attempts > 10) {
+ HTAlert("Redirection limit of 10 URL's reached.");
+ redirection_attempts = 0;
+ FREE(use_this_url_instead);
+ return NO;
+ }
+
+ /*
+ ** Set up the redirection. - FM
+ **/
+ StrAllocCopy(use_this_url_instead, cp+9);
+ NewDoc.address = use_this_url_instead;
+ NewDoc.post_data = NULL;
+ NewDoc.post_content_type = NULL;
+ NewDoc.bookmark = anchor->bookmark;
+ NewDoc.isHEAD = anchor->isHEAD;
+ NewDoc.safe = anchor->safe;
+ anchor = (HTParentAnchor *)HTAnchor_findAddress(&NewDoc);
+ }
+ }
+ /*
+ ** If we had previous redirection, go back and check out
+ ** that the URL under the current restrictions. - FM
+ */
+ if (use_this_url_instead) {
+ FREE(redirecting_url);
+ return(NO);
+ }
+
+ /*
+ ** See if we can use an already loaded document.
+ */
+ if (!LYforce_no_cache && (text = (HText *)HTAnchor_document(anchor))) {
+ /*
+ ** We have a cached rendition of the target document.
+ ** Check if it's OK to re-use it. We consider it OK if:
+ ** (1) the anchor does not have the no_cache element set, or
+ ** (2) we've overridden it, e.g., because we are acting on
+ ** a PREV_DOC command or a link in the History Page and
+ ** it's not a reply from a POST with the LYresubmit_posts
+ ** flag set, or
+ ** (3) we are repositioning within the currently loaded document
+ ** based on the target anchor's address (URL_Reference).
+ *
+ * If DONT_TRACK_INTERNAL_LINKS is defined, HText_AreDifferent()
+ * is used to determine whether (3) applies. If the target address
+ * differs from that of the current document only by a fragment
+ * and the taget address has an appended fragment, repositioning
+ * without reloading is always assumed.
+ * Note that HText_AreDifferent() currently always returns TRUE
+ * if the target has a LYNXIMGMAP URL, so that an internally
+ * generated pseudo-document will normally not be re-used unless
+ * condition (2) appplies. (Condition (1) cannot apply since in
+ * LYMap.c, no_cache is always set in the anchor object). This
+ * doesn't guarantee that the resource from which the MAP element
+ * is taken will be read again (reloaded) when the list of links
+ * for a client-side image map is regenerated, when in some cases
+ * it should (e.g. user requested RELOAD, or HTTP response with
+ * no-cache header and we are not overriding).
+ *
+ * If DONT_TRACK_INTERNAL_LINKS is undefined, a target address that
+ * points to the same URL as the current document may still result in
+ * reloading, depending on whether the original URL-Reference
+ * was given as an internal link in the context of the previously
+ * loaded document. HText_AreDifferent() is not used here for
+ * testing whether we are just repositioning. For an internal
+ * link, the potential callers of this function from mainloop()
+ * down will either avoid making the call (and do the repositioning
+ * differently) or set LYinternal_flag (or LYoverride_no_cache).
+ * Note that (a) LYNXIMGMAP pseudo-documents and (b) The "List Page"
+ * document are treated logically as being part of the document on
+ * which they are based, for the purpose of whether to treat a link
+ * as internal, but the logic for this (by setting LYinternal_flag
+ * as necessary) is implemented elsewhere. There is a specific
+ * test for LYNXIMGMAP here so that the generated pseudo-document
+ * will not be re-used unless LYoverride_no_cache is set. The same
+ * caveat as above applies w.r.t. reloading of the underlying
+ * resource.
+ *
+ ** We also should be checking other aspects of cache
+ ** regulation (e.g., based on an If-Modified-Since check,
+ ** etc.) but the code for doing those other things isn't
+ ** available yet.
+ */
+#ifdef DONT_TRACK_INTERNAL_LINKS
+ if (LYoverride_no_cache || !HText_hasNoCacheSet(text) ||
+ !HText_AreDifferent(anchor, full_address))
+#else
+ if (LYoverride_no_cache ||
+ ((LYinternal_flag || !HText_hasNoCacheSet(text)) &&
+ strncmp(full_address, "LYNXIMGMAP:", 11)))
+#endif /* TRACK_INTERNAL_LINKS */
+ {
+ if (TRACE)
+ fprintf(stderr, "HTAccess: Document already in memory.\n");
+ HText_select(text);
+
+#ifdef DIRED_SUPPORT
+ if (HTAnchor_format(anchor) == WWW_DIRED)
+ lynx_edit_mode = TRUE;
+#endif
+ redirection_attempts = 0;
+ return YES;
+ } else {
+#if NOT_USED_CODE
+ /* disabled 1997-10-28 - kw
+ callers already do this when requested
+ */
+ reloading = TRUE;
+#endif
+ ForcingNoCache = YES;
+ if (TRACE) {
+ fprintf(stderr, "HTAccess: Auto-reloading document.\n");
+ }
+ }
+ }
+
+ /*
+ ** Get the document from the net. If we are auto-reloading,
+ ** the mutable anchor elements from the previous rendition
+ ** should be freed in conjunction with loading of the new
+ ** rendition. - FM
+ */
+ LYforce_no_cache = NO; /* reset after each time through */
+ if (ForcingNoCache) {
+ FREE(anchor->title);
+ }
+ status = HTLoad(address_to_load, anchor, format_out, sink);
+ if (TRACE) {
+ fprintf(stderr, "HTAccess: status=%d\n", status);
+ }
+
+ /*
+ ** Log the access if necessary.
+ */
+ if (HTlogfile) {
+ time_t theTime;
+ time(&theTime);
+ fprintf(HTlogfile, "%24.24s %s %s %s\n",
+ ctime(&theTime),
+ HTClientHost ? HTClientHost : "local",
+ status < 0 ? "FAIL" : "GET",
+ full_address);
+ fflush(HTlogfile); /* Actually update it on disk */
+ if (TRACE)
+ fprintf(stderr, "Log: %24.24s %s %s %s\n",
+ ctime(&theTime),
+ HTClientHost ? HTClientHost : "local",
+ status < 0 ? "FAIL" : "GET",
+ full_address);
+ }
+
+ /*
+ ** Check out what we received from the net.
+ */
+ if (status == HT_REDIRECTING) {
+ /* Exported from HTMIME.c, of all places. *//** NO!! - FM **/
+ /*
+ ** Doing this via HTMIME.c meant that the redirection cover
+ ** page was already loaded before we learned that we want a
+ ** different URL. Also, changing anchor->address, as Lynx
+ ** was doing, meant we could never again access its hash
+ ** table entry, creating an insolvable memory leak. Instead,
+ ** if we had a 301 status and set permanent_redirection,
+ ** we'll load the new URL in anchor->physical, preceded by a
+ ** token, which we can check to make replacements on subsequent
+ ** access attempts. We'll check recursively, and retrieve the
+ ** final URL if we had multiple redirections to it. If we just
+ ** went to HTLoad now, as Lou originally had this, we couldn't do
+ ** Lynx's security checks and alternate handling of some URL types.
+ ** So, instead, we'll go all the way back to the top of getfile
+ ** in LYGetFile.c when the status is HT_REDIRECTING. This may
+ ** seem bizarre, but it works like a charm! - FM
+ */
+ if (TRACE) {
+ fprintf(stderr, "HTAccess: '%s' is a redirection URL.\n",
+ address_to_load);
+ fprintf(stderr, "HTAccess: Redirecting to '%s'\n",
+ redirecting_url);
+ }
+ /*
+ ** Prevent circular references.
+ */
+ if (strcmp(address_to_load, redirecting_url)) { /* if different */
+ /*
+ ** Load token and redirecting url into anchor->physical
+ ** if we had 301 Permanent redirection. HTTP.c does not
+ ** allow this if we have POST content. - FM
+ */
+ if (permanent_redirection) {
+ StrAllocCopy(anchor->physical, "Location=");
+ StrAllocCat(anchor->physical, redirecting_url);
+ }
+
+ /*
+ ** Set up flags before return to getfile. - FM
+ */
+ StrAllocCopy(use_this_url_instead, redirecting_url);
+ if (ForcingNoCache)
+ LYforce_no_cache = YES;
+ ++redirection_attempts;
+ FREE(redirecting_url);
+ permanent_redirection = FALSE;
+ return(NO);
+ }
+ ++redirection_attempts;
+ FREE(redirecting_url);
+ permanent_redirection = FALSE;
+ return(YES);
+ }
+
+ /*
+ ** We did not receive a redirecting URL. - FM
+ */
+ redirection_attempts = 0;
+ FREE(redirecting_url);
+ permanent_redirection = FALSE;
+
+ if (status == HT_LOADED) {
+ if (TRACE) {
+ fprintf(stderr, "HTAccess: `%s' has been accessed.\n",
+ full_address);
+ }
+ return YES;
+ }
+ if (status == HT_PARTIAL_CONTENT) {
+ HTAlert("Loading incomplete.");
+ if (TRACE) {
+ fprintf(stderr, "HTAccess: `%s' has been accessed, partial content.\n",
+ full_address);
+ }
+ return YES;
+ }
+
+ if (status == HT_NO_DATA) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTAccess: `%s' has been accessed, No data left.\n",
+ full_address);
+ }
+ return NO;
+ }
+
+ if (status == HT_NOT_LOADED) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTAccess: `%s' has been accessed, No data loaded.\n",
+ full_address);
+ }
+ return NO;
+ }
+
+ if (status == HT_INTERRUPTED) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTAccess: `%s' has been accessed, transfer interrupted.\n",
+ full_address);
+ }
+/* _HTProgress("Data transfer interrupted."); */
+ return NO;
+ }
+
+ if (status <= 0) { /* Failure in accessing a document */
+ char *temp = NULL;
+ StrAllocCopy(temp, "Can't Access `");
+ StrAllocCat(temp, full_address);
+ StrAllocCat(temp, "'");
+ _HTProgress(temp);
+ FREE(temp);
+ if (TRACE) fprintf(stderr,
+ "HTAccess: Can't access `%s'\n", full_address);
+ HTLoadError(sink, 500, "Unable to access document.");
+ return NO;
+ }
+
+ /*
+ ** If you get this, then please find which routine is returning
+ ** a positive unrecognised error code!
+ */
+ fprintf(stderr,
+ "**** HTAccess: socket or file number returned by obsolete load routine!\n");
+ fprintf(stderr,
+ "**** HTAccess: Internal software error. Please mail lynx_dev@sig.net!\n");
+ fprintf(stderr, "**** HTAccess: Status returned was: %d\n",status);
+ exit(-1);
+
+} /* HTLoadDocument */
+
+/* Load a document from absolute name. HTLoadAbsolute()
+** -----------------------------------
+**
+** On Entry,
+** addr The absolute address of the document to be accessed.
+** filter if YES, treat document as HTML
+**
+** On Exit,
+** returns YES Success in opening document
+** NO Failure
+*/
+PUBLIC BOOL HTLoadAbsolute ARGS1(
+ CONST DocAddress *, docaddr)
+{
+ return HTLoadDocument(docaddr->address,
+ HTAnchor_parent(HTAnchor_findAddress(docaddr)),
+ (HTOutputFormat ? HTOutputFormat : WWW_PRESENT),
+ HTOutputStream);
+}
+
+#ifdef NOT_USED_CODE
+/* Load a document from absolute name to stream. HTLoadToStream()
+** ---------------------------------------------
+**
+** On Entry,
+** addr The absolute address of the document to be accessed.
+** sink if non-NULL, send data down this stream
+**
+** On Exit,
+** returns YES Success in opening document
+** NO Failure
+*/
+PUBLIC BOOL HTLoadToStream ARGS3(
+ CONST char *, addr,
+ BOOL, filter,
+ HTStream *, sink)
+{
+ return HTLoadDocument(addr,
+ HTAnchor_parent(HTAnchor_findAddress(addr)),
+ (HTOutputFormat ? HTOutputFormat : WWW_PRESENT),
+ sink);
+}
+#endif /* NOT_USED_CODE */
+
+/* Load a document from relative name. HTLoadRelative()
+** -----------------------------------
+**
+** On Entry,
+** relative_name The relative address of the document
+** to be accessed.
+**
+** On Exit,
+** returns YES Success in opening document
+** NO Failure
+*/
+PUBLIC BOOL HTLoadRelative ARGS2(
+ CONST char *, relative_name,
+ HTParentAnchor *, here)
+{
+ DocAddress full_address;
+ BOOL result;
+ char * mycopy = NULL;
+ char * stripped = NULL;
+ char * current_address = HTAnchor_address((HTAnchor*)here);
+
+ full_address.address = NULL;
+ full_address.post_data = NULL;
+ full_address.post_content_type = NULL;
+ full_address.bookmark = NULL;
+ full_address.isHEAD = FALSE;
+ full_address.safe = FALSE;
+
+ StrAllocCopy(mycopy, relative_name);
+
+ stripped = HTStrip(mycopy);
+ full_address.address =
+ HTParse(stripped,
+ current_address,
+ PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
+ result = HTLoadAbsolute(&full_address);
+ /*
+ ** If we got redirection, result will be NO, but use_this_url_instead
+ ** will be set. The calling routine should check both and do whatever
+ ** is appropriate. - FM
+ */
+ FREE(full_address.address);
+ FREE(current_address);
+ FREE(mycopy); /* Memory leak fixed 10/7/92 -- JFG */
+ return result;
+}
+
+/* Load if necessary, and select an anchor. HTLoadAnchor()
+** ----------------------------------------
+**
+** On Entry,
+** destination The child or parenet anchor to be loaded.
+**
+** On Exit,
+** returns YES Success
+** NO Failure
+*/
+PUBLIC BOOL HTLoadAnchor ARGS1(
+ HTAnchor *, destination)
+{
+ HTParentAnchor * parent;
+ BOOL loaded = NO;
+ if (!destination)
+ return NO; /* No link */
+
+ parent = HTAnchor_parent(destination);
+
+ if (HTAnchor_document(parent) == NULL) { /* If not alread loaded */
+ /* TBL 921202 */
+ BOOL result;
+ char * address = HTAnchor_address((HTAnchor*) parent);
+
+ result = HTLoadDocument(address,
+ parent,
+ HTOutputFormat ?
+ HTOutputFormat : WWW_PRESENT,
+ HTOutputStream);
+ FREE(address);
+ if (!result) return NO;
+ loaded = YES;
+ }
+
+ {
+ HText *text = (HText*)HTAnchor_document(parent);
+
+ if (destination != (HTAnchor *)parent) { /* If child anchor */
+ HText_selectAnchor(text, /* Double display? @@ */
+ (HTChildAnchor*)destination);
+ } else {
+ if (!loaded)
+ HText_select(text);
+ }
+ }
+ return YES;
+
+} /* HTLoadAnchor */
+
+/* Search. HTSearch()
+** -------
+**
+** Performs a keyword search on word given by the user. Adds the
+** keyword to the end of the current address and attempts to open
+** the new address.
+**
+** On Entry,
+** *keywords space-separated keyword list or similar search list
+** here is anchor search is to be done on.
+*/
+PRIVATE char hex ARGS1(
+ int, i)
+{
+ char * hexchars = "0123456789ABCDEF";
+ return hexchars[i];
+}
+
+PUBLIC BOOL HTSearch ARGS2(
+ CONST char *, keywords,
+ HTParentAnchor *, here)
+{
+#define acceptable \
+"1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
+
+ char *q, *u;
+ CONST char * p, *s, *e; /* Pointers into keywords */
+ char * address = NULL;
+ BOOL result;
+ char * escaped = (char *)calloc(1, ((strlen(keywords)*3) + 1));
+ static CONST BOOL isAcceptable[96] =
+
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0, /* 2x !"#$%&'()*+,-./ */
+ 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4x @ABCDEFGHIJKLMNO */
+ 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6x `abcdefghijklmno */
+ 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 }; /* 7X pqrstuvwxyz{\}~ DEL */
+
+ if (escaped == NULL)
+ outofmem(__FILE__, "HTSearch");
+
+ StrAllocCopy(address, here->isIndexAction);
+
+ /*
+ ** Convert spaces to + and hex escape unacceptable characters.
+ */
+ for (s = keywords; *s && WHITE(*s); s++) /* Scan */
+ ; /* Skip white space */
+ for (e = s + strlen(s); e > s && WHITE(*(e-1)); e--) /* Scan */
+ ; /* Skip trailers */
+ for (q = escaped, p = s; p < e; p++) { /* Scan stripped field */
+ unsigned char c = (unsigned char)TOASCII(*p);
+ if (WHITE(*p)) {
+ *q++ = '+';
+ } else if (HTCJK != NOCJK) {
+ *q++ = *p;
+ } else if (c>=32 && c<=(unsigned char)127 && isAcceptable[c-32]) {
+ *q++ = *p; /* 930706 TBL for MVS bug */
+ } else {
+ *q++ = '%';
+ *q++ = hex((int)(c >> 4));
+ *q++ = hex((int)(c & 15));
+ }
+ } /* Loop over string */
+ *q = '\0'; /* Terminate escaped string */
+ u = strchr(address, '?'); /* Find old search string */
+ if (u != NULL)
+ *u = '\0'; /* Chop old search off */
+
+ StrAllocCat(address, "?");
+ StrAllocCat(address, escaped);
+ FREE(escaped);
+ result = HTLoadRelative(address, here);
+ FREE(address);
+
+ /*
+ ** If we got redirection, result will be NO, but use_this_url_instead
+ ** will be set. The calling routine should check both and do whatever
+ ** is appropriate. Only an http server (not a gopher or wais server)
+ ** could return redirection. Lynx will go all the way back to its
+ ** mainloop() and subject a redirecting URL to all of its security and
+ ** restrictions checks. - FM
+ */
+ return result;
+}
+
+/* Search Given Indexname. HTSearchAbsolute()
+** -----------------------
+**
+** Performs a keyword search on word given by the user. Adds the
+** keyword to the end of the current address and attempts to open
+** the new address.
+**
+** On Entry,
+** *keywords space-separated keyword list or similar search list
+** *addres is name of object search is to be done on.
+*/
+PUBLIC BOOL HTSearchAbsolute ARGS2(
+ CONST char *, keywords,
+ CONST char *, indexname)
+{
+ DocAddress abs_doc;
+ HTParentAnchor * anchor;
+ abs_doc.address = (char *)indexname;
+ abs_doc.post_data = NULL;
+ abs_doc.post_content_type = NULL;
+ abs_doc.bookmark = NULL;
+ abs_doc.isHEAD = FALSE;
+ abs_doc.safe = FALSE;
+
+ anchor = (HTParentAnchor*)HTAnchor_findAddress(&abs_doc);
+ return HTSearch(keywords, anchor);
+}
+
+#ifdef NOT_USED_CODE
+/* Generate the anchor for the home page. HTHomeAnchor()
+** --------------------------------------
+**
+** As it involves file access, this should only be done once
+** when the program first runs.
+** This is a default algorithm -- browser don't HAVE to use this.
+** But consistency betwen browsers is STRONGLY recommended!
+**
+** Priority order is:
+** 1 WWW_HOME environment variable (logical name, etc)
+** 2 ~/WWW/default.html
+** 3 /usr/local/bin/default.html
+** 4 http://www.w3.org/default.html
+*/
+PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
+{
+ char * my_home_document = NULL;
+ char * home = (char *)getenv(LOGICAL_DEFAULT);
+ char * ref;
+ HTParentAnchor * anchor;
+
+ if (home) {
+ StrAllocCopy(my_home_document, home);
+#define MAX_FILE_NAME 1024 /* @@@ */
+ } else if (HTClientHost) { /* Telnet server */
+ /*
+ ** Someone telnets in, they get a special home.
+ */
+ FILE * fp = fopen(REMOTE_POINTER, "r");
+ char * status;
+ if (fp) {
+ my_home_document = (char*)calloc(1, MAX_FILE_NAME);
+ if (my_home_document == NULL)
+ outofmem(__FILE__, "HTHomeAnchor");
+ status = fgets(my_home_document, MAX_FILE_NAME, fp);
+ if (!status) {
+ FREE(my_home_document);
+ }
+ fclose(fp);
+ }
+ if (my_home_document == NULL)
+ StrAllocCopy(my_home_document, REMOTE_ADDRESS);
+ }
+
+#ifdef unix
+ if (my_home_document == NULL) {
+ FILE * fp = NULL;
+ CONST char * home = (CONST char*)getenv("HOME");
+ if (home != null) {
+ my_home_document = (char *)calloc(1,
+ (strlen(home) + 1 + strlen(PERSONAL_DEFAULT) + 1));
+ if (my_home_document == NULL)
+ outofmem(__FILE__, "HTAnchorHome");
+ sprintf(my_home_document, "%s/%s", home, PERSONAL_DEFAULT);
+ fp = fopen(my_home_document, "r");
+ }
+
+ if (!fp) {
+ StrAllocCopy(my_home_document, LOCAL_DEFAULT_FILE);
+ fp = fopen(my_home_document, "r");
+ }
+ if (fp) {
+ fclose(fp);
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "HTBrowse: No local home document ~/%s or %s\n",
+ PERSONAL_DEFAULT, LOCAL_DEFAULT_FILE);
+ FREE(my_home_document);
+ }
+ }
+#endif /* unix */
+ ref = HTParse((my_home_document ?
+ my_home_document : (HTClientHost ?
+ REMOTE_ADDRESS : LAST_RESORT)),
+ "file:",
+ PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
+ if (my_home_document) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTAccess: Using custom home page %s i.e. address %s\n",
+ my_home_document, ref);
+ FREE(my_home_document);
+ }
+ anchor = (HTParentAnchor*)HTAnchor_findAddress(ref);
+ FREE(ref);
+ return anchor;
+}
+#endif /* NOT_USED_CODE */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.h
new file mode 100644
index 00000000000..2826d13aa0a
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAccess.h
@@ -0,0 +1,325 @@
+/* HTAccess: Access manager for libwww
+ ACCESS MANAGER
+
+ This module keeps a list of valid protocol (naming scheme) specifiers with associated
+ access code. It allows documents to be loaded given various combinations of
+ parameters. New access protocols may be registered at any time.
+
+ Part of the libwww library .
+
+ */
+#ifndef HTACCESS_H
+#define HTACCESS_H
+
+extern char * use_this_url_instead;
+
+/* Definition uses:
+*/
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "tcp.h"
+#include "HTAnchor.h"
+#include "HTFormat.h"
+
+#ifdef SHORT_NAMES
+#define HTClientHost HTClHost
+#define HTSearchAbsolute HTSeAbso
+#define HTOutputStream HTOuStre
+#define HTOutputFormat HTOuForm
+#endif
+
+/* Return codes from load routines:
+**
+** These codes may be returned by the protocol modules,
+** and by the HTLoad routines.
+** In general, positive codes are OK and negative ones are bad.
+*/
+
+#define HT_NO_DATA -9999 /* return code: OK but no data was loaded */
+ /* Typically, other app started or forked */
+
+/*
+
+Default Addresses
+
+ These control the home page selection. To mess with these for normal browses is asking
+ for user confusion.
+
+ */
+#define LOGICAL_DEFAULT "WWW_HOME" /* Defined to be the home page */
+
+#ifndef PERSONAL_DEFAULT
+#define PERSONAL_DEFAULT "WWW/default.html" /* in home directory */
+#endif
+#ifndef LOCAL_DEFAULT_FILE
+#define LOCAL_DEFAULT_FILE "/usr/local/lib/WWW/default.html"
+#endif
+/* If one telnets to a www access point,
+ it will look in this file for home page */
+#ifndef REMOTE_POINTER
+#define REMOTE_POINTER "/etc/www-remote.url" /* can't be file */
+#endif
+/* and if that fails it will use this. */
+#ifndef REMOTE_ADDRESS
+#define REMOTE_ADDRESS "http://www.w3.org/remote.html" /* can't be file */
+#endif
+
+/* If run from telnet daemon and no -l specified, use this file:
+*/
+#ifndef DEFAULT_LOGFILE
+#define DEFAULT_LOGFILE "/usr/adm/www-log/www-log"
+#endif
+
+/* If the home page isn't found, use this file:
+*/
+#ifndef LAST_RESORT
+#define LAST_RESORT "http://www.w3.org/default.html"
+#endif
+
+
+/*
+
+Flags which may be set to control this module
+
+ */
+#ifdef NOT
+extern int HTDiag; /* Flag: load source as plain text */
+#endif /* NOT */
+extern char * HTClientHost; /* Name or number of telnetting host */
+extern FILE * HTlogfile; /* File to output one-liners to */
+extern BOOL HTSecure; /* Disable security holes? */
+extern HTStream* HTOutputStream; /* For non-interactive, set this */
+extern HTFormat HTOutputFormat; /* To convert on load, set this */
+
+/* Check for proxy override. override_proxy()
+**
+** Check the no_proxy environment variable to get the list
+** of hosts for which proxy server is not consulted.
+**
+** no_proxy is a comma- or space-separated list of machine
+** or domain names, with optional :port part. If no :port
+** part is present, it applies to all ports on that domain.
+**
+** Example:
+** no_proxy="cern.ch,some.domain:8001"
+**
+** Use "*" to override all proxy service:
+** no_proxy="*"
+*/
+extern BOOL override_proxy PARAMS((
+ CONST char * addr));
+
+/*
+
+Load a document from relative name
+
+ ON ENTRY,
+
+ relative_name The relative address of the file to be accessed.
+
+ here The anchor of the object being searched
+
+ ON EXIT,
+
+ returns YES Success in opening file
+
+ NO Failure
+
+ */
+extern BOOL HTLoadRelative PARAMS((
+ CONST char * relative_name,
+ HTParentAnchor * here));
+
+
+/*
+
+Load a document from absolute name
+
+ ON ENTRY,
+
+ addr The absolute address of the document to be accessed.
+
+ filter_it if YES, treat document as HTML
+
+ */
+
+/*
+
+ ON EXIT,
+
+ */
+
+/*
+
+ returns YES Success in opening document
+
+ NO Failure
+
+ */
+extern BOOL HTLoadAbsolute PARAMS((CONST DocAddress * addr));
+
+
+/*
+
+Load a document from absolute name to a stream
+
+ ON ENTRY,
+
+ addr The absolute address of the document to be accessed.
+
+ filter_it if YES, treat document as HTML
+
+ ON EXIT,
+
+ returns YES Success in opening document
+
+ NO Failure
+
+ Note: This is equivalent to HTLoadDocument
+
+ */
+extern BOOL HTLoadToStream PARAMS((CONST char * addr, BOOL filter_it,
+ HTStream * sink));
+
+
+/*
+
+Load if necessary, and select an anchor
+
+ ON ENTRY,
+
+ destination The child or parenet anchor to be loaded.
+
+ */
+
+/*
+
+ ON EXIT,
+
+ */
+
+/*
+
+ returns YES Success
+
+ returns NO Failure
+
+ */
+
+
+
+extern BOOL HTLoadAnchor PARAMS((HTAnchor * destination));
+
+
+/*
+
+Make a stream for Saving object back
+
+ ON ENTRY,
+
+ anchor is valid anchor which has previously beeing loaded
+
+ ON EXIT,
+
+ returns 0 if error else a stream to save the object to.
+
+ */
+
+
+extern HTStream * HTSaveStream PARAMS((HTParentAnchor * anchor));
+
+
+/*
+
+Search
+
+ Performs a search on word given by the user. Adds the search words to the end of the
+ current address and attempts to open the new address.
+
+ ON ENTRY,
+
+ *keywords space-separated keyword list or similar search list
+
+ here The anchor of the object being searched
+
+ */
+extern BOOL HTSearch PARAMS((CONST char * keywords, HTParentAnchor* here));
+
+
+/*
+
+Search Given Indexname
+
+ Performs a keyword search on word given by the user. Adds the keyword to the end of
+ the current address and attempts to open the new address.
+
+ ON ENTRY,
+
+ *keywords space-separated keyword list or similar search list
+
+ *indexname is name of object search is to be done on.
+
+ */
+extern BOOL HTSearchAbsolute PARAMS((
+ CONST char * keywords,
+ CONST char * indexname));
+
+
+/*
+
+Register an access method
+
+ */
+
+typedef struct _HTProtocol {
+ char * name;
+
+ int (*load)PARAMS((
+ CONST char * full_address,
+ HTParentAnchor * anchor,
+ HTFormat format_out,
+ HTStream* sink));
+
+ HTStream* (*saveStream)PARAMS((HTParentAnchor * anchor));
+
+} HTProtocol;
+
+extern BOOL HTRegisterProtocol PARAMS((HTProtocol * protocol));
+
+
+/*
+
+Generate the anchor for the home page
+
+ */
+
+/*
+
+ As it involves file access, this should only be done once when the program first runs.
+ This is a default algorithm -- browser don't HAVE to use this.
+
+ */
+extern HTParentAnchor * HTHomeAnchor NOPARAMS;
+
+/*
+
+Return Host Name
+
+ */
+extern CONST char * HTHostName NOPARAMS;
+
+/*
+
+For registering protocols supported by Lynx
+
+*/
+extern void LYRegisterLynxProtocols NOARGS;
+
+extern void LYUCPushAssumed PARAMS((
+ HTParentAnchor * anchor));
+
+#endif /* HTACCESS_H */
+/*
+
+ end of HTAccess */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.c
new file mode 100644
index 00000000000..799db6cba5f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.c
@@ -0,0 +1,126 @@
+/* Displaying messages and getting input for LineMode Browser
+** ==========================================================
+**
+** REPLACE THIS MODULE with a GUI version in a GUI environment!
+**
+** History:
+** Jun 92 Created May 1992 By C.T. Barker
+** Feb 93 Simplified, portablised TBL
+** Sep 93 Corrected 3 bugs in HTConfirm() :-( AL
+*/
+
+
+#include "HTUtils.h"
+#include "tcp.h" /* for TOUPPER */
+
+#include "HTAlert.h"
+
+#include <ctype.h> /* for toupper - should be in tcp.h */
+#ifdef VMS
+extern char * getpass PARAMS((CONST char *prompt));
+#endif /* VMS */
+
+#include "LYLeaks.h"
+
+PUBLIC void HTAlert ARGS1(CONST char *, Msg)
+{
+#ifdef NeXTStep
+ NXRunAlertPanel(NULL, "%s", NULL, NULL, NULL, Msg);
+#else
+ fprintf(stderr, "WWW Alert: %s\n", Msg);
+#endif
+}
+
+
+PUBLIC void HTProgress ARGS1(CONST char *, Msg)
+{
+ fprintf(stderr, " %s ...\n", Msg);
+}
+
+
+PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
+{
+ char Reply[4]; /* One more for terminating NULL -- AL */
+ char *URep;
+
+ fprintf(stderr, "WWW: %s (y/n) ", Msg);
+ /* (y/n) came twice -- AL */
+
+ fgets(Reply, 4, stdin); /* get reply, max 3 characters */
+ URep=Reply;
+ while (*URep) {
+ if (*URep == '\n') {
+ *URep = (char)0; /* Overwrite newline */
+ break;
+ }
+ *URep=TOUPPER(*URep);
+ URep++; /* This was previously embedded in the TOUPPER */
+ /* call an it became evaluated twice because */
+ /* TOUPPER is a macro -- AL */
+ }
+
+ if ((strcmp(Reply,"YES")==0) || (strcmp(Reply,"Y")==0))
+ return(YES);
+ else
+ return(NO);
+}
+
+/* Prompt for answer and get text back
+*/
+PUBLIC char * HTPrompt ARGS2(CONST char *, Msg, CONST char *, deflt)
+{
+ char Tmp[200];
+ char * rep = 0;
+ fprintf(stderr, "WWW: %s", Msg);
+ if (deflt) fprintf(stderr, " (RETURN for [%s]) ", deflt);
+
+ fgets(Tmp, 200, stdin);
+ Tmp[strlen(Tmp)-1] = (char)0; /* Overwrite newline */
+
+ StrAllocCopy(rep, *Tmp ? Tmp : deflt);
+ return rep;
+}
+
+
+/* Prompt for password without echoing the reply
+*/
+PUBLIC char * HTPromptPassword ARGS1(CONST char *, Msg)
+{
+ char *result = NULL;
+ char *pw = (char*)getpass(Msg ? Msg : "Password: ");
+
+ StrAllocCopy(result, pw);
+ return result;
+}
+
+
+/* Prompt both username and password HTPromptUsernameAndPassword()
+** ---------------------------------
+** On entry,
+** Msg is the prompting message.
+** *username and
+** *password are char pointers; they are changed
+** to point to result strings.
+**
+** If *username is not NULL, it is taken
+** to point to a default value.
+** Initial value of *password is
+** completely discarded.
+**
+** On exit,
+** *username and *password point to newly allocated
+** strings -- original strings pointed to by them
+** are NOT freed.
+**
+*/
+PUBLIC void HTPromptUsernameAndPassword ARGS4(CONST char *, Msg,
+ char **, username,
+ char **, password,
+ BOOL, IsProxy)
+{
+ if (Msg)
+ fprintf(stderr, "WWW: %s\n", Msg);
+ *username = HTPrompt("Username: ", *username);
+ *password = HTPromptPassword("Password: ");
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.h
new file mode 100644
index 00000000000..03b970b63e0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAlert.h
@@ -0,0 +1,128 @@
+/* */
+
+/* Displaying messages and getting input for WWW Library
+** =====================================================
+**
+** May 92 Created By C.T. Barker
+** Feb 93 Portablized etc TBL
+*/
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "tcp.h"
+
+/* Display a message and get the input
+**
+** On entry,
+** Msg is the message.
+**
+** On exit,
+** Return value is malloc'd string which must be freed.
+*/
+extern char * HTPrompt PARAMS((CONST char * Msg, CONST char * deflt));
+
+
+/* Display a message, don't wait for input
+**
+** On entry,
+** The input is a list of parameters for printf.
+*/
+extern void HTAlert PARAMS((CONST char * Msg));
+
+
+/* Display a progress message for information (and diagnostics) only
+**
+** On entry,
+** The input is a list of parameters for printf.
+*/
+extern void HTProgress PARAMS((CONST char * Msg));
+extern BOOLEAN mustshow;
+#define _HTProgress(msg) mustshow = TRUE, HTProgress(msg)
+
+
+/* Display a message, then wait for 'yes' or 'no'.
+**
+** On entry,
+** Takes a list of parameters for printf.
+**
+** On exit,
+** If the user enters 'YES', returns TRUE, returns FALSE
+** otherwise.
+*/
+extern BOOL HTConfirm PARAMS ((CONST char * Msg));
+
+
+/* Prompt for password without echoing the reply
+*/
+extern char * HTPromptPassword PARAMS((CONST char * Msg));
+
+/* Prompt both username and password HTPromptUsernameAndPassword()
+** ---------------------------------
+** On entry,
+** Msg is the prompting message.
+** *username and
+** *password are char pointers; they are changed
+** to point to result strings.
+** IsProxy should be TRUE if this is for
+** proxy authentication.
+**
+** If *username is not NULL, it is taken
+** to point to a default value.
+** Initial value of *password is
+** completely discarded.
+**
+** On exit,
+** *username and *password point to newly allocated
+** strings -- original strings pointed to by them
+** are NOT freed.
+**
+*/
+extern void HTPromptUsernameAndPassword PARAMS((
+ CONST char * Msg,
+ char ** username,
+ char ** password,
+ BOOL IsProxy));
+
+
+/* Confirm a cookie operation. HTConfirmCookie()
+** ---------------------------
+**
+** On entry,
+** server is the server sending the Set-Cookie.
+** domain is the domain of the cookie.
+** path is the path of the cookie.
+** name is the name of the cookie.
+** value is the value of the cookie.
+**
+** On exit,
+** Returns FALSE on cancel,
+** TRUE if the cookie should be set.
+*/
+extern BOOL HTConfirmCookie PARAMS((
+ void * dp,
+ CONST char * server,
+ CONST char * domain,
+ CONST char * path,
+ CONST char * name,
+ CONST char * value));
+
+
+/* Confirm redirection of POST. HTConfirmPostRedirect()
+** ----------------------------
+** On entry,
+** redirecting_url is the Location.
+** server_status is the server status code.
+**
+** On exit,
+** Returns 0 on cancel,
+** 1 for redirect of POST with content,
+** 303 for redirect as GET without content
+*/
+extern int HTConfirmPostRedirect PARAMS((
+ CONST char * redirecting_url_arg,
+ int server_status));
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.c
new file mode 100644
index 00000000000..6f8c0d3fbd1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.c
@@ -0,0 +1,1325 @@
+/* Hypertext "Anchor" Object HTAnchor.c
+** ==========================
+**
+** An anchor represents a region of a hypertext document which is linked to
+** another anchor in the same or a different document.
+**
+** History
+**
+** Nov 1990 Written in Objective-C for the NeXT browser (TBL)
+** 24-Oct-1991 (JFG), written in C, browser-independant
+** 21-Nov-1991 (JFG), first complete version
+**
+** (c) Copyright CERN 1991 - See Copyright.html
+*/
+
+#define HASH_SIZE 101 /* Arbitrary prime. Memory/speed tradeoff */
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include <ctype.h>
+#include "HTAnchor.h"
+#include "HTParse.h"
+#include "UCAux.h"
+#include "UCMap.h"
+
+#include "LYCharSets.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef NOT_DEFINED
+/*
+ * This is the hashing function used to determine which list in the
+ * adult_table a parent anchor should be put in. This is a
+ * much simpler function than the original used.
+ */
+#define HASH_FUNCTION(cp_address) ((unsigned short int)strlen(cp_address) *\
+ (unsigned short int)TOUPPER(*cp_address) % HASH_SIZE)
+#endif /* NOT_DEFINED */
+/*
+ * This is the original function. We'll use it again. - FM
+ */
+PRIVATE int HASH_FUNCTION ARGS1(
+ CONST char *, cp_address)
+{
+ int hash;
+ unsigned char *p;
+
+ for (p = (unsigned char *)cp_address, hash = 0; *p; p++)
+ hash = (int) (hash * 3 + (*(unsigned char *)p)) % HASH_SIZE;
+
+ return hash;
+}
+
+typedef struct _HyperDoc Hyperdoc;
+#ifdef VMS
+struct _HyperDoc {
+ int junk; /* VMS cannot handle pointers to undefined structs */
+};
+#endif /* VMS */
+
+PRIVATE HTList **adult_table = 0; /* Point to table of lists of all parents */
+
+/* Creation Methods
+** ================
+**
+** Do not use "new" by itself outside this module. In order to enforce
+** consistency, we insist that you furnish more information about the
+** anchor you are creating : use newWithParent or newWithAddress.
+*/
+PRIVATE HTParentAnchor * HTParentAnchor_new NOARGS
+{
+ HTParentAnchor *newAnchor =
+ (HTParentAnchor *)calloc(1, sizeof(HTParentAnchor)); /* zero-filled */
+ newAnchor->parent = newAnchor;
+ newAnchor->bookmark = NULL; /* Bookmark filename. - FM */
+ newAnchor->isISMAPScript = FALSE; /* Lynx appends ?0,0 if TRUE. - FM */
+ newAnchor->isHEAD = FALSE; /* HEAD request if TRUE. - FM */
+ newAnchor->safe = FALSE; /* Safe. - FM */
+ newAnchor->FileCache = NULL; /* Path to a disk-cached copy. - FM */
+ newAnchor->SugFname = NULL; /* Suggested filename. - FM */
+ newAnchor->RevTitle = NULL; /* TITLE for a LINK with REV. - FM */
+ newAnchor->cache_control = NULL; /* Cache-Control. - FM */
+ newAnchor->no_cache = FALSE; /* no-cache? - FM */
+ newAnchor->content_type = NULL; /* Content-Type. - FM */
+ newAnchor->content_language = NULL; /* Content-Language. - FM */
+ newAnchor->content_encoding = NULL; /* Compression algorith. - FM */
+ newAnchor->content_base = NULL; /* Content-Base. - FM */
+ newAnchor->content_disposition = NULL; /* Content-Disposition. - FM */
+ newAnchor->content_location = NULL; /* Content-Location. - FM */
+ newAnchor->content_md5 = NULL; /* Content-MD5. - FM */
+ newAnchor->content_length = 0; /* Content-Length. - FM */
+ newAnchor->date = NULL; /* Date. - FM */
+ newAnchor->expires = NULL; /* Expires. - FM */
+ newAnchor->last_modified = NULL; /* Last-Modified. - FM */
+ newAnchor->server = NULL; /* Server. - FM */
+ return newAnchor;
+}
+
+PRIVATE HTChildAnchor * HTChildAnchor_new NOARGS
+{
+ return (HTChildAnchor *)calloc(1, sizeof(HTChildAnchor)); /* zero-filled */
+}
+
+
+#ifdef CASE_INSENSITIVE_ANCHORS
+/* Case insensitive string comparison
+** ----------------------------------
+** On entry,
+** s Points to one string, null terminated
+** t points to the other.
+** On exit,
+** returns YES if the strings are equivalent ignoring case
+** NO if they differ in more than their case.
+*/
+PRIVATE BOOL HTEquivalent ARGS2(
+ CONST char *, s,
+ CONST char *, t)
+{
+ if (s && t) { /* Make sure they point to something */
+ for (; *s && *t; s++, t++) {
+ if (TOUPPER(*s) != TOUPPER(*t)) {
+ return NO;
+ }
+ }
+ return TOUPPER(*s) == TOUPPER(*t);
+ } else {
+ return s == t; /* Two NULLs are equivalent, aren't they ? */
+ }
+}
+
+#else
+
+/* Case sensitive string comparison
+** ----------------------------------
+** On entry,
+** s Points to one string, null terminated
+** t points to the other.
+** On exit,
+** returns YES if the strings are identical or both NULL
+** NO if they differ.
+*/
+PRIVATE BOOL HTIdentical ARGS2(
+ CONST char *, s,
+ CONST char *, t)
+{
+ if (s && t) { /* Make sure they point to something */
+ for (; *s && *t; s++, t++) {
+ if (*s != *t) {
+ return NO;
+ }
+ }
+ return *s == *t;
+ } else {
+ return s == t; /* Two NULLs are identical, aren't they ? */
+ }
+}
+#endif /* CASE_INSENSITIVE_ANCHORS */
+
+
+/* Create new or find old sub-anchor
+** ---------------------------------
+**
+** Me one is for a new anchor being edited into an existing
+** document. The parent anchor must already exist.
+*/
+PUBLIC HTChildAnchor * HTAnchor_findChild ARGS2(
+ HTParentAnchor *, parent,
+ CONST char *, tag)
+{
+ HTChildAnchor *child;
+ HTList *kids;
+
+ if (!parent) {
+ if (TRACE)
+ fprintf(stderr, "HTAnchor_findChild called with NULL parent.\n");
+ return NULL;
+ }
+ if ((kids = parent->children) != 0) {
+ /*
+ ** Parent has children. Search them.
+ */
+ if (tag && *tag) { /* TBL */
+ while (NULL != (child=(HTChildAnchor *)HTList_nextObject(kids))) {
+#ifdef CASE_INSENSITIVE_ANCHORS
+ if (HTEquivalent(child->tag, tag)) { /* Case insensitive */
+#else
+ if (HTIdentical(child->tag, tag)) { /* Case sensitive - FM */
+#endif /* CASE_INSENSITIVE_ANCHORS */
+ if (TRACE)
+ fprintf(stderr,
+ "Child anchor %p of parent %p with name `%s' already exists.\n",
+ (void *)child, (void *)parent, tag);
+ return child;
+ }
+ }
+ } /* end if tag is void */
+ } else { /* parent doesn't have any children yet : create family */
+ parent->children = HTList_new();
+ }
+
+ child = HTChildAnchor_new();
+ if (TRACE)
+ fprintf(stderr,
+ "new Anchor %p named `%s' is child of %p\n",
+ (void *)child,
+ tag ? tag : (CONST char *)"",
+ (void *)parent); /* int for apollo */
+ HTList_addObject (parent->children, child);
+ child->parent = parent;
+ StrAllocCopy(child->tag, tag);
+ return child;
+}
+
+
+/* Create or find a child anchor with a possible link
+** --------------------------------------------------
+**
+** Create new anchor with a given parent and possibly
+** a name, and possibly a link to a _relatively_ named anchor.
+** (Code originally in ParseHTML.h)
+*/
+PUBLIC HTChildAnchor * HTAnchor_findChildAndLink ARGS4(
+ HTParentAnchor *, parent, /* May not be 0 */
+ CONST char *, tag, /* May be "" or 0 */
+ CONST char *, href, /* May be "" or 0 */
+ HTLinkType *, ltype) /* May be 0 */
+{
+ HTChildAnchor * child = HTAnchor_findChild(parent, tag);
+
+ if (TRACE)
+ fprintf(stderr,"Entered HTAnchor_findChildAndLink\n");
+
+ if (href && *href) {
+ char *relative_to = HTAnchor_address((HTAnchor *)parent);
+ DocAddress parsed_doc;
+ HTAnchor * dest;
+
+ parsed_doc.address = HTParse(href, relative_to, PARSE_ALL);
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (ltype && parent->post_data && ltype == LINK_INTERNAL) {
+ /* for internal links, find a destination with the same
+ post data if the source of the link has post data. - kw */
+ parsed_doc.post_data = parent->post_data;
+ parsed_doc.post_content_type = parent->post_content_type;
+ } else
+#endif
+ {
+ parsed_doc.post_data = NULL;
+ parsed_doc.post_content_type = NULL;
+ }
+ parsed_doc.bookmark = NULL;
+ parsed_doc.isHEAD = FALSE;
+ parsed_doc.safe = FALSE;
+ dest = HTAnchor_findAddress(&parsed_doc);
+
+ HTAnchor_link((HTAnchor *)child, dest, ltype);
+ FREE(parsed_doc.address);
+ FREE(relative_to);
+ }
+ return child;
+}
+
+/*
+** Function for freeing the adult hash table. - FM
+*/
+PRIVATE void free_adult_table NOARGS
+{
+ int i_counter;
+ HTList * HTAp_freeme;
+ HTParentAnchor * parent;
+ /*
+ * Loop through all lists.
+ */
+ for (i_counter = 0; i_counter < HASH_SIZE; i_counter++) {
+ /*
+ ** Loop through the list.
+ */
+ while (adult_table[i_counter] != NULL) {
+ /*
+ ** Free off items - FM
+ */
+ HTAp_freeme = adult_table[i_counter];
+ adult_table[i_counter] = HTAp_freeme->next;
+ if (HTAp_freeme->object) {
+ parent = (HTParentAnchor *)HTAp_freeme->object;
+ HTAnchor_delete(parent);
+ }
+ FREE(HTAp_freeme);
+ }
+ }
+ FREE(adult_table);
+}
+
+/* Create new or find old named anchor
+** -----------------------------------
+**
+** Me one is for a reference which is found in a document, and might
+** not be already loaded.
+** Note: You are not guaranteed a new anchor -- you might get an old one,
+** like with fonts.
+*/
+PUBLIC HTAnchor * HTAnchor_findAddress ARGS1(
+ CONST DocAddress *, newdoc)
+{
+ /* Anchor tag specified ? */
+ char *tag = HTParse(newdoc->address, "", PARSE_ANCHOR);
+
+ if (TRACE)
+ fprintf(stderr,"Entered HTAnchor_findAddress\n");
+
+ /*
+ ** If the address represents a sub-anchor, we recursively load its
+ ** parent, then we create a child anchor within that document.
+ */
+ if (*tag) {
+ DocAddress parsed_doc;
+ HTParentAnchor * foundParent;
+ HTChildAnchor * foundAnchor;
+
+ parsed_doc.address = HTParse(newdoc->address, "",
+ PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
+ parsed_doc.post_data = newdoc->post_data;
+ parsed_doc.post_content_type = newdoc->post_content_type;
+ parsed_doc.bookmark = newdoc->bookmark;
+ parsed_doc.isHEAD = newdoc->isHEAD;
+ parsed_doc.safe = newdoc->safe;
+
+ foundParent = (HTParentAnchor *)HTAnchor_findAddress(&parsed_doc);
+ foundAnchor = HTAnchor_findChild (foundParent, tag);
+ FREE(parsed_doc.address);
+ FREE(tag);
+ return (HTAnchor *)foundAnchor;
+ } else {
+ /*
+ ** If the address has no anchor tag,
+ ** check whether we have this node.
+ */
+ int hash;
+ HTList * adults;
+ HTList *grownups;
+ HTParentAnchor * foundAnchor;
+
+ FREE(tag);
+
+ /*
+ ** Select list from hash table,
+ */
+ hash = HASH_FUNCTION(newdoc->address);
+ if (!adult_table) {
+ adult_table = (HTList **)calloc(HASH_SIZE, sizeof(HTList *));
+ atexit(free_adult_table);
+ }
+ if (!adult_table[hash])
+ adult_table[hash] = HTList_new();
+ adults = adult_table[hash];
+
+ /*
+ ** Search list for anchor.
+ */
+ grownups = adults;
+ while (NULL != (foundAnchor =
+ (HTParentAnchor *)HTList_nextObject(grownups))) {
+#ifdef CASE_INSENSITIVE_ANCHORS
+ if (HTEquivalent(foundAnchor->address, newdoc->address) &&
+ HTEquivalent(foundAnchor->post_data, newdoc->post_data) &&
+ foundAnchor->isHEAD == newdoc->isHEAD)
+#else
+ if (HTIdentical(foundAnchor->address, newdoc->address) &&
+ HTIdentical(foundAnchor->post_data, newdoc->post_data) &&
+ foundAnchor->isHEAD == newdoc->isHEAD)
+#endif /* CASE_INSENSITIVE_ANCHORS */
+ {
+ if (TRACE)
+ fprintf(stderr,
+ "Anchor %p with address `%s' already exists.\n",
+ (void *)foundAnchor, newdoc->address);
+ return (HTAnchor *)foundAnchor;
+ }
+ }
+
+ /*
+ ** Node not found: create new anchor.
+ */
+ foundAnchor = HTParentAnchor_new();
+ if (TRACE)
+ fprintf(stderr,
+ "New anchor %p has hash %d and address `%s'\n",
+ (void *)foundAnchor, hash, newdoc->address);
+ StrAllocCopy(foundAnchor->address, newdoc->address);
+ if (newdoc->post_data)
+ StrAllocCopy(foundAnchor->post_data, newdoc->post_data);
+ if (newdoc->post_content_type)
+ StrAllocCopy(foundAnchor->post_content_type,
+ newdoc->post_content_type);
+ if (newdoc->bookmark)
+ StrAllocCopy(foundAnchor->bookmark, newdoc->bookmark);
+ foundAnchor->isHEAD = newdoc->isHEAD;
+ foundAnchor->safe = newdoc->safe;
+ HTList_addObject (adults, foundAnchor);
+ return (HTAnchor *)foundAnchor;
+ }
+}
+
+
+/* Delete an anchor and possibly related things (auto garbage collection)
+** --------------------------------------------
+**
+** The anchor is only deleted if the corresponding document is not loaded.
+** All outgoing links from parent and children are deleted, and this anchor
+** is removed from the sources list of all its targets.
+** We also try to delete the targets whose documents are not loaded.
+** If this anchor's source list is empty, we delete it and its children.
+*/
+PRIVATE void deleteLinks ARGS1(
+ HTAnchor *, me)
+{
+ /*
+ * Memory leaks fixed.
+ * 05-27-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+
+ /*
+ * Anchor is NULL, do nothing.
+ */
+ if (!me) {
+ return;
+ }
+
+ /*
+ * Unregister me with our mainLink destination anchor's parent.
+ */
+ if (me->mainLink.dest) {
+ HTParentAnchor *parent = me->mainLink.dest->parent;
+
+ /*
+ * Remove me from the parent's sources so that the
+ * parent knows one less anchor is it's dest.
+ */
+ if (!HTList_isEmpty(parent->sources)) {
+ /*
+ * Really should only need to deregister once.
+ */
+ HTList_removeObject(parent->sources, (void *)me);
+ }
+
+ /*
+ * Test here to avoid calling overhead.
+ * If the parent has no loaded document, then we should
+ * tell it to attempt to delete itself.
+ * Don't do this jass if the anchor passed in is the same
+ * as the anchor to delete.
+ * Also, don't do this if the destination parent is our
+ * parent.
+ */
+ if (!parent->document &&
+ parent != (HTParentAnchor *)me &&
+ me->parent != parent) {
+ HTAnchor_delete(parent);
+ }
+
+ /*
+ * At this point, we haven't a mainLink. Set it to be
+ * so.
+ * Leave the HTAtom pointed to by type up to other code to
+ * handle (reusable, near static).
+ */
+ me->mainLink.dest = NULL;
+ me->mainLink.type = NULL;
+ }
+
+ /*
+ * Check for extra destinations in our links list.
+ */
+ if (!HTList_isEmpty(me->links)) {
+ HTLink *target;
+ HTParentAnchor *parent;
+
+ /*
+ * Take out our extra non mainLinks one by one, calling
+ * their parents to know that they are no longer
+ * the destination of me's anchor.
+ */
+ while ((target = (HTLink *)HTList_removeLastObject(me->links)) != 0) {
+ parent = target->dest->parent;
+ if (!HTList_isEmpty(parent->sources)) {
+ /*
+ * Only need to tell destination parent
+ * anchor once.
+ */
+ HTList_removeObject(parent->sources, (void *)me);
+ }
+
+ /*
+ * Avoid calling overhead.
+ * If the parent hasn't a loaded document, then
+ * we will attempt to have the parent
+ * delete itself.
+ * Don't call twice if this is the same anchor
+ * that we are trying to delete.
+ * Also, don't do this if we are trying to delete
+ * our parent.
+ */
+ if (!parent->document &&
+ (HTParentAnchor *)me != parent &&
+ me->parent != parent) {
+ HTAnchor_delete(parent);
+ }
+ /*
+ * The link structure has to be deleted, too!
+ * That was missing, but this code probably never
+ * got exercised by Lynx. - KW
+ */
+ FREE(target);
+ }
+
+ /*
+ * At this point, me no longer has any destination in
+ * the links list. Get rid of it.
+ */
+ if (me->links) {
+ HTList_delete(me->links);
+ me->links = NULL;
+ }
+ }
+
+ /*
+ * Catch in case links list exists but nothing in it.
+ */
+ if (me->links) {
+ HTList_delete(me->links);
+ me->links = NULL;
+ }
+}
+
+PUBLIC BOOL HTAnchor_delete ARGS1(
+ HTParentAnchor *, me)
+{
+ /*
+ * Memory leaks fixed.
+ * 05-27-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ HTList *cur;
+ HTChildAnchor *child;
+
+ /*
+ * Do nothing if nothing to do.
+ */
+ if (!me) {
+ return(NO);
+ }
+
+ /*
+ * Don't delete if document is loaded or being loaded.
+ */
+ if (me->document || me->underway) {
+ return(NO);
+ }
+
+ /*
+ * Recursively try to delete destination anchors of this parent.
+ * In any event, this will tell all destination anchors that we
+ * no longer consider them a destination.
+ */
+ deleteLinks((HTAnchor *)me);
+
+ /*
+ * There are still incoming links to this one (we are the
+ * destination of another anchor).
+ * Don't actually delete this anchor, but children are OK to
+ * delete their links.
+ */
+ if (!HTList_isEmpty(me->sources)) {
+ /*
+ * Delete all outgoing links from children, do not
+ * delete the children, though.
+ */
+ if (!HTList_isEmpty(me->children)) {
+ cur = me->children;
+ while ((child = (HTChildAnchor *)HTList_nextObject(cur)) != 0) {
+ if (child != NULL) {
+ deleteLinks((HTAnchor *)child);
+ }
+ }
+ }
+
+ /*
+ * Can't delete parent, still have sources.
+ */
+ return(NO);
+ }
+
+ /*
+ * No more incoming links : kill everything
+ * First, recursively delete children and their links.
+ */
+ if (!HTList_isEmpty(me->children)) {
+ while ((child = (HTChildAnchor *)HTList_removeLastObject(
+ me->children)) != 0) {
+ if (child) {
+ deleteLinks((HTAnchor *)child);
+ if (child->tag) {
+ FREE(child->tag);
+ }
+ FREE(child);
+ }
+ }
+ }
+
+ /*
+ * Delete our empty list of children.
+ */
+ if (me->children) {
+ HTList_delete(me->children);
+ me->children = NULL;
+ }
+
+ /*
+ * Delete our empty list of sources.
+ */
+ if (me->sources) {
+ HTList_delete(me->sources);
+ me->sources = NULL;
+ }
+
+ /*
+ * Delete the methods list.
+ */
+ if (me->methods) {
+ /*
+ * Leave what the methods point to up in memory for
+ * other code (near static stuff).
+ */
+ HTList_delete(me->methods);
+ me->methods = NULL;
+ }
+
+ /*
+ * Free up all allocated members.
+ */
+ FREE(me->charset);
+ FREE(me->isIndexAction);
+ FREE(me->isIndexPrompt);
+ FREE(me->title);
+ FREE(me->physical);
+ FREE(me->post_data);
+ FREE(me->post_content_type);
+ FREE(me->bookmark);
+ FREE(me->owner);
+ FREE(me->RevTitle);
+ if (me->FileCache) {
+ FILE *fd;
+ if ((fd = fopen(me->FileCache, "r")) != NULL) {
+ fclose(fd);
+ remove(me->FileCache);
+ }
+ FREE(me->FileCache);
+ }
+ FREE(me->SugFname);
+ FREE(me->cache_control);
+ FREE(me->content_type);
+ FREE(me->content_language);
+ FREE(me->content_encoding);
+ FREE(me->content_base);
+ FREE(me->content_disposition);
+ FREE(me->content_location);
+ FREE(me->content_md5);
+ FREE(me->date);
+ FREE(me->expires);
+ FREE(me->last_modified);
+ FREE(me->server);
+#ifdef USE_HASH
+ FREE(me->style);
+#endif
+
+ /*
+ * Remove ourselves from the hash table's list.
+ */
+ if (adult_table) {
+ unsigned short int usi_hash = HASH_FUNCTION(me->address);
+
+ if (adult_table[usi_hash]) {
+ HTList_removeObject(adult_table[usi_hash], (void *)me);
+ }
+ }
+
+ /*
+ * Original code wanted a way to clean out the HTFormat if no
+ * longer needed (ref count?). I'll leave it alone since
+ * those HTAtom objects are a little harder to know where
+ * they are being referenced all at one time. (near static)
+ */
+
+ /*
+ * Free the address.
+ */
+ FREE(me->address);
+
+ FREE (me->UCStages);
+ ImageMapList_free(me->imaps);
+
+
+ /*
+ * Finally, kill the parent anchor passed in.
+ */
+ FREE(me);
+
+ return(YES);
+}
+
+
+/* Move an anchor to the head of the list of its siblings
+** ------------------------------------------------------
+**
+** This is to ensure that an anchor which might have already existed
+** is put in the correct order as we load the document.
+*/
+PUBLIC void HTAnchor_makeLastChild ARGS1(
+ HTChildAnchor *, me)
+{
+ if (me->parent != (HTParentAnchor *)me) { /* Make sure it's a child */
+ HTList * siblings = me->parent->children;
+ HTList_removeObject (siblings, me);
+ HTList_addObject (siblings, me);
+ }
+}
+
+/* Data access functions
+** ---------------------
+*/
+PUBLIC HTParentAnchor * HTAnchor_parent ARGS1(
+ HTAnchor *, me)
+{
+ return me ? me->parent : NULL;
+}
+
+PUBLIC void HTAnchor_setDocument ARGS2(
+ HTParentAnchor *, me,
+ HyperDoc *, doc)
+{
+ if (me)
+ me->document = doc;
+}
+
+PUBLIC HyperDoc * HTAnchor_document ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->document : NULL;
+}
+
+
+/* We don't want code to change an address after anchor creation... yet ?
+PUBLIC void HTAnchor_setAddress ARGS2(
+ HTAnchor *, me,
+ char *, addr)
+{
+ if (me)
+ StrAllocCopy (me->parent->address, addr);
+}
+*/
+
+PUBLIC char * HTAnchor_address ARGS1(
+ HTAnchor *, me)
+{
+ char *addr = NULL;
+
+ if (me) {
+ if (((HTParentAnchor *)me == me->parent) ||
+ !((HTChildAnchor *)me)->tag) { /* it's an adult or no tag */
+ StrAllocCopy(addr, me->parent->address);
+ } else { /* it's a named child */
+ addr = malloc(2 +
+ strlen(me->parent->address) +
+ strlen(((HTChildAnchor *)me)->tag));
+ if (addr == NULL)
+ outofmem(__FILE__, "HTAnchor_address");
+ sprintf(addr, "%s#%s",
+ me->parent->address, ((HTChildAnchor *)me)->tag);
+ }
+ }
+ return addr;
+}
+
+PUBLIC void HTAnchor_setFormat ARGS2(
+ HTParentAnchor *, me,
+ HTFormat, form)
+{
+ if (me)
+ me->format = form;
+}
+
+PUBLIC HTFormat HTAnchor_format ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->format : NULL;
+}
+
+PUBLIC void HTAnchor_setIndex ARGS2(
+ HTParentAnchor *, me,
+ char *, address)
+{
+ if (me) {
+ me->isIndex = YES;
+ StrAllocCopy(me->isIndexAction, address);
+ }
+}
+
+PUBLIC void HTAnchor_setPrompt ARGS2(
+ HTParentAnchor *, me,
+ char *, prompt)
+{
+ if (me) {
+ StrAllocCopy(me->isIndexPrompt, prompt);
+ }
+}
+
+PUBLIC BOOL HTAnchor_isIndex ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->isIndex : NO;
+}
+
+/* Whether Anchor has been designated as an ISMAP link
+** (normally by presence of an ISMAP attribute on A or IMG) - KW
+*/
+PUBLIC BOOL HTAnchor_isISMAPScript ARGS1(
+ HTAnchor *, me)
+{
+ return me ? me->parent->isISMAPScript : NO;
+}
+
+PUBLIC BOOL HTAnchor_hasChildren ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? ! HTList_isEmpty(me->children) : NO;
+}
+
+#if defined(USE_HASH)
+/* Style handling.
+*/
+PUBLIC CONST char * HTAnchor_style ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->style : NULL;
+}
+
+PUBLIC void HTAnchor_setStyle ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, style)
+{
+ if (me) {
+ StrAllocCopy(me->style, style);
+ }
+}
+#endif
+
+
+/* Title handling.
+*/
+PUBLIC CONST char * HTAnchor_title ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->title : NULL;
+}
+
+PUBLIC void HTAnchor_setTitle ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, title)
+{
+ int i;
+
+ if (me) {
+ StrAllocCopy(me->title, title);
+ for (i = 0; me->title[i]; i++) {
+ if ((unsigned char)me->title[i] == 1 ||
+ (unsigned char)me->title[i] == 2) {
+ me->title[i] = ' ';
+ }
+ }
+ }
+}
+
+PUBLIC void HTAnchor_appendTitle ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, title)
+{
+ int i;
+
+ if (me) {
+ StrAllocCat(me->title, title);
+ for (i = 0; me->title[i]; i++) {
+ if ((unsigned char)me->title[i] == 1 ||
+ (unsigned char)me->title[i] == 2) {
+ me->title[i] = ' ';
+ }
+ }
+ }
+}
+
+/* Bookmark handling.
+*/
+PUBLIC CONST char * HTAnchor_bookmark ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->bookmark : NULL;
+}
+
+PUBLIC void HTAnchor_setBookmark ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, bookmark)
+{
+ if (me)
+ StrAllocCopy(me->bookmark, bookmark);
+}
+
+/* Owner handling.
+*/
+PUBLIC CONST char * HTAnchor_owner ARGS1(
+ HTParentAnchor *, me)
+{
+ return (me ? me->owner : NULL);
+}
+
+PUBLIC void HTAnchor_setOwner ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, owner)
+{
+ if (me) {
+ StrAllocCopy(me->owner, owner);
+ }
+}
+
+/* TITLE handling in LINKs with REV="made" or REV="owner". - FM
+*/
+PUBLIC CONST char * HTAnchor_RevTitle ARGS1(
+ HTParentAnchor *, me)
+{
+ return (me ? me->RevTitle : NULL);
+}
+
+PUBLIC void HTAnchor_setRevTitle ARGS2(
+ HTParentAnchor *, me,
+ CONST char *, title)
+{
+ int i;
+
+ if (me) {
+ StrAllocCopy(me->RevTitle, title);
+ for (i = 0; me->RevTitle[i]; i++) {
+ if ((unsigned char)me->RevTitle[i] == 1 ||
+ (unsigned char)me->RevTitle[i] == 2) {
+ me->RevTitle[i] = ' ';
+ }
+ }
+ }
+}
+
+/* Suggested filename handling. - FM
+** (will be loaded if we had a Content-Disposition
+** header or META element with filename=name.suffix)
+*/
+PUBLIC CONST char * HTAnchor_SugFname ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->SugFname : NULL;
+}
+
+/* Content-Encoding handling. - FM
+** (will be loaded if we had a Content-Encoding
+** header.)
+*/
+PUBLIC CONST char * HTAnchor_content_encoding ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->content_encoding : NULL;
+}
+
+/* Content-Type handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_content_type ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->content_type : NULL;
+}
+
+/* Last-Modified header handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_last_modified ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->last_modified : NULL;
+}
+
+/* Date header handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_date ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->date : NULL;
+}
+
+/* Server header handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_server ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->server : NULL;
+}
+
+/* Safe header handling. - FM
+*/
+PUBLIC BOOL HTAnchor_safe ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->safe : FALSE;
+}
+
+/* Content-Base header handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_content_base ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->content_base : NULL;
+}
+
+/* Content-Location header handling. - FM
+*/
+PUBLIC CONST char * HTAnchor_content_location ARGS1(
+ HTParentAnchor *, me)
+{
+ return me ? me->content_location : NULL;
+}
+
+/* Link me Anchor to another given one
+** -------------------------------------
+*/
+PUBLIC BOOL HTAnchor_link ARGS3(
+ HTAnchor *, source,
+ HTAnchor *, destination,
+ HTLinkType *, type)
+{
+ if (!(source && destination))
+ return NO; /* Can't link to/from non-existing anchor */
+ if (TRACE)
+ fprintf(stderr,
+ "Linking anchor %p to anchor %p\n", source, destination);
+ if (!source->mainLink.dest) {
+ source->mainLink.dest = destination;
+ source->mainLink.type = type;
+ } else {
+ HTLink * newLink = (HTLink *)calloc (1, sizeof (HTLink));
+ if (newLink == NULL)
+ outofmem(__FILE__, "HTAnchor_link");
+ newLink->dest = destination;
+ newLink->type = type;
+ if (!source->links)
+ source->links = HTList_new();
+ HTList_addObject (source->links, newLink);
+ }
+ if (!destination->parent->sources)
+ destination->parent->sources = HTList_new();
+ HTList_addObject (destination->parent->sources, source);
+ return YES; /* Success */
+}
+
+
+/* Manipulation of links
+** ---------------------
+*/
+PUBLIC HTAnchor * HTAnchor_followMainLink ARGS1(
+ HTAnchor *, me)
+{
+ return me->mainLink.dest;
+}
+
+PUBLIC HTAnchor * HTAnchor_followTypedLink ARGS2(
+ HTAnchor *, me,
+ HTLinkType *, type)
+{
+ if (me->mainLink.type == type)
+ return me->mainLink.dest;
+ if (me->links) {
+ HTList *links = me->links;
+ HTLink *the_link;
+ while (NULL != (the_link=(HTLink *)HTList_nextObject(links))) {
+ if (the_link->type == type) {
+ return the_link->dest;
+ }
+ }
+ }
+ return NULL; /* No link of me type */
+}
+
+
+/* Make main link
+*/
+PUBLIC BOOL HTAnchor_makeMainLink ARGS2(
+ HTAnchor *, me,
+ HTLink *, movingLink)
+{
+ /* Check that everything's OK */
+ if (!(me && HTList_removeObject (me->links, movingLink))) {
+ return NO; /* link not found or NULL anchor */
+ } else {
+ /* First push current main link onto top of links list */
+ HTLink *newLink = (HTLink *)calloc (1, sizeof (HTLink));
+ if (newLink == NULL)
+ outofmem(__FILE__, "HTAnchor_makeMainLink");
+ memcpy((void *)newLink,
+ (CONST char *)&me->mainLink, sizeof (HTLink));
+ HTList_addObject (me->links, newLink);
+
+ /* Now make movingLink the new main link, and free it */
+ memcpy((void *)&me->mainLink,
+ (CONST void *)movingLink, sizeof (HTLink));
+ FREE(movingLink);
+ return YES;
+ }
+}
+
+
+/* Methods List
+** ------------
+*/
+PUBLIC HTList * HTAnchor_methods ARGS1(
+ HTParentAnchor *, me)
+{
+ if (!me->methods) {
+ me->methods = HTList_new();
+ }
+ return me->methods;
+}
+
+/* Protocol
+** --------
+*/
+PUBLIC void * HTAnchor_protocol ARGS1(
+ HTParentAnchor *, me)
+{
+ return me->protocol;
+}
+
+PUBLIC void HTAnchor_setProtocol ARGS2(
+ HTParentAnchor *, me,
+ void*, protocol)
+{
+ me->protocol = protocol;
+}
+
+/* Physical Address
+** ----------------
+*/
+PUBLIC char * HTAnchor_physical ARGS1(
+ HTParentAnchor *, me)
+{
+ return me->physical;
+}
+
+PUBLIC void HTAnchor_setPhysical ARGS2(
+ HTParentAnchor *, me,
+ char *, physical)
+{
+ if (me) {
+ StrAllocCopy(me->physical, physical);
+ }
+}
+
+/*
+** We store charset info in the HTParentAnchor object, for several
+** "stages". (See UCDefs.h)
+** A stream method is supposed to know what stage in the model it is.
+**
+** General model MIME -> parser -> structured -> HText
+** e.g., text/html
+** from HTTP: HTMIME.c -> SGML.c -> HTML.c -> GridText.c
+** text/plain
+** from file: HTFile.c -> HTPlain.c -> GridText.c
+**
+** The lock/set_by is used to lock e.g. a charset set by an explicit
+** HTTP MIME header against overriding by a HTML META tag - the MIME
+** header has higher priority. Defaults (from -assume_.. options etc.)
+** will not override charset explicitly given by server.
+**
+** Some advantages of keeping this in the HTAnchor:
+** - Global variables are bad.
+** - Can remember a charset given by META tag when toggling to SOURCE view.
+** - Can remember a charset given by <A CHARSET=...> href in another doc.
+**
+** We don't modify the HTParentAnchor's charset element
+** here, that one will only be set when explicitly given.
+*/
+PUBLIC LYUCcharset * HTAnchor_getUCInfoStage ARGS2(
+ HTParentAnchor *, me,
+ int, which_stage)
+{
+ if (me && !me->UCStages) {
+ int i;
+ int chndl = UCLYhndl_for_unspec;
+ UCAnchorInfo * stages = (UCAnchorInfo*)calloc(1,
+ sizeof(UCAnchorInfo));
+ if (stages == NULL)
+ outofmem(__FILE__, "HTAnchor_getUCInfoStage");
+ for (i = 0; i < UCT_STAGEMAX; i++) {
+ stages->s[i].C.MIMEname = "";
+ stages->s[i].LYhndl = -1;
+ }
+ if (me->charset) {
+ chndl = UCGetLYhndl_byMIME(me->charset);
+ if (chndl < 0) {
+ chndl = UCLYhndl_for_unrec;
+ }
+ }
+ if (chndl >= 0) {
+ memcpy(&stages->s[UCT_STAGE_MIME].C, &LYCharSet_UC[chndl],
+ sizeof(LYUCcharset));
+ stages->s[UCT_STAGE_MIME].lock = UCT_SETBY_DEFAULT;
+ } else {
+ /*
+ * Should not happen...
+ */
+ stages->s[UCT_STAGE_MIME].C.UChndl = -1;
+ stages->s[UCT_STAGE_MIME].lock = UCT_SETBY_NONE;
+ }
+ stages->s[UCT_STAGE_MIME].LYhndl = chndl;
+ me->UCStages = stages;
+ }
+ if (me) {
+ return &me->UCStages->s[which_stage].C;
+ }
+ return NULL;
+}
+
+PUBLIC int HTAnchor_getUCLYhndl ARGS2(
+ HTParentAnchor *, me,
+ int, which_stage)
+{
+ if (me) {
+ if (!me->UCStages) {
+ /*
+ * This will allocate and initialize, if not yet done.
+ */
+ (void) HTAnchor_getUCInfoStage(me, which_stage);
+ }
+ if (me->UCStages->s[which_stage].lock > UCT_SETBY_NONE) {
+ return me->UCStages->s[which_stage].LYhndl;
+ }
+ }
+ return -1;
+}
+
+PUBLIC LYUCcharset * HTAnchor_setUCInfoStage ARGS4(
+ HTParentAnchor *, me,
+ int, LYhndl,
+ int, which_stage,
+ int, set_by)
+{
+ if (me) {
+ /*
+ * This will allocate and initialize, if not yet done.
+ */
+ LYUCcharset * p = HTAnchor_getUCInfoStage(me, which_stage);
+ /*
+ * Can we override?
+ */
+ if (set_by >= me->UCStages->s[which_stage].lock) {
+ me->UCStages->s[which_stage].lock = set_by;
+ me->UCStages->s[which_stage].LYhndl = LYhndl;
+ if (LYhndl >= 0) {
+ memcpy(p, &LYCharSet_UC[LYhndl], sizeof(LYUCcharset));
+ }
+ else {
+ p->UChndl = -1;
+ }
+ return p;
+ }
+ }
+ return NULL;
+}
+
+PUBLIC LYUCcharset * HTAnchor_resetUCInfoStage ARGS4(
+ HTParentAnchor *, me,
+ int, LYhndl,
+ int, which_stage,
+ int, set_by)
+{
+ if (!me || !me->UCStages)
+ return NULL;
+ me->UCStages->s[which_stage].lock = set_by;
+ me->UCStages->s[which_stage].LYhndl = LYhndl;
+ return &me->UCStages->s[which_stage].C;
+}
+
+/*
+** A set_by of (-1) means use the lock value from the from_stage.
+*/
+PUBLIC LYUCcharset * HTAnchor_copyUCInfoStage ARGS4(
+ HTParentAnchor *, me,
+ int, to_stage,
+ int, from_stage,
+ int, set_by)
+{
+ if (me) {
+ /*
+ * This will allocate and initialize, if not yet done.
+ */
+ LYUCcharset * p_from = HTAnchor_getUCInfoStage(me, from_stage);
+ LYUCcharset * p_to = HTAnchor_getUCInfoStage(me, to_stage);
+ /*
+ * Can we override?
+ */
+ if (set_by == -1)
+ set_by = me->UCStages->s[from_stage].lock;
+ if (set_by == UCT_SETBY_NONE)
+ set_by = UCT_SETBY_DEFAULT;
+ if (set_by >= me->UCStages->s[to_stage].lock) {
+ me->UCStages->s[to_stage].lock = set_by;
+ me->UCStages->s[to_stage].LYhndl =
+ me->UCStages->s[from_stage].LYhndl;
+ if (p_to != p_from)
+ memcpy(p_to, p_from, sizeof(LYUCcharset));
+ return p_to;
+ }
+ }
+ return NULL;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.h
new file mode 100644
index 00000000000..e3847184045
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAnchor.h
@@ -0,0 +1,447 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTAnchor.html
+ */
+
+/* Hypertext "Anchor" Object HTAnchor.h
+** ==========================
+**
+** An anchor represents a region of a hypertext document which is linked
+** to another anchor in the same or a different document.
+*/
+
+#ifndef HTANCHOR_H
+#define HTANCHOR_H
+
+/* Version 0 (TBL) written in Objective-C for the NeXT browser */
+/* Version 1 of 24-Oct-1991 (JFG), written in C, browser-independant */
+
+#include "HTList.h"
+#include "HTAtom.h"
+#include "UCDefs.h"
+
+#ifdef SHORT_NAMES
+#define HTAnchor_findChild HTAnFiCh
+#define HTAnchor_findChildAndLink HTAnFiLi
+#define HTAnchor_findAddress HTAnFiAd
+#define HTAnchor_delete HTAnDele
+#define HTAnchor_makeLastChild HTAnMaLa
+#define HTAnchor_parent HTAnPare
+#define HTAnchor_setDocument HTAnSeDo
+#define HTAnchor_document HTAnDocu
+#define HTAnchor_setFormat HTAnSeFo
+#define HTAnchor_format HTAnForm
+#define HTAnchor_setIndex HTAnSeIn
+#define HTAnchor_setPrompt HTAnSePr
+#define HTAnchor_isIndex HTAnIsIn
+#define HTAnchor_address HTAnAddr
+#define HTAnchor_hasChildren HTAnHaCh
+#define HTAnchor_title HTAnTitl
+#define HTAnchor_setTitle HTAnSeTi
+#define HTAnchor_appendTitle HTAnApTi
+#define HTAnchor_link HTAnLink
+#define HTAnchor_followMainLink HTAnFoMa
+#define HTAnchor_followTypedLink HTAnFoTy
+#define HTAnchor_makeMainLink HTAnMaMa
+#define HTAnchor_setProtocol HTAnSePr
+#define HTAnchor_protocol HTAnProt
+#define HTAnchor_physical HTAnPhys
+#define HTAnchor_setPhysical HTAnSePh
+#define HTAnchor_methods HtAnMeth
+#endif /* SHORT_NAMES */
+
+/* Main definition of anchor
+** =========================
+*/
+
+typedef struct _HyperDoc HyperDoc; /* Ready for forward references */
+typedef struct _HTAnchor HTAnchor;
+typedef struct _HTParentAnchor HTParentAnchor;
+
+/* After definition of HTFormat: */
+#include "HTFormat.h"
+
+typedef HTAtom HTLinkType;
+
+typedef struct {
+ HTAnchor * dest; /* The anchor to which this leads */
+ HTLinkType * type; /* Semantics of this link */
+} HTLink;
+
+struct _HTAnchor { /* Generic anchor : just links */
+ HTLink mainLink; /* Main (or default) destination of this */
+ HTList * links; /* List of extra links from this, if any */
+ /* We separate the first link from the others to avoid too many small mallocs
+ involved by a list creation. Most anchors only point to one place. */
+ HTParentAnchor * parent; /* Parent of this anchor (self for adults) */
+};
+
+struct _HTParentAnchor {
+ /* Common part from the generic anchor structure */
+ HTLink mainLink; /* Main (or default) destination of this */
+ HTList * links; /* List of extra links from this, if any */
+ HTParentAnchor * parent; /* Parent of this anchor (self) */
+
+ /* ParentAnchor-specific information */
+ HTList * children; /* Subanchors of this, if any */
+ HTList * sources; /* List of anchors pointing to this, if any */
+ HyperDoc * document; /* The document within which this is an anchor */
+ char * address; /* Absolute address of this node */
+ char * post_data; /* Posting data */
+ char * post_content_type; /* Type of post data */
+ char * bookmark; /* Bookmark filname */
+ HTFormat format; /* Pointer to node format descriptor */
+ char * charset; /* Pointer to character set (kludge, for now */
+ BOOL isIndex; /* Acceptance of a keyword search */
+ char * isIndexAction; /* URL of isIndex server */
+ char * isIndexPrompt; /* Prompt for isIndex query */
+ char * title; /* Title of document */
+ char * owner; /* Owner of document */
+ char * RevTitle; /* TITLE in REV="made" or REV="owner" LINK */
+#ifdef USE_HASH
+ char * style;
+#endif
+
+ HTList* methods; /* Methods available as HTAtoms */
+ void * protocol; /* Protocol object */
+ char * physical; /* Physical address */
+ BOOL underway; /* Document about to be attached to it */
+ BOOL isISMAPScript; /* Script for clickable image map */
+ BOOL isHEAD; /* Document is headers from a HEAD request */
+ BOOL safe; /* Safe */
+ char * FileCache; /* Path to a disk-cached copy */
+ char * SugFname; /* Suggested filename */
+ char * cache_control; /* Cache-Control */
+ BOOL no_cache; /* Cache-Control, Pragma or META "no-cache"? */
+ char * content_type; /* Content-Type */
+ char * content_language; /* Content-Language */
+ char * content_encoding; /* Compression algorithm */
+ char * content_base; /* Content-Base */
+ char * content_disposition; /* Content-Dispositon */
+ char * content_location; /* Content-Location */
+ char * content_md5; /* Content-MD5 */
+ int content_length; /* Content-Length */
+ char * date; /* Date */
+ char * expires; /* Expires */
+ char * last_modified; /* Last-Modified */
+ char * server; /* Server */
+ UCAnchorInfo *UCStages; /* chartrans stages */
+ HTList * imaps; /* client side image maps */
+};
+
+typedef struct {
+ /* Common part from the generic anchor structure */
+ HTLink mainLink; /* Main (or default) destination of this */
+ HTList * links; /* List of extra links from this, if any */
+ HTParentAnchor * parent; /* Parent of this anchor */
+
+ /* ChildAnchor-specific information */
+ char * tag; /* Address of this anchor relative to parent */
+} HTChildAnchor;
+
+/*
+** DocAddress structure is used for loading an absolute anchor with all
+** needed information including posting data and post content type.
+*/
+typedef struct _DocAddress {
+ char * address;
+ char * post_data;
+ char * post_content_type;
+ char * bookmark;
+ BOOL isHEAD;
+ BOOL safe;
+} DocAddress;
+
+/* "internal" means "within the same document, with certainty".
+ It includes a space so it cannot conflict with any (valid) "TYPE"
+ attributes on A elements. [According to which DTD, anyway??] - kw */
+
+#define LINK_INTERNAL HTAtom_for("internal link")
+
+/* Create new or find old sub-anchor
+** ---------------------------------
+**
+** This one is for a new anchor being edited into an existing
+** document. The parent anchor must already exist.
+*/
+extern HTChildAnchor * HTAnchor_findChild PARAMS((
+ HTParentAnchor * parent,
+ CONST char * tag));
+
+/* Create or find a child anchor with a possible link
+** --------------------------------------------------
+**
+** Create new anchor with a given parent and possibly
+** a name, and possibly a link to a _relatively_ named anchor.
+** (Code originally in ParseHTML.h)
+*/
+extern HTChildAnchor * HTAnchor_findChildAndLink PARAMS((
+ HTParentAnchor * parent, /* May not be 0 */
+ CONST char * tag, /* May be "" or 0 */
+ CONST char * href, /* May be "" or 0 */
+ HTLinkType * ltype)); /* May be 0 */
+
+/* Create new or find old named anchor
+** -----------------------------------
+**
+** This one is for a reference which is found in a document, and might
+** not be already loaded.
+** Note: You are not guaranteed a new anchor -- you might get an old one,
+** like with fonts.
+*/
+extern HTAnchor * HTAnchor_findAddress PARAMS((
+ CONST DocAddress * address));
+
+/* Delete an anchor and possibly related things (auto garbage collection)
+** --------------------------------------------
+**
+** The anchor is only deleted if the corresponding document is not loaded.
+** All outgoing links from parent and children are deleted, and this anchor
+** is removed from the sources list of all its targets.
+** We also try to delete the targets whose documents are not loaded.
+** If this anchor's source list is empty, we delete it and its children.
+*/
+extern BOOL HTAnchor_delete PARAMS((
+ HTParentAnchor * me));
+
+/* Move an anchor to the head of the list of its siblings
+** ------------------------------------------------------
+**
+** This is to ensure that an anchor which might have already existed
+** is put in the correct order as we load the document.
+*/
+extern void HTAnchor_makeLastChild PARAMS((
+ HTChildAnchor * me));
+
+/* Data access functions
+** ---------------------
+*/
+extern HTParentAnchor * HTAnchor_parent PARAMS((
+ HTAnchor * me));
+
+extern void HTAnchor_setDocument PARAMS((
+ HTParentAnchor * me,
+ HyperDoc * doc));
+
+extern HyperDoc * HTAnchor_document PARAMS((
+ HTParentAnchor * me));
+
+/* We don't want code to change an address after anchor creation... yet ?
+extern void HTAnchor_setAddress PARAMS((
+ HTAnchor * me,
+ char * addr));
+*/
+
+/* Returns the full URI of the anchor, child or parent
+** as a malloc'd string to be freed by the caller.
+*/
+extern char * HTAnchor_address PARAMS((
+ HTAnchor * me));
+
+extern void HTAnchor_setFormat PARAMS((
+ HTParentAnchor * me,
+ HTFormat form));
+
+extern HTFormat HTAnchor_format PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setIndex PARAMS((
+ HTParentAnchor * me,
+ char * address));
+
+extern void HTAnchor_setPrompt PARAMS((
+ HTParentAnchor * me,
+ char * prompt));
+
+extern BOOL HTAnchor_isIndex PARAMS((
+ HTParentAnchor * me));
+
+extern BOOL HTAnchor_isISMAPScript PARAMS((
+ HTAnchor * me));
+
+extern BOOL HTAnchor_hasChildren PARAMS((
+ HTParentAnchor * me));
+
+#if defined(USE_HASH)
+extern CONST char * HTAnchor_style PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setStyle PARAMS((
+ HTParentAnchor * me,
+ CONST char * style));
+#endif
+
+/* Title handling.
+*/
+extern CONST char * HTAnchor_title PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setTitle PARAMS((
+ HTParentAnchor * me,
+ CONST char * title));
+
+extern void HTAnchor_appendTitle PARAMS((
+ HTParentAnchor * me,
+ CONST char * title));
+
+/* Bookmark handling.
+*/
+extern CONST char * HTAnchor_bookmark PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setBookmark PARAMS((
+ HTParentAnchor * me,
+ CONST char * bookmark));
+
+/* Owner handling.
+*/
+extern CONST char * HTAnchor_owner PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setOwner PARAMS((
+ HTParentAnchor * me,
+ CONST char * owner));
+
+/* TITLE handling in LINKs with REV="made" or REV="owner". - FM
+*/
+extern CONST char * HTAnchor_RevTitle PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setRevTitle PARAMS((
+ HTParentAnchor * me,
+ CONST char * title));
+
+/* Suggested filename handling. - FM
+** (will be loaded if we had a Content-Disposition
+** header or META element with filename=name.suffix)
+*/
+extern CONST char * HTAnchor_SugFname PARAMS((
+ HTParentAnchor * me));
+
+/* Content-Type handling. - FM
+*/
+extern CONST char * HTAnchor_content_type PARAMS((
+ HTParentAnchor * me));
+
+/* Content-Encoding handling. - FM
+** (will be loaded if we had a Content-Encoding
+** header.)
+*/
+extern CONST char * HTAnchor_content_encoding PARAMS((
+ HTParentAnchor * me));
+
+/* Last-Modified header handling. - FM
+*/
+extern CONST char * HTAnchor_last_modified PARAMS((
+ HTParentAnchor * me));
+
+/* Date header handling. - FM
+*/
+extern CONST char * HTAnchor_date PARAMS((
+ HTParentAnchor * me));
+
+/* Server header handling. - FM
+*/
+extern CONST char * HTAnchor_server PARAMS((
+ HTParentAnchor * me));
+
+/* Safe header handling. - FM
+*/
+extern BOOL HTAnchor_safe PARAMS((
+ HTParentAnchor * me));
+
+/* Content-Base header handling. - FM
+*/
+extern CONST char * HTAnchor_content_base PARAMS((
+ HTParentAnchor * me));
+
+/* Content-Location header handling. - FM
+*/
+extern CONST char * HTAnchor_content_location PARAMS((
+ HTParentAnchor * me));
+
+/* Link this Anchor to another given one
+** -------------------------------------
+*/
+extern BOOL HTAnchor_link PARAMS((
+ HTAnchor * source,
+ HTAnchor * destination,
+ HTLinkType * type));
+
+/* Manipulation of links
+** ---------------------
+*/
+extern HTAnchor * HTAnchor_followMainLink PARAMS((
+ HTAnchor * me));
+
+extern HTAnchor * HTAnchor_followTypedLink PARAMS((
+ HTAnchor * me,
+ HTLinkType * type));
+
+extern BOOL HTAnchor_makeMainLink PARAMS((
+ HTAnchor * me,
+ HTLink * movingLink));
+
+/* Read and write methods
+** ----------------------
+*/
+extern HTList * HTAnchor_methods PARAMS((
+ HTParentAnchor * me));
+
+/* Protocol
+** --------
+*/
+extern void * HTAnchor_protocol PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setProtocol PARAMS((
+ HTParentAnchor * me,
+ void * protocol));
+
+/* Physical address
+** ----------------
+*/
+extern char * HTAnchor_physical PARAMS((
+ HTParentAnchor * me));
+
+extern void HTAnchor_setPhysical PARAMS((
+ HTParentAnchor * me,
+ char * protocol));
+
+extern LYUCcharset * HTAnchor_getUCInfoStage PARAMS((
+ HTParentAnchor * me,
+ int which_stage));
+
+extern int HTAnchor_getUCLYhndl PARAMS((
+ HTParentAnchor * me,
+ int which_stage));
+
+extern LYUCcharset * HTAnchor_setUCInfoStage PARAMS((
+ HTParentAnchor * me,
+ int LYhndl,
+ int which_stage,
+ int set_by));
+
+extern LYUCcharset * HTAnchor_setUCInfoStage PARAMS((
+ HTParentAnchor * me,
+ int LYhndl,
+ int which_stage,
+ int set_by));
+
+extern LYUCcharset * HTAnchor_resetUCInfoStage PARAMS((
+ HTParentAnchor * me,
+ int LYhndl,
+ int which_stage,
+ int set_by));
+
+extern LYUCcharset * HTAnchor_copyUCInfoStage PARAMS((
+ HTParentAnchor * me,
+ int to_stage,
+ int from_stage,
+ int set_by));
+
+extern void ImageMapList_free PARAMS((HTList * list));
+
+#endif /* HTANCHOR_H */
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.c
new file mode 100644
index 00000000000..e63c0213cb1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.c
@@ -0,0 +1,87 @@
+
+/* MODULE HTAssoc.c
+** ASSOCIATION LIST FOR STORING NAME-VALUE PAIRS.
+** NAMES NOT CASE SENSITIVE, AND ONLY COMMON LENGTH
+** IS CHECKED (allows abbreviations; well, length is
+** taken from lookup-up name, so if table contains
+** a shorter abbrev it is not found).
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+**
+**
+** BUGS:
+**
+**
+*/
+
+
+#include "HTUtils.h"
+
+#include <string.h>
+
+#include "HTAAUtil.h"
+#include "HTAssoc.h"
+#include "HTString.h"
+
+#include "LYLeaks.h"
+
+PUBLIC HTAssocList *HTAssocList_new NOARGS
+{
+ return HTList_new();
+}
+
+
+PUBLIC void HTAssocList_delete ARGS1(HTAssocList *, alist)
+{
+ if (alist) {
+ HTAssocList *cur = alist;
+ HTAssoc *assoc;
+ while (NULL != (assoc = (HTAssoc*)HTList_nextObject(cur))) {
+ FREE(assoc->name);
+ FREE(assoc->value);
+ FREE(assoc);
+ }
+ HTList_delete(alist);
+ alist = NULL;
+ }
+}
+
+
+PUBLIC void HTAssocList_add ARGS3(HTAssocList *, alist,
+ CONST char *, name,
+ CONST char *, value)
+{
+ HTAssoc *assoc;
+
+ if (alist) {
+ if (!(assoc = (HTAssoc*)malloc(sizeof(HTAssoc))))
+ outofmem(__FILE__, "HTAssoc_add");
+ assoc->name = NULL;
+ assoc->value = NULL;
+
+ if (name)
+ StrAllocCopy(assoc->name, name);
+ if (value)
+ StrAllocCopy(assoc->value, value);
+ HTList_addObject(alist, (void*)assoc);
+ } else if (TRACE) {
+ fprintf(stderr, "HTAssoc_add: ERROR: assoc list NULL!!\n");
+ }
+}
+
+
+PUBLIC char *HTAssocList_lookup ARGS2(HTAssocList *, alist,
+ CONST char *, name)
+{
+ HTAssocList *cur = alist;
+ HTAssoc *assoc;
+
+ while (NULL != (assoc = (HTAssoc*)HTList_nextObject(cur))) {
+ if (!strncasecomp(assoc->name, name, strlen(name)))
+ return assoc->value;
+ }
+ return NULL;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.h
new file mode 100644
index 00000000000..71b0c9189c5
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAssoc.h
@@ -0,0 +1,44 @@
+/* ASSOCIATION LIST FOR STORING NAME-VALUE PAIRS
+
+ Lookups from assosiation list are not case-sensitive.
+
+ */
+
+#ifndef HTASSOC_H
+#define HTASSOC_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTList.h"
+
+
+#ifdef SHORT_NAMES
+#define HTAL_new HTAssocList_new
+#define HTAL_del HTAssocList_delete
+#define HTAL_add HTAssocList_add
+#define HTAL_lup HTAssocList_lookup
+#endif /*SHORT_NAMES*/
+
+typedef HTList HTAssocList;
+
+typedef struct {
+ char * name;
+ char * value;
+} HTAssoc;
+
+
+PUBLIC HTAssocList *HTAssocList_new NOPARAMS;
+PUBLIC void HTAssocList_delete PARAMS((HTAssocList * alist));
+
+PUBLIC void HTAssocList_add PARAMS((HTAssocList * alist,
+ CONST char * name,
+ CONST char * value));
+
+PUBLIC char *HTAssocList_lookup PARAMS((HTAssocList * alist,
+ CONST char * name));
+
+#endif /* not HTASSOC_H */
+/*
+
+ End of file HTAssoc.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.c
new file mode 100644
index 00000000000..8fc95d16565
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.c
@@ -0,0 +1,169 @@
+/* Atoms: Names to numbers HTAtom.c
+** =======================
+**
+** Atoms are names which are given representative pointer values
+** so that they can be stored more efficiently, and comparisons
+** for equality done more efficiently.
+**
+** Atoms are kept in a hash table consisting of an array of linked lists.
+**
+** Authors:
+** TBL Tim Berners-Lee, WorldWideWeb project, CERN
+** (c) Copyright CERN 1991 - See Copyright.html
+**
+*/
+#include "HTUtils.h"
+
+#define HASH_SIZE 101 /* Tunable */
+#include "HTAtom.h"
+
+/*#include <stdio.h> included by HTUtils.h -- FM *//* joe@athena, TBL 921019 */
+#include <string.h>
+
+#include "HTList.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PRIVATE HTAtom * hash_table[HASH_SIZE];
+PRIVATE BOOL initialised = NO;
+
+/*
+ * To free off all atoms.
+ */
+PRIVATE void free_atoms NOPARAMS;
+
+/*
+ * Alternate hashing function.
+ */
+#define HASH_FUNCTION(cp_hash) ((strlen(cp_hash) * (unsigned char)*cp_hash) % HASH_SIZE)
+
+PUBLIC HTAtom * HTAtom_for ARGS1(CONST char *, string)
+{
+ int hash;
+ HTAtom * a;
+
+ /* First time around, clear hash table
+ */
+ /*
+ * Memory leak fixed.
+ * 05-29-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ if (!initialised) {
+ int i;
+ for (i = 0; i < HASH_SIZE; i++)
+ hash_table[i] = (HTAtom *) 0;
+ initialised = YES;
+ atexit(free_atoms);
+ }
+
+ /* Generate hash function
+ */
+ hash = HASH_FUNCTION(string);
+
+ /* Search for the string in the list
+ */
+ for (a = hash_table[hash]; a; a = a->next) {
+ if (0 == strcasecomp(a->name, string)) {
+ /* if (TRACE) fprintf(stderr,
+ "HTAtom: Old atom %p for `%s'\n", a, string); */
+ return a; /* Found: return it */
+ }
+ }
+
+ /* Generate a new entry
+ */
+ a = (HTAtom *)malloc(sizeof(*a));
+ if (a == NULL)
+ outofmem(__FILE__, "HTAtom_for");
+ a->name = (char *)malloc(strlen(string)+1);
+ if (a->name == NULL)
+ outofmem(__FILE__, "HTAtom_for");
+ strcpy(a->name, string);
+ a->next = hash_table[hash]; /* Put onto the head of list */
+ hash_table[hash] = a;
+#ifdef NOT_DEFINED
+ if (TRACE)
+ fprintf(stderr, "HTAtom: New atom %p for `%s'\n", a, string);
+#endif /* NOT_DEFINED */
+ return a;
+}
+
+/*
+ * Purpose: Free off all atoms.
+ * Arguments: void
+ * Return Value: void
+ * Remarks/Portability/Dependencies/Restrictions:
+ * To be used at program exit.
+ * Revision History:
+ * 05-29-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+PRIVATE void free_atoms NOARGS
+{
+ auto int i_counter;
+ HTAtom *HTAp_freeme;
+ /*
+ * Loop through all lists of atoms.
+ */
+ for (i_counter = 0; i_counter < HASH_SIZE; i_counter++) {
+ /*
+ * Loop through the list.
+ */
+ while (hash_table[i_counter] != NULL) {
+ /*
+ * Free off atoms and any members.
+ */
+ HTAp_freeme = hash_table[i_counter];
+ hash_table[i_counter] = HTAp_freeme->next;
+ FREE(HTAp_freeme->name);
+ FREE(HTAp_freeme);
+ }
+ }
+}
+
+PRIVATE BOOL mime_match ARGS2(CONST char *, name,
+ CONST char *, templ)
+{
+ if (name && templ) {
+ static char *n1 = NULL;
+ static char *t1 = NULL;
+ char *n2;
+ char *t2;
+
+ StrAllocCopy(n1, name); /* These also free the ones */
+ StrAllocCopy(t1, templ); /* from previous call. */
+
+ if (!(n2 = strchr(n1, '/')) || !(t2 = strchr(t1, '/')))
+ return NO;
+
+ *(n2++) = (char)0;
+ *(t2++) = (char)0;
+
+ if ((0 == strcmp(t1, "*") || 0 == strcmp(t1, n1)) &&
+ (0 == strcmp(t2, "*") || 0 == strcmp(t2, n2)))
+ return YES;
+ }
+ return NO;
+}
+
+
+PUBLIC HTList *HTAtom_templateMatches ARGS1(CONST char *, templ)
+{
+ HTList *matches = HTList_new();
+
+ if (initialised && templ) {
+ int i;
+ HTAtom *cur;
+
+ for (i = 0; i < HASH_SIZE; i++) {
+ for (cur = hash_table[i]; cur; cur = cur->next) {
+ if (mime_match(cur->name, templ))
+ HTList_addObject(matches, (void*)cur);
+ }
+ }
+ }
+ return matches;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.h
new file mode 100644
index 00000000000..b8dd10ec0b0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAtom.h
@@ -0,0 +1,49 @@
+/* */
+
+/* Atoms: Names to numbers HTAtom.h
+** =======================
+**
+** Atoms are names which are given representative pointer values
+** so that they can be stored more efficiently, and compaisons
+** for equality done more efficiently.
+**
+** HTAtom_for(string) returns a representative value such that it
+** will always (within one run of the program) return the same
+** value for the same given string.
+**
+** Authors:
+** TBL Tim Berners-Lee, WorldWideWeb project, CERN
+**
+** (c) Copyright CERN 1991 - See Copyright.html
+**
+*/
+
+#ifndef HTATOM_H
+#define HTATOM_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTList.h"
+
+#ifdef SHORT_NAMES
+#define HTAt_for HTAtom_for
+#define HTAt_tMa HTAtom_templateMatches
+#endif /*SHORT_NAMES*/
+
+typedef struct _HTAtom HTAtom;
+struct _HTAtom {
+ HTAtom * next;
+ char * name;
+}; /* struct _HTAtom */
+
+
+PUBLIC HTAtom * HTAtom_for PARAMS((CONST char * string));
+PUBLIC HTList * HTAtom_templateMatches PARAMS((CONST char * templ));
+
+#define HTAtom_name(a) ((a)->name)
+
+#endif /* HTATOM_H */
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.c
new file mode 100644
index 00000000000..c3364db9fdf
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.c
@@ -0,0 +1,210 @@
+
+/* MODULE HTAuth.c
+** USER AUTHENTICATION
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+** AL 14.10.93 Fixed the colon-not-allowed-in-password-bug.
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include <string.h>
+#include "HTPasswd.h" /* Password file routines */
+#include "HTAssoc.h"
+#include "HTAuth.h" /* Implemented here */
+#include "HTUU.h" /* Uuencoding and uudecoding */
+
+#include "LYLeaks.h"
+
+/* PRIVATE decompose_auth_string()
+** DECOMPOSE AUTHENTICATION STRING
+** FOR BASIC OR PUBKEY SCHEME
+** ON ENTRY:
+** authstring is the authorization string received
+** from browser.
+**
+** ON EXIT:
+** returns a node representing the user information
+** (as always, this is automatically freed
+** by AA package).
+*/
+PRIVATE HTAAUser *decompose_auth_string ARGS2(char *, authstring,
+ HTAAScheme, scheme)
+{
+ static HTAAUser *user = NULL;
+ static char *cleartext = NULL;
+ char *username = NULL;
+ char *password = NULL;
+ char *i_net_adr = NULL;
+ char *timestamp = NULL;
+ char *browsers_key = NULL;
+
+ if (!user && !(user = (HTAAUser*)malloc(sizeof(HTAAUser)))) /* Allocated */
+ outofmem(__FILE__, "decompose_auth_string"); /* only once */
+
+ user->scheme = scheme;
+ user->username = NULL; /* Not freed, because freeing */
+ user->password = NULL; /* cleartext also frees these */
+ user->inet_addr = NULL; /* See below: || */
+ user->timestamp = NULL; /* || */
+ user->secret_key = NULL; /* || */
+ /* \/ */
+ FREE(cleartext); /* From previous call. */
+ /* NOTE: parts of this memory are pointed to by */
+ /* pointers in HTAAUser structure. Therefore, */
+ /* this also frees all the strings pointed to */
+ /* by the static 'user'. */
+
+ if (!authstring || !*authstring ||
+ scheme != HTAA_BASIC || scheme == HTAA_PUBKEY)
+ return NULL;
+
+ if (scheme == HTAA_PUBKEY) { /* Decrypt authentication string */
+ int bytes_decoded;
+ char *ciphertext;
+ int len = strlen(authstring) + 1;
+
+ if (!(ciphertext = (char*)malloc(len)) ||
+ !(cleartext = (char*)malloc(len)))
+ outofmem(__FILE__, "decompose_auth_string");
+
+ bytes_decoded = HTUU_decode(authstring,
+ (unsigned char *)ciphertext, len);
+ ciphertext[bytes_decoded] = (char)0;
+#ifdef PUBKEY
+ HTPK_decrypt(ciphertext, cleartext, private_key);
+#endif
+ FREE(ciphertext);
+ }
+ else { /* Just uudecode */
+ int bytes_decoded;
+ int len = strlen(authstring) + 1;
+
+ if (!(cleartext = (char*)malloc(len)))
+ outofmem(__FILE__, "decompose_auth_string");
+ bytes_decoded = HTUU_decode(authstring,
+ (unsigned char *)cleartext, len);
+ cleartext[bytes_decoded] = (char)0;
+ }
+
+
+/*
+** Extract username and password (for both schemes)
+*/
+ username = cleartext;
+ if (!(password = strchr(cleartext, ':'))) {
+ if (TRACE)
+ fprintf(stderr, "%s %s\n",
+ "decompose_auth_string: password field",
+ "missing in authentication string.\n");
+ return NULL;
+ }
+ *(password++) = '\0';
+
+/*
+** Extract rest of the fields
+*/
+ if (scheme == HTAA_PUBKEY) {
+ if ( !(i_net_adr =strchr(password, ':')) ||
+ (*(i_net_adr++) ='\0'), !(timestamp =strchr(i_net_adr,':')) ||
+ (*(timestamp++) ='\0'), !(browsers_key=strchr(timestamp,':')) ||
+ (*(browsers_key++)='\0')) {
+
+ if (TRACE) fprintf(stderr, "%s %s\n",
+ "decompose_auth_string: Pubkey scheme",
+ "fields missing in authentication string");
+ return NULL;
+ }
+ }
+
+/*
+** Set the fields into the result
+*/
+ user->username = username;
+ user->password = password;
+ user->inet_addr = i_net_adr;
+ user->timestamp = timestamp;
+ user->secret_key = browsers_key;
+
+ if (TRACE) {
+ if (scheme==HTAA_BASIC)
+ fprintf(stderr, "decompose_auth_string: %s (%s,%s)\n",
+ "Basic scheme authentication string:",
+ username, password);
+ else
+ fprintf(stderr, "decompose_auth_string: %s (%s,%s,%s,%s,%s)\n",
+ "Pubkey scheme authentication string:",
+ username, password, i_net_adr, timestamp, browsers_key);
+ }
+
+ return user;
+}
+
+
+
+PRIVATE BOOL HTAA_checkTimeStamp ARGS1(CONST char *, timestamp)
+{
+ return NO; /* This is just a stub */
+}
+
+
+PRIVATE BOOL HTAA_checkInetAddress ARGS1(CONST char *, i_net_adr)
+{
+ return NO; /* This is just a stub */
+}
+
+
+/* SERVER PUBLIC HTAA_authenticate()
+** AUTHENTICATE USER
+** ON ENTRY:
+** scheme used authentication scheme.
+** scheme_specifics the scheme specific parameters
+** (authentication string for Basic and
+** Pubkey schemes).
+** prot is the protection information structure
+** for the file.
+**
+** ON EXIT:
+** returns NULL, if authentication failed.
+** Otherwise a pointer to a structure
+** representing authenticated user,
+** which should not be freed.
+*/
+PUBLIC HTAAUser *HTAA_authenticate ARGS3(HTAAScheme, scheme,
+ char *, scheme_specifics,
+ HTAAProt *, prot)
+{
+ if (HTAA_UNKNOWN == scheme || !prot ||
+ -1 == HTList_indexOf(prot->valid_schemes, (void*)scheme))
+ return NULL;
+
+ switch (scheme) {
+ case HTAA_BASIC:
+ case HTAA_PUBKEY:
+ {
+ HTAAUser *user = decompose_auth_string(scheme_specifics, scheme);
+ /* Remember, user is auto-freed */
+ if (user &&
+ HTAA_checkPassword(user->username,
+ user->password,
+ HTAssocList_lookup(prot->values, "passw")) &&
+ (HTAA_BASIC == scheme ||
+ (HTAA_checkTimeStamp(user->timestamp) &&
+ HTAA_checkInetAddress(user->inet_addr))))
+ return user;
+ else
+ return NULL;
+ }
+ break;
+ default:
+ /* Other authentication routines go here */
+ return NULL;
+ }
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.h
new file mode 100644
index 00000000000..6dc4c51616d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTAuth.h
@@ -0,0 +1,66 @@
+/* AUTHENTICATION MODULE
+
+ This is the authentication module. By modifying the function HTAA_authenticate() it can
+ be made to support external authentication methods.
+
+ */
+
+#ifndef HTAUTH_H
+#define HTAUTH_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTAAUtil.h"
+#include "HTAAProt.h"
+
+
+#ifdef SHORT_NAMES
+#define HTAAauth HTAA_authenticate
+#endif /* SHORT_NAMES */
+
+
+/*
+** Server's representation of a user (fields in authentication string)
+*/
+typedef struct {
+ HTAAScheme scheme; /* Scheme used to authenticate this user */
+ char * username;
+ char * password;
+ char * inet_addr;
+ char * timestamp;
+ char * secret_key;
+} HTAAUser;
+/*
+
+User Authentication
+
+ */
+
+/* SERVER PUBLIC HTAA_authenticate()
+** AUTHENTICATE USER
+** ON ENTRY:
+** scheme used authentication scheme.
+** scheme_specifics the scheme specific parameters
+** (authentication string for Basic and
+** Pubkey schemes).
+** prot is the protection information structure
+** for the file.
+**
+** ON EXIT:
+** returns NULL, if authentication failed.
+** Otherwise a pointer to a structure
+** representing authenticated user,
+** which should not be freed.
+*/
+PUBLIC HTAAUser *HTAA_authenticate PARAMS((HTAAScheme scheme,
+ char * scheme_specifics,
+ HTAAProt * prot));
+/*
+
+ */
+
+#endif /* not HTAUTH_H */
+/*
+
+ End of file HTAuth.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.c
new file mode 100644
index 00000000000..6515be77260
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.c
@@ -0,0 +1,720 @@
+/* Binary Tree for sorting things
+** ==============================
+** Author: Arthur Secret
+**
+** 4 March 94: Bug fixed in the balancing procedure
+**
+*/
+
+
+#include "HTUtils.h"
+#include "HTBTree.h"
+#ifndef __STRICT_BSD__
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#define MAXIMUM(a,b) ((a)>(b)?(a):(b))
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+
+PUBLIC HTBTree * HTBTree_new ARGS1(HTComparer, comp)
+ /*********************************************************
+ ** This function returns an HTBTree with memory allocated
+ ** for it when given a mean to compare things
+ */
+{
+ HTBTree * tree = (HTBTree *)malloc(sizeof(HTBTree));
+ if (tree==NULL) outofmem(__FILE__, "HTBTree_new");
+
+ tree->compare = comp;
+ tree->top = NULL;
+
+ return tree;
+}
+
+
+
+
+PRIVATE void HTBTElement_free ARGS1(HTBTElement*, element)
+ /**********************************************************
+ ** This void will free the memory allocated for one element
+ */
+{
+ if (element) {
+ if (element->left != NULL)
+ HTBTElement_free(element->left);
+ if (element->right != NULL)
+ HTBTElement_free(element->right);
+ FREE(element);
+ }
+}
+
+PUBLIC void HTBTree_free ARGS1(HTBTree*, tree)
+ /**************************************************************
+ ** This void will free the memory allocated for the whole tree
+ */
+{
+ HTBTElement_free(tree->top);
+ FREE(tree);
+}
+
+
+
+
+PRIVATE void HTBTElementAndObject_free ARGS1(HTBTElement*, element)
+ /**********************************************************
+ ** This void will free the memory allocated for one element
+ */
+{
+ if (element) { /* Just in case nothing was in the tree anyway */
+ if (element->left != NULL)
+ HTBTElementAndObject_free(element->left);
+ if (element->right != NULL)
+ HTBTElementAndObject_free(element->right);
+ FREE(element->object);
+ FREE(element);
+ }
+}
+
+PUBLIC void HTBTreeAndObject_free ARGS1(HTBTree*, tree)
+ /**************************************************************
+ ** This void will free the memory allocated for the whole tree
+ */
+{
+ HTBTElementAndObject_free(tree->top);
+ FREE(tree);
+}
+
+
+
+
+PUBLIC void HTBTree_add ARGS2(
+ HTBTree*, tree,
+ void*, object)
+ /**********************************************************************
+ ** This void is the core of HTBTree.c . It will
+ ** 1/ add a new element to the tree at the right place
+ ** so that the tree remains sorted
+ ** 2/ balance the tree to be as fast as possible when reading it
+ */
+{
+ HTBTElement * father_of_element;
+ HTBTElement * added_element;
+ HTBTElement * forefather_of_element;
+ HTBTElement * father_of_forefather;
+ BOOL father_found,top_found;
+ int depth,depth2,corrections;
+ /* father_of_element is a pointer to the structure that is the father of the
+ ** new object "object".
+ ** added_element is a pointer to the structure that contains or will contain
+ ** the new object "object".
+ ** father_of_forefather and forefather_of_element are pointers that are used
+ ** to modify the depths of upper elements, when needed.
+ **
+ ** father_found indicates by a value NO when the future father of "object"
+ ** is found.
+ ** top_found indicates by a value NO when, in case of a difference of depths
+ ** < 2, the top of the tree is encountered and forbids any further try to
+ ** balance the tree.
+ ** corrections is an integer used to avoid infinite loops in cases
+ ** such as:
+ **
+ ** 3 3
+ ** 4 4
+ ** 5 5
+ **
+ ** 3 is used here to show that it need not be the top of the tree.
+ */
+
+ /*
+ ** 1/ Adding of the element to the binary tree
+ */
+
+ if (tree->top == NULL)
+ {
+ tree->top = (HTBTElement *)malloc(sizeof(HTBTElement));
+ if (tree->top == NULL) outofmem(__FILE__, "HTBTree_add");
+ tree->top->up = NULL;
+ tree->top->object = object;
+ tree->top->left = NULL;
+ tree->top->left_depth = 0;
+ tree->top->right = NULL;
+ tree->top->right_depth = 0;
+ }
+ else
+ {
+ father_found = YES;
+ father_of_element = tree->top;
+ added_element = NULL;
+ father_of_forefather = NULL;
+ forefather_of_element = NULL;
+ while (father_found)
+ {
+ if (tree->compare(object,father_of_element->object)<0)
+ {
+ if (father_of_element->left != NULL)
+ father_of_element = father_of_element->left;
+ else
+ {
+ father_found = NO;
+ father_of_element->left =
+ (HTBTElement *)malloc(sizeof(HTBTElement));
+ if (father_of_element->left==NULL)
+ outofmem(__FILE__, "HTBTree_add");
+ added_element = father_of_element->left;
+ added_element->up = father_of_element;
+ added_element->object = object;
+ added_element->left = NULL;
+ added_element->left_depth = 0;
+ added_element->right = NULL;
+ added_element->right_depth = 0;
+ }
+ }
+ if (tree->compare(object,father_of_element->object)>=0)
+ {
+ if (father_of_element->right != NULL)
+ father_of_element = father_of_element->right;
+ else
+ {
+ father_found = NO;
+ father_of_element->right =
+ (HTBTElement *)malloc(sizeof(HTBTElement));
+ if (father_of_element->right==NULL)
+ outofmem(__FILE__, "HTBTree_add");
+ added_element = father_of_element->right;
+ added_element->up = father_of_element;
+ added_element->object = object;
+ added_element->left = NULL;
+ added_element->left_depth = 0;
+ added_element->right = NULL;
+ added_element->right_depth = 0;
+ }
+ }
+ }
+ /*
+ ** Changing of all depths that need to be changed
+ */
+ father_of_forefather = father_of_element;
+ forefather_of_element = added_element;
+ do
+ {
+ if (father_of_forefather->left == forefather_of_element)
+ {
+ depth = father_of_forefather->left_depth;
+ father_of_forefather->left_depth = 1
+ + MAXIMUM(forefather_of_element->right_depth,
+ forefather_of_element->left_depth);
+ depth2 = father_of_forefather->left_depth;
+ }
+ else
+ {
+ depth = father_of_forefather->right_depth;
+ father_of_forefather->right_depth = 1
+ + MAXIMUM(forefather_of_element->right_depth,
+ forefather_of_element->left_depth);
+ depth2 = father_of_forefather->right_depth;
+ }
+ forefather_of_element = father_of_forefather;
+ father_of_forefather = father_of_forefather->up;
+ } while ((depth != depth2) && (father_of_forefather != NULL));
+
+
+
+ /*
+ ** 2/ Balancing the binary tree, if necessary
+ */
+ top_found = YES;
+ corrections = 0;
+ while ((top_found) && (corrections < 7))
+ {
+ if ((abs(father_of_element->left_depth
+ - father_of_element->right_depth)) < 2)
+ {
+ if (father_of_element->up != NULL)
+ father_of_element = father_of_element->up;
+ else top_found = NO;
+ }
+ else
+ { /* We start the process of balancing */
+
+ corrections = corrections + 1;
+ /*
+ ** corrections is an integer used to avoid infinite
+ ** loops in cases such as:
+ **
+ ** 3 3
+ ** 4 4
+ ** 5 5
+ **
+ ** 3 is used to show that it need not be the top of the tree
+ ** But let's avoid these two exceptions anyhow
+ ** with the two following conditions (4 March 94 - AS)
+ */
+
+ if ((father_of_element->left == NULL)
+ && (father_of_element->right->right == NULL)
+ && (father_of_element->right->left->left == NULL)
+ && (father_of_element->right->left->right == NULL))
+ corrections = 7;
+
+ if ((father_of_element->right == NULL)
+ && (father_of_element->left->left == NULL)
+ && (father_of_element->left->right->right == NULL)
+ && (father_of_element->left->right->left == NULL))
+ corrections = 7;
+
+
+ if (father_of_element->left_depth > father_of_element->right_depth)
+ {
+ added_element = father_of_element->left;
+ father_of_element->left_depth = added_element->right_depth;
+ added_element->right_depth = 1
+ + MAXIMUM(father_of_element->right_depth,
+ father_of_element->left_depth);
+ if (father_of_element->up != NULL)
+ {
+ /* Bug fixed in March 94 - AS */
+ BOOL first_time;
+
+ father_of_forefather = father_of_element->up;
+ forefather_of_element = added_element;
+ first_time = YES;
+ do
+ {
+ if (father_of_forefather->left
+ == forefather_of_element->up)
+ {
+ depth = father_of_forefather->left_depth;
+ if (first_time)
+ {
+ father_of_forefather->left_depth = 1
+ + MAXIMUM(forefather_of_element->left_depth,
+ forefather_of_element->right_depth);
+ first_time = NO;
+ }
+ else
+ father_of_forefather->left_depth = 1
+ + MAXIMUM(forefather_of_element->up->left_depth,
+ forefather_of_element->up->right_depth);
+
+ depth2 = father_of_forefather->left_depth;
+ }
+ else
+ {
+ depth = father_of_forefather->right_depth;
+ if (first_time)
+ {
+ father_of_forefather->right_depth = 1
+ + MAXIMUM(forefather_of_element->left_depth,
+ forefather_of_element->right_depth);
+ first_time = NO;
+ }
+ else
+ father_of_forefather->right_depth = 1
+ + MAXIMUM(forefather_of_element->up->left_depth,
+ forefather_of_element->up->right_depth);
+ depth2 = father_of_forefather->right_depth;
+ }
+ forefather_of_element = forefather_of_element->up;
+ father_of_forefather = father_of_forefather->up;
+ } while ((depth != depth2) &&
+ (father_of_forefather != NULL));
+ father_of_forefather = father_of_element->up;
+ if (father_of_forefather->left == father_of_element)
+ {
+ /*
+ ** 3 3
+ ** 4 5
+ ** When tree 5 6 becomes 7 4
+ ** 7 8 8 6
+ **
+ ** 3 is used to show that it may not be the top of the
+ ** tree.
+ */
+ father_of_forefather->left = added_element;
+ father_of_element->left = added_element->right;
+ added_element->right = father_of_element;
+ }
+ if (father_of_forefather->right == father_of_element)
+ {
+ /*
+ ** 3 3
+ ** 4 5
+ ** When tree 5 6 becomes 7 4
+ ** 7 8 8 6
+ **
+ ** 3 is used to show that it may not be the top of the
+ ** tree
+ */
+ father_of_forefather->right = added_element;
+ father_of_element->left = added_element->right;
+ added_element->right = father_of_element;
+ }
+ added_element->up = father_of_forefather;
+ }
+ else
+ {
+ /*
+ **
+ ** 1 2
+ ** When tree 2 3 becomes 4 1
+ ** 4 5 5 3
+ **
+ ** 1 is used to show that it is the top of the tree
+ */
+ added_element->up = NULL;
+ father_of_element->left = added_element->right;
+ added_element->right = father_of_element;
+ }
+ father_of_element->up = added_element;
+ if (father_of_element->left != NULL)
+ father_of_element->left->up = father_of_element;
+ }
+ else
+ {
+ added_element = father_of_element->right;
+ father_of_element->right_depth = added_element->left_depth;
+ added_element->left_depth = 1 +
+ MAXIMUM(father_of_element->right_depth,
+ father_of_element->left_depth);
+ if (father_of_element->up != NULL)
+ /* Bug fixed in March 94 - AS */
+ {
+ BOOL first_time;
+
+ father_of_forefather = father_of_element->up;
+ forefather_of_element = added_element;
+ first_time = YES;
+ do
+ {
+ if (father_of_forefather->left
+ == forefather_of_element->up)
+ {
+ depth = father_of_forefather->left_depth;
+ if (first_time)
+ {
+ father_of_forefather->left_depth = 1
+ + MAXIMUM(forefather_of_element->left_depth,
+ forefather_of_element->right_depth);
+ first_time = NO;
+ }
+ else
+ father_of_forefather->left_depth = 1
+ + MAXIMUM(forefather_of_element->up->left_depth,
+ forefather_of_element->up->right_depth);
+ depth2 = father_of_forefather->left_depth;
+ }
+ else
+ {
+ depth = father_of_forefather->right_depth;
+ if (first_time)
+ {
+ father_of_forefather->right_depth = 1
+ + MAXIMUM(forefather_of_element->left_depth,
+ forefather_of_element->right_depth);
+ first_time = NO;
+ }
+ else
+ father_of_forefather->right_depth = 1
+ + MAXIMUM(forefather_of_element->up->left_depth,
+ forefather_of_element->up->right_depth);
+ depth2 = father_of_forefather->right_depth;
+ }
+ father_of_forefather = father_of_forefather->up;
+ forefather_of_element = forefather_of_element->up;
+ } while ((depth != depth2) &&
+ (father_of_forefather != NULL));
+ father_of_forefather = father_of_element->up;
+ if (father_of_forefather->left == father_of_element)
+ {
+ /*
+ ** 3 3
+ ** 4 6
+ ** When tree 5 6 becomes 4 8
+ ** 7 8 5 7
+ **
+ ** 3 is used to show that it may not be the top of the
+ ** tree.
+ */
+ father_of_forefather->left = added_element;
+ father_of_element->right = added_element->left;
+ added_element->left = father_of_element;
+ }
+ if (father_of_forefather->right == father_of_element)
+ {
+ /*
+ ** 3 3
+ ** 4 6
+ ** When tree 5 6 becomes 4 8
+ ** 7 8 5 7
+ **
+ ** 3 is used to show that it may not be the top of the
+ ** tree
+ */
+ father_of_forefather->right = added_element;
+ father_of_element->right = added_element->left;
+ added_element->left = father_of_element;
+ }
+ added_element->up = father_of_forefather;
+ }
+ else
+ {
+ /*
+ **
+ ** 1 3
+ ** When tree 2 3 becomes 1 5
+ ** 4 5 2 4
+ **
+ ** 1 is used to show that it is the top of the tree.
+ */
+ added_element->up = NULL;
+ father_of_element->right = added_element->left;
+ added_element->left = father_of_element;
+ }
+ father_of_element->up = added_element;
+ if (father_of_element->right != NULL)
+ father_of_element->right->up = father_of_element;
+ }
+ }
+ }
+ while (father_of_element->up != NULL)
+ {
+ father_of_element = father_of_element->up;
+ }
+ tree->top = father_of_element;
+ }
+}
+
+
+
+PUBLIC HTBTElement * HTBTree_next ARGS2(
+ HTBTree*, tree,
+ HTBTElement*, ele)
+ /**************************************************************************
+ ** this function returns a pointer to the leftmost element if ele is NULL,
+ ** and to the next object to the right otherways.
+ ** If no elements left, returns a pointer to NULL.
+ */
+{
+ HTBTElement * father_of_element;
+ HTBTElement * father_of_forefather;
+
+ if (ele == NULL)
+ {
+ father_of_element = tree->top;
+ if (father_of_element != NULL)
+ while (father_of_element->left != NULL)
+ father_of_element = father_of_element->left;
+ }
+ else
+ {
+ father_of_element = ele;
+ if (father_of_element->right != NULL)
+ {
+ father_of_element = father_of_element->right;
+ while (father_of_element->left != NULL)
+ father_of_element = father_of_element->left;
+ }
+ else
+ {
+ father_of_forefather = father_of_element->up;
+ while (father_of_forefather &&
+ (father_of_forefather->right == father_of_element))
+ {
+ father_of_element = father_of_forefather;
+ father_of_forefather = father_of_element->up;
+ }
+ father_of_element = father_of_forefather;
+ }
+ }
+#ifdef BTREE_TRACE
+ /* The option -DBTREE_TRACE will give much more information
+ ** about the way the process is running, for debugging matters
+ */
+ if (father_of_element != NULL)
+ {
+ printf("\nObject = %s\t",(char *)father_of_element->object);
+ if (father_of_element->up != NULL)
+ printf("Objet du pere = %s\n",
+ (char *)father_of_element->up->object);
+ else printf("Pas de Pere\n");
+ if (father_of_element->left != NULL)
+ printf("Objet du fils gauche = %s\t",
+ (char *)father_of_element->left->object);
+ else printf("Pas de fils gauche\t");
+ if (father_of_element->right != NULL)
+ printf("Objet du fils droit = %s\n",
+ (char *)father_of_element->right->object);
+ else printf("Pas de fils droit\n");
+ printf("Profondeur gauche = %d\t",father_of_element->left_depth);
+ printf("Profondeur droite = %d\n",father_of_element->right_depth);
+ printf(" **************\n");
+ }
+#endif
+ return father_of_element;
+}
+
+
+#ifdef TEST
+main ()
+ /******************************************************
+ ** This is just a test to show how to handle HTBTree.c
+ */
+{
+ HTBTree * tree;
+ HTBTElement * next_element;
+
+ tree = HTBTree_new((HTComparer)strcasecomp);
+ HTBTree_add(tree,"hypertext");
+ HTBTree_add(tree,"Addressing");
+ HTBTree_add(tree,"X11");
+ HTBTree_add(tree,"Tools");
+ HTBTree_add(tree,"Proposal.wn");
+ HTBTree_add(tree,"Protocols");
+ HTBTree_add(tree,"NeXT");
+ HTBTree_add(tree,"Daemon");
+ HTBTree_add(tree,"Test");
+ HTBTree_add(tree,"Administration");
+ HTBTree_add(tree,"LineMode");
+ HTBTree_add(tree,"DesignIssues");
+ HTBTree_add(tree,"MarkUp");
+ HTBTree_add(tree,"Macintosh");
+ HTBTree_add(tree,"Proposal.rtf.wn");
+ HTBTree_add(tree,"FIND");
+ HTBTree_add(tree,"Paper");
+ HTBTree_add(tree,"Tcl");
+ HTBTree_add(tree,"Talks");
+ HTBTree_add(tree,"Architecture");
+ HTBTree_add(tree,"VMSHelp");
+ HTBTree_add(tree,"Provider");
+ HTBTree_add(tree,"Archive");
+ HTBTree_add(tree,"SLAC");
+ HTBTree_add(tree,"Project");
+ HTBTree_add(tree,"News");
+ HTBTree_add(tree,"Viola");
+ HTBTree_add(tree,"Users");
+ HTBTree_add(tree,"FAQ");
+ HTBTree_add(tree,"WorkingNotes");
+ HTBTree_add(tree,"Windows");
+ HTBTree_add(tree,"FineWWW");
+ HTBTree_add(tree,"Frame");
+ HTBTree_add(tree,"XMosaic");
+ HTBTree_add(tree,"People");
+ HTBTree_add(tree,"All");
+ HTBTree_add(tree,"Curses");
+ HTBTree_add(tree,"Erwise");
+ HTBTree_add(tree,"Carl");
+ HTBTree_add(tree,"MidasWWW");
+ HTBTree_add(tree,"XPM");
+ HTBTree_add(tree,"MailRobot");
+ HTBTree_add(tree,"Illustrations");
+ HTBTree_add(tree,"VMClient");
+ HTBTree_add(tree,"XPA");
+ HTBTree_add(tree,"Clients.html");
+ HTBTree_add(tree,"Library");
+ HTBTree_add(tree,"CERNLIB_Distribution");
+ HTBTree_add(tree,"libHTML");
+ HTBTree_add(tree,"WindowsPC");
+ HTBTree_add(tree,"tkWWW");
+ HTBTree_add(tree,"tk2.3");
+ HTBTree_add(tree,"CVS-RCS");
+ HTBTree_add(tree,"DecnetSockets");
+ HTBTree_add(tree,"SGMLStream");
+ HTBTree_add(tree,"NextStep");
+ HTBTree_add(tree,"CVSRepository_old");
+ HTBTree_add(tree,"ArthurSecret");
+ HTBTree_add(tree,"CVSROOT");
+ HTBTree_add(tree,"HytelnetGate");
+ HTBTree_add(tree,"cern.www.new.src");
+ HTBTree_add(tree,"Conditions");
+ HTBTree_add(tree,"HTMLGate");
+ HTBTree_add(tree,"Makefile");
+ HTBTree_add(tree,"Newsgroups.html");
+ HTBTree_add(tree,"People.html");
+ HTBTree_add(tree,"Bugs.html");
+ HTBTree_add(tree,"Summary.html");
+ HTBTree_add(tree,"zDesignIssues.wn");
+ HTBTree_add(tree,"HT.draw");
+ HTBTree_add(tree,"HTandCERN.wn");
+ HTBTree_add(tree,"Ideas.wn");
+ HTBTree_add(tree,"MarkUp.wn");
+ HTBTree_add(tree,"Proposal.html");
+ HTBTree_add(tree,"SearchPanel.draw");
+ HTBTree_add(tree,"Comments.wn");
+ HTBTree_add(tree,"Xanadu.html");
+ HTBTree_add(tree,"Storinglinks.html");
+ HTBTree_add(tree,"TheW3Book.html");
+ HTBTree_add(tree,"Talk_Feb-91.html");
+ HTBTree_add(tree,"JFosterEntry.txt");
+ HTBTree_add(tree,"Summary.txt");
+ HTBTree_add(tree,"Bibliography.html");
+ HTBTree_add(tree,"HTandCern.txt");
+ HTBTree_add(tree,"Talk.draw");
+ HTBTree_add(tree,"zDesignNotes.html");
+ HTBTree_add(tree,"Link.html");
+ HTBTree_add(tree,"Status.html");
+ HTBTree_add(tree,"http.txt");
+ HTBTree_add(tree,"People.html~");
+ HTBTree_add(tree,"TAGS");
+ HTBTree_add(tree,"summary.txt");
+ HTBTree_add(tree,"Technical.html");
+ HTBTree_add(tree,"Terms.html");
+ HTBTree_add(tree,"JANETAccess.html");
+ HTBTree_add(tree,"People.txt");
+ HTBTree_add(tree,"README.txt");
+ HTBTree_add(tree,"CodingStandards.html");
+ HTBTree_add(tree,"Copyright.txt");
+ HTBTree_add(tree,"Status_old.html");
+ HTBTree_add(tree,"patches~");
+ HTBTree_add(tree,"RelatedProducts.html");
+ HTBTree_add(tree,"Implementation");
+ HTBTree_add(tree,"History.html");
+ HTBTree_add(tree,"Makefile.bak");
+ HTBTree_add(tree,"Makefile.old");
+ HTBTree_add(tree,"Policy.html");
+ HTBTree_add(tree,"WhatIs.html");
+ HTBTree_add(tree,"TheProject.html");
+ HTBTree_add(tree,"Notation.html");
+ HTBTree_add(tree,"Helping.html");
+ HTBTree_add(tree,"Cyber-WWW.sit.Hqx");
+ HTBTree_add(tree,"Glossary.html");
+ HTBTree_add(tree,"maketags.html");
+ HTBTree_add(tree,"IntroCS.html");
+ HTBTree_add(tree,"Contrib");
+ HTBTree_add(tree,"Help.html");
+ HTBTree_add(tree,"CodeManagExec");
+ HTBTree_add(tree,"HT-0.1draz");
+ HTBTree_add(tree,"Cello");
+ HTBTree_add(tree,"TOPUB");
+ HTBTree_add(tree,"BUILD");
+ HTBTree_add(tree,"BUILDALL");
+ HTBTree_add(tree,"Lynx");
+ HTBTree_add(tree,"ArthurLibrary");
+ HTBTree_add(tree,"RashtyClient");
+ HTBTree_add(tree,"#History.html#");
+ HTBTree_add(tree,"PerlServers");
+ HTBTree_add(tree,"modules");
+ HTBTree_add(tree,"NCSA_httpd");
+ HTBTree_add(tree,"MAIL2HTML");
+ HTBTree_add(tree,"core");
+ HTBTree_add(tree,"EmacsWWW");
+#ifdef BTREE_TRACE
+ printf("\nTreeTopObject=%s\n\n",tree->top->object);
+#endif
+ next_element = HTBTree_next(tree,NULL);
+ while (next_element != NULL)
+ {
+#ifndef BTREE_TRACE
+ printf("The next element is %s\n",next_element->object);
+#endif
+ next_element = HTBTree_next(tree,next_element);
+ }
+ HTBTree_free(tree);
+}
+
+
+#endif
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.h
new file mode 100644
index 00000000000..55bfe6aba26
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTBTree.h
@@ -0,0 +1,104 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTBTree.html
+ BALANCED BINARY TREE FOR SORTING THINGS
+
+ Tree creation, traversal and freeing. User-supplied comparison routine.
+
+ Author: Arthur Secret, CERN. Public domain. Please mail bugs and changes to
+ www-request@info.cern.ch
+
+ part of libWWW
+
+ */
+#ifdef SHORT_NAMES
+#define HTBTree_new HTBTNew
+#define HTBTree_free HTBTFree
+#define HTBTreeAndObject_free HTBTAOFr
+#define HTBTree_add HTBTAdd
+#define HTBTree_next HTBTNext
+/* #define HTBTree_object HTBTObje already a macro */
+#endif
+
+
+/*
+
+Data structures
+
+ */
+typedef struct _HTBTree_element {
+ void *object; /* User object */
+ struct _HTBTree_element *up;
+ struct _HTBTree_element *left;
+ int left_depth;
+ struct _HTBTree_element *right;
+ int right_depth;
+} HTBTElement;
+
+typedef int (*HTComparer) PARAMS((void * a, void * b));
+
+typedef struct _HTBTree_top {
+ HTComparer compare;
+ struct _HTBTree_element *top;
+} HTBTree;
+
+
+/*
+
+Create a binary tree given its discrimination routine
+
+ */
+extern HTBTree * HTBTree_new PARAMS((HTComparer comp));
+
+
+
+/*
+
+Free storage of the tree but not of the objects
+
+ */
+extern void HTBTree_free PARAMS((HTBTree* tree));
+
+
+
+/*
+
+Free storage of the tree and of the objects
+
+ */
+extern void HTBTreeAndObject_free PARAMS((HTBTree* tree));
+
+
+
+/*
+
+Add an object to a binary tree
+
+ */
+
+extern void HTBTree_add PARAMS((HTBTree* tree, void * object));
+
+
+/*
+
+Find user object for element
+
+ */
+#define HTBTree_object(element) ((element)->object)
+
+
+/*
+
+Find next element in depth-first order
+
+ ON ENTRY,
+
+ ele if NULL, start with leftmost element. if != 0 give next object to
+ the right.
+
+ returns Pointer to element ot NULL if none left.
+
+ */
+extern HTBTElement * HTBTree_next PARAMS((HTBTree* tree, HTBTElement * ele));
+
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTCJK.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTCJK.h
new file mode 100644
index 00000000000..c5fa51afac5
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTCJK.h
@@ -0,0 +1,110 @@
+/* CJK character converter HTCJK.h
+** =======================
+**
+** Added 11-Jun-96 by FM, based on jiscode.h for
+** Yutaka Sato's (ysato@etl.go.jp) SJIS.c, and
+** Takuya ASADA's (asada@three-a.co.jp) CJK patches.
+** (see SGML.c).
+**
+*/
+
+#ifndef HTCJK_H
+#define HTCJK_H
+
+/*
+** STATUS CHANGE CODES
+*/
+#ifdef ESC
+#undef ESC
+#endif /* ESC */
+#define ESC '\033'
+#define TO_2BCODE '$'
+#define TO_1BCODE '('
+
+#define TO_KANA '\016'
+#define TO_KANAOUT '\017'
+
+#define TO_KANJI "\033$B"
+#define TO_HANJI "\033$A"
+#define TO_HANGUL "\033$(C"
+#define TO_ASCII "\033(B"
+
+#define IS_SJIS_LO(lo) ((0x40<=lo)&&(lo!=0x7F)&&(lo<=0xFC))
+#define IS_SJIS_HI1(hi) ((0x81<=hi)&&(hi<=0x9F)) /* 1st lev. */
+#define IS_SJIS_HI2(hi) ((0xE0<=hi)&&(hi<=0xEF)) /* 2nd lev. */
+#define IS_SJIS(hi,lo,in_sjis) (!IS_SJIS_LO(lo)?0:IS_SJIS_HI1(hi)?(in_sjis=1):in_sjis&&IS_SJIS_HI2(hi))
+
+#define IS_EUC_LOS(lo) ((0x21<=lo)&&(lo<=0x7E)) /* standard */
+#define IS_EUC_LOX(lo) ((0xA1<=lo)&&(lo<=0xFE)) /* extended */
+#define IS_EUC_HI(hi) ((0xA1<=hi)&&(hi<=0xFE))
+#define IS_EUC(hi,lo) IS_EUC_HI(hi) && (IS_EUC_LOS(lo) || IS_EUC_LOX(lo))
+
+#define IS_BIG5_LOS(lo) ((0x40<=lo)&&(lo<=0x7E)) /* standard */
+#define IS_BIG5_LOX(lo) ((0xA1<=lo)&&(lo<=0xFE)) /* extended */
+#define IS_BIG5_HI(hi) ((0xA1<=hi)&&(hi<=0xFE))
+#define IS_BIG5(hi,lo) IS_BIG5_HI(hi) && (IS_BIG5_LOS(lo) || IS_BIG5_LOX(lo))
+
+typedef enum _HTkcode {NOKANJI, EUC, SJIS, JIS} HTkcode;
+typedef enum _HTCJKlang {NOCJK, JAPANESE, CHINESE, KOREAN, TAIPEI} HTCJKlang;
+
+/*
+** Function prototypes.
+*/
+extern void JISx0201TO0208_EUC PARAMS((
+ register unsigned char IHI,
+ register unsigned char ILO,
+ register unsigned char * OHI,
+ register unsigned char * OLO));
+
+extern unsigned char * SJIS_TO_JIS1 PARAMS((
+ register unsigned char HI,
+ register unsigned char LO,
+ register unsigned char * JCODE));
+
+extern unsigned char * JIS_TO_SJIS1 PARAMS((
+ register unsigned char HI,
+ register unsigned char LO,
+ register unsigned char * SJCODE));
+
+extern unsigned char * EUC_TO_SJIS1 PARAMS((
+ unsigned char HI,
+ unsigned char LO,
+ register unsigned char * SJCODE));
+
+extern void JISx0201TO0208_SJIS PARAMS((
+ register unsigned char I,
+ register unsigned char * OHI,
+ register unsigned char * OLO));
+
+extern unsigned char * SJIS_TO_EUC1 PARAMS((
+ unsigned char HI,
+ unsigned char LO,
+ unsigned char * EUCp));
+
+extern unsigned char * SJIS_TO_EUC PARAMS((
+ unsigned char * src,
+ unsigned char * dst));
+
+extern unsigned char * EUC_TO_SJIS PARAMS((
+ unsigned char * src,
+ unsigned char * dst));
+
+extern unsigned char * EUC_TO_JIS PARAMS((
+ unsigned char * src,
+ unsigned char * dst,
+ CONST char * toK,
+ CONST char * toA));
+
+extern unsigned char * TO_EUC PARAMS((
+ unsigned char * jis,
+ unsigned char * euc));
+
+extern void TO_SJIS PARAMS((
+ unsigned char * any,
+ unsigned char * sjis));
+
+extern void TO_JIS PARAMS((
+ unsigned char * any,
+ unsigned char * jis));
+
+#endif /* HTCJK_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.c
new file mode 100644
index 00000000000..fd66a482324
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.c
@@ -0,0 +1,204 @@
+/* Chunk handling: Flexible arrays
+** ===============================
+**
+*/
+
+#include "HTUtils.h"
+#include "HTChunk.h"
+/*#include <stdio.h> included by HTUtils.h -- FM */
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* Create a chunk with a certain allocation unit
+** --------------
+*/
+PUBLIC HTChunk * HTChunkCreate ARGS1 (int,grow)
+{
+ HTChunk * ch = (HTChunk *) calloc(1, sizeof(HTChunk));
+ if (ch == NULL)
+ outofmem(__FILE__, "creation of chunk");
+
+ ch->data = 0;
+ ch->growby = grow;
+ ch->size = 0;
+ ch->allocated = 0;
+ return ch;
+}
+
+/* Create a chunk with a certain allocation unit and ensured size
+** --------------
+*/
+PUBLIC HTChunk * HTChunkCreate2 ARGS2 (int,grow, size_t, needed)
+{
+ HTChunk * ch = (HTChunk *) calloc(1, sizeof(HTChunk));
+ if (ch == NULL)
+ outofmem(__FILE__, "HTChunkCreate2");
+
+ ch->growby = grow;
+ if (needed > 0) {
+ ch->allocated = needed-1 - ((needed-1) % ch->growby)
+ + ch->growby; /* Round up */
+ ch->data = (char *)calloc(1, ch->allocated);
+ if (!ch->data)
+ outofmem(__FILE__, "HTChunkCreate2 data");
+ }
+ ch->size = 0;
+ return ch;
+}
+
+
+/* Clear a chunk of all data
+** --------------------------
+*/
+PUBLIC void HTChunkClear ARGS1 (HTChunk *,ch)
+{
+ FREE(ch->data);
+ ch->size = 0;
+ ch->allocated = 0;
+}
+
+
+/* Free a chunk
+** ------------
+*/
+PUBLIC void HTChunkFree ARGS1 (HTChunk *,ch)
+{
+ FREE(ch->data);
+ FREE(ch);
+}
+
+
+/* Append a character
+** ------------------
+*/
+PUBLIC void HTChunkPutc ARGS2 (HTChunk *,ch, char,c)
+{
+ if (ch->size >= ch->allocated) {
+ ch->allocated = ch->allocated + ch->growby;
+ ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+ : (char *)calloc(1, ch->allocated);
+ if (!ch->data)
+ outofmem(__FILE__, "HTChunkPutc");
+ }
+ ch->data[ch->size++] = c;
+}
+
+
+/* Ensure a certain size
+** ---------------------
+*/
+PUBLIC void HTChunkEnsure ARGS2 (HTChunk *,ch, int,needed)
+{
+ if (needed <= ch->allocated) return;
+ ch->allocated = needed-1 - ((needed-1) % ch->growby)
+ + ch->growby; /* Round up */
+ ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+ : (char *)calloc(1, ch->allocated);
+ if (ch->data == NULL)
+ outofmem(__FILE__, "HTChunkEnsure");
+}
+
+PUBLIC void HTChunkPutb ARGS3 (HTChunk *,ch, CONST char *,b, int,l)
+{
+ int needed = ch->size + l;
+ if (l <= 0) return;
+ if (needed > ch->allocated) {
+ ch->allocated = needed-1 - ((needed-1) % ch->growby)
+ + ch->growby; /* Round up */
+ ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+ : (char *)calloc(1, ch->allocated);
+ if (ch->data == NULL)
+ outofmem(__FILE__, "HTChunkPutb");
+ }
+ memcpy(ch->data + ch->size, b, l);
+ ch->size += l;
+}
+
+#define PUTC(code) ch->data[ch->size++] = (char)(code)
+#define PUTC2(code) ch->data[ch->size++] = (char)(0x80|(0x3f &(code)))
+
+PUBLIC void HTChunkPutUtf8Char ARGS2(
+ HTChunk *, ch,
+ UCode_t, code)
+{
+ int utflen;
+
+ if (code < 128)
+ utflen = 1;
+ else if (code < 0x800L) {
+ utflen = 2;
+ } else if (code < 0x10000L) {
+ utflen = 3;
+ } else if (code < 0x200000L) {
+ utflen = 4;
+ } else if (code < 0x4000000L) {
+ utflen = 5;
+ } else if (code<=0x7fffffffL) {
+ utflen = 6;
+ } else
+ utflen = 0;
+
+ if (ch->size + utflen > ch->allocated) {
+ int growby = (ch->growby >= utflen) ? ch->growby : utflen;
+ ch->allocated = ch->allocated + growby;
+ ch->data = ch->data ? (char *)realloc(ch->data, ch->allocated)
+ : (char *)calloc(1, ch->allocated);
+ if (!ch->data)
+ outofmem(__FILE__, "HTChunkPutUtf8Char");
+ }
+
+ switch (utflen) {
+ case 0:
+ return;
+ case 1:
+ ch->data[ch->size++] = (char)code;
+ return;
+ case 2:
+ PUTC(0xc0 | (code>>6));
+ break;
+ case 3:
+ PUTC(0xe0 | (code>>12));
+ break;
+ case 4:
+ PUTC(0xf0 | (code>>18));
+ break;
+ case 5:
+ PUTC(0xf8 | (code>>24));
+ break;
+ case 6:
+ PUTC(0xfc | (code>>30));
+ }
+ switch (utflen) {
+ case 6:
+ PUTC2(code>>24);
+ case 5:
+ PUTC2(code>>18);
+ case 4:
+ PUTC2(code>>12);
+ case 3:
+ PUTC2(code>>6);
+ case 2:
+ PUTC2(code);
+ }
+}
+
+/* Terminate a chunk
+** -----------------
+*/
+PUBLIC void HTChunkTerminate ARGS1 (HTChunk *,ch)
+{
+ HTChunkPutc(ch, (char)0);
+}
+
+
+/* Append a string
+** ---------------
+*/
+PUBLIC void HTChunkPuts ARGS2 (HTChunk *,ch, CONST char *,s)
+{
+ CONST char * p;
+ for (p=s; *p; p++)
+ HTChunkPutc(ch, *p);
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.h
new file mode 100644
index 00000000000..37ef890c95f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTChunk.h
@@ -0,0 +1,171 @@
+/* HTChunk: Flexible array handling for libwww
+ CHUNK HANDLING:
+ FLEXIBLE ARRAYS
+
+ This module implements a flexible array. It is a general utility module. A chunk is a
+ structure which may be extended. These routines create and append data to chunks,
+ automatically reallocating them as necessary.
+
+ */
+#include "UCMap.h"
+
+typedef struct {
+ int size; /* In bytes */
+ int growby; /* Allocation unit in bytes */
+ int allocated; /* Current size of *data */
+ char * data; /* Pointer to malloced area or 0 */
+} HTChunk;
+
+
+#ifdef SHORT_NAMES
+#define HTChunkClear HTChClea
+#define HTChunkPutc HTChPutc
+#define HTChunkPuts HTChPuts
+#define HTChunkCreate HTChCrea
+#define HTChunkTerminate HTChTerm
+#define HTChunkEnsure HtChEnsu
+#endif
+
+
+/*
+
+Create new chunk
+
+ ON ENTRY,
+
+ growby The number of bytes to allocate at a time when the chunk is
+ later extended. Arbitrary but normally a trade-off time vs.
+ memory
+
+ ON EXIT,
+
+ returns A chunk pointer to the new chunk,
+
+ */
+
+extern HTChunk * HTChunkCreate PARAMS((int growby));
+
+/*
+ * Like HTChunkCreate but with initial allocation - kw
+ *
+ */
+extern HTChunk * HTChunkCreate2 PARAMS((int growby, size_t needed));
+
+
+/*
+
+Free a chunk
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ ON EXIT,
+
+ ch is invalid and may not be used.
+
+ */
+
+extern void HTChunkFree PARAMS((HTChunk * ch));
+
+
+/*
+
+Clear a chunk
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ ON EXIT,
+
+ *ch The size of the chunk is zero.
+
+ */
+
+extern void HTChunkClear PARAMS((HTChunk * ch));
+
+
+/*
+
+Ensure a chunk has a certain space in
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ s The size required
+
+ ON EXIT,
+
+ *ch Has size at least s
+
+ */
+
+extern void HTChunkEnsure PARAMS((HTChunk * ch, int s));
+
+
+/*
+
+Append a character to a chunk
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ c The character to be appended
+
+ ON EXIT,
+
+ *ch Is one character bigger
+
+ */
+extern void HTChunkPutc PARAMS((HTChunk * ch, char c));
+
+extern void HTChunkPutb PARAMS((HTChunk * ch, CONST char *b, int l));
+
+extern void HTChunkPutUtf8Char PARAMS((HTChunk * ch, UCode_t code));
+
+/*
+Append a string to a chunk
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ str Tpoints to a zero-terminated string to be appended
+
+ ON EXIT,
+
+ *ch Is bigger by strlen(str)
+
+ */
+
+
+extern void HTChunkPuts PARAMS((HTChunk * ch, const char *str));
+
+
+/*
+
+Append a zero character to a chunk
+
+ */
+
+/*
+
+ ON ENTRY,
+
+ ch A valid chunk pointer made by HTChunkCreate()
+
+ ON EXIT,
+
+ *ch Is one character bigger
+
+ */
+
+
+extern void HTChunkTerminate PARAMS((HTChunk * ch));
+
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.c
new file mode 100644
index 00000000000..5e22915b1ed
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.c
@@ -0,0 +1,94 @@
+/* DOS specific routines
+
+ */
+
+#include <mem.h>
+#include <dos.h>
+
+
+/* PUBLIC HTDOS_wwwName()
+** CONVERTS DOS Name into WWW Name
+** ON ENTRY:
+** dosname DOS file specification (NO NODE)
+**
+** ON EXIT:
+** returns WWW file specification
+**
+*/
+char * HTDOS_wwwName (char *dosname)
+{
+ static char wwwname[1024];
+ char *cp_url = wwwname;
+
+ strcpy(wwwname,dosname);
+
+ for ( ; *cp_url != '\0' ; cp_url++)
+ if(*cp_url == '\\') *cp_url = '/'; /* convert dos backslash to unix-style */
+
+ if(strlen(wwwname) > 3 && *cp_url == '/')
+ *cp_url = '\0';
+
+ if(*cp_url == ':')
+ {
+ cp_url++;
+ *cp_url = '/';
+ }
+
+/*
+ if((strlen(wwwname)>2)&&(wwwname[1]==':')) wwwname[1]='|';
+ printf("\n\nwww: %s\n\ndos: %s\n\n",wwwname,dosname);
+ sleep(5);
+*/
+ return(wwwname);
+}
+
+
+/* PUBLIC HTDOS_name()
+** CONVERTS WWW name into a DOS name
+** ON ENTRY:
+** wwwname WWW file name
+**
+** ON EXIT:
+** returns DOS file specification
+**
+** Bug(?): Returns pointer to input string, which is modified
+*/
+char * HTDOS_name(char *wwwname)
+{
+ static char cp_url[1024];
+ int joe;
+
+ memset(cp_url, 0, 1023);
+ sprintf(cp_url, "%s",wwwname);
+
+ for(joe = 0; cp_url[joe] != '\0'; joe++) {
+ if(cp_url[joe] == '/') {
+ cp_url[joe] = '\\';
+ }
+ }
+
+/* if(strlen(cp_url) < 4) cp_url[] = ':';
+ if(strlen(cp_url) == 3) cp_url[3] = '\\';
+
+ if(strlen(cp_url) == 4) cp_url[4] = '.'; */
+
+ if((strlen(cp_url) > 2) && (cp_url[1] == '|'))
+ cp_url[1] = ':';
+
+ if((cp_url[1] == '\\') || (cp_url[0] != '\\'))
+ {
+#if 0
+ printf("\n\n%s = i%\n\n",cp_url,strlen(cp_url));
+ sleep(5);
+#endif
+ strcpy(wwwname, cp_url);
+ return(wwwname); /* return(cp_url); */
+ } else {
+#if 0
+ printf("\n\n%s = %i\n\n",cp_url+1,strlen(cp_url));
+ sleep(5);
+#endif
+ strcpy(wwwname, cp_url+1);
+ return(wwwname); /* return(cp_url+1); */
+ }
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.h
new file mode 100644
index 00000000000..d2a2e0beec1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTDOS.h
@@ -0,0 +1,32 @@
+/* DOS specific routines */
+
+#ifndef HTDOS_H
+#define HTDOS_H
+
+
+/* PUBLIC HTDOS_wwwName()
+** CONVERTS DOS Name into WWW Name
+** ON ENTRY:
+** dosname DOS file specification (NO NODE)
+**
+** ON EXIT:
+** returns WWW file specification
+**
+*/
+char * HTDOS_wwwName (char * dosname);
+
+
+/* PUBLIC HTDOS_name()
+** CONVERTS WWW name into a DOS name
+** ON ENTRY:
+** wwwname WWW file name
+**
+** ON EXIT:
+** returns DOS file specification
+**
+** Bug: Returns pointer to static -- non-reentrant
+*/
+char * HTDOS_name (char * wwwname);
+
+
+#endif /* HTDOS_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.c
new file mode 100644
index 00000000000..8c014f76e9f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.c
@@ -0,0 +1,3399 @@
+/* File Transfer Protocol (FTP) Client
+** for a WorldWideWeb browser
+** ===================================
+**
+** A cache of control connections is kept.
+**
+** Note: Port allocation
+**
+** It is essential that the port is allocated by the system, rather
+** than chosen in rotation by us (POLL_PORTS), or the following
+** problem occurs.
+**
+** It seems that an attempt by the server to connect to a port which has
+** been used recently by a listen on the same socket, or by another
+** socket this or another process causes a hangup of (almost exactly)
+** one minute. Therefore, we have to use a rotating port number.
+** The problem remains that if the application is run twice in quick
+** succession, it will hang for what remains of a minute.
+**
+** Authors
+** TBL Tim Berners-lee <timbl@info.cern.ch>
+** DD Denis DeLaRoca 310 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
+** LM Lou Montulli <montulli@ukanaix.cc.ukans.edu>
+** FM Foteos Macrides <macrides@sci.wfeb.edu>
+** History:
+** 2 May 91 Written TBL, as a part of the WorldWideWeb project.
+** 15 Jan 92 Bug fix: close() was used for NETCLOSE for control soc
+** 10 Feb 92 Retry if cached connection times out or breaks
+** 8 Dec 92 Bug fix 921208 TBL after DD
+** 17 Dec 92 Anon FTP password now just WWWuser@ suggested by DD
+** fails on princeton.edu!
+** 27 Dec 93 (FM) Fixed up so FTP now works with VMS hosts. Path
+** must be Unix-style and cannot include the device
+** or top directory.
+** ?? ??? ?? (LM) Added code to prompt and send passwords for non
+** anonymous FTP
+** 25 Mar 94 (LM) Added code to recognize different ftp server types
+** and code to parse dates and sizes on most hosts.
+** 27 Mar 93 (FM) Added code for getting dates and sizes on VMS hosts.
+**
+** Options:
+** LISTEN We listen, the other guy connects for data.
+** Otherwise, other way round, but problem finding our
+** internet address!
+**
+** Notes:
+** Portions Copyright 1994 Trustees of Dartmouth College
+** Code for recognizing different FTP servers and
+** parsing "ls -l" output taken from Macintosh Fetch
+** program with permission from Jim Matthews,
+** Dartmouth Software Development Team.
+*/
+
+/*
+** If LISTEN is not defined, PASV is used instead of PORT, and not
+** all FTP servers support PASV, so define it unless there is no
+** alternative for your system.
+*/
+#ifndef NOPORT
+#define LISTEN /* @@@@ Test LJM */
+#endif /* !NOPORT */
+
+/*
+BUGS: @@@ Limit connection cache size!
+ Error reporting to user.
+ 400 & 500 errors are acked by user with windows.
+ Use configuration file for user names
+
+** Note for portablility this version does not use select() and
+** so does not watch the control and data channels at the
+** same time.
+*/
+
+#ifdef DJGPP
+#define u_long unsigned long
+#endif
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTAlert.h"
+
+#include "HTFTP.h" /* Implemented here */
+
+/* this define should be in HTFont.h :( */
+#define HT_NON_BREAK_SPACE ((char)1) /* For now */
+
+#define REPEAT_PORT /* Give the port number for each file */
+#define REPEAT_LISTEN /* Close each listen socket and open a new one */
+
+/* define POLL_PORTS If allocation does not work, poll ourselves.*/
+#define LISTEN_BACKLOG 2 /* Number of pending connect requests (TCP)*/
+
+#define FIRST_TCP_PORT 1024 /* Region to try for a listening port */
+#define LAST_TCP_PORT 5999
+
+#define LINE_LENGTH 256
+#define COMMAND_LENGTH 256
+
+#define INFINITY 512
+
+#include "HTParse.h"
+#include "HTTCP.h"
+#include "HTAnchor.h"
+#include "HTFile.h" /* For HTFileFormat() */
+#include "HTBTree.h"
+#include "HTChunk.h"
+#include "HTAlert.h"
+#ifndef IPPORT_FTP
+#define IPPORT_FTP 21
+#endif /* !IPORT_FTP */
+
+#include "LYLeaks.h"
+
+typedef struct _connection {
+ struct _connection * next; /* Link on list */
+ u_long addr; /* IP address */
+ int socket; /* Socket number for communication */
+ BOOL binary; /* Binary mode? */
+} connection;
+
+#ifndef NIL
+#define NIL 0
+#endif /* !NIL */
+
+/* Hypertext object building machinery
+*/
+#include "HTML.h"
+
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET (*targetClass._free)(target)
+#define ABORT_TARGET (*targetClass._free)(target)
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern int HTCheckForInterrupt NOPARAMS;
+
+
+/* Global Variables
+** ---------------------
+*/
+PUBLIC BOOLEAN HTfileSortMethod = FILE_BY_NAME;
+PRIVATE char ThisYear[8];
+PRIVATE char LastYear[8];
+PRIVATE int TheDate;
+PRIVATE BOOLEAN HaveYears = FALSE;
+#ifdef SOCKS
+extern BOOLEAN socks_flag;
+extern unsigned long socks_bind_remoteAddr;
+#endif /* SOCKS */
+extern char *personal_mail_address;
+
+/* Module-Wide Variables
+** ---------------------
+*/
+PRIVATE connection * connections = NULL;/* Linked list of connections */
+PRIVATE char response_text[LINE_LENGTH+1];/* Last response from ftp host */
+PRIVATE connection * control = NULL; /* Current connection */
+PRIVATE int data_soc = -1; /* Socket for data transfer =invalid */
+PRIVATE char *user_entered_password = NULL;
+PRIVATE char *last_username_and_host = NULL;
+
+#define GENERIC_SERVER 0
+#define MACHTEN_SERVER 1
+#define UNIX_SERVER 2
+#define VMS_SERVER 3
+#define CMS_SERVER 4
+#define DCTS_SERVER 5
+#define TCPC_SERVER 6
+#define PETER_LEWIS_SERVER 7
+#define NCSA_SERVER 8
+#define WINDOWS_NT_SERVER 9
+#define MS_WINDOWS_SERVER 10
+#define MSDOS_SERVER 11
+#define APPLESHARE_SERVER 12
+#define NETPRESENZ_SERVER 13
+
+PRIVATE int server_type = GENERIC_SERVER; /* the type of ftp host */
+PRIVATE int unsure_type = FALSE; /* sure about the type? */
+PRIVATE BOOLEAN use_list = FALSE; /* use the LIST command? */
+
+PRIVATE int interrupted_in_next_data_char = FALSE;
+
+#ifdef POLL_PORTS
+PRIVATE unsigned short port_number = FIRST_TCP_PORT;
+#endif /* POLL_PORTS */
+
+#ifdef LISTEN
+PRIVATE int master_socket = -1; /* Listening socket = invalid */
+PRIVATE char port_command[255]; /* Command for setting the port */
+PRIVATE fd_set open_sockets; /* Mask of active channels */
+PRIVATE int num_sockets; /* Number of sockets to scan */
+#else
+PRIVATE unsigned short passive_port; /* Port server specified for data */
+#endif /* LISTEN */
+
+
+#define NEXT_CHAR HTGetCharacter() /* Use function in HTFormat.c */
+
+#define DATA_BUFFER_SIZE 2048
+PRIVATE char data_buffer[DATA_BUFFER_SIZE]; /* Input data buffer */
+PRIVATE char * data_read_pointer;
+PRIVATE char * data_write_pointer;
+#define NEXT_DATA_CHAR next_data_char()
+PRIVATE int close_connection PARAMS((
+ connection * con));
+
+
+/*
+** This function frees module globals. - FM
+*/
+PRIVATE void free_FTPGlobals NOARGS
+{
+ FREE(user_entered_password);
+ FREE(last_username_and_host);
+ if (control) {
+ if (control->socket != -1)
+ close_connection(control);
+ FREE(control);
+ }
+}
+
+/* PUBLIC HTMake_VMS_name()
+** CONVERTS WWW name into a VMS name
+** ON ENTRY:
+** nn Node Name (optional)
+** fn WWW file name
+**
+** ON EXIT:
+** returns vms file specification
+**
+** Bug: Returns pointer to static -- non-reentrant
+*/
+PUBLIC char * HTMake_VMS_name ARGS2(
+ CONST char *, nn,
+ CONST char *, fn)
+{
+
+/* We try converting the filename into Files-11 syntax. That is, we assume
+** first that the file is, like us, on a VMS node. We try remote
+** (or local) DECnet access. Files-11, VMS, VAX and DECnet
+** are trademarks of Digital Equipment Corporation.
+** The node is assumed to be local if the hostname WITHOUT DOMAIN
+** matches the local one. @@@
+*/
+ static char vmsname[INFINITY]; /* returned */
+ char * filename = (char*)malloc(strlen(fn)+1);
+ char * nodename = (char*)malloc(strlen(nn)+2+1); /* Copies to hack */
+ char *second; /* 2nd slash */
+ char *last; /* last slash */
+
+ CONST char * hostname = HTHostName();
+
+ if (!filename || !nodename)
+ outofmem(__FILE__, "HTVMSname");
+ strcpy(filename, fn);
+ strcpy(nodename, ""); /* On same node? Yes if node names match */
+ if (strncmp(nn, "localhost", 9)) {
+ CONST char *p;
+ char *q;
+ for (p = hostname, q = (char *)nn;
+ *p && *p != '.' && *q && *q != '.'; p++, q++){
+ if (TOUPPER(*p) != TOUPPER(*q)) {
+ strcpy(nodename, nn);
+ q = strchr(nodename, '.'); /* Mismatch */
+ if (q)
+ *q = '\0'; /* Chop domain */
+ strcat(nodename, "::"); /* Try decnet anyway */
+ break;
+ }
+ }
+ }
+
+ second = strchr(filename+1, '/'); /* 2nd slash */
+ last = strrchr(filename, '/'); /* last slash */
+
+ if (!second) { /* Only one slash */
+ sprintf(vmsname, "%s%s", nodename, filename + 1);
+ } else if (second == last) { /* Exactly two slashes */
+ *second = '\0'; /* Split filename from disk */
+ sprintf(vmsname, "%s%s:%s", nodename, filename+1, second+1);
+ *second = '/'; /* restore */
+ } else { /* More than two slashes */
+ char * p;
+ *second = '\0'; /* Split disk from directories */
+ *last = '\0'; /* Split dir from filename */
+ sprintf(vmsname, "%s%s:[%s]%s",
+ nodename, filename+1, second+1, last+1);
+ *second = *last = '/'; /* restore filename */
+ for (p = strchr(vmsname, '['); *p!=']'; p++)
+ if (*p == '/')
+ *p = '.'; /* Convert dir sep. to dots */
+ }
+ FREE(nodename);
+ FREE(filename);
+ return vmsname;
+}
+
+/* Procedure: Read a character from the data connection
+** ----------------------------------------------------
+*/
+PRIVATE char next_data_char NOARGS
+{
+ int status;
+ if (data_read_pointer >= data_write_pointer) {
+ status = NETREAD(data_soc, data_buffer, DATA_BUFFER_SIZE);
+ if (status == HT_INTERRUPTED)
+ interrupted_in_next_data_char = 1;
+ if (status <= 0)
+ return (char)-1;
+ data_write_pointer = data_buffer + status;
+ data_read_pointer = data_buffer;
+ }
+#ifdef NOT_ASCII
+ {
+ char c = *data_read_pointer++;
+ return FROMASCII(c);
+ }
+#else
+ return *data_read_pointer++;
+#endif /* NOT_ASCII */
+}
+
+
+/* Close an individual connection
+**
+*/
+PRIVATE int close_connection ARGS1(
+ connection *, con)
+{
+ connection * scan;
+ int status = NETCLOSE(con->socket);
+ if (TRACE) {
+ fprintf(stderr, "HTFTP: Closing control socket %d\n", con->socket);
+#ifdef UNIX
+ if (status != 0)
+ perror("HTFTP:close_connection");
+#endif
+ }
+ con->socket = -1;
+ if (connections == con) {
+ connections = con->next;
+ return status;
+ }
+ for (scan = connections; scan; scan = scan->next) {
+ if (scan->next == con) {
+ scan->next = con->next; /* Unlink */
+ if (control == con)
+ control = (connection*)0;
+ return status;
+ } /*if */
+ } /* for */
+ return -1; /* very strange -- was not on list. */
+}
+
+PRIVATE char *help_message_buffer = NULL; /* global :( */
+
+PRIVATE void init_help_message_cache NOARGS
+{
+ FREE(help_message_buffer);
+}
+
+PRIVATE void help_message_cache_add ARGS1(
+ char *, string)
+{
+ if (help_message_buffer)
+ StrAllocCat(help_message_buffer, string);
+ else
+ StrAllocCopy(help_message_buffer, string);
+
+ if (TRACE)
+ fprintf(stderr,"Adding message to help cache: %s\n",string);
+}
+
+PRIVATE char *help_message_cache_non_empty NOARGS
+{
+ return(help_message_buffer);
+}
+PRIVATE char *help_message_cache_contents NOARGS
+{
+ return(help_message_buffer);
+}
+
+/* Execute Command and get Response
+** --------------------------------
+**
+** See the state machine illustrated in RFC959, p57. This implements
+** one command/reply sequence. It also interprets lines which are to
+** be continued, which are marked with a "-" immediately after the
+** status code.
+**
+** Continuation then goes on until a line with a matching reply code
+** an a space after it.
+**
+** On entry,
+** con points to the connection which is established.
+** cmd points to a command, or is NIL to just get the response.
+**
+** The command is terminated with the CRLF pair.
+**
+** On exit,
+** returns: The first digit of the reply type,
+** or negative for communication failure.
+*/
+PRIVATE int response ARGS1(
+ char *, cmd)
+{
+ int result; /* Three-digit decimal code */
+ int continuation_response = -1;
+ int status;
+
+ if (!control) {
+ if (TRACE)
+ fprintf(stderr, "HTFTP: No control connection set up!!\n");
+ return -99;
+ }
+
+ if (cmd) {
+ if (TRACE)
+ fprintf(stderr, " Tx: %s", cmd);
+#ifdef NOT_ASCII
+ {
+ char * p;
+ for (p = cmd; *p; p++) {
+ *p = TOASCII(*p);
+ }
+ }
+#endif /* NOT_ASCII */
+ status = NETWRITE(control->socket, cmd, (int)strlen(cmd));
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTFTP: Error %d sending command: closing socket %d\n",
+ status, control->socket);
+ close_connection(control);
+ return status;
+ }
+ }
+
+ do {
+ char *p = response_text;
+ for (;;) {
+ if (((*p++ = NEXT_CHAR) == LF)
+ || (p == &response_text[LINE_LENGTH])) {
+
+ char continuation;
+
+ if (interrupted_in_htgetcharacter)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted in HTGetCharacter, apparently.\n");
+ NETCLOSE (control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+
+ *p = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, " Rx: %s", response_text);
+
+ /* Check for login or help messages */
+ if (!strncmp(response_text,"230-",4) ||
+ !strncmp(response_text,"250-",4) ||
+ !strncmp(response_text,"220-",4))
+ help_message_cache_add(response_text+4);
+
+ sscanf(response_text, "%d%c", &result, &continuation);
+ if (continuation_response == -1) {
+ if (continuation == '-') /* start continuation */
+ continuation_response = result;
+ } else { /* continuing */
+ if (continuation_response == result &&
+ continuation == ' ')
+ continuation_response = -1; /* ended */
+ }
+ break;
+ } /* if end of line */
+
+ if (interrupted_in_htgetcharacter)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted in HTGetCharacter, apparently.\n");
+ NETCLOSE (control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+
+ if (*(p-1) == (char) EOF) {
+ if (TRACE)
+ fprintf(stderr, "Error on rx: closing socket %d\n",
+ control->socket);
+ strcpy(response_text, "000 *** TCP read error on response\n");
+ close_connection(control);
+ return -1; /* End of file on response */
+ }
+ } /* Loop over characters */
+
+ } while (continuation_response != -1);
+
+ if (result == 421) {
+ if (TRACE)
+ fprintf(stderr, "HTFTP: They close so we close socket %d\n",
+ control->socket);
+ close_connection(control);
+ return -1;
+ }
+ if ((result == 255 && server_type == CMS_SERVER) &&
+ (0 == strncasecomp(cmd, "CWD", 3) ||
+ 0 == strcasecomp(cmd, "CDUP"))) {
+ /*
+ ** Alas, CMS returns 255 on failure to CWD to parent of root. - PG
+ */
+ result = 555;
+ }
+ return result/100;
+}
+
+/*
+ * This function should try to set the macintosh server into binary mode.
+ * Some servers need an additional letter after the MACB command.
+ */
+PRIVATE int set_mac_binary ARGS1(
+ int, ServerType)
+{
+ /* try to set mac binary mode */
+ if (ServerType == APPLESHARE_SERVER ||
+ ServerType == NETPRESENZ_SERVER) {
+ /*
+ * Presumably E means "Enable". - KW
+ */
+ return(2 == response("MACB E\r\n"));
+ } else {
+ return(2 == response("MACB\r\n"));
+ }
+}
+
+/* This function gets the current working directory to help
+ * determine what kind of host it is
+ */
+
+PRIVATE void get_ftp_pwd ARGS2(
+ int *, ServerType,
+ BOOLEAN *, UseList)
+{
+
+ char *cp;
+ /* get the working directory (to see what it looks like) */
+ int status = response("PWD\r\n");
+ if (status < 0) {
+ return;
+ } else {
+ cp = strchr(response_text+5,'"');
+ if (cp)
+ *cp = '\0';
+ if (*ServerType == TCPC_SERVER) {
+ *ServerType = ((response_text[5] == '/') ?
+ NCSA_SERVER : TCPC_SERVER);
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as %s server.\n",
+ ((*ServerType == NCSA_SERVER) ?
+ "NCSA" : "TCPC"));
+ } else if (response_text[5] == '/') {
+ /* path names beginning with / imply Unix,
+ * right?
+ */
+ if (set_mac_binary(*ServerType)) {
+ *ServerType = NCSA_SERVER;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as NCSA server.\n");
+ } else {
+ *ServerType = UNIX_SERVER;
+ *UseList = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as Unix server.\n");
+ }
+ return;
+ } else if (response_text[strlen(response_text)-1] == ']') {
+ /* path names ending with ] imply VMS, right? */
+ *ServerType = VMS_SERVER;
+ *UseList = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as VMS server.\n");
+ } else {
+ *ServerType = GENERIC_SERVER;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as Generic server.\n");
+ }
+
+ if ((*ServerType == NCSA_SERVER) ||
+ (*ServerType == TCPC_SERVER) ||
+ (*ServerType == PETER_LEWIS_SERVER) ||
+ (*ServerType == NETPRESENZ_SERVER))
+ set_mac_binary(*ServerType);
+ }
+}
+
+/* Get a valid connection to the host
+** ----------------------------------
+**
+** On entry,
+** arg points to the name of the host in a hypertext address
+** On exit,
+** returns <0 if error
+** socket number if success
+**
+** This routine takes care of managing timed-out connections, and
+** limiting the number of connections in use at any one time.
+**
+** It ensures that all connections are logged in if they exist.
+** It ensures they have the port number transferred.
+*/
+PRIVATE int get_connection ARGS2(
+ CONST char *, arg,
+ HTParentAnchor *, anchor)
+{
+ int status;
+ char * command;
+ connection * con;
+ char * username = NULL;
+ char * password = NULL;
+ static BOOLEAN firstuse = TRUE;
+
+ if (firstuse) {
+ /*
+ ** Set up freeing at exit. - FM
+ */
+ atexit(free_FTPGlobals);
+ firstuse = FALSE;
+ }
+
+ if (control) {
+ /*
+ ** Reuse this object - KW, DW & FM
+ */
+ if (control->socket != -1) {
+ NETCLOSE(control->socket);
+ }
+ con = control;
+ con->addr = 0;
+ con->binary = FALSE;
+ } else {
+ /*
+ ** Allocate and init control struct.
+ */
+ con = (connection *)calloc(1, sizeof(connection));
+ if (con == NULL)
+ outofmem(__FILE__, "get_connection");
+ }
+ con->socket = -1;
+
+ if (!arg) return -1; /* Bad if no name specified */
+ if (!*arg) return -1; /* Bad if name had zero length */
+
+/* Get node name:
+*/
+ {
+ char *p1 = HTParse(arg, "", PARSE_HOST);
+ char *p2 = strrchr(p1, '@'); /* user? */
+ char * pw = NULL;
+
+ if (p2 != NULL) {
+ username = p1;
+ *p2 = '\0'; /* terminate */
+ p1 = p2+1; /* point to host */
+ pw = strchr(username, ':');
+ if (pw != NULL) {
+ *pw++ = '\0';
+ password = HTUnEscape(pw);
+ }
+ if (*username)
+ HTUnEscape(username);
+
+ /*
+ * If the password doesn't exist then we are going to have
+ * to ask the user for it. The only problem is that we
+ * don't want to ask for it every time, so we will store
+ * away in a primitive fashion.
+ */
+ if (!password) {
+ char tmp[256];
+
+ sprintf(tmp, "%s@%s", username, p1);
+ /*
+ * If the user@host is not equal to the last time through
+ * or user_entered_password has no data then we need
+ * to ask the user for the password.
+ */
+ if (!last_username_and_host ||
+ strcmp(tmp, last_username_and_host) ||
+ !user_entered_password) {
+
+ StrAllocCopy(last_username_and_host, tmp);
+ sprintf(tmp, "Enter password for user %s@%s:",
+ username, p1);
+ FREE(user_entered_password);
+ user_entered_password = (char *)HTPromptPassword(tmp);
+
+ } /* else we already know the password */
+ password = user_entered_password;
+ }
+ }
+
+ if (!username)
+ FREE(p1);
+ } /* scope of p1 */
+
+ status = HTDoConnect (arg, "FTP", IPPORT_FTP, (int *)&con->socket);
+
+ if (status < 0)
+ {
+ if (TRACE)
+ {
+ if (status == HT_INTERRUPTED)
+ fprintf (stderr,
+ "HTFTP: Interrupted on connect\n");
+ else
+ fprintf(stderr,
+ "HTFTP: Unable to connect to remote host for `%s'.\n",
+ arg);
+ }
+ if (status == HT_INTERRUPTED) {
+ _HTProgress ("Connection interrupted.");
+ status = HT_NOT_LOADED;
+ } else {
+ HTAlert("Unable to connect to FTP host.");
+ }
+ if (con->socket != -1)
+ {
+ NETCLOSE(con->socket);
+ }
+
+ FREE(username);
+ if (control == con)
+ control = NULL;
+ FREE(con);
+ return status; /* Bad return */
+ }
+
+ if (TRACE) {
+ fprintf(stderr, "FTP connected, socket %d control %ld\n",
+ con->socket, (long)con);
+ }
+ control = con; /* Current control connection */
+
+ /* Initialise buffering for control connection */
+ HTInitInput(control->socket);
+ init_help_message_cache(); /* Clear the login message buffer. */
+
+
+/* Now we log in Look up username, prompt for pw.
+*/
+ status = response((char *)0); /* Get greeting */
+
+ if (status == HT_INTERRUPTED)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted at beginning of login.\n");
+ _HTProgress ("Connection interrupted.");
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+ server_type = GENERIC_SERVER; /* reset */
+ if (status == 2) { /* Send username */
+ char *cp; /* look at greeting text */
+
+ if (strlen(response_text) > 4) {
+ if ((cp = strstr(response_text, " awaits your command")) ||
+ (cp = strstr(response_text, " ready."))) {
+ *cp = '\0';
+ }
+ cp = response_text + 4;
+ if (!strncasecomp(cp, "NetPresenz", 10))
+ server_type = NETPRESENZ_SERVER;
+ } else {
+ cp = response_text;
+ }
+ StrAllocCopy(anchor->server, cp);
+
+ if (username && *username) {
+ command = (char*)malloc(10+strlen(username)+2+1);
+ if (command == NULL)
+ outofmem(__FILE__, "get_connection");
+ sprintf(command, "USER %s%c%c", username, CR, LF);
+ } else {
+ command = (char*)malloc(24);
+ if (command == NULL)
+ outofmem(__FILE__, "get_connection");
+ sprintf(command, "USER anonymous%c%c", CR, LF);
+ }
+ status = response(command);
+ FREE(command);
+ if (status == HT_INTERRUPTED)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted while sending username.\n");
+ _HTProgress ("Connection interrupted.");
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+ }
+ if (status == 3) { /* Send password */
+ if (password) {
+ /*
+ * We have non-zero length password, so send it. - FM
+ */
+ command = (char*)malloc(10+strlen(password)+2+1);
+ if (command == NULL)
+ outofmem(__FILE__, "get_connection");
+ sprintf(command, "PASS %s%c%c", password, CR, LF);
+ } else {
+ /*
+ * Create and send a mail address as the password. - FM
+ */
+ char *user = NULL;
+ CONST char *host = NULL;
+ char * cp;
+
+ if (personal_mail_address && *personal_mail_address) {
+ /*
+ * We have a non-zero length personal
+ * mail address, so use that. - FM
+ */
+ StrAllocCopy(user, personal_mail_address);
+ if ((cp=strchr(user, '@')) != NULL) {
+ *cp++ = '\0';
+ host = cp;
+ } else {
+ host = HTHostName();
+ }
+ } else {
+ /*
+ * Use an environment variable and the host global. - FM
+ */
+ if ((cp=getenv("USER")) != NULL)
+ StrAllocCopy(user, cp);
+ else
+ StrAllocCopy(user, "WWWuser");
+ host = HTHostName();
+ }
+
+ /*
+ * If host is not fully qualified, suppress it
+ * as ftp.uu.net prefers a blank to a bad name
+ */
+ if (!(host) || strchr(host, '.') == NULL)
+ host = "";
+
+ command = (char*)malloc(10+strlen(user)+1+strlen(host)+2+1);
+ if (command == NULL)
+ outofmem(__FILE__, "get_connection");
+ sprintf(command, "PASS %s@%s%c%c", user, host, CR, LF);
+ FREE(user);
+ }
+ status = response(command);
+ FREE(command);
+ if (status == HT_INTERRUPTED)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted while sending password.\n");
+ _HTProgress ("Connection interrupted.");
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+ }
+ FREE(username);
+
+ if (status == 3) {
+ char temp[80];
+ sprintf(temp, "ACCT noaccount%c%c", CR, LF);
+ status = response(temp);
+ if (status == HT_INTERRUPTED)
+ {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted while sending password.\n");
+ _HTProgress ("Connection interrupted.");
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return HT_INTERRUPTED;
+ }
+
+ }
+ if (status != 2) {
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Login fail: %s", response_text);
+ /* if (control->socket > 0) close_connection(control->socket); */
+ return -1; /* Bad return */
+ }
+ if (TRACE) fprintf(stderr, "HTFTP: Logged in.\n");
+
+ /** Check for host type **/
+ if (server_type != NETPRESENZ_SERVER)
+ server_type = GENERIC_SERVER; /* reset */
+ use_list = FALSE; /* reset */
+ if ((status=response("SYST\r\n")) == 2) {
+ /* we got a line -- what kind of server are we talking to? */
+ if (strncmp(response_text+4,
+ "UNIX Type: L8 MAC-OS MachTen", 28) == 0) {
+ server_type = MACHTEN_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as MachTen server.\n");
+
+ } else if (strstr(response_text+4, "UNIX") != NULL ||
+ strstr(response_text+4, "Unix") != NULL) {
+ server_type = UNIX_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as Unix server.\n");
+
+ } else if (strstr(response_text+4, "MSDOS") != NULL) {
+ server_type = MSDOS_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr,
+ "HTFTP: Treating as MSDOS (Unix emulation) server.\n");
+
+ } else if (strncmp(response_text+4, "VMS", 3) == 0) {
+ server_type = VMS_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as VMS server.\n");
+
+ } else if ((strncmp(response_text+4, "VM/CMS", 6) == 0) ||
+ (strncmp(response_text+4, "VM ", 3) == 0)) {
+ server_type = CMS_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as CMS server.\n");
+
+ } else if (strncmp(response_text+4, "DCTS", 4) == 0) {
+ server_type = DCTS_SERVER;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as DCTS server.\n");
+
+ } else if (strstr(response_text+4, "MAC-OS TCP/Connect II") != NULL) {
+ server_type = TCPC_SERVER;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Looks like a TCPC server.\n");
+ get_ftp_pwd(&server_type, &use_list);
+ unsure_type = TRUE;
+
+ } else if (server_type == NETPRESENZ_SERVER) { /* already set above */
+ use_list = TRUE;
+ set_mac_binary(server_type);
+ if (TRACE)
+ fprintf(stderr,
+ "HTFTP: Treating as NetPresenz (MACOS) server.\n");
+
+ } else if (strncmp(response_text+4, "MACOS Peter's Server", 20) == 0) {
+ server_type = PETER_LEWIS_SERVER;
+ use_list = TRUE;
+ set_mac_binary(server_type);
+ if (TRACE)
+ fprintf(stderr,
+ "HTFTP: Treating as Peter Lewis (MACOS) server.\n");
+
+ } else if (strncmp(response_text+4, "Windows_NT", 10) == 0) {
+ server_type = WINDOWS_NT_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as Window_NT server.\n");
+
+ } else if (strncmp(response_text+4, "MS Windows", 10) == 0) {
+ server_type = MS_WINDOWS_SERVER;
+ use_list = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Treating as MS Windows server.\n");
+
+ } else if (strncmp(response_text+4,
+ "MACOS AppleShare IP FTP Server", 30) == 0) {
+ server_type = APPLESHARE_SERVER;
+ use_list = TRUE;
+ set_mac_binary(server_type);
+ if (TRACE)
+ fprintf(stderr,
+ "HTFTP: Treating as AppleShare server.\n");
+
+ } else {
+ server_type = GENERIC_SERVER;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Ugh! A Generic server.\n");
+ get_ftp_pwd(&server_type, &use_list);
+ unsure_type = TRUE;
+ }
+ } else {
+ /* SYST fails :( try to get the type from the PWD command */
+ get_ftp_pwd(&server_type, &use_list);
+ }
+
+/* Now we inform the server of the port number we will listen on
+*/
+#ifdef NOTREPEAT_PORT
+ {
+ int status = response(port_command);
+ if (status != 2) {
+ if (control->socket)
+ close_connection(control->socket);
+ return -status; /* Bad return */
+ }
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Port defined.\n");
+ }
+#endif /* NOTREPEAT_PORT */
+ return con->socket; /* Good return */
+}
+
+
+#ifdef LISTEN
+
+/* Close Master (listening) socket
+** -------------------------------
+**
+**
+*/
+PRIVATE int close_master_socket NOARGS
+{
+ int status;
+ FD_CLR(master_socket, &open_sockets);
+ status = NETCLOSE(master_socket);
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Closed master socket %d\n", master_socket);
+ master_socket = -1;
+ if (status < 0)
+ return HTInetStatus("close master socket");
+ else
+ return status;
+}
+
+
+/* Open a master socket for listening on
+** -------------------------------------
+**
+** When data is transferred, we open a port, and wait for the server to
+** connect with the data.
+**
+** On entry,
+** master_socket Must be negative if not set up already.
+** On exit,
+** Returns socket number if good
+** less than zero if error.
+** master_socket is socket number if good, else negative.
+** port_number is valid if good.
+*/
+PRIVATE int get_listen_socket NOARGS
+{
+ struct sockaddr_in soc_address; /* Binary network address */
+ struct sockaddr_in* soc_in = &soc_address;
+ int new_socket; /* Will be master_socket */
+
+
+ FD_ZERO(&open_sockets); /* Clear our record of open sockets */
+ num_sockets = 0;
+
+#ifndef REPEAT_LISTEN
+ if (master_socket >= 0)
+ return master_socket; /* Done already */
+#endif /* !REPEAT_LISTEN */
+
+/* Create internet socket
+*/
+ new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ if (new_socket < 0)
+ return HTInetStatus("socket for master socket");
+
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Opened master socket number %d\n", new_socket);
+
+/* Search for a free port.
+*/
+ soc_in->sin_family = AF_INET; /* Family = internet, host order */
+ soc_in->sin_addr.s_addr = INADDR_ANY; /* Any peer address */
+#ifdef POLL_PORTS
+ {
+ unsigned short old_port_number = port_number;
+ for (port_number = (old_port_number+1); ; port_number++) {
+ int status;
+ if (port_number > LAST_TCP_PORT)
+ port_number = FIRST_TCP_PORT;
+ if (port_number == old_port_number) {
+ return HTInetStatus("bind");
+ }
+ soc_address.sin_port = htons(port_number);
+#ifdef SOCKS
+ if (socks_flag)
+ if ((status=Rbind(new_socket,
+ (struct sockaddr*)&soc_address,
+ /* Cast to generic sockaddr */
+ sizeof(soc_address)
+#ifndef SHORTENED_RBIND
+ ,socks_bind_remoteAddr
+#endif /* !SHORTENED_RBIND */
+ )) == 0)
+ break;
+ else
+#endif /* SOCKS */
+ if ((status=bind(new_socket,
+ (struct sockaddr*)&soc_address,
+ /* Cast to generic sockaddr */
+ sizeof(soc_address))) == 0)
+ break;
+ if (TRACE)
+ fprintf(stderr,
+ "TCP bind attempt to port %d yields %d, errno=%d\n",
+ port_number, status, SOCKET_ERRNO);
+ } /* for */
+ }
+#else
+ {
+ int status;
+ int address_length = sizeof(soc_address);
+#ifdef SOCKS
+ if (socks_flag)
+ status = Rgetsockname(control->socket,
+ (struct sockaddr *)&soc_address,
+ (void *)&address_length);
+ else
+#endif /* SOCKS */
+ status = getsockname(control->socket,
+ (struct sockaddr *)&soc_address,
+ (void *)&address_length);
+ if (status<0) return HTInetStatus("getsockname");
+ CTRACE(tfp, "HTFTP: This host is %s\n",
+ HTInetString(soc_in));
+
+ soc_address.sin_port = 0; /* Unspecified: please allocate */
+#ifdef SOCKS
+ if (socks_flag)
+ status=Rbind(new_socket,
+ (struct sockaddr*)&soc_address,
+ /* Cast to generic sockaddr */
+ sizeof(soc_address)
+#ifndef SHORTENED_RBIND
+ ,socks_bind_remoteAddr
+#endif /* !SHORTENED_RBIND */
+ );
+ else
+#endif /* SOCKS */
+ status=bind(new_socket,
+ (struct sockaddr*)&soc_address,
+ /* Cast to generic sockaddr */
+ sizeof(soc_address));
+ if (status<0) return HTInetStatus("bind");
+
+ address_length = sizeof(soc_address);
+#ifdef SOCKS
+ if (socks_flag)
+ status = Rgetsockname(new_socket,
+ (struct sockaddr*)&soc_address,
+ (void *)&address_length);
+ else
+#endif /* SOCKS */
+ status = getsockname(new_socket,
+ (struct sockaddr*)&soc_address,
+ (void *)&address_length);
+ if (status<0) return HTInetStatus("getsockname");
+ }
+#endif /* POLL_PORTS */
+
+ CTRACE(tfp, "HTFTP: bound to port %d on %s\n",
+ (int)ntohs(soc_in->sin_port),
+ HTInetString(soc_in));
+
+#ifdef REPEAT_LISTEN
+ if (master_socket >= 0)
+ (void) close_master_socket();
+#endif /* REPEAD_LISTEN */
+
+ master_socket = new_socket;
+
+/* Now we must find out who we are to tell the other guy
+*/
+ (void)HTHostName(); /* Make address valid - doesn't work*/
+ sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d%c%c",
+ (int)*((unsigned char *)(&soc_in->sin_addr)+0),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+1),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+2),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+3),
+ (int)*((unsigned char *)(&soc_in->sin_port)+0),
+ (int)*((unsigned char *)(&soc_in->sin_port)+1),
+ CR, LF);
+
+
+/* Inform TCP that we will accept connections
+*/
+ {
+ int status;
+#ifdef SOCKS
+ if (socks_flag)
+ status = Rlisten(master_socket, 1);
+ else
+#endif /* SOCKS */
+ status = listen(master_socket, 1);
+ if (status < 0) {
+ master_socket = -1;
+ return HTInetStatus("listen");
+ }
+ }
+ CTRACE(tfp, "TCP: Master socket(), bind() and listen() all OK\n");
+ FD_SET(master_socket, &open_sockets);
+ if ((master_socket+1) > num_sockets)
+ num_sockets = master_socket+1;
+
+ return master_socket; /* Good */
+
+} /* get_listen_socket */
+#endif /* LISTEN */
+
+PRIVATE char * months[12] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+/* Procedure: Set the current and last year strings and date integer
+** -----------------------------------------------------------------
+**
+** Bug:
+** This code is for sorting listings by date, if that option
+** is selected in Lynx, and doesn't take into account time
+** zones or ensure resetting at midnight, so the sort may not
+** be perfect, but the actual date isn't changed in the display,
+** i.e., the date is still correct. - FM
+*/
+PRIVATE void set_years_and_date NOARGS
+{
+ char day[8], month[8], date[12];
+ time_t NowTime;
+ int i;
+
+ NowTime = time(NULL);
+ strncpy(day, (char *)ctime(&NowTime)+8, 2);
+ day[2] = '\0';
+ if (day[0] == ' ') {
+ day[0] = '0';
+ }
+ strncpy(month, (char *)ctime(&NowTime)+4, 3);
+ strncpy(month, (char *)ctime(&NowTime)+4, 3);
+ month[3] = '\0';
+ for (i = 0; i < 12; i++) {
+ if (!strcasecomp(month, months[i])) {
+ break;
+ }
+ }
+ i++;
+ sprintf(month, "%s%d", (i < 10 ? "0" : ""), i);
+ sprintf(date, "9999%s%s", month, day);
+ TheDate = atoi(date);
+ strcpy(ThisYear, (char *)ctime(&NowTime)+20);
+ ThisYear[4] = '\0';
+ sprintf(LastYear, "%d", (atoi(ThisYear) - 1));
+ HaveYears = TRUE;
+}
+
+typedef struct _EntryInfo {
+ char * filename;
+ char * type;
+ char * date;
+ unsigned int size;
+ BOOLEAN display; /* show this entry? */
+} EntryInfo;
+
+PRIVATE void free_entryinfo_struct_contents ARGS1(
+ EntryInfo *, entry_info)
+{
+ if (entry_info) {
+ FREE(entry_info->filename);
+ FREE(entry_info->type);
+ FREE(entry_info->date);
+ }
+ /* dont free the struct */
+}
+
+/*
+ * is_ls_date() --
+ * Return TRUE if s points to a string of the form:
+ * "Sep 1 1990 " or
+ * "Sep 11 11:59 " or
+ * "Dec 12 1989 " or
+ * "FCv 23 1990 " ...
+ */
+PRIVATE BOOLEAN is_ls_date ARGS1(
+ char *, s)
+{
+ /* must start with three alpha characters */
+ if (!isalpha(*s++) || !isalpha(*s++) || !isalpha(*s++))
+ return FALSE;
+
+ /* space or HT_NON_BREAK_SPACE */
+ if (!(*s == ' ' || *s == HT_NON_BREAK_SPACE)) {
+ s++;
+ return FALSE;
+ }
+ s++;
+
+ /* space or digit */
+ if (!(*s == ' ' || isdigit(*s))) {
+ s++;
+ return FALSE;
+ }
+ s++;
+
+ /* digit */
+ if (!isdigit(*s++))
+ return FALSE;
+
+ /* space */
+ if (*s++ != ' ')
+ return FALSE;
+
+ /* space or digit */
+ if (!(*s == ' ' || isdigit(*s))) {
+ s++;
+ return FALSE;
+ }
+ s++;
+
+ /* digit */
+ if (!isdigit(*s++))
+ return FALSE;
+
+ /* colon or digit */
+ if (!(*s == ':' || isdigit(*s))) {
+ s++;
+ return FALSE;
+ }
+ s++;
+
+ /* digit */
+ if (!isdigit(*s++))
+ return FALSE;
+
+ /* space or digit */
+ if (!(*s == ' ' || isdigit(*s))) {
+ s++;
+ return FALSE;
+ }
+ s++;
+
+ /* space */
+ if (*s++ != ' ')
+ return FALSE;
+
+ return TRUE;
+} /* is_ls_date() */
+
+/*
+ * parse_eplf_line() --
+ * Extract the name, size, and date from an EPLF line. - 08-06-96 DJB
+ */
+PRIVATE void parse_eplf_line ARGS2(
+ char *, line,
+ EntryInfo *, info)
+{
+ char *cp = line;
+ char ct[26];
+ unsigned long size;
+ time_t secs;
+ static time_t base; /* time() value on this OS in 1970 */
+ static int flagbase = 0;
+
+ if (!flagbase) {
+ struct tm t;
+ t.tm_year = 70; t.tm_mon = 0; t.tm_mday = 0;
+ t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0;
+ t.tm_isdst = -1;
+ base = mktime(&t); /* could return -1 */
+ flagbase = 1;
+ }
+
+ while (*cp) {
+ switch(*cp) {
+ case '\t':
+ StrAllocCopy(info->filename, cp + 1);
+ return;
+ case 's':
+ size = 0;
+ while (*(++cp) && (*cp != ','))
+ size = (size * 10) + (*cp - '0');
+ info->size = size;
+ break;
+ case 'm':
+ secs = 0;
+ while (*(++cp) && (*cp != ','))
+ secs = (secs * 10) + (*cp - '0');
+ secs += base; /* assumes that time_t is #seconds */
+ strcpy(ct, ctime(&secs));
+ ct[24] = 0;
+ StrAllocCopy(info->date, ct);
+ break;
+ case '/':
+ StrAllocCopy(info->type, "Directory");
+ default:
+ while (*cp) {
+ if (*cp++ == ',')
+ break;
+ }
+ break;
+ }
+ }
+} /* parse_eplf_line */
+
+/*
+ * parse_ls_line() --
+ * Extract the name, size, and date from an ls -l line.
+ */
+PRIVATE void parse_ls_line ARGS2(
+ char *, line,
+ EntryInfo *, entry_info)
+{
+ short i, j;
+ int base=1;
+ int size_num=0;
+
+ for (i = strlen(line) - 1;
+ (i > 13) && (!isspace(line[i]) || !is_ls_date(&line[i-12])); i--)
+ ; /* null body */
+ line[i] = '\0';
+ if (i > 13) {
+ StrAllocCopy(entry_info->date, &line[i-12]);
+ /* replace the 4th location with nbsp if it is a space or zero */
+ if (entry_info->date[4] == ' ' || entry_info->date[4] == '0')
+ entry_info->date[4] = HT_NON_BREAK_SPACE;
+ /* make sure year or time is flush right */
+ if (entry_info->date[11] == ' ') {
+ for (j = 11; j > 6; j--) {
+ entry_info->date[j] = entry_info->date[j-1];
+ }
+ }
+ }
+ j = i - 14;
+ while (isdigit(line[j])) {
+ size_num += (line[j] - '0') * base;
+ base *= 10;
+ j--;
+ }
+ entry_info->size = size_num;
+ StrAllocCopy(entry_info->filename, &line[i + 1]);
+} /* parse_ls_line() */
+
+/*
+ * parse_vms_dir_entry()
+ * Format the name, date, and size from a VMS LIST line
+ * into the EntryInfo structure - FM
+ */
+PRIVATE void parse_vms_dir_entry ARGS2(
+ char *, line,
+ EntryInfo *, entry_info)
+{
+ int i, j, ialloc;
+ char *cp, *cpd, *cps, date[16], *sp = " ";
+
+ /** Get rid of blank lines, and information lines. **/
+ /** Valid lines have the ';' version number token. **/
+ if (!strlen(line) || (cp=strchr(line, ';')) == NULL) {
+ entry_info->display = FALSE;
+ return;
+ }
+
+ /** Cut out file or directory name at VMS version number. **/
+ *cp++ ='\0';
+ StrAllocCopy(entry_info->filename,line);
+
+ /** Cast VMS non-README file and directory names to lowercase. **/
+ if (strstr(entry_info->filename, "READ") == NULL) {
+ for (i = 0; entry_info->filename[i]; i++)
+ entry_info->filename[i] = TOLOWER(entry_info->filename[i]);
+ } else {
+ i = ((strstr(entry_info->filename, "READ") - entry_info->filename) + 4);
+ if (!strncmp((char *)&entry_info->filename[i], "ME", 2)) {
+ i += 2;
+ while (entry_info->filename[i] && entry_info->filename[i] != '.') {
+ i++;
+ }
+ } else if (!strncmp((char *)&entry_info->filename[i], ".ME", 3)) {
+ i = strlen(entry_info->filename);
+ } else {
+ i = 0;
+ }
+ for (; entry_info->filename[i]; i++)
+ entry_info->filename[i] = TOLOWER(entry_info->filename[i]);
+ }
+
+ /** Uppercase terminal .z's or _z's. **/
+ if ((--i > 2) &&
+ entry_info->filename[i] == 'z' &&
+ (entry_info->filename[i-1] == '.' ||
+ entry_info->filename[i-1] == '_'))
+ entry_info->filename[i] = 'Z';
+
+ /** Convert any tabs in rest of line to spaces. **/
+ cps = cp-1;
+ while ((cps=strchr(cps+1, '\t')) != NULL)
+ *cps = ' ';
+
+ /** Collapse serial spaces. **/
+ i = 0; j = 1;
+ cps = cp;
+ while (cps[j] != '\0') {
+ if (cps[i] == ' ' && cps[j] == ' ')
+ j++;
+ else
+ cps[++i] = cps[j++];
+ }
+ cps[++i] = '\0';
+
+ /* Set the years and date, if we don't have them yet. **/
+ if (!HaveYears) {
+ set_years_and_date();
+ }
+
+ /** Track down the date. **/
+ if ((cpd=strchr(cp, '-')) != NULL &&
+ strlen(cpd) > 9 && isdigit(*(cpd-1)) &&
+ isalpha(*(cpd+1)) && *(cpd+4) == '-') {
+
+ /** Month **/
+ *(cpd+4) = '\0';
+ *(cpd+2) = TOLOWER(*(cpd+2));
+ *(cpd+3) = TOLOWER(*(cpd+3));
+ sprintf(date, "%s ", cpd+1);
+ *(cpd+4) = '-';
+
+ /** Day **/
+ *cpd = '\0';
+ if (isdigit(*(cpd-2)))
+ sprintf(date+4, "%s ", cpd-2);
+ else
+ sprintf(date+4, "%c%s ", HT_NON_BREAK_SPACE, cpd-1);
+ *cpd = '-';
+
+ /** Time or Year **/
+ if (!strncmp(ThisYear, cpd+5, 4) &&
+ strlen(cpd) > 15 && *(cpd+12) == ':') {
+ *(cpd+15) = '\0';
+ sprintf(date+7, "%s", cpd+10);
+ *(cpd+15) = ' ';
+ } else {
+ *(cpd+9) = '\0';
+ sprintf(date+7, " %s", cpd+5);
+ *(cpd+9) = ' ';
+ }
+
+ StrAllocCopy(entry_info->date, date);
+ }
+
+ /** Track down the size **/
+ if ((cpd=strchr(cp, '/')) != NULL) {
+ /* Appears be in used/allocated format */
+ cps = cpd;
+ while (isdigit(*(cps-1)))
+ cps--;
+ if (cps < cpd)
+ *cpd = '\0';
+ entry_info->size = atoi(cps);
+ cps = cpd+1;
+ while (isdigit(*cps))
+ cps++;
+ *cps = '\0';
+ ialloc = atoi(cpd+1);
+ /* Check if used is in blocks or bytes */
+ if (entry_info->size <= ialloc)
+ entry_info->size *= 512;
+
+ } else if ((cps=strtok(cp, sp)) != NULL) {
+ /* We just initialized on the version number */
+ /* Now let's hunt for a lone, size number */
+ while ((cps=strtok(NULL, sp)) != NULL) {
+ cpd = cps;
+ while (isdigit(*cpd))
+ cpd++;
+ if (*cpd == '\0') {
+ /* Assume it's blocks */
+ entry_info->size = atoi(cps) * 512;
+ break;
+ }
+ }
+ }
+
+ /** Wrap it up **/
+ if (TRACE)
+ fprintf(stderr, "HTFTP: VMS filename: %s date: %s size: %d\n",
+ entry_info->filename,
+ entry_info->date ? entry_info->date : "",
+ entry_info->size);
+ return;
+} /* parse_vms_dir_entry() */
+
+/*
+ * parse_ms_windows_dir_entry() --
+ * Format the name, date, and size from an MS_WINDOWS LIST line into
+ * the EntryInfo structure (assumes Chameleon NEWT format). - FM
+ */
+PRIVATE void parse_ms_windows_dir_entry ARGS2(
+ char *, line,
+ EntryInfo *, entry_info)
+{
+ char *cp = line;
+ char *cps, *cpd, date[16];
+ char *end = line + strlen(line);
+
+ /** Get rid of blank or junk lines. **/
+ while (*cp && isspace(*cp))
+ cp++;
+ if (!(*cp)) {
+ entry_info->display = FALSE;
+ return;
+ }
+
+ /** Cut out file or directory name. **/
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ ='\0';
+ cpd = cps;
+ StrAllocCopy(entry_info->filename, cp);
+
+ /** Track down the size **/
+ if (cps < end) {
+ while (*cps && isspace(*cps))
+ cps++;
+ cpd = cps;
+ while (*cpd && !isspace(*cpd))
+ cpd++;
+ *cpd++ = '\0';
+ if (isdigit(*cps)) {
+ entry_info->size = atoi(cps);
+ } else {
+ StrAllocCopy(entry_info->type, "Directory");
+ }
+ } else {
+ StrAllocCopy(entry_info->type, "");
+ }
+
+ /* Set the years and date, if we don't have them yet. **/
+ if (!HaveYears) {
+ set_years_and_date();
+ }
+
+ /** Track down the date. **/
+ if (cpd < end) {
+ while (*cpd && isspace(*cpd))
+ cpd++;
+ if (strlen(cpd) > 17) {
+ *(cpd+6) = '\0'; /* Month and Day */
+ *(cpd+11) = '\0'; /* Year */
+ *(cpd+17) = '\0'; /* Time */
+ if (strcmp(ThisYear, cpd+7))
+ /* Not this year, so show the year */
+ sprintf(date, "%s %s", cpd, (cpd+7));
+ else
+ /* Is this year, so show the time */
+ sprintf(date, "%s %s", cpd, (cpd+12));
+ StrAllocCopy(entry_info->date, date);
+ if (entry_info->date[4] == ' '|| entry_info->date[4] == '0') {
+ entry_info->date[4] = HT_NON_BREAK_SPACE;
+ }
+ }
+ }
+
+ /** Wrap it up **/
+ if (TRACE)
+ fprintf(stderr, "HTFTP: MS Windows filename: %s date: %s size: %d\n",
+ entry_info->filename,
+ entry_info->date ? entry_info->date : "",
+ entry_info->size);
+ return;
+} /* parse_ms_windows_dir_entry */
+
+/*
+ * parse_windows_nt_dir_entry() --
+ * Format the name, date, and size from a WINDOWS_NT LIST line into
+ * the EntryInfo structure (assumes Chameleon NEWT format). - FM
+ */
+#ifdef NOTDEFINED
+PRIVATE void parse_windows_nt_dir_entry ARGS2(
+ char *, line,
+ EntryInfo *, entry_info)
+{
+ char *cp = line;
+ char *cps, *cpd, date[16];
+ char *end = line + strlen(line);
+ int i;
+
+ /** Get rid of blank or junk lines. **/
+ while (*cp && isspace(*cp))
+ cp++;
+ if (!(*cp)) {
+ entry_info->display = FALSE;
+ return;
+ }
+
+ /** Cut out file or directory name. **/
+ cpd = cp;
+ cps = (end-1);
+ while (cps >= cpd && !isspace(*cps))
+ cps--;
+ cp = (cps+1);
+ if (!strcmp(cp, ".") || !strcmp(cp, "..")) {
+ entry_info->display = FALSE;
+ return;
+ }
+ StrAllocCopy(entry_info->filename, cp);
+ if (cps < cpd)
+ return;
+ *cp = '\0';
+ end = cp;
+
+ /* Set the years and date, if we don't have them yet. **/
+ if (!HaveYears) {
+ set_years_and_date();
+ }
+
+ /** Cut out the date. **/
+ cp = cps = cpd;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ ='\0';
+ if (cps > end) {
+ entry_info->display = FALSE;
+ return;
+ }
+ while (*cps && isspace(*cps))
+ cps++;
+ cpd = cps;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ ='\0';
+ if (cps > end || cpd == cps || strlen(cpd) < 7) {
+ entry_info->display = FALSE;
+ return;
+ }
+ if (strlen(cp) == 8 &&
+ isdigit(*cp) && isdigit(*(cp+1)) && *(cp+2) == '-' &&
+ isdigit(*(cp+3)) && isdigit(*(cp+4)) && *(cp+5) == '-') {
+ *(cp+2) = '\0'; /* Month */
+ i = atoi(cp) - 1;
+ *(cp+5) = '\0'; /* Day */
+ sprintf(date, "%s %s", months[i], (cp+3));
+ if (date[4] == '0')
+ date[4] = ' ';
+ cp += 6; /* Year */
+ if (strcmp((ThisYear+2), cp)) {
+ /* Not this year, so show the year */
+ if (atoi(cp) < 70) {
+ sprintf((char *)&date[6], " 20%s", cp);
+ } else {
+ sprintf((char *)&date[6], " 19%s", cp);
+ }
+ } else {
+ /* Is this year, so show the time */
+ *(cpd+2) = '\0'; /* Hour */
+ i = atoi(cpd);
+ if (*(cpd+5) == 'P' || *(cpd+5) == 'p')
+ i += 12;
+ *(cpd+5) = '\0';
+ sprintf((char*)&date[6], " %s%d:%s",
+ (i < 10 ? "0" : ""), i, (cpd+3));
+ }
+ StrAllocCopy(entry_info->date, date);
+ if (entry_info->date[4] == ' '|| entry_info->date[4] == '0') {
+ entry_info->date[4] = HT_NON_BREAK_SPACE;
+ }
+ }
+
+ /** Track down the size **/
+ if (cps < end) {
+ while (*cps && isspace(*cps))
+ cps++;
+ cpd = cps;
+ while (*cpd && !isspace(*cpd))
+ cpd++;
+ *cpd = '\0';
+ if (isdigit(*cps)) {
+ entry_info->size = atoi(cps);
+ } else {
+ StrAllocCopy(entry_info->type, "Directory");
+ }
+ } else {
+ StrAllocCopy(entry_info->type, "");
+ }
+
+ /** Wrap it up **/
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Windows NT filename: %s date: %s size: %d\n",
+ entry_info->filename,
+ entry_info->date ? entry_info->date : "",
+ entry_info->size);
+ return;
+} /* parse_windows_nt_dir_entry */
+#endif /* NOTDEFINED */
+
+/*
+ * parse_cms_dir_entry() --
+ * Format the name, date, and size from a VM/CMS line into
+ * the EntryInfo structure. - FM
+ */
+PRIVATE void parse_cms_dir_entry ARGS2(
+ char *, line,
+ EntryInfo *, entry_info)
+{
+ char *cp = line;
+ char *cps, *cpd, date[16];
+ char *end = line + strlen(line);
+ int RecordLength = 0;
+ int Records = 0;
+ int i;
+
+ /** Get rid of blank or junk lines. **/
+ while (*cp && isspace(*cp))
+ cp++;
+ if (!(*cp)) {
+ entry_info->display = FALSE;
+ return;
+ }
+
+ /** Cut out file or directory name. **/
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ ='\0';
+ StrAllocCopy(entry_info->filename, cp);
+ if (strchr(entry_info->filename, '.') != NULL)
+ /** If we already have a dot, we did an NLST. **/
+ return;
+ cp = cps;
+ while (*cp && isspace(*cp))
+ cp++;
+ if (!(*cp)) {
+ /** If we don't have more, we've misparsed. **/
+ FREE(entry_info->filename);
+ FREE(entry_info->type);
+ entry_info->display = FALSE;
+ return;
+ }
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ ='\0';
+ if ((0 == strcasecomp(cp, "DIR")) && (cp - line) > 17) {
+ /** It's an SFS directory. **/
+ StrAllocCopy(entry_info->type, "Directory");
+ entry_info->size = 0;
+ } else {
+ /** It's a file. **/
+ cp--;
+ *cp = '.';
+ StrAllocCat(entry_info->filename, cp);
+
+ /** Track down the VM/CMS RECFM or type. **/
+ cp = cps;
+ if (cp < end) {
+ while (*cp && isspace(*cp))
+ cp++;
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ = '\0';
+ /** Check cp here, if it's relevant someday. **/
+ }
+ }
+
+ /** Track down the record length or dash. **/
+ cp = cps;
+ if (cp < end) {
+ while (*cp && isspace(*cp))
+ cp++;
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ = '\0';
+ if (isdigit(*cp)) {
+ RecordLength = atoi(cp);
+ }
+ }
+
+ /** Track down the number of records or the dash. **/
+ cp = cps;
+ if (cps < end) {
+ while (*cp && isspace(*cp))
+ cp++;
+ cps = cp;
+ while (*cps && !isspace(*cps))
+ cps++;
+ *cps++ = '\0';
+ if (isdigit(*cp)) {
+ Records = atoi(cp);
+ }
+ if (Records > 0 && RecordLength > 0) {
+ /** Compute an approximate size. **/
+ entry_info->size = (Records * RecordLength);
+ }
+ }
+
+ /** Set the years and date, if we don't have them yet. **/
+ if (!HaveYears) {
+ set_years_and_date();
+ }
+
+ /** Track down the date. **/
+ cpd = cps;
+ if (((cps < end) &&
+ (cps = strchr(cpd, ':')) != NULL) &&
+ (cps < (end - 3) &&
+ isdigit(*(cps+1)) && isdigit(*(cps+2)) && *(cps+3) == ':')) {
+ cps += 3;
+ *cps = '\0';
+ if ((cps - cpd) >= 14) {
+ cpd = (cps - 14);
+ *(cpd+2) = '\0'; /* Month */
+ *(cpd+5) = '\0'; /* Day */
+ *(cpd+8) = '\0'; /* Year */
+ cps -= 5; /* Time */
+ if (*cpd == ' ')
+ *cpd = '0';
+ i = atoi(cpd) - 1;
+ sprintf(date, "%s %s", months[i], (cpd+3));
+ if (date[4] == '0')
+ date[4] = ' ';
+ cpd += 6; /* Year */
+ if (strcmp((ThisYear+2), cpd)) {
+ /* Not this year, so show the year. */
+ if (atoi(cpd) < 70) {
+ sprintf((char *)&date[6], " 20%s", cpd);
+ } else {
+ sprintf((char *)&date[6], " 19%s", cpd);
+ }
+ } else {
+ /* Is this year, so show the time. */
+ *(cps+2) = '\0'; /* Hour */
+ i = atoi(cps);
+ sprintf((char*)&date[6], " %s%d:%s",
+ (i < 10 ? "0" : ""), i, (cps+3));
+ }
+ StrAllocCopy(entry_info->date, date);
+ if (entry_info->date[4] == ' '|| entry_info->date[4] == '0') {
+ entry_info->date[4] = HT_NON_BREAK_SPACE;
+ }
+ }
+ }
+
+ /** Wrap it up. **/
+ if (TRACE)
+ fprintf(stderr, "HTFTP: VM/CMS filename: %s date: %s size: %d\n",
+ entry_info->filename,
+ entry_info->date ? entry_info->date : "",
+ entry_info->size);
+ return;
+} /* parse_cms_dir_entry */
+
+/*
+ * parse_dir_entry()
+ * Given a line of LIST/NLST output in entry, return results
+ * and a file/dir name in entry_info struct
+ *
+ * If first is true, this is the first name in a directory.
+ */
+
+PRIVATE EntryInfo * parse_dir_entry ARGS2(
+ char *, entry,
+ BOOLEAN *, first)
+{
+ EntryInfo *entry_info;
+ int i;
+ int len;
+ BOOLEAN remove_size=FALSE;
+ char *cp;
+
+ entry_info = (EntryInfo *)malloc(sizeof(EntryInfo));
+ entry_info->filename = NULL;
+ entry_info->type = NULL;
+ entry_info->date = NULL;
+ entry_info->size = 0;
+ entry_info->display = TRUE;
+
+ switch (server_type) {
+ case UNIX_SERVER:
+ case PETER_LEWIS_SERVER:
+ case MACHTEN_SERVER:
+ case MSDOS_SERVER:
+ case WINDOWS_NT_SERVER:
+ case APPLESHARE_SERVER:
+ case NETPRESENZ_SERVER:
+ /*
+ ** Check for EPLF output (local times).
+ */
+ if (*entry == '+') {
+ parse_eplf_line(entry, entry_info);
+ break;
+ }
+
+ /*
+ ** Interpret and edit LIST output from Unix server.
+ */
+ len = strlen(entry);
+ if (*first) {
+ if (!strcmp(entry, "can not access directory .")) {
+ /*
+ * Don't reset *first, nothing real will follow. - KW
+ */
+ entry_info->display = FALSE;
+ return(entry_info);
+ }
+ *first = FALSE;
+ if (!strncmp(entry, "total ", 6) ||
+ strstr(entry, "not available") != NULL) {
+ entry_info->display=FALSE;
+ return(entry_info);
+ } else if (unsure_type) {
+ /* this isn't really a unix server! */
+ server_type = GENERIC_SERVER;
+ entry_info->display=FALSE;
+ return(entry_info);
+ }
+ }
+
+ /*
+ ** Check first character of ls -l output.
+ */
+ if (TOUPPER(entry[0]) == 'D') {
+ /*
+ ** It's a directory.
+ */
+ StrAllocCopy(entry_info->type, "Directory");
+ remove_size=TRUE; /* size is not useful */
+ } else if (entry[0] == 'l') {
+ /*
+ ** It's a symbolic link, does the user care about
+ ** knowing if it is symbolic? I think so since
+ ** it might be a directory.
+ */
+ StrAllocCopy(entry_info->type, "Symbolic Link");
+ remove_size=TRUE; /* size is not useful */
+
+ /*
+ ** Strip off " -> pathname".
+ */
+ for (i = len - 1; (i > 3) &&
+ (!isspace(entry[i]) ||
+ (entry[i-1] != '>') ||
+ (entry[i-2] != '-') ||
+ (entry[i-3] != ' ')); i--)
+ ; /* null body */
+ if (i > 3) {
+ entry[i-3] = '\0';
+ len = i - 3;
+ }
+ } /* link */
+
+ parse_ls_line(entry, entry_info);
+
+ if (!strcmp(entry_info->filename,"..") ||
+ !strcmp(entry_info->filename,"."))
+ entry_info->display=FALSE;
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+
+ case VMS_SERVER:
+ /*
+ ** Interpret and edit LIST output from VMS server
+ ** and convert information lines to zero length.
+ */
+ parse_vms_dir_entry(entry, entry_info);
+
+ /*
+ ** Get rid of any junk lines.
+ */
+ if (!entry_info->display)
+ return(entry_info);
+
+ /*
+ ** Trim off VMS directory extensions.
+ */
+ len = strlen(entry_info->filename);
+ if ((len > 4) && !strcmp(&entry_info->filename[len-4], ".dir")) {
+ entry_info->filename[len-4] = '\0';
+ StrAllocCopy(entry_info->type, "Directory");
+ remove_size=TRUE; /* size is not useful */
+ }
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+
+ case MS_WINDOWS_SERVER:
+ /*
+ ** Interpret and edit LIST output from MS_WINDOWS server
+ ** and convert information lines to zero length.
+ */
+ parse_ms_windows_dir_entry(entry, entry_info);
+
+ /*
+ ** Get rid of any junk lines.
+ */
+ if (!entry_info->display)
+ return(entry_info);
+ if (entry_info->type && *entry_info->type == '\0') {
+ FREE(entry_info->type);
+ return(entry_info);
+ }
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+
+#ifdef NOTDEFINED
+ case WINDOWS_NT_SERVER:
+ /*
+ ** Interpret and edit LIST output from MS_WINDOWS server
+ ** and convert information lines to zero length.
+ */
+ parse_windows_nt_dir_entry(entry, entry_info);
+
+ /*
+ ** Get rid of any junk lines.
+ */
+ if (!entry_info->display)
+ return(entry_info);
+ if (entry_info->type && *entry_info->type == '\0') {
+ FREE(entry_info->type);
+ return(entry_info);
+ }
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+#endif /* NOTDEFINED */
+
+ case CMS_SERVER:
+ {
+ /*
+ ** Interpret and edit LIST output from VM/CMS server
+ ** and convert any information lines to zero length.
+ */
+ parse_cms_dir_entry(entry, entry_info);
+
+ /*
+ ** Get rid of any junk lines.
+ */
+ if (!entry_info->display)
+ return(entry_info);
+ if (entry_info->type && *entry_info->type == '\0') {
+ FREE(entry_info->type);
+ return(entry_info);
+ }
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+ }
+
+ case NCSA_SERVER:
+ case TCPC_SERVER:
+ /*
+ ** Directories identified by trailing "/" characters.
+ */
+ StrAllocCopy(entry_info->filename, entry);
+ len = strlen(entry);
+ if (entry[len-1] == '/') {
+ /*
+ ** It's a dir, remove / and mark it as such.
+ */
+ entry[len-1] = '\0';
+ StrAllocCopy(entry_info->type, "Directory");
+ remove_size=TRUE; /* size is not useful */
+ }
+ /*
+ ** Goto the bottom and get real type.
+ */
+ break;
+
+ default:
+ /*
+ ** We can't tell if it is a directory since we only
+ ** did an NLST :( List bad file types anyways? NOT!
+ */
+ StrAllocCopy(entry_info->filename, entry);
+ return(entry_info); /* mostly empty info */
+ break; /* not needed */
+
+ } /* switch (server_type) */
+
+ if (remove_size && entry_info->size) {
+ entry_info->size = 0;
+ }
+
+ if (entry_info->filename && strlen(entry_info->filename) > 3) {
+ if (((cp=strrchr(entry_info->filename, '.')) != NULL &&
+ 0 == strncasecomp(cp, ".me", 3)) &&
+ (cp[3] == '\0' || cp[3] == ';')) {
+ /*
+ ** Don't treat this as application/x-Troff-me
+ ** if it's a Unix server but has the string
+ ** "read.me", or if it's not a Unix server. - FM
+ */
+ if ((server_type != UNIX_SERVER) ||
+ (cp > (entry_info->filename + 3) &&
+ 0 == strncasecomp((cp - 4), "read.me", 7))) {
+ StrAllocCopy(entry_info->type, "text/plain");
+ }
+ }
+ }
+
+ /*
+ ** Get real types eventually.
+ */
+ if (!entry_info->type) {
+ CONST char *cp2;
+ HTFormat format;
+ HTAtom * encoding; /* @@ not used at all */
+ format = HTFileFormat(entry_info->filename, &encoding, &cp2);
+
+ if (cp2 == NULL) {
+ if (!strncmp(HTAtom_name(format), "application",11)) {
+ cp2 = HTAtom_name(format) + 12;
+ if (!strncmp(cp2,"x-",2))
+ cp2 += 2;
+ } else {
+ cp2 = HTAtom_name(format);
+ }
+ }
+
+ StrAllocCopy(entry_info->type, cp2);
+ }
+
+ return(entry_info);
+} /* parse_dir_entry */
+
+PRIVATE int compare_EntryInfo_structs ARGS2(
+ EntryInfo *, entry1,
+ EntryInfo *, entry2)
+{
+ int i, status;
+ char date1[16], date2[16], time1[8], time2[8], month[4];
+
+ switch(HTfileSortMethod) {
+ case FILE_BY_SIZE:
+ /* both equal or both 0 */
+ if (entry1->size == entry2->size)
+ return(strcmp(entry1->filename, entry2->filename));
+ else
+ if (entry1->size > entry2->size)
+ return(1);
+ else
+ return(-1);
+ break;
+
+ case FILE_BY_TYPE:
+ if (entry1->type && entry2->type) {
+ status = strcasecomp(entry1->type, entry2->type);
+ if (status)
+ return(status);
+ /* else fall to filename comparison */
+ }
+ return (strcmp(entry1->filename, entry2->filename));
+ break;
+
+ case FILE_BY_DATE:
+ if (entry1->date && entry2->date) {
+ /*
+ ** Make sure we have the correct length. - FM
+ */
+ if (strlen(entry1->date) != 12 || strlen(entry2->date) != 12) {
+ return(strcmp(entry1->filename, entry2->filename));
+ }
+ /*
+ ** Set the years and date,
+ ** if we don't have them yet.
+ */
+ if (!HaveYears) {
+ set_years_and_date();
+ }
+ /*
+ ** Set up for sorting in reverse
+ ** chronological order. - FM
+ */
+ if (entry1->date[9] == ':') {
+ strcpy(date1, "9999");
+ strcpy(time1, (char *)&entry1->date[7]);
+ if (time1[0] == ' ') {
+ time1[0] = '0';
+ }
+ } else {
+ strcpy(date1, (char *)&entry1->date[8]);
+ strcpy(time1, "00:00");
+ }
+ strncpy(month, entry1->date, 3);
+ month[3] = '\0';
+ for (i = 0; i < 12; i++) {
+ if (!strcasecomp(month, months[i])) {
+ break;
+ }
+ }
+ i++;
+ sprintf(month, "%s%d", (i < 10 ? "0" : ""), i);
+ strcat(date1, month);
+ strncat(date1, (char *)&entry1->date[4], 2);
+ date1[8] = '\0';
+ if (date1[6] == ' ' || date1[6] == HT_NON_BREAK_SPACE) {
+ date1[6] = '0';
+ }
+ if (date1[0] == '9' && atoi(date1) > TheDate) {
+ for (i = 0; i < 4; i++) {
+ date1[i] = LastYear[i];
+ }
+ }
+ strcat(date1, time1);
+ if (entry2->date[9] == ':') {
+ strcpy(date2, "9999");
+ strcpy(time2, (char *)&entry2->date[7]);
+ if (time2[0] == ' ') {
+ time2[0] = '0';
+ }
+ } else {
+ strcpy(date2, (char *)&entry2->date[8]);
+ strcpy(time2, "00:00");
+ }
+ strncpy(month, entry2->date, 3);
+ month[3] = '\0';
+ for (i = 0; i < 12; i++) {
+ if (!strcasecomp(month, months[i])) {
+ break;
+ }
+ }
+ i++;
+ sprintf(month, "%s%d", (i < 10 ? "0" : ""), i);
+ strcat(date2, month);
+ strncat(date2, (char *)&entry2->date[4], 2);
+ date2[8] = '\0';
+ if (date2[6] == ' ' || date2[6] == HT_NON_BREAK_SPACE) {
+ date2[6] = '0';
+ }
+ if (date2[0] == '9' && atoi(date2) > TheDate) {
+ for (i = 0; i < 4; i++) {
+ date2[i] = LastYear[i];
+ }
+ }
+ strcat(date2, time2);
+ /*
+ ** Do the comparison. - FM
+ */
+ status = strcasecomp(date2, date1);
+ if (status)
+ return(status);
+ /* else fall to filename comparison */
+ }
+ return (strcmp(entry1->filename, entry2->filename));
+ break;
+
+ case FILE_BY_NAME:
+ default:
+ return (strcmp(entry1->filename, entry2->filename));
+ }
+}
+
+
+/* Read a directory into an hypertext object from the data socket
+** --------------------------------------------------------------
+**
+** On entry,
+** anchor Parent anchor to link the this node to
+** address Address of the directory
+** On exit,
+** returns HT_LOADED if OK
+** <0 if error.
+*/
+PRIVATE int read_directory ARGS4(
+ HTParentAnchor *, parent,
+ CONST char *, address,
+ HTFormat, format_out,
+ HTStream *, sink)
+{
+ int status;
+ BOOLEAN WasInterrupted = FALSE;
+ HTStructured* target = HTML_new(parent, format_out, sink);
+ HTStructuredClass targetClass;
+ char *filename = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
+ EntryInfo *entry_info;
+ BOOLEAN first = TRUE;
+ char string_buffer[64];
+ char *lastpath = NULL;/* prefix for link, either "" (for root) or xxx */
+ BOOL need_parent_link = FALSE;
+ BOOL tildeIsTop = FALSE;
+
+ targetClass = *(target->isa);
+
+ _HTProgress ("Receiving FTP directory.");
+
+ /*
+ ** Check whether we always want the home
+ ** directory treated as Welcome. - FM
+ */
+ if (server_type == VMS_SERVER)
+ tildeIsTop = TRUE;
+
+ /*
+ ** This should always come back FALSE, since the
+ ** flag is set only for local directory listings
+ ** if LONG_LIST was defined on compilation, but
+ ** we could someday set up an equivalent listing
+ ** for Unix ftp servers. - FM
+ */
+ need_parent_link = HTDirTitles(target, (HTAnchor*)parent, tildeIsTop);
+
+ data_read_pointer = data_write_pointer = data_buffer;
+
+ if (*filename == '\0') { /* Empty filename: use root. */
+ StrAllocCopy (lastpath, "/");
+ } else if (!strcmp(filename,"/")) { /* Root path. */
+ StrAllocCopy (lastpath, "/foo/..");
+ } else {
+ char * p = strrchr(filename, '/'); /* Find the lastslash. */
+ char *cp;
+
+ if (server_type == CMS_SERVER) {
+ StrAllocCopy(lastpath, filename); /* Use absolute path for CMS. */
+ } else {
+ StrAllocCopy(lastpath, p+1); /* Take slash off the beginning. */
+ }
+ if ((cp = strrchr(lastpath, ';')) != NULL) { /* Trim type= param. */
+ if (!strncasecomp((cp+1), "type=", 5)) {
+ if (TOUPPER(*(cp+6)) == 'D' ||
+ TOUPPER(*(cp+6)) == 'A' ||
+ TOUPPER(*(cp+6)) == 'I')
+ *cp = '\0';
+ }
+ }
+ }
+ FREE (filename);
+
+
+ {
+ HTBTree * bt = HTBTree_new((HTComparer)compare_EntryInfo_structs);
+ char c;
+ HTChunk * chunk = HTChunkCreate(128);
+ int BytesReceived = 0;
+ int BytesReported = 0;
+ char NumBytes[64];
+ PUTS("\n"); /* prettier LJM */
+ for (c = 0; c != (char)EOF;) { /* For each entry in the directory */
+ HTChunkClear(chunk);
+
+ if (HTCheckForInterrupt()) {
+ WasInterrupted = TRUE;
+ if (BytesReceived) {
+ goto unload_btree; /* unload btree */
+ } else {
+ ABORT_TARGET;
+ HTBTreeAndObject_free(bt);
+ return HT_INTERRUPTED;
+ }
+ }
+
+ /* read directory entry
+ */
+ for (;;) { /* Read in one line as filename */
+ c = NEXT_DATA_CHAR;
+AgainForMultiNet:
+ if (interrupted_in_next_data_char) {
+ WasInterrupted = TRUE;
+ if (BytesReceived) {
+ goto unload_btree; /* unload btree */
+ } else {
+ ABORT_TARGET;
+ HTBTreeAndObject_free(bt);
+ return HT_INTERRUPTED;
+ }
+ } else if (c == CR || c == LF) { /* Terminator? */
+ if (chunk->size != 0) { /* got some text */
+ /* Deal with MultiNet's wrapping of long lines */
+ if (server_type == VMS_SERVER) {
+ /* Deal with MultiNet's wrapping of long lines - F.M. */
+ if (data_read_pointer < data_write_pointer &&
+ *(data_read_pointer+1) == ' ')
+ data_read_pointer++;
+ else if (data_read_pointer >= data_write_pointer) {
+ status = NETREAD(data_soc, data_buffer,
+ DATA_BUFFER_SIZE);
+ if (status == HT_INTERRUPTED) {
+ interrupted_in_next_data_char = 1;
+ goto AgainForMultiNet;
+ }
+ if (status <= 0) {
+ c = (char)EOF;
+ break;
+ }
+ data_write_pointer = data_buffer + status;
+ data_read_pointer = data_buffer;
+ if (*data_read_pointer == ' ')
+ data_read_pointer++;
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break; /* finish getting one entry */
+ }
+ } else if (c == (char)EOF) {
+ break; /* End of file */
+ } else {
+ HTChunkPutc(chunk, c);
+ }
+ }
+ HTChunkTerminate(chunk);
+
+ BytesReceived += chunk->size;
+ if (BytesReceived > BytesReported + 1024) {
+ sprintf(NumBytes,"Transferred %d bytes",BytesReceived);
+ HTProgress(NumBytes);
+ BytesReported = BytesReceived;
+ }
+
+ if (c == (char) EOF && chunk->size == 1)
+ /* 1 means empty: includes terminating 0 */
+ break;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Line in %s is %s\n",
+ lastpath, chunk->data);
+
+ entry_info = parse_dir_entry(chunk->data, &first);
+ if (entry_info->display) {
+ if (TRACE)
+ fprintf(stderr, "Adding file to BTree: %s\n",
+ entry_info->filename);
+ HTBTree_add(bt, (EntryInfo *)entry_info);
+ } else {
+ FREE(entry_info);
+ }
+
+ } /* next entry */
+
+unload_btree:
+
+ HTChunkFree(chunk);
+
+ /* print out the handy help message if it exits :) */
+ if (help_message_cache_non_empty()) {
+ START(HTML_PRE);
+ START(HTML_HR);
+ PUTS(help_message_cache_contents());
+ init_help_message_cache(); /* to free memory */
+ START(HTML_HR);
+ } else {
+ START(HTML_PRE);
+ PUTS("\n");
+ }
+
+ /* Put up header
+ */
+ /* PUTS(" Date Type Size Filename\n");
+ */
+
+ /* Run through tree printing out in order
+ */
+ {
+ HTBTElement * ele;
+ int i;
+ for (ele = HTBTree_next(bt, NULL);
+ ele != NULL;
+ ele = HTBTree_next(bt, ele)) {
+ entry_info = (EntryInfo *)HTBTree_object(ele);
+
+ if (entry_info->date) {
+ PUTS(entry_info->date);
+ PUTS(" ");
+ } else {
+ PUTS(" * ");
+ }
+
+ if (entry_info->type) {
+ for (i = 0; entry_info->type[i] != '\0' && i < 15; i++)
+ PUTC(entry_info->type[i]);
+ for (; i < 17; i++)
+ PUTC(' ');
+ }
+
+ /* start the anchor */
+ HTDirEntry(target, lastpath, entry_info->filename);
+ PUTS(entry_info->filename);
+ END(HTML_A);
+
+ if (entry_info->size) {
+ if (entry_info->size < 1024)
+ sprintf(string_buffer, " %d bytes",
+ entry_info->size);
+ else
+ sprintf(string_buffer, " %dKb",
+ entry_info->size/1024);
+ PUTS(string_buffer);
+ }
+
+ PUTC('\n'); /* end of this entry */
+
+ free_entryinfo_struct_contents(entry_info);
+ }
+ }
+ END(HTML_PRE);
+ FREE_TARGET;
+ HTBTreeAndObject_free(bt);
+ }
+
+ FREE(lastpath);
+
+ if (server_type == APPLESHARE_SERVER ||
+ server_type == NETPRESENZ_SERVER) {
+ /*
+ * Without closing the data socket first,
+ * the response(NIL) below hangs. - KW
+ */
+ NETCLOSE(data_soc);
+ }
+
+ if (WasInterrupted || HTCheckForInterrupt()) {
+ if (server_type != CMS_SERVER)
+ response(NIL);
+ _HTProgress("Data transfer interrupted.");
+ return HT_LOADED;
+ }
+ if (server_type != CMS_SERVER)
+ response(NIL);
+ return HT_LOADED;
+#ifdef NOTDEFINED
+ return response(NIL) == 2 ? HT_LOADED : -1;
+#endif /* NOTDEFINED */
+}
+
+/* Retrieve File from Server
+** -------------------------
+**
+** On entry,
+** name WWW address of a file: document, including hostname
+** On exit,
+** returns Socket number for file if good.
+** <0 if bad.
+*/
+PUBLIC int HTFTPLoad ARGS4(
+ CONST char *, name,
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream *, sink)
+{
+ BOOL isDirectory = NO;
+ HTAtom * encoding = NULL;
+ int status;
+ int retry; /* How many times tried? */
+ HTFormat format;
+ char command[LINE_LENGTH+1];
+
+
+ /* set use_list to NOT since we don't know what kind of server
+ * this is yet. And set the type to GENERIC
+ */
+ use_list = FALSE;
+ server_type = GENERIC_SERVER;
+
+ for (retry = 0; retry < 2; retry++) { /* For timed out/broken connections */
+ status = get_connection(name, anchor);
+ if (status < 0)
+ return status;
+
+#ifdef LISTEN
+ status = get_listen_socket();
+ if (status < 0) {
+ NETCLOSE (control->socket);
+ control->socket = -1;
+ close_master_socket ();
+ /* HT_INTERRUPTED would fall through, if we could interrupt
+ somehow in the middle of it, which we currently can't. */
+ return status;
+ }
+
+#ifdef REPEAT_PORT
+/* Inform the server of the port number we will listen on
+*/
+ {
+ status = response(port_command);
+ if (status == HT_INTERRUPTED) {
+ if (TRACE)
+ fprintf (stderr,
+ "HTFTP: Interrupted in response (port_command)\n");
+ _HTProgress ("Connection interrupted.");
+ NETCLOSE (control->socket);
+ control->socket = -1;
+ close_master_socket ();
+ return HT_INTERRUPTED;
+ }
+ if (status != 2) { /* Could have timed out */
+ if (status < 0)
+ continue; /* try again - net error*/
+ return -status; /* bad reply */
+ }
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Port defined.\n");
+ }
+#endif /* REPEAT_PORT */
+#else /* Use PASV */
+/* Tell the server to be passive
+*/
+ {
+ char *p;
+ int reply, h0, h1, h2, h3, p0, p1; /* Parts of reply */
+ int status;
+ data_soc = status;
+
+ sprintf(command, "PASV%c%c", CR, LF);
+ status = response(command);
+ if (status != 2) {
+ if (status < 0)
+ continue; /* retry or Bad return */
+ return -status; /* bad reply */
+ }
+ for (p = response_text; *p && *p != ','; p++)
+ ; /* null body */
+
+ while (--p > response_text && '0' <= *p && *p <= '9')
+ ; /* null body */
+
+ status = sscanf(p+1, "%d,%d,%d,%d,%d,%d",
+ &h0, &h1, &h2, &h3, &p0, &p1);
+ if (status < 4) {
+ fprintf(stderr, "HTFTP: PASV reply has no inet address!\n");
+ return -99;
+ }
+ passive_port = (p0<<8) + p1;
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Server is listening on port %d\n",
+ passive_port);
+
+
+/* Open connection for data:
+*/
+ sprintf(command,
+ "ftp://%d.%d.%d.%d:%d/",h0,h1,h2,h3,passive_port);
+ status = HTDoConnect(name, "FTP", passive_port, &data_soc);
+
+ if (status < 0) {
+ (void) HTInetStatus("connect for data");
+ NETCLOSE(data_soc);
+ return status; /* Bad return */
+ }
+
+ if (TRACE)
+ fprintf(stderr, "FTP data connected, socket %d\n", data_soc);
+ }
+#endif /* use PASV */
+ status = 0;
+ break; /* No more retries */
+
+ } /* for retries */
+ if (status < 0)
+ return status; /* Failed with this code */
+
+/* Ask for the file:
+*/
+ {
+ char *filename = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
+ char *fname = filename; /** Save for subsequent free() **/
+ BOOL binary;
+ char *type = NULL;
+ char *cp;
+
+ if (server_type == CMS_SERVER) {
+ /** If the unescaped path has a %2f, reject it as illegal. - FM **/
+ if (((cp = strstr(filename, "%2")) != NULL) &&
+ TOUPPER(cp[2]) == 'F') {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ if (TRACE) {
+ fprintf(stderr,
+ "HTFTP: Rejecting path due to illegal escaped slash.\n");
+ }
+ return -1;
+ }
+ }
+
+ if (!*filename) {
+ StrAllocCopy(filename, "/");
+ type = "D";
+ } else if ((type = strrchr(filename, ';')) != NULL) {
+ /*
+ ** Check and trim the type= parameter. - FM
+ */
+ if (!strncasecomp((type+1), "type=", 5)) {
+ switch(TOUPPER(*(type+6))) {
+ case 'D':
+ *type = '\0';
+ type = "D";
+ break;
+ case 'A':
+ *type = '\0';
+ type = "A";
+ break;
+ case 'I':
+ *type = '\0';
+ type = "I";
+ break;
+ default:
+ type = "";
+ break;
+ }
+ if (!*filename) {
+ *filename = '/';
+ *(filename+1) = '\0';
+ }
+ }
+ if (TRACE && *type != '\0') {
+ fprintf(stderr, "HTFTP: type=%s\n", type);
+ }
+ }
+ HTUnEscape(filename);
+ if (TRACE)
+ fprintf(stderr, "HTFTP: UnEscaped %s\n", filename);
+ if (filename[1] == '~') {
+ /*
+ ** Check if translation of HOME as tilde is supported,
+ ** and adjust filename if so. - FM
+ */
+ char *cp2 = NULL;
+ char *fn = NULL;
+
+ if ((cp2 = strchr((filename+1), '/')) != NULL) {
+ *cp2 = '\0';
+ }
+ sprintf(command, "PWD%c%c", CR, LF);
+ status = response(command);
+ if (status == 2 && response_text[5] == '/') {
+ sprintf(command, "CWD %s%c%c", (filename+1), CR, LF);
+ status = response(command);
+ if (status == 2) {
+ StrAllocCopy(fn, (filename+1));
+ if (cp2) {
+ *cp2 = '/';
+ if (fn[strlen(fn)-1] != '/') {
+ StrAllocCat(fn, cp2);
+ } else {
+ StrAllocCat(fn, (cp2+1));
+ }
+ cp2 = NULL;
+ }
+ FREE(fname);
+ fname = filename = fn;
+ }
+ }
+ if (cp2) {
+ *cp2 = '/';
+ }
+ }
+ if (strlen(filename) > 3) {
+ char *cp2;
+ if (((cp2=strrchr(filename, '.')) != NULL &&
+ 0 == strncasecomp(cp2, ".me", 3)) &&
+ (cp2[3] == '\0' || cp2[3] == ';')) {
+ /*
+ ** Don't treat this as application/x-Troff-me
+ ** if it's a Unix server but has the string
+ ** "read.me", or if it's not a Unix server. - FM
+ */
+ if ((server_type != UNIX_SERVER) ||
+ (cp2 > (filename + 3) &&
+ 0 == strncasecomp((cp2 - 4), "read.me", 7))) {
+ *cp2 = '\0';
+ format = HTFileFormat(filename, &encoding, NULL);
+ *cp2 = '.';
+ } else {
+ format = HTFileFormat(filename, &encoding, NULL);
+ }
+ } else {
+ format = HTFileFormat(filename, &encoding, NULL);
+ }
+ } else {
+ format = HTFileFormat(filename, &encoding, NULL);
+ }
+ format = HTCharsetFormat(format, anchor, -1);
+ binary = (encoding != HTAtom_for("8bit") &&
+ encoding != HTAtom_for("7bit"));
+ if (!binary &&
+ /*
+ ** Force binary if we're in source, download or dump
+ ** mode and this is not a VM/CMS server, so we don't
+ ** get CRLF instead of LF (or CR) for newlines in text
+ ** files. Can't do this for VM/CMS or we'll get
+ ** raw EBCDIC. - FM
+ */
+ (format_out == WWW_SOURCE ||
+ format_out == HTAtom_for("www/download") ||
+ format_out == HTAtom_for("www/dump")) &&
+ (server_type != CMS_SERVER))
+ binary = TRUE;
+ if (!binary && type && *type == 'I') {
+ /*
+ ** Force binary if we had ;type=I - FM
+ */
+ binary = TRUE;
+ } else if (binary && type && *type == 'A') {
+ /*
+ ** Force ASCII if we had ;type=A - FM
+ */
+ binary = FALSE;
+ }
+ if (binary != control->binary) {
+ /*
+ ** Act on our setting if not alread set. - FM
+ */
+ char * mode = binary ? "I" : "A";
+ sprintf(command, "TYPE %s%c%c", mode, CR, LF);
+ status = response(command);
+ if (status != 2) {
+ init_help_message_cache(); /* to free memory */
+ return ((status < 0) ? status : -status);
+ }
+ control->binary = binary;
+ }
+ switch (server_type) {
+ /*
+ ** Handle what for Lynx are special case servers, e.g.,
+ ** for which we respect RFC 1738, or which have known
+ ** conflicts in suffix mappings. - FM
+ */
+ case VMS_SERVER:
+ {
+ char *cp1, *cp2;
+ BOOL included_device = FALSE;
+ /** Accept only Unix-style filename **/
+ if (strchr(filename, ':') != NULL ||
+ strchr(filename, '[') != NULL) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ if (TRACE) {
+ fprintf(stderr,
+ "HTFTP: Rejecting path due to non-Unix-style syntax.\n");
+ }
+ return -1;
+ }
+ /** Handle any unescaped "/%2F" path **/
+ if (!strncmp(filename, "//", 2)) {
+ int i;
+ included_device = TRUE;
+ for (i = 0; filename[(i+1)]; i++)
+ filename[i] = filename[(i+1)];
+ filename[i] = '\0';
+ if (TRACE) {
+ fprintf(stderr, "HTFTP: Trimmed '%s'\n", filename);
+ }
+ cp = HTMake_VMS_name("", filename);
+ if (TRACE) {
+ fprintf(stderr, "HTFTP: VMSized '%s'\n", cp);
+ }
+ if ((cp1=strrchr(cp, ']')) != NULL) {
+ cp1++;
+ for (i = 0; cp1[i]; i++)
+ filename[i] = cp1[i];
+ filename[i] = '\0';
+ if (TRACE) {
+ fprintf(stderr, "HTFTP: Filename '%s'\n", filename);
+ }
+ *cp1 = '\0';
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ if ((cp1=strchr(cp, '[')) != NULL) {
+ *cp1++ = '\0';
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ sprintf(command, "CWD [.%s%c%c", cp1, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ } else {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ }
+ } else if ((cp1=strchr(cp, ':')) != NULL &&
+ strchr(cp, '[') == NULL &&
+ strchr(cp, ']') == NULL) {
+ cp1++;
+ if (*cp1 != '\0') {
+ for (i = 0; cp1[i]; i++)
+ filename[i] = cp1[i];
+ filename[i] = '\0';
+ if (TRACE) {
+ fprintf(stderr, "HTFTP: Filename '%s'\n", filename);
+ }
+ *cp1 = '\0';
+ strcat(cp, "[");
+ strcat(cp, filename);
+ strcat(cp, "]");
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ *cp1 = '\0';
+ strcat(cp, "[000000]");
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ *cp1 = '\0';
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache();
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ }
+ } else {
+ strcpy(cp, "000000");
+ filename = cp;
+ }
+ }
+ } else if (0==strcmp(cp, (filename+1))) {
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ strcat(cp, ":");
+ sprintf(command, "CWD %s%c%c", cp, CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ }
+ strcpy(cp, "000000");
+ filename = cp;
+ }
+ }
+ /** Trim trailing slash if filename is not the top directory **/
+ if (strlen(filename) > 1 && filename[strlen(filename)-1] == '/')
+ filename[strlen(filename)-1] = '\0';
+
+#ifdef MAINTAIN_CONNECTION /* Don't need this if always new connection - F.M. */
+ if (!included_device) {
+ /** Get the current default VMS device:[directory] **/
+ sprintf(command, "PWD%c%c", CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ /** Go to the VMS account's top directory **/
+ if ((cp=strchr(response_text, '[')) != NULL &&
+ (cp1=strrchr(response_text, ']')) != NULL) {
+ sprintf(command, "CWD %s", cp);
+ if ((cp2=strchr(cp, '.')) != NULL && cp2 < cp1)
+ sprintf(command+(cp2-cp)+4, "]%c%c", CR, LF);
+ else
+ sprintf(command+(cp1-cp)+4, "]%c%c", CR, LF);
+ status = response (command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ }
+ }
+#endif /* MAINTAIN_CONNECTION */
+
+ /** If we want the VMS account's top directory, list it now **/
+ if (!(strcmp(filename, "/~")) ||
+ (included_device && 0==strcmp(filename, "000000")) ||
+ (strlen(filename) == 1 && *filename == '/')) {
+ isDirectory = YES;
+ sprintf(command, "LIST%c%c", CR, LF);
+ status = response (command);
+ FREE(fname);
+ if (status != 1) {
+ /* Action not started */
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ /** Big goto! **/
+ goto listen;
+ }
+ /** Otherwise, go to appropriate directory and doctor filename **/
+ if (!strncmp(filename, "/~", 2))
+ filename += 2;
+ if (!included_device &&
+ (cp = strchr(filename, '/')) != NULL &&
+ (cp1 = strrchr(cp, '/')) != NULL && cp != cp1) {
+ sprintf(command, "CWD [.%s", cp+1);
+ sprintf(command+(cp1-cp)+5, "]%c%c", CR, LF);
+ while ((cp2 = strrchr(command, '/')) != NULL)
+ *cp2 = '.';
+ status = response(command);
+ if (status != 2) {
+ FREE(fname);
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ filename = cp1+1;
+ } else {
+ if (!included_device) {
+ filename += 1;
+ }
+ }
+ break;
+ }
+ case CMS_SERVER:
+ {
+ /*
+ ** If we want the CMS account's top directory, or a base
+ ** SFS or anonymous directory path (i.e., without a slash),
+ ** list it now. FM
+ */
+ if ((strlen(filename) == 1 && *filename == '/') ||
+ ((0 == strncasecomp((filename+1), "vmsysu:", 7)) &&
+ (cp = strchr((filename+1), '.')) != NULL &&
+ strchr(cp, '/') == NULL) ||
+ (0 == strncasecomp(filename+1, "anonymou.", 9) &&
+ strchr(filename+1, '/') == NULL)) {
+ if (filename[1] != '\0') {
+ sprintf(command, "CWD %s%c%c", (filename+1), CR, LF);
+ status = response(command);
+ if (status != 2) {
+ /* Action not started */
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ }
+ isDirectory = YES;
+ if (use_list)
+ sprintf(command, "LIST%c%c", CR, LF);
+ else
+ sprintf(command, "NLST%c%c", CR, LF);
+ status = response (command);
+ FREE(fname);
+ if (status != 1) {
+ /* Action not started */
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ /** Big goto! **/
+ goto listen;
+ }
+ filename++;
+
+ /** Otherwise, go to appropriate directory and adjust filename **/
+ while ((cp = strchr(filename, '/')) != NULL) {
+ *cp++ = '\0';
+ sprintf(command, "CWD %s%c%c", filename, CR, LF);
+ status = response(command);
+ if (status == 2) {
+ if (*cp == '\0') {
+ isDirectory = YES;
+ if (use_list)
+ sprintf(command, "LIST%c%c", CR, LF);
+ else
+ sprintf(command, "NLST%c%c", CR, LF);
+ status = response (command);
+ FREE(fname);
+ if (status != 1) {
+ /** Action not started **/
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ return ((status < 0) ? status : -status);
+ }
+ /** Clear any messages from the login directory **/
+ init_help_message_cache();
+ /** Big goto! **/
+ goto listen;
+ }
+ filename = cp;
+ }
+ }
+ break;
+ }
+ default:
+ /** Shift for any unescaped "/%2F" path **/
+ if (!strncmp(filename, "//", 2))
+ filename++;
+ break;
+ }
+ /*
+ ** Act on a file or listing request, or try to figure out
+ ** which we're dealing with if we don't know yet. - FM
+ */
+ if (!(type) || (type && *type != 'D')) {
+ sprintf(command, "RETR %s%c%c", filename, CR, LF);
+ status = response(command);
+ } else {
+ status = 5; /* Failed status set as flag. - FM */
+ }
+ if (status != 1) { /* Failed : try to CWD to it */
+ /** Clear any login messages if this isn't the login directory **/
+ if (strcmp(filename, "/"))
+ init_help_message_cache();
+
+ sprintf(command, "CWD %s%c%c", filename, CR, LF);
+ status = response(command);
+
+ if (status == 2) { /* Successed : let's NAME LIST it */
+ isDirectory = YES;
+ if (use_list)
+ sprintf(command, "LIST%c%c", CR, LF);
+ else
+ sprintf(command, "NLST%c%c", CR, LF);
+ status = response (command);
+ }
+ }
+ FREE(fname);
+ if (status != 1) {
+ init_help_message_cache(); /* to free memory */
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ if (status < 0)
+ return status;
+ else
+ return -status;
+ }
+ }
+
+listen:
+#ifdef LISTEN
+/* Wait for the connection
+*/
+ {
+ struct sockaddr_in soc_address;
+ int soc_addrlen=sizeof(soc_address);
+#ifdef SOCKS
+ if (socks_flag)
+ status = Raccept(master_socket,
+ (struct sockaddr *)&soc_address,
+ (void *)&soc_addrlen);
+ else
+#endif /* SOCKS */
+ status = accept(master_socket,
+ (struct sockaddr *)&soc_address,
+ (void *)&soc_addrlen);
+ if (status < 0) {
+ init_help_message_cache(); /* to free memory */
+ return HTInetStatus("accept");
+ }
+ CTRACE(tfp, "TCP: Accepted new socket %d\n", status);
+ data_soc = status;
+ }
+#else
+/* @@ */
+#endif /* LISTEN */
+ if (isDirectory) {
+ status = read_directory (anchor, name, format_out, sink);
+ NETCLOSE(data_soc);
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ init_help_message_cache(); /* to free memory */
+ return status;
+ /* returns HT_LOADED or error */
+ } else {
+ int rv;
+ int len;
+ char *FileName = HTParse(name, "", PARSE_PATH + PARSE_PUNCTUATION);
+
+ /** Clear any login messages **/
+ init_help_message_cache();
+
+ /** Fake a Content-Encoding for compressed files. - FM **/
+ HTUnEscape(FileName);
+ if (!IsUnityEnc(encoding)) {
+ /*
+ * We already know from the call to HTFileFormat above that
+ * this is a compressed file, no need to look at the filename
+ * again. - kw
+ */
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, HTAtom_name(encoding));
+ format = HTAtom_for("www/compressed");
+
+ } else if ((len = strlen(FileName)) > 2) {
+ if ((FileName[len - 1] == 'Z') &&
+ (FileName[len - 2] == '.' ||
+ FileName[len - 2] == '-' ||
+ FileName[len - 2] == '_')) {
+
+ FileName[len - 2] = '\0';
+ format = HTFileFormat(FileName, &encoding, NULL);
+ format = HTCharsetFormat(format, anchor, -1);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-compress");
+ format = HTAtom_for("www/compressed");
+ } else if ((len > 3) &&
+ !strcasecomp((char *)&FileName[len - 2], "gz")) {
+ if (FileName[len - 3] == '.' ||
+ FileName[len - 3] == '-' ||
+ FileName[len - 3] == '_') {
+ FileName[len - 3] = '\0';
+ format = HTFileFormat(FileName, &encoding, NULL);
+ format = HTCharsetFormat(format, anchor, -1);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-gzip");
+ format = HTAtom_for("www/compressed");
+ }
+ }
+ }
+ FREE(FileName);
+
+ _HTProgress ("Receiving FTP file.");
+ rv = HTParseSocket(format, format_out, anchor, data_soc, sink);
+
+ if (rv == HT_INTERRUPTED)
+ _HTProgress("Data transfer interrupted.");
+
+ HTInitInput(control->socket);
+ /* Reset buffering to control connection DD 921208 */
+
+ status = NETCLOSE(data_soc);
+ if (TRACE)
+ fprintf(stderr, "HTFTP: Closing data socket %d\n", data_soc);
+ if (status < 0 && rv != HT_INTERRUPTED && rv != -1) {
+ (void) HTInetStatus("close"); /* Comment only */
+ data_soc = -1; /* invalidate it */
+ } else {
+ data_soc = -1; /* invalidate it */
+ status = response(NIL); /* Pick up final reply */
+ if (status != 2 && rv != HT_INTERRUPTED && rv != -1) {
+ init_help_message_cache(); /* to free memory */
+ return HTLoadError(sink, 500, response_text);
+ }
+ }
+
+ NETCLOSE(control->socket);
+ control->socket = -1;
+ init_help_message_cache(); /* to free memory */
+ return HT_LOADED;
+ }
+} /* open_file_read */
+
+/*
+** This function frees any user entered password, so that
+** it must be entered again for a future request. - FM
+*/
+PUBLIC void HTClearFTPPassword NOARGS
+{
+ /*
+ ** Need code to check cached documents from
+ ** non-anonymous ftp accounts and do something
+ ** to ensure that they no longer can be accessed
+ ** without a new retrieval. - FM
+ */
+
+ /*
+ ** Now free the current user entered password,
+ ** if any. - FM
+ */
+ FREE(user_entered_password);
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.h
new file mode 100644
index 00000000000..814772d4acc
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFTP.h
@@ -0,0 +1,77 @@
+/* FTP access module for libwww
+ FTP ACCESS FUNCTIONS
+
+ This isn't really a valid protocol module -- it is lumped together with HTFile . That
+ could be changed easily.
+
+ Author: Tim Berners-Lee. Public Domain. Please mail changes to timbl@info.cern.ch
+
+ */
+#ifndef HTFTP_H
+#define HTFTP_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTAnchor.h"
+#include "HTStream.h"
+#include "HTParse.h"
+
+#define FILE_BY_NAME 0
+#define FILE_BY_TYPE 1
+#define FILE_BY_SIZE 2
+#define FILE_BY_DATE 3
+extern BOOLEAN HTfileSortMethod; /* specifies the method of sorting */
+
+
+/* PUBLIC HTMake_VMS_name()
+** CONVERTS WWW name into a VMS name
+** ON ENTRY:
+** nn Node Name (optional)
+** fn WWW file name
+**
+** ON EXIT:
+** returns vms file specification
+**
+** Bug: Returns pointer to static -- non-reentrant
+*/
+PUBLIC char * HTMake_VMS_name PARAMS((
+ CONST char * nn,
+ CONST char * fn));
+
+
+/*
+
+Retrieve File from Server
+
+ ON EXIT,
+
+ returns Socket number for file if good.<0 if bad.
+
+ */
+extern int HTFTPLoad PARAMS
+((
+ CONST char * name,
+ HTParentAnchor * anchor,
+ HTFormat format_out,
+ HTStream* sink
+));
+
+/*
+** This function frees any user entered password, so that
+** it must be entered again for a future request. - FM
+*/
+extern void HTClearFTPPassword NOPARAMS;
+
+/*
+
+Return Host Name
+
+ */
+extern CONST char * HTHostName NOPARAMS;
+
+#endif
+
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.c
new file mode 100644
index 00000000000..8ef9ba1b6e1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.c
@@ -0,0 +1,358 @@
+/* FILE WRITER HTFWrite.h
+** ===========
+**
+** This version of the stream object just writes to a C file.
+** The file is assumed open and left open.
+**
+** Bugs:
+** strings written must be less than buffer size.
+*/
+
+#include "HTUtils.h"
+
+#include "HTFWriter.h"
+
+#include "HTFormat.h"
+#include "HTAlert.h"
+#include "HTFile.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* Stream Object
+** ------------
+*/
+
+struct _HTStream {
+ CONST HTStreamClass * isa;
+
+ FILE * fp;
+ char * end_command;
+ char * remove_command;
+ BOOL announce;
+};
+
+
+/*_________________________________________________________________________
+**
+** B L A C K H O L E C L A S S
+**
+** There is only one black hole instance shared by anyone
+** who wanst a black hole. These black holes don't radiate,
+** they just absorb data.
+*/
+PRIVATE void HTBlackHole_put_character ARGS2(HTStream *, me, char, c)
+{}
+PRIVATE void HTBlackHole_put_string ARGS2(HTStream *, me, CONST char*, s)
+{}
+PRIVATE void HTBlackHole_write ARGS3(HTStream *, me, CONST char*, s, int, l)
+{}
+PRIVATE void HTBlackHole_free ARGS1(HTStream *, me)
+{}
+PRIVATE void HTBlackHole_abort ARGS2(HTStream *, me, HTError, e)
+{}
+
+
+/* Black Hole stream
+** -----------------
+*/
+PRIVATE CONST HTStreamClass HTBlackHoleClass =
+{
+ "BlackHole",
+ HTBlackHole_free,
+ HTBlackHole_abort,
+ HTBlackHole_put_character, HTBlackHole_put_string,
+ HTBlackHole_write
+};
+
+PRIVATE HTStream HTBlackHoleInstance =
+{
+ &HTBlackHoleClass,
+ NULL,
+ NULL,
+ NULL,
+ NO
+};
+
+/* Black hole craetion
+*/
+PUBLIC HTStream * HTBlackHole NOARGS
+{
+ return &HTBlackHoleInstance;
+}
+
+
+/*_________________________________________________________________________
+**
+** F I L E A C T I O N R O U T I N E S
+** Bug:
+** All errors are ignored.
+*/
+
+/* Character handling
+** ------------------
+*/
+
+PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
+{
+ putc(c, me->fp);
+}
+
+
+
+/* String handling
+** ---------------
+**
+** Strings must be smaller than this buffer size.
+*/
+PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
+{
+ fputs(s, me->fp);
+}
+
+
+/* Buffer write. Buffers can (and should!) be big.
+** ------------
+*/
+PRIVATE void HTFWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
+{
+ fwrite(s, 1, l, me->fp);
+}
+
+
+
+
+/* Free an HTML object
+** -------------------
+**
+** Note that the SGML parsing context is freed, but the created
+** object is not,
+** as it takes on an existence of its own unless explicitly freed.
+*/
+PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
+{
+ fclose(me->fp);
+ if (me->end_command) { /* Temp file */
+ _HTProgress(me->end_command); /* Tell user what's happening */
+ system(me->end_command);
+ FREE(me->end_command);
+ if (me->remove_command) {
+ system(me->remove_command);
+ FREE(me->remove_command);
+ }
+ }
+
+ FREE(me);
+}
+
+/* End writing
+*/
+
+PRIVATE void HTFWriter_abort ARGS2(HTStream *, me, HTError, e)
+{
+ fclose(me->fp);
+ if (me->end_command) { /* Temp file */
+ if (TRACE) fprintf(stderr,
+ "HTFWriter: Aborting: file not executed.\n");
+ FREE(me->end_command);
+ if (me->remove_command) {
+ system(me->remove_command);
+ FREE(me->remove_command);
+ }
+ }
+
+ FREE(me);
+}
+
+
+
+/* Structured Object Class
+** -----------------------
+*/
+PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
+{
+ "FileWriter",
+ HTFWriter_free,
+ HTFWriter_abort,
+ HTFWriter_put_character, HTFWriter_put_string,
+ HTFWriter_write
+};
+
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+
+PUBLIC HTStream* HTFWriter_new ARGS1(FILE *, fp)
+{
+ HTStream* me;
+
+ if (!fp) return NULL;
+
+ me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL) outofmem(__FILE__, "HTML_new");
+ me->isa = &HTFWriter;
+
+ me->fp = fp;
+ me->end_command = NULL;
+ me->remove_command = NULL;
+ me->announce = NO;
+
+ return me;
+}
+
+/* Make system command from template
+** ---------------------------------
+**
+** See mailcap spec for description of template.
+*/
+/* @@ to be written. sprintfs will do for now. */
+
+
+
+/* Take action using a system command
+** ----------------------------------
+**
+** originally from Ghostview handling by Marc Andreseen.
+** Creates temporary file, writes to it, executes system command
+** on end-document. The suffix of the temp file can be given
+** in case the application is fussy, or so that a generic opener can
+** be used.
+*/
+PUBLIC HTStream* HTSaveAndExecute ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor, /* Not used */
+ HTStream *, sink) /* Not used */
+
+#ifdef unix
+#define REMOVE_COMMAND "/bin/rm -f %s\n"
+#endif
+#ifdef VMS
+#define REMOVE_COMMAND "delete/noconfirm/nolog %s.."
+#endif
+
+#ifdef REMOVE_COMMAND
+{
+ char *fnam;
+ CONST char * suffix;
+
+ HTStream* me;
+
+ if (HTClientHost) {
+ HTAlert("Can't save data to file -- please run WWW locally");
+ return HTBlackHole();
+ }
+
+ me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL) outofmem(__FILE__, "Save and execute");
+ me->isa = &HTFWriter;
+
+ /* Save the file under a suitably suffixed name */
+
+ suffix = HTFileSuffix(pres->rep);
+
+ fnam = (char *)malloc (L_tmpnam + 16 + strlen(suffix));
+ tmpnam (fnam);
+ if (suffix) strcat(fnam, suffix);
+
+ me->fp = fopen (fnam, "w");
+ if (!me->fp) {
+ HTAlert("Can't open temporary file!");
+ FREE(fnam);
+ FREE(me);
+ return NULL;
+ }
+
+/* Make command to process file
+*/
+ me->end_command = (char *)malloc (
+ (strlen (pres->command) + 10+ 3*strlen(fnam))
+ * sizeof (char));
+ if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
+
+ sprintf (me->end_command, pres->command, fnam, fnam, fnam);
+
+ me->remove_command = NULL; /* If needed, put into end_command */
+#ifdef NOPE
+/* Make command to delete file
+*/
+ me->remove_command = (char *)malloc (
+ (strlen (REMOVE_COMMAND) + 10+ strlen(fnam))
+ * sizeof (char));
+ if (me == NULL) outofmem(__FILE__, "SaveAndExecute");
+
+ sprintf (me->remove_command, REMOVE_COMMAND, fnam);
+#endif
+
+ me->announce = NO;
+ FREE(fnam);
+ return me;
+}
+
+#else /* can do remove */
+{ return NULL; }
+#endif
+
+
+/* Save Locally
+** ------------
+**
+** Bugs:
+** GUI Apps should open local Save panel here really.
+**
+*/
+PUBLIC HTStream* HTSaveLocally ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor, /* Not used */
+ HTStream *, sink) /* Not used */
+
+{
+ char *fnam;
+ char *answer;
+ CONST char * suffix;
+
+ HTStream* me;
+
+ if (HTClientHost) {
+ HTAlert("Can't save data to file -- please run WWW locally");
+ return HTBlackHole();
+ }
+
+ me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL) outofmem(__FILE__, "SaveLocally");
+ me->isa = &HTFWriter;
+ me->end_command = NULL;
+ me->remove_command = NULL; /* If needed, put into end_command */
+ me->announce = YES;
+
+ /* Save the file under a suitably suffixed name */
+
+ suffix = HTFileSuffix(pres->rep);
+
+ fnam = (char *)malloc (L_tmpnam + 16 + strlen(suffix));
+ tmpnam (fnam);
+ if (suffix) strcat(fnam, suffix);
+
+ /* Save Panel */
+ answer = HTPrompt("Give name of file to save in", fnam);
+
+ FREE(fnam);
+
+ me->fp = fopen (answer, "w");
+ if (!me->fp) {
+ HTAlert("Can't open local file to write into.");
+ FREE(answer);
+ FREE(me);
+ return NULL;
+ }
+
+ FREE(answer);
+ return me;
+}
+
+
+
+/* Format Converter using system command
+** -------------------------------------
+*/
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.h
new file mode 100644
index 00000000000..052bdd7e3a3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFWriter.h
@@ -0,0 +1,37 @@
+/* File Writer for libwww
+ C FILE WRITER
+
+ It is useful to have both FWriter and Writer for environments in which fdopen() doesn't
+ exist for example.
+
+ */
+#ifndef HTFWRITE_H
+#define HTFWRITE_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTStream.h"
+/*#include <stdio.h> included by HTUtils.h -- FM */
+#include "HTFormat.h"
+
+#ifdef SHORT_NAMES
+#define HTFWriter_new HTFWnew
+#endif
+
+extern HTStream * HTFWriter_new PARAMS((FILE * fp));
+
+extern HTStream * HTSaveAndExecute PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor, /* Not used */
+ HTStream * sink));
+
+extern HTStream * HTSaveLocally PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor, /* Not used */
+ HTStream * sink));
+
+#endif
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c
new file mode 100644
index 00000000000..89a93d14f81
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.c
@@ -0,0 +1,2426 @@
+/* File Access HTFile.c
+** ===========
+**
+** This is unix-specific code in general, with some VMS bits.
+** These are routines for file access used by browsers.
+** Development of this module for Unix DIRED_SUPPORT in Lynx
+** regrettably has has been conducted in a manner with now
+** creates a major impediment for hopes of adapting Lynx to
+** a newer version of the library.
+**
+** History:
+** Feb 91 Written Tim Berners-Lee CERN/CN
+** Apr 91 vms-vms access included using DECnet syntax
+** 26 Jun 92 (JFG) When running over DECnet, suppressed FTP.
+** Fixed access bug for relative names on VMS.
+** Sep 93 (MD) Access to VMS files allows sharing.
+** 15 Nov 93 (MD) Moved HTVMSname to HTVMSUTILS.C
+** 27 Dec 93 (FM) FTP now works with VMS hosts.
+** FTP path must be Unix-style and cannot include
+** the device or top directory.
+*/
+
+#ifndef VMS
+/* #define LONG_LIST */ /* Define this for long style unix listings (ls -l) */
+/* #define NO_PARENT_DIR_REFERENCE */ /* Define this for no parent links */
+#endif /* !VMS */
+
+#ifdef DOSPATH
+#define HAVE_READDIR 1
+#include <dirent.h>
+#define USE_DIRENT
+#include "HTDOS.h"
+#endif /* DOSPATH */
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFile.h" /* Implemented here */
+#ifdef VMS
+#include <stat.h>
+#endif /* VMS */
+
+#ifndef VMS
+#ifdef LONG_LIST
+#include <pwd.h>
+#include <grp.h>
+#endif /* LONG_LIST */
+#endif /* !VMS */
+
+#ifdef USE_ZLIB
+#include <GridText.h>
+#endif
+
+#define INFINITY 512 /* file name length @@ FIXME */
+#define MULTI_SUFFIX ".multi" /* Extension for scanning formats */
+
+#define HT_EM_SPACE ((char)2)
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+
+#include "HTParse.h"
+#include "HTTCP.h"
+#ifndef DECNET
+#include "HTFTP.h"
+#endif /* !DECNET */
+#include "HTAnchor.h"
+#include "HTAtom.h"
+#include "HTWriter.h"
+#include "HTFWriter.h"
+#include "HTInit.h"
+#include "HTBTree.h"
+#include "HTAlert.h"
+#include "HTCJK.h"
+#include "UCDefs.h"
+#include "UCMap.h"
+#include "UCAux.h"
+
+#include "LYexit.h"
+#include "LYCharSets.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYLeaks.h"
+
+typedef struct _HTSuffix {
+ char * suffix;
+ HTAtom * rep;
+ HTAtom * encoding;
+ char * desc;
+ float quality;
+} HTSuffix;
+
+#ifndef NGROUPS
+#ifdef NGROUPS_MAX
+#define NGROUPS NGROUPS_MAX
+#else
+#define NGROUPS 32
+#endif /* NGROUPS_MAX */
+#endif /* NGROUPS */
+
+#include "HTML.h" /* For directory object building */
+
+#define PUTC(c) (*target->isa->put_character)(target, c)
+#define PUTS(s) (*target->isa->put_string)(target, s)
+#define START(e) (*target->isa->start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*target->isa->end_element)(target, e, 0)
+#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
+ (*target->isa->end_element)(target, e, 0)
+#define FREE_TARGET (*target->isa->_free)(target)
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+
+/*
+** Controlling globals.
+*/
+PUBLIC int HTDirAccess = HT_DIR_OK;
+
+#ifdef DIRED_SUPPORT
+PUBLIC int HTDirReadme = HT_DIR_README_NONE;
+#define FILES_FIRST 1
+#define MIXED_STYLE 2
+extern BOOLEAN lynx_edit_mode;
+extern BOOLEAN dir_list_style;
+#else
+PUBLIC int HTDirReadme = HT_DIR_README_TOP;
+#endif /* DIRED_SUPPORT */
+
+extern BOOLEAN LYRawMode;
+extern BOOL HTPassEightBitRaw;
+extern HTCJKlang HTCJK;
+
+PRIVATE char *HTMountRoot = "/Net/"; /* Where to find mounts */
+#ifdef VMS
+PRIVATE char *HTCacheRoot = "/WWW$SCRATCH"; /* Where to cache things */
+#else
+PRIVATE char *HTCacheRoot = "/tmp/W3_Cache_"; /* Where to cache things */
+#endif /* VMS */
+
+/*PRIVATE char *HTSaveRoot = "$(HOME)/WWW/";*/ /* Where to save things */
+
+/*
+** Suffix registration.
+*/
+PRIVATE HTList * HTSuffixes = 0;
+PRIVATE HTSuffix no_suffix = { "*", NULL, NULL, NULL, 1.0 };
+PRIVATE HTSuffix unknown_suffix = { "*.*", NULL, NULL, NULL, 1.0};
+
+
+#ifdef _WINDOWS
+int exists(char *filename)
+{
+ return (access(filename,0)==0);
+}
+#endif
+
+
+/* To free up the suffixes at program exit.
+** ----------------------------------------
+*/
+PRIVATE void free_suffixes NOPARAMS;
+
+#ifdef LONG_LIST
+PRIVATE void LYListFmtParse ARGS5(
+ char *, fmtstr,
+ char *, file,
+ HTStructured *, target,
+ char *, entry,
+ char *, tail)
+{
+ char c;
+ char *s;
+ char *end;
+ char *start;
+ char *str = NULL;
+ struct stat st;
+ char buf[512];
+ char fmt[512];
+ char type;
+ struct passwd *p;
+ struct group *g;
+ time_t now;
+ char *datestr;
+ int len;
+#define SEC_PER_YEAR (60 * 60 * 24 * 365)
+ static char *pbits[] = { "---", "--x", "-w-", "-wx",
+ "r--", "r-x", "rw-", "rwx", 0 };
+ static char *psbits[] = { "--S", "--s", "-wS", "-ws",
+ "r-S", "r-s", "rwS", "rws", 0 };
+#define PBIT(a, n, s) (s) ? psbits[((a) >> (n)) & 0x7] : \
+ pbits[((a) >> (n)) & 0x7]
+
+ if (lstat(file, &st) < 0)
+ fmtstr = "%a"; /* can't stat so just do anchor */
+
+ StrAllocCopy(str, fmtstr);
+ s = str;
+ end = str + strlen(str);
+ START(HTML_PRE);
+ while (*s) {
+ start = s;
+ while (*s) {
+ if (*s == '%') {
+ if (*(s+1) == '%') /* literal % */
+ s++;
+ else
+ break;
+ }
+ s++;
+ }
+ /* s is positioned either at a % or at \0 */
+ *s = '\0';
+ if (s > start) { /* some literal chars. */
+ PUTS(start);
+ }
+ if (s == end)
+ break;
+ start = ++s;
+ while (isdigit(*s) || *s == '.' || *s == '-')
+ s++;
+ c = *s; /* the format char. or \0 */
+ *s = '\0';
+
+ switch (c) {
+ case '\0':
+ break;
+
+ case 'A':
+ case 'a': /* anchor */
+ HTDirEntry(target, tail, entry);
+ sprintf(fmt, "%%%ss", start);
+ sprintf(buf, fmt, entry);
+ PUTS(buf);
+ END(HTML_A);
+#ifdef S_IFLNK
+ if (c != 'A' && (st.st_mode & S_IFMT) == S_IFLNK &&
+ (len = readlink(file, buf, sizeof(buf))) >= 0) {
+ PUTS(" -> ");
+ buf[len] = '\0';
+ PUTS(buf);
+ }
+#endif
+ *buf = '\0';
+ break;
+
+ case 'd': /* date */
+ now = time(0);
+ datestr = ctime(&st.st_mtime);
+ if ((now - st.st_mtime) < SEC_PER_YEAR/2)
+ /*
+ ** MMM DD HH:MM
+ */
+ sprintf(buf, "%.12s", datestr + 4);
+ else
+ /*
+ ** MMM DD YYYY
+ */
+ sprintf(buf, "%.7s %.4s ", datestr + 4,
+ datestr + 20);
+ sprintf(fmt, "%%%ss", start);
+ sprintf(buf, fmt, buf);
+ break;
+
+ case 's': /* size in bytes */
+ sprintf(fmt, "%%%sd", start);
+ sprintf(buf, fmt, st.st_size);
+ break;
+
+ case 'K': /* size in Kilobytes but not for directories */
+ if ((st.st_mode & S_IFMT) == S_IFDIR) {
+ sprintf(fmt, "%%%ss ", start);
+ sprintf(buf, fmt, "");
+ break;
+ }
+ /* FALL THROUGH */
+ case 'k': /* size in Kilobytes */
+ sprintf(fmt, "%%%sdK", start);
+ sprintf(buf, fmt, (st.st_size+1023)/1024);
+ break;
+
+ case 'p': /* unix-style permission bits */
+ switch(st.st_mode & S_IFMT) {
+ case S_IFIFO: type = 'p'; break;
+ case S_IFCHR: type = 'c'; break;
+ case S_IFDIR: type = 'd'; break;
+ case S_IFREG: type = '-'; break;
+#ifdef S_IFBLK
+ case S_IFBLK: type = 'b'; break;
+#endif
+#ifdef S_IFLNK
+ case S_IFLNK: type = 'l'; break;
+#endif
+#ifdef S_IFSOCK
+# ifdef S_IFIFO /* some older machines (e.g., apollo) have a conflict */
+# if S_IFIFO != S_IFSOCK
+ case S_IFSOCK: type = 's'; break;
+# endif
+# else
+ case S_IFSOCK: type = 's'; break;
+# endif
+#endif /* S_IFSOCK */
+ default: type = '?'; break;
+ }
+ sprintf(buf, "%c%s%s%s", type,
+ PBIT(st.st_mode, 6, st.st_mode & S_ISUID),
+ PBIT(st.st_mode, 3, st.st_mode & S_ISGID),
+ PBIT(st.st_mode, 0, 0));
+ sprintf(fmt, "%%%ss", start);
+ sprintf(buf, fmt, buf);
+ break;
+
+ case 'o': /* owner */
+ sprintf(fmt, "%%%ss", start);
+ p = getpwuid(st.st_uid);
+ if (p) {
+ sprintf(fmt, "%%%ss", start);
+ sprintf(buf, fmt, p->pw_name);
+ } else {
+
+ sprintf(fmt, "%%%sd", start);
+ sprintf(buf, fmt, st.st_uid);
+ }
+ break;
+
+ case 'g': /* group */
+ g = getgrgid(st.st_gid);
+ if (g) {
+ sprintf(fmt, "%%%ss", start);
+ sprintf(buf, fmt, g->gr_name);
+ } else {
+ sprintf(fmt, "%%%sd", start);
+ sprintf(buf, fmt, st.st_gid);
+ }
+ break;
+
+ case 'l': /* link count */
+ sprintf(fmt, "%%%sd", start);
+ sprintf(buf, fmt, st.st_nlink);
+ break;
+
+ default:
+ fprintf(stderr,
+ "Unknown format character `%c' in list format\n", c);
+ break;
+ }
+ PUTS(buf);
+
+ s++;
+ }
+ END(HTML_PRE);
+ PUTS("\n");
+ FREE(str);
+}
+#endif /* LONG_LIST */
+
+/* Define the representation associated with a file suffix.
+** --------------------------------------------------------
+**
+** Calling this with suffix set to "*" will set the default
+** representation.
+** Calling this with suffix set to "*.*" will set the default
+** representation for unknown suffix files which contain a ".".
+**
+** The encoding parameter can give a trivial (8bit, 7bit, binary)
+** or real (gzip, compress) encoding.
+**
+** If filename suffix is already defined with the same encoding
+** its previous definition is overridden.
+*/
+PUBLIC void HTSetSuffix5 ARGS5(
+ CONST char *, suffix,
+ CONST char *, representation,
+ CONST char *, encoding,
+ CONST char *, desc,
+ float, value)
+{
+ HTSuffix * suff;
+ BOOL trivial_enc = IsUnityEncStr(encoding);
+
+ if (strcmp(suffix, "*") == 0)
+ suff = &no_suffix;
+ else if (strcmp(suffix, "*.*") == 0)
+ suff = &unknown_suffix;
+ else {
+ HTList *cur = HTSuffixes;
+
+ while (NULL != (suff = (HTSuffix*)HTList_nextObject(cur))) {
+ if (suff->suffix && 0 == strcmp(suff->suffix, suffix) &&
+ ((trivial_enc && IsUnityEnc(suff->encoding)) ||
+ (!trivial_enc && !IsUnityEnc(suff->encoding) &&
+ strcmp(encoding, HTAtom_name(suff->encoding)) == 0)))
+ break;
+ }
+ if (!suff) { /* Not found -- create a new node */
+ suff = (HTSuffix *) calloc(1, sizeof(HTSuffix));
+ if (suff == NULL)
+ outofmem(__FILE__, "HTSetSuffix");
+
+ /*
+ ** Memory leak fixed.
+ ** 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ if (!HTSuffixes) {
+ HTSuffixes = HTList_new();
+ atexit(free_suffixes);
+ }
+
+ HTList_addObject(HTSuffixes, suff);
+
+ StrAllocCopy(suff->suffix, suffix);
+ }
+ }
+
+ if (representation)
+ suff->rep = HTAtom_for(representation);
+
+ /*
+ ** Memory leak fixed.
+ ** 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ ** Invariant code removed.
+ */
+ suff->encoding = HTAtom_for(encoding);
+
+ StrAllocCopy(suff->desc, desc);
+
+ suff->quality = value;
+}
+
+/*
+** Purpose: Free all added suffixes.
+** Arguments: void
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** To be used at program exit.
+** Revision History:
+** 05-28-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void free_suffixes NOARGS
+{
+ HTSuffix * suff = NULL;
+
+ /*
+ ** Loop through all suffixes.
+ */
+ while (!HTList_isEmpty(HTSuffixes)) {
+ /*
+ ** Free off each item and its members if need be.
+ */
+ suff = (HTSuffix *)HTList_removeLastObject(HTSuffixes);
+ FREE(suff->suffix);
+ FREE(suff->desc);
+ FREE(suff);
+ }
+ /*
+ ** Free off the list itself.
+ */
+ HTList_delete(HTSuffixes);
+ HTSuffixes = NULL;
+}
+
+/* Send README file.
+** -----------------
+**
+** If a README file exists, then it is inserted into the document here.
+*/
+#ifdef HAVE_READDIR
+PRIVATE void do_readme ARGS2(HTStructured *, target, CONST char *, localname)
+{
+ FILE * fp;
+ char * readme_file_name =
+ malloc(strlen(localname)+ 1 + strlen(HT_DIR_README_FILE) + 1);
+ if (readme_file_name == NULL)
+ outofmem(__FILE__, "do_readme");
+ strcpy(readme_file_name, localname);
+ strcat(readme_file_name, "/");
+ strcat(readme_file_name, HT_DIR_README_FILE);
+
+ fp = fopen(readme_file_name, "r");
+
+ if (fp) {
+ HTStructuredClass targetClass;
+
+ targetClass = *target->isa; /* (Can't init agregate in K&R) */
+ START(HTML_PRE);
+ for (;;){
+ char c = fgetc(fp);
+ if (c == (char)EOF) break;
+#ifdef NOTDEFINED
+ switch (c) {
+ case '&':
+ case '<':
+ case '>':
+ PUTC('&');
+ PUTC('#');
+ PUTC((char)(c / 10));
+ PUTC((char) (c % 10));
+ PUTC(';');
+ break;
+/* case '\n':
+ PUTC('\r');
+Bug removed thanks to joe@athena.mit.edu */
+ default:
+ PUTC(c);
+ }
+#else
+ PUTC(c);
+#endif /* NOTDEFINED */
+ }
+ END(HTML_PRE);
+ fclose(fp);
+ }
+}
+#endif /* HAVE_READDIR */
+
+/* Make the cache file name for a W3 document.
+** -------------------------------------------
+** Make up a suitable name for saving the node in
+**
+** E.g. /tmp/WWW_Cache_news/1234@cernvax.cern.ch
+** /tmp/WWW_Cache_http/crnvmc/FIND/xx.xxx.xx
+**
+** On exit:
+** Returns a malloc'ed string which must be freed by the caller.
+*/
+PUBLIC char * HTCacheFileName ARGS1(
+ CONST char *, name)
+{
+ char * acc_method = HTParse(name, "", PARSE_ACCESS);
+ char * host = HTParse(name, "", PARSE_HOST);
+ char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
+
+ char * result;
+ result = (char *)malloc(
+ strlen(HTCacheRoot)+strlen(acc_method)
+ +strlen(host)+strlen(path)+6+1);
+ if (result == NULL)
+ outofmem(__FILE__, "HTCacheFileName");
+ sprintf(result, "%s/WWW/%s/%s%s", HTCacheRoot, acc_method, host, path);
+ FREE(path);
+ FREE(acc_method);
+ FREE(host);
+ return result;
+}
+
+/* Open a file for write, creating the path.
+** -----------------------------------------
+*/
+#ifdef NOT_IMPLEMENTED
+PRIVATE int HTCreatePath ARGS1(CONST char *,path)
+{
+ return -1;
+}
+#endif /* NOT_IMPLEMENTED */
+
+/* Convert filenames between local and WWW formats.
+** ------------------------------------------------
+** Make up a suitable name for saving the node in
+**
+** E.g. $(HOME)/WWW/news/1234@cernvax.cern.ch
+** $(HOME)/WWW/http/crnvmc/FIND/xx.xxx.xx
+**
+** On exit:
+** Returns a malloc'ed string which must be freed by the caller.
+*/
+PUBLIC char * HTLocalName ARGS1(
+ CONST char *, name)
+{
+ char * acc_method = HTParse(name, "", PARSE_ACCESS);
+ char * host = HTParse(name, "", PARSE_HOST);
+ char * path = HTParse(name, "", PARSE_PATH+PARSE_PUNCTUATION);
+
+ HTUnEscape(path); /* Interpret % signs */
+
+ if (0 == strcmp(acc_method, "file")) { /* local file */
+ FREE(acc_method);
+ if ((0 == strcasecomp(host, HTHostName())) ||
+ (0 == strcasecomp(host, "localhost")) || !*host) {
+ FREE(host);
+ if (TRACE)
+ fprintf(stderr, "Node `%s' means path `%s'\n", name, path);
+#ifdef DOSPATH
+ {
+ char *ret_path = NULL;
+ StrAllocCopy(ret_path, HTDOS_name(path));
+ if (TRACE) {
+ fprintf(stderr, "HTDOS_name changed `%s' to `%s'\n",
+ path, ret_path);
+ }
+ FREE(path);
+ return(ret_path);
+ }
+#else
+ return(path);
+#endif /* DOSPATH */
+ } else {
+ char * result = (char *)malloc(
+ strlen("/Net/")+strlen(host)+strlen(path)+1);
+ if (result == NULL)
+ outofmem(__FILE__, "HTLocalName");
+ sprintf(result, "%s%s%s", "/Net/", host, path);
+ FREE(host);
+ FREE(path);
+ if (TRACE)
+ fprintf(stderr, "Node `%s' means file `%s'\n", name, result);
+ return result;
+ }
+ } else { /* other access */
+ char * result;
+#ifdef VMS
+ char * home = getenv("HOME");
+ if (!home)
+ home = HTCacheRoot;
+ else
+ home = HTVMS_wwwName(home);
+#else
+ CONST char * home = (CONST char*)getenv("HOME");
+ if (!home)
+ home = "/tmp";
+#endif /* VMS */
+ result = (char *)malloc(
+ strlen(home)+strlen(acc_method)+strlen(host)+strlen(path)+6+1);
+ if (result == NULL)
+ outofmem(__FILE__, "HTLocalName");
+ sprintf(result, "%s/WWW/%s/%s%s", home, acc_method, host, path);
+ FREE(path);
+ FREE(acc_method);
+ FREE(host);
+ return result;
+ }
+}
+
+/* Make a WWW name from a full local path name.
+** --------------------------------------------
+**
+** Bugs:
+** At present, only the names of two network root nodes are hand-coded
+** in and valid for the NeXT only. This should be configurable in
+** the general case.
+*/
+PUBLIC char * WWW_nameOfFile ARGS1(
+ CONST char *, name)
+{
+ char * result;
+#ifdef NeXT
+ if (0 == strncmp("/private/Net/", name, 13)) {
+ result = (char *)malloc(7+strlen(name+13)+1);
+ if (result == NULL)
+ outofmem(__FILE__, "WWW_nameOfFile");
+ sprintf(result, "file://%s", name+13);
+ } else
+#endif /* NeXT */
+ if (0 == strncmp(HTMountRoot, name, 5)) {
+ result = (char *)malloc(7+strlen(name+5)+1);
+ if (result == NULL)
+ outofmem(__FILE__, "WWW_nameOfFile");
+ sprintf(result, "file://%s", name+5);
+ } else {
+ result = (char *)malloc(7+strlen(HTHostName())+strlen(name)+1);
+ if (result == NULL)
+ outofmem(__FILE__, "WWW_nameOfFile");
+ sprintf(result, "file://%s%s", HTHostName(), name);
+ }
+ if (TRACE)
+ fprintf(stderr, "File `%s'\n\tmeans node `%s'\n", name, result);
+ return result;
+}
+
+/* Determine a suitable suffix, given the representation.
+** ------------------------------------------------------
+**
+** On entry,
+** rep is the atomized MIME style representation
+** enc is an encoding, trivial (8bit, binary, etc.) or gzip etc.
+**
+** On exit:
+** Returns a pointer to a suitable suffix string if one has been
+** found, else "".
+*/
+PUBLIC CONST char * HTFileSuffix ARGS2(
+ HTAtom*, rep,
+ CONST char *, enc)
+{
+ HTSuffix * suff;
+#ifdef FNAMES_8_3
+ HTSuffix * first_found = NULL;
+#endif
+ BOOL trivial_enc;
+ int n;
+ int i;
+
+#define NO_INIT /* don't init anymore since I do it in Lynx at startup */
+#ifndef NO_INIT
+ if (!HTSuffixes)
+ HTFileInit();
+#endif /* !NO_INIT */
+
+ trivial_enc = IsUnityEncStr(enc);
+ n = HTList_count(HTSuffixes);
+ for (i = 0; i < n; i++) {
+ suff = (HTSuffix *)HTList_objectAt(HTSuffixes, i);
+ if (suff->rep == rep &&
+#if defined(VMS) || defined(FNAMES_8_3)
+ /* Don't return a suffix whose first char is a dot, and which
+ has more dots or asterisks after that, for
+ these systems - kw */
+ (!suff->suffix || !suff->suffix[0] || suff->suffix[0] != '.' ||
+ (strchr(suff->suffix + 1, '.') == NULL &&
+ strchr(suff->suffix + 1, '*') == NULL)) &&
+#endif
+ ((trivial_enc && IsUnityEnc(suff->encoding)) ||
+ (!trivial_enc && !IsUnityEnc(suff->encoding) &&
+ strcmp(enc, HTAtom_name(suff->encoding)) == 0))) {
+#ifdef FNAMES_8_3
+ if (suff->suffix && (strlen(suff->suffix) <= 4)) {
+ /*
+ * If length of suffix (including dot) is 4 or smaller,
+ * return this one even if we found a longer one
+ * earlier - kw
+ */
+ return suff->suffix;
+ } else if (!first_found) {
+ first_found = suff; /* remember this one */
+ }
+#else
+ return suff->suffix; /* OK -- found */
+#endif
+ }
+ }
+#ifdef FNAMES_8_3
+ if (first_found)
+ return first_found->suffix;
+#endif
+ return ""; /* Dunno */
+}
+
+/* Determine file format from file name.
+** -------------------------------------
+**
+** This version will return the representation and also set
+** a variable for the encoding.
+**
+** Encoding may be a unity encoding (binary, 8bit, etc.) or
+** a content-coding like gzip, compress.
+**
+** It will handle for example x.txt, x.txt,Z, x.Z
+*/
+PUBLIC HTFormat HTFileFormat ARGS3(
+ CONST char *, filename,
+ HTAtom **, pencoding,
+ CONST char**, pdesc)
+{
+ HTSuffix * suff;
+ int n;
+ int i;
+ int lf;
+#ifdef VMS
+ char *semicolon = NULL;
+#endif /* VMS */
+
+ if (pencoding)
+ *pencoding = NULL;
+ if (pdesc)
+ *pdesc = NULL;
+ if (LYforce_HTML_mode) {
+ if (pencoding)
+ *pencoding = WWW_ENC_8BIT;
+ return WWW_HTML;
+ }
+
+#ifdef VMS
+ /*
+ ** Trim at semicolon if a version number was
+ ** included, so it doesn't interfere with the
+ ** code for getting the MIME type. - FM
+ */
+ if ((semicolon = strchr(filename, ';')) != NULL)
+ *semicolon = '\0';
+#endif /* VMS */
+
+#ifndef NO_INIT
+ if (!HTSuffixes)
+ HTFileInit();
+#endif /* !NO_INIT */
+ lf = strlen(filename);
+ n = HTList_count(HTSuffixes);
+ for (i = 0; i < n; i++) {
+ int ls;
+ suff = (HTSuffix *)HTList_objectAt(HTSuffixes, i);
+ ls = strlen(suff->suffix);
+ if ((ls <= lf) && 0 == strcasecomp(suff->suffix, filename + lf - ls)) {
+ int j;
+ if (pencoding)
+ *pencoding = suff->encoding;
+ if (pdesc)
+ *pdesc = suff->desc;
+ if (suff->rep) {
+#ifdef VMS
+ if (semicolon != NULL)
+ *semicolon = ';';
+#endif /* VMS */
+ return suff->rep; /* OK -- found */
+ }
+ for (j = 0; j < n; j++) { /* Got encoding, need representation */
+ int ls2;
+ suff = (HTSuffix *)HTList_objectAt(HTSuffixes, j);
+ ls2 = strlen(suff->suffix);
+ if ((ls + ls2 <= lf) && 0 == strncasecomp(
+ suff->suffix, filename + lf - ls -ls2, ls2)) {
+ if (suff->rep) {
+ if (pdesc && !(*pdesc))
+ *pdesc = suff->desc;
+#ifdef VMS
+ if (semicolon != NULL)
+ *semicolon = ';';
+#endif /* VMS */
+ return suff->rep;
+ }
+ }
+ }
+
+ }
+ }
+
+ /* defaults tree */
+
+ suff = strchr(filename, '.') ? /* Unknown suffix */
+ ( unknown_suffix.rep ? &unknown_suffix : &no_suffix)
+ : &no_suffix;
+
+ /*
+ ** Set default encoding unless found with suffix already.
+ */
+ if (pencoding && !*pencoding)
+ *pencoding = suff->encoding ? suff->encoding
+ : HTAtom_for("binary");
+#ifdef VMS
+ if (semicolon != NULL)
+ *semicolon = ';';
+#endif /* VMS */
+ return suff->rep ? suff->rep : WWW_BINARY;
+}
+
+/* Revise the file format in relation to the Lynx charset. - FM
+** -------------------------------------------------------
+**
+** This checks the format associated with an anchor for
+** an extended MIME Content-Type, and if a charset is
+** indicated, sets Lynx up for proper handling in relation
+** to the currently selected character set. - FM
+*/
+PUBLIC HTFormat HTCharsetFormat ARGS3(
+ HTFormat, format,
+ HTParentAnchor *, anchor,
+ int, default_LYhndl)
+{
+ char *cp = NULL, *cp1, *cp2, *cp3 = NULL, *cp4;
+ BOOL chartrans_ok = FALSE;
+ int chndl = -1;
+ int i;
+
+ FREE(anchor->charset);
+ StrAllocCopy(cp, format->name);
+ for (i = 0; cp[i]; i++)
+ cp[i] = TOLOWER(cp[i]);
+ if (((cp1 = strchr(cp, ';')) != NULL) &&
+ (cp2 = strstr(cp1, "charset")) != NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTCharsetFormat: Extended MIME Content-Type is %s\n",
+ format->name);
+ cp2 += 7;
+ while (*cp2 == ' ' || *cp2 == '=')
+ cp2++;
+ StrAllocCopy(cp3, cp2); /* copy to mutilate more */
+ for (cp4 = cp3; (*cp4 != '\0' && *cp4 != '"' &&
+ *cp4 != ';' && *cp4 != ':' &&
+ !WHITE(*cp4)); cp4++) {
+ ; /* do nothing */
+ }
+ *cp4 = '\0';
+ cp4 = cp3;
+ chndl = UCGetLYhndl_byMIME(cp3);
+ if (UCCanTranslateFromTo(chndl, current_char_set)) {
+ chartrans_ok = YES;
+ *cp1 = '\0';
+ format = HTAtom_for(cp);
+ StrAllocCopy(anchor->charset, cp4);
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_MIME,
+ UCT_SETBY_MIME);
+ } else if (chndl < 0) {
+ /*
+ ** Got something but we don't recognize it.
+ */
+ chndl = UCLYhndl_for_unrec;
+ if (UCCanTranslateFromTo(chndl, current_char_set)) {
+ chartrans_ok = YES;
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ }
+ }
+ if (chartrans_ok) {
+ LYUCcharset *p_in = HTAnchor_getUCInfoStage(anchor,
+ UCT_STAGE_MIME);
+ LYUCcharset *p_out = HTAnchor_setUCInfoStage(anchor,
+ current_char_set,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ if (!p_out) {
+ /*
+ ** Try again.
+ */
+ p_out = HTAnchor_getUCInfoStage(anchor, UCT_STAGE_HTEXT);
+ }
+ if (!strcmp(p_in->MIMEname, "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(anchor,
+ HTAnchor_getUCLYhndl(anchor,
+ UCT_STAGE_HTEXT),
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ }
+ if (!strcmp(p_out->MIMEname, "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(anchor,
+ HTAnchor_getUCLYhndl(anchor,
+ UCT_STAGE_MIME),
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ }
+ if (p_in->enc != UCT_ENC_CJK) {
+ HTCJK = NOCJK;
+ if (!(p_in->codepoints &
+ UCT_CP_SUBSETOF_LAT1) &&
+ chndl == current_char_set) {
+ HTPassEightBitRaw = TRUE;
+ }
+ } else if (p_out->enc == UCT_ENC_CJK) {
+ if (LYRawMode) {
+ if ((!strcmp(p_in->MIMEname, "euc-jp") ||
+ !strcmp(p_in->MIMEname, "shift_jis")) &&
+ (!strcmp(p_out->MIMEname, "euc-jp") ||
+ !strcmp(p_out->MIMEname, "shift_jis"))) {
+ HTCJK = JAPANESE;
+ } else if (!strcmp(p_in->MIMEname, "euc-cn") &&
+ !strcmp(p_out->MIMEname, "euc-cn")) {
+ HTCJK = CHINESE;
+ } else if (!strcmp(p_in->MIMEname, "big-5") &&
+ !strcmp(p_out->MIMEname, "big-5")) {
+ HTCJK = TAIPEI;
+ } else if (!strcmp(p_in->MIMEname, "euc-kr") &&
+ !strcmp(p_out->MIMEname, "euc-kr")) {
+ HTCJK = KOREAN;
+ } else {
+ HTCJK = NOCJK;
+ }
+ } else {
+ HTCJK = NOCJK;
+ }
+ }
+ /*
+ ** Check for an iso-8859-# we don't know. - FM
+ */
+ } else if (!strncmp(cp4, "iso-8859-", 9) &&
+ isdigit((unsigned char)cp4[9]) &&
+ !strncmp(LYchar_set_names[current_char_set],
+ "Other ISO Latin", 15)) {
+ /*
+ ** Hope it's a match, for now. - FM
+ */
+ *cp1 = '\0';
+ format = HTAtom_for(cp);
+ cp1 = &cp4[10];
+ while (*cp1 &&
+ isdigit((unsigned char)(*cp1)))
+ cp1++;
+ *cp1 = '\0';
+ StrAllocCopy(anchor->charset, cp4);
+ HTPassEightBitRaw = TRUE;
+ HTAlert(anchor->charset);
+ }
+ FREE(cp3);
+ } else if (cp1 != NULL) {
+ /*
+ ** No charset parameter is present.
+ ** Ignore all other parameters, as
+ ** we do when charset is present. - FM
+ */
+ *cp1 = '\0';
+ format = HTAtom_for(cp);
+ }
+ FREE(cp);
+
+ /*
+ ** Set up defaults, if needed. - FM
+ */
+ if (!chartrans_ok && !anchor->charset && default_LYhndl >= 0) {
+ HTAnchor_setUCInfoStage(anchor, default_LYhndl,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ }
+ HTAnchor_copyUCInfoStage(anchor,
+ UCT_STAGE_PARSER,
+ UCT_STAGE_MIME,
+ -1);
+
+ return format;
+}
+
+/* Determine value from file name.
+** -------------------------------
+**
+*/
+PUBLIC float HTFileValue ARGS1(
+ CONST char *, filename)
+{
+ HTSuffix * suff;
+ int n;
+ int i;
+ int lf = strlen(filename);
+
+#ifndef NO_INIT
+ if (!HTSuffixes)
+ HTFileInit();
+#endif /* !NO_INIT */
+ n = HTList_count(HTSuffixes);
+ for (i = 0; i < n; i++) {
+ int ls;
+ suff = (HTSuffix *)HTList_objectAt(HTSuffixes, i);
+ ls = strlen(suff->suffix);
+ if ((ls <= lf) && 0==strcmp(suff->suffix, filename + lf - ls)) {
+ if (TRACE)
+ fprintf(stderr, "File: Value of %s is %.3f\n",
+ filename, suff->quality);
+ return suff->quality; /* OK -- found */
+ }
+ }
+ return 0.3; /* Dunno! */
+}
+
+/* Determine write access to a file.
+** ---------------------------------
+**
+** On exit:
+** Returns YES if file can be accessed and can be written to.
+**
+** Bugs:
+** 1. No code for non-unix systems.
+** 2. Isn't there a quicker way?
+*/
+
+#if defined(HAVE_CONFIG_H)
+
+#ifndef HAVE_GETGROUPS
+#define NO_GROUPS
+#endif
+
+#else
+
+#ifdef VMS
+#define NO_GROUPS
+#endif /* VMS */
+#ifdef NO_UNIX_IO
+#define NO_GROUPS
+#endif /* NO_UNIX_IO */
+#ifdef PCNFS
+#define NO_GROUPS
+#endif /* PCNFS */
+#ifdef NOUSERS
+#define NO_GROUPS
+#endif /* PCNFS */
+
+#endif /* HAVE_CONFIG_H */
+
+PUBLIC BOOL HTEditable ARGS1(
+ CONST char *, filename)
+{
+#ifdef NO_GROUPS
+ return NO; /* Safe answer till we find the correct algorithm */
+#else
+#ifdef NeXT
+ int groups[NGROUPS];
+#else
+ gid_t groups[NGROUPS];
+#endif /* NeXT */
+ uid_t myUid;
+ int ngroups; /* The number of groups */
+ struct stat fileStatus;
+ int i;
+
+ if (stat(filename, &fileStatus)) /* Get details of filename */
+ return NO; /* Can't even access file! */
+
+ ngroups = getgroups(NGROUPS, groups); /* Groups to which I belong */
+ myUid = geteuid(); /* Get my user identifier */
+
+ if (TRACE) {
+ int i2;
+ fprintf(stderr,
+ "File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (",
+ (unsigned int) fileStatus.st_mode, fileStatus.st_uid,
+ fileStatus.st_gid,
+ myUid, ngroups);
+ for (i2 = 0; i2 < ngroups; i2++)
+ fprintf(stderr, " %d", groups[i2]);
+ fprintf(stderr, ")\n");
+ }
+
+ if (fileStatus.st_mode & 0002) /* I can write anyway? */
+ return YES;
+
+ if ((fileStatus.st_mode & 0200) /* I can write my own file? */
+ && (fileStatus.st_uid == myUid))
+ return YES;
+
+ if (fileStatus.st_mode & 0020) /* Group I am in can write? */
+ {
+ for (i = 0; i < ngroups; i++) {
+ if (groups[i] == fileStatus.st_gid)
+ return YES;
+ }
+ }
+ if (TRACE)
+ fprintf(stderr, "\tFile is not editable.\n");
+ return NO; /* If no excuse, can't do */
+#endif /* NO_GROUPS */
+}
+
+/* Make a save stream.
+** -------------------
+**
+** The stream must be used for writing back the file.
+** @@@ no backup done
+*/
+PUBLIC HTStream * HTFileSaveStream ARGS1(
+ HTParentAnchor *, anchor)
+{
+ CONST char * addr = HTAnchor_address((HTAnchor*)anchor);
+ char * localname = HTLocalName(addr);
+
+ FILE* fp = fopen(localname, "w");
+ if (!fp)
+ return NULL;
+
+ return HTFWriter_new(fp);
+}
+
+/* Output one directory entry.
+** ---------------------------
+*/
+PUBLIC void HTDirEntry ARGS3(
+ HTStructured *, target,
+ CONST char *, tail,
+ CONST char *, entry)
+{
+ char * relative = NULL;
+ char * escaped = NULL;
+ int len;
+
+ if (0 == strcmp(entry,"../")) {
+ /*
+ ** Undo slash appending for anchor creation.
+ */
+ StrAllocCopy(escaped,"..");
+ } else {
+ escaped = HTEscape(entry, URL_XPALPHAS);
+ if (((len = strlen(escaped)) > 2) &&
+ escaped[(len - 3)] == '%' &&
+ escaped[(len - 2)] == '2' &&
+ TOUPPER(escaped[(len - 1)]) == 'F') {
+ escaped[(len - 3)] = '\0';
+ }
+ }
+
+ if (tail == NULL || *tail == '\0') {
+ /*
+ ** Handle extra slash at end of path.
+ */
+ HTStartAnchor(target, NULL, (escaped[0] != '\0' ? escaped : "/"));
+ } else {
+ /*
+ ** If empty tail, gives absolute ref below.
+ */
+ relative = (char*)malloc(strlen(tail) + strlen(escaped)+2);
+ if (relative == NULL)
+ outofmem(__FILE__, "HTDirEntry");
+ sprintf(relative, "%s%s%s",
+ tail,
+ (*escaped != '\0' ? "/" : ""),
+ escaped);
+ HTStartAnchor(target, NULL, relative);
+ FREE(relative);
+ }
+ FREE(escaped);
+}
+
+/* Output parent directory entry.
+** ------------------------------
+**
+** This gives the TITLE and H1 header, and also a link
+** to the parent directory if appropriate.
+**
+** On exit:
+** Returns TRUE if an "Up to <parent>" link was not created
+** for a readable local directory because LONG_LIST is defined
+** and NO_PARENT_DIR_REFERENCE is not defined, such that the
+** calling function use LYListFmtParse() to create a link to
+** the parent directory. Otherwise, it returns FALSE. - FM
+*/
+PUBLIC BOOL HTDirTitles ARGS3(
+ HTStructured *, target,
+ HTAnchor *, anchor,
+ BOOL, tildeIsTop)
+{
+ char * logical = HTAnchor_address(anchor);
+ char * path = HTParse(logical, "", PARSE_PATH + PARSE_PUNCTUATION);
+ char * current;
+ char * cp = NULL;
+ BOOL need_parent_link = FALSE;
+ int i;
+
+#ifdef DOSPATH
+ BOOL local_link = FALSE;
+ if (logical[18] == ':') local_link = TRUE;
+#endif
+ /*
+ ** Check tildeIsTop for treating home directory as Welcome
+ ** (assume the tilde is not followed by a username). - FM
+ */
+ if (tildeIsTop && !strncmp(path, "/~", 2)) {
+ if (path[2] == '\0') {
+ path[1] = '\0';
+ } else {
+ for (i = 0; path[(i + 2)]; i++) {
+ path[i] = path[(i + 2)];
+ }
+ path[i] = '\0';
+ }
+ }
+
+ /*
+ ** Trim out the ;type= parameter, if present. - FM
+ */
+ if ((cp = strrchr(path, ';')) != NULL) {
+ if (!strncasecomp((cp+1), "type=", 5)) {
+ if (TOUPPER(*(cp+6)) == 'D' ||
+ TOUPPER(*(cp+6)) == 'A' ||
+ TOUPPER(*(cp+6)) == 'I')
+ *cp = '\0';
+ }
+ cp = NULL;
+ }
+ current = strrchr(path, '/'); /* last part or "" */
+
+ {
+ char * printable = NULL;
+
+#ifdef DIRED_SUPPORT
+ if (0 == strncasecomp(path, "/%2F", 4))
+ StrAllocCopy(printable, (path+1));
+ else
+ StrAllocCopy(printable, path);
+ if (0 == strncasecomp(printable, "/vmsysu%2b", 10) ||
+ 0 == strncasecomp(printable, "/anonymou.", 10)) {
+ StrAllocCopy(cp, (printable+1));
+ StrAllocCopy(printable, cp);
+ FREE(cp);
+ }
+#else
+ StrAllocCopy(printable, (current ? current + 1 : ""));
+#endif /* DIRED_SUPPORT */
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ HTUnEscape(printable);
+ START(HTML_TITLE);
+ PUTS(*printable ? printable : "Welcome");
+ PUTS(" directory");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+
+#ifdef DIRED_SUPPORT
+ START(HTML_H2);
+ PUTS(*printable ? "Current directory is " : "");
+ PUTS(*printable ? printable : "Welcome");
+ END(HTML_H2);
+ PUTS("\n");
+#else
+ START(HTML_H1);
+ PUTS(*printable ? printable : "Welcome");
+ END(HTML_H1);
+ PUTS("\n");
+#endif /* DIRED_SUPPORT */
+ if (((0 == strncasecomp(printable, "vmsysu:", 7)) &&
+ (cp = strchr(printable, '.')) != NULL &&
+ strchr(cp, '/') == NULL) ||
+ (0 == strncasecomp(printable, "anonymou.", 9) &&
+ strchr(printable, '/') == NULL)) {
+ FREE(printable);
+ FREE(logical);
+ FREE(path);
+ return(need_parent_link);
+ }
+ FREE(printable);
+ }
+
+#ifndef NO_PARENT_DIR_REFERENCE
+ /*
+ ** Make link back to parent directory.
+ */
+ if (current && current[1]) { /* was a slash AND something else too */
+ char * parent = NULL;
+ char * relative = NULL;
+
+ *current++ = '\0';
+ parent = strrchr(path, '/'); /* penultimate slash */
+
+ if ((parent &&
+ (!strcmp(parent, "/..") ||
+ !strncasecomp(parent, "/%2F", 4))) ||
+ !strncasecomp(current, "%2F", 3)) {
+ FREE(logical);
+ FREE(path);
+ return(need_parent_link);
+ }
+
+ relative = (char*) malloc(strlen(current) + 4);
+ if (relative == NULL)
+ outofmem(__FILE__, "HTDirTitles");
+ sprintf(relative, "%s/..", current);
+
+#ifdef DOSPATH
+ if (local_link)
+ if (strlen(parent) == 3 )
+ StrAllocCat(relative, "/.");
+#endif
+
+#if !defined (VMS)
+#ifdef DOSPATH
+ if(!local_link)
+#endif
+ {
+ /*
+ ** On Unix, if it's not ftp and the directory cannot
+ ** be read, don't put out a link.
+ **
+ ** On VMS, this problem is dealt with internally by
+ ** HTVMSBrowseDir().
+ */
+ DIR * dp = NULL;
+
+ if (LYisLocalFile(logical)) {
+ /*
+ ** We need an absolute file path for the opendir.
+ ** We also need to unescape for this test.
+ ** Don't worry about %2F now, they presumably have been
+ ** dealt with above, and shouldn't appear for local
+ ** files anyway... Assume OS / filesystem will just
+ ** ignore superfluous slashes. - KW
+ */
+ char * fullparentpath = NULL;
+
+ /*
+ ** Path has been shortened above.
+ */
+ StrAllocCopy(fullparentpath, *path ? path : "/");
+
+ /*
+ ** Guard against weirdness.
+ */
+ if (0 == strcmp(current,"..")) {
+ StrAllocCat(fullparentpath,"/../..");
+ } else if (0 == strcmp(current,".")) {
+ StrAllocCat(fullparentpath,"/..");
+ }
+
+ HTUnEscape(fullparentpath);
+ if ((dp = opendir(fullparentpath)) == NULL) {
+ FREE(fullparentpath);
+ FREE(logical);
+ FREE(relative);
+ FREE(path);
+ return(need_parent_link);
+ }
+ closedir(dp);
+ FREE(fullparentpath);
+#ifdef LONG_LIST
+ need_parent_link = TRUE;
+ FREE(logical);
+ FREE(path);
+ FREE(relative);
+ return(need_parent_link);
+#endif /* LONG_LIST */
+ }
+ }
+#endif /* !VMS */
+ HTStartAnchor(target, "", relative);
+ FREE(relative);
+
+ PUTS("Up to ");
+ if (parent) {
+ if ((0 == strcmp(current,".")) ||
+ (0 == strcmp(current,".."))) {
+ /*
+ ** Should not happen, but if it does,
+ ** at least avoid giving misleading info. - KW
+ */
+ PUTS("..");
+ } else {
+ char * printable = NULL;
+ StrAllocCopy(printable, parent + 1);
+ HTUnEscape(printable);
+ PUTS(printable);
+ FREE(printable);
+ }
+ } else {
+ PUTS("/");
+ }
+ END(HTML_A);
+ }
+#endif /* !NO_PARENT_DIR_REFERENCE */
+
+ FREE(logical);
+ FREE(path);
+ return(need_parent_link);
+}
+
+/* Load a document.
+** ----------------
+**
+** On entry:
+** addr must point to the fully qualified hypertext reference.
+** This is the physical address of the file
+**
+** On exit:
+** returns <0 Error has occurred.
+** HTLOADED OK
+**
+*/
+PUBLIC int HTLoadFile ARGS4(
+ CONST char *, addr,
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream *, sink)
+{
+ char * filename = NULL;
+ char * acc_method = NULL;
+ HTFormat format;
+ char * nodename = NULL;
+ char * newname = NULL; /* Simplified name of file */
+ HTAtom * encoding; /* @@ not used yet */
+ HTAtom * myEncoding = NULL; /* enc of this file, may be gzip etc. */
+ int status;
+#ifdef VMS
+ struct stat stat_info;
+#endif /* VMS */
+#ifdef USE_ZLIB
+ gzFile gzfp = 0;
+ BOOL use_gzread = NO;
+#endif /* USE_ZLIB */
+
+ /*
+ ** Reduce the filename to a basic form (hopefully unique!).
+ */
+ StrAllocCopy(newname, addr);
+ filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION);
+ nodename=HTParse(newname, "", PARSE_HOST);
+
+ /*
+ ** If access is ftp, or file is on another host, invoke ftp now.
+ */
+ acc_method = HTParse(newname, "", PARSE_ACCESS);
+ if (strcmp("ftp", acc_method) == 0 ||
+ (strcmp("localhost", nodename) != 0 &&
+#ifdef VMS
+ strcasecomp(nodename, HTHostName()) != 0
+#else
+ strcmp(nodename, HTHostName()) != 0
+#endif /* VMS */
+ )) {
+ FREE(newname);
+ FREE(filename);
+ FREE(nodename);
+ FREE(acc_method);
+ return HTFTPLoad(addr, anchor, format_out, sink);
+ } else {
+ FREE(newname);
+ FREE(acc_method);
+ }
+#ifdef VMS
+ HTUnEscape(filename);
+#endif /* VMS */
+
+ /*
+ ** Determine the format and encoding mapped to any suffix.
+ */
+ if (anchor->content_type && anchor->content_encoding) {
+ /*
+ * If content_type and content_encoding are BOTH already set
+ * in the anchor object, we believe it and don't try to
+ * derive format and encoding from the filename. - kw
+ */
+ format = HTAtom_for(anchor->content_type);
+ myEncoding = HTAtom_for(anchor->content_encoding);
+ } else {
+ format = HTFileFormat(filename, &myEncoding, NULL);
+
+ /*
+ ** Check the format for an extended MIME charset value, and
+ ** act on it if present. Otherwise, assume what is indicated
+ ** by the last parameter (fallback will effectively be
+ ** UCLYhndl_for_unspec, by default ISO-8859-1). - kw
+ */
+ format = HTCharsetFormat(format, anchor, UCLYhndl_HTFile_for_unspec);
+ }
+
+#ifdef VMS
+ /*
+ ** Check to see if the 'filename' is in fact a directory. If it is
+ ** create a new hypertext object containing a list of files and
+ ** subdirectories contained in the directory. All of these are links
+ ** to the directories or files listed.
+ */
+ if (HTStat(filename, &stat_info) == -1) {
+ if (TRACE)
+ fprintf(stderr, "HTLoadFile: Can't stat %s\n", filename);
+ } else {
+ if (((stat_info.st_mode) & S_IFMT) == S_IFDIR) {
+ if (HTDirAccess == HT_DIR_FORBID) {
+ FREE(filename);
+ FREE(nodename);
+ return HTLoadError(sink, 403,
+ "Directory browsing is not allowed.");
+ }
+
+ if (HTDirAccess == HT_DIR_SELECTIVE) {
+ char * enable_file_name =
+ malloc(strlen(filename)+ 1 +
+ strlen(HT_DIR_ENABLE_FILE) + 1);
+ if (enable_file_name == NULL)
+ outofmem(__FILE__, "HTLoadFile");
+ strcpy(enable_file_name, filename);
+ strcat(enable_file_name, "/");
+ strcat(enable_file_name, HT_DIR_ENABLE_FILE);
+ if (HTStat(enable_file_name, &stat_info) == -1) {
+ FREE(filename);
+ FREE(nodename);
+ return HTLoadError(sink, 403,
+ "Selective access is not enabled for this directory");
+ }
+ }
+
+ FREE(filename);
+ FREE(nodename);
+ return HTVMSBrowseDir(addr, anchor, format_out, sink);
+ }
+ }
+
+ /*
+ ** Assume that the file is in Unix-style syntax if it contains a '/'
+ ** after the leading one. @@
+ */
+ {
+ FILE * fp;
+ char * vmsname = strchr(filename + 1, '/') ?
+ HTVMS_name(nodename, filename) : filename + 1;
+ fp = fopen(vmsname, "r", "shr=put", "shr=upd");
+
+ /*
+ ** If the file wasn't VMS syntax, then perhaps it is Ultrix.
+ */
+ if (!fp) {
+ char ultrixname[INFINITY];
+ if (TRACE)
+ fprintf(stderr, "HTLoadFile: Can't open as %s\n", vmsname);
+ sprintf(ultrixname, "%s::\"%s\"", nodename, filename);
+ fp = fopen(ultrixname, "r", "shr=put", "shr=upd");
+ if (!fp) {
+ if (TRACE)
+ fprintf(stderr, "HTLoadFile: Can't open as %s\n",
+ ultrixname);
+ }
+ }
+ if (fp) {
+ int len;
+ char *cp = NULL;
+ char *semicolon = NULL;
+
+ if (HTEditable(vmsname)) {
+ HTAtom * put = HTAtom_for("PUT");
+ HTList * methods = HTAnchor_methods(anchor);
+ if (HTList_indexOf(methods, put) == (-1)) {
+ HTList_addObject(methods, put);
+ }
+ }
+ /*
+ ** Trim vmsname at semicolon if a version number was
+ ** included, so it doesn't interfere with the check
+ ** for a compressed file. - FM
+ */
+ if ((semicolon = strchr(vmsname, ';')) != NULL)
+ *semicolon = '\0';
+ /*
+ ** Fake a Content-Encoding for compressed files. - FM
+ */
+ if (!IsUnityEnc(myEncoding)) {
+ /*
+ * We already know from the call to HTFileFormat above
+ * that this is a compressed file, no need to look at
+ * the filename again. - kw
+ */
+#ifdef USE_ZLIB
+ if (strcmp(format_out->name, "www/download") != 0 &&
+ (!strcmp(HTAtom_name(myEncoding), "gzip") ||
+ !strcmp(HTAtom_name(myEncoding), "x-gzip"))) {
+ fclose(fp);
+ if (semicolon != NULL)
+ *semicolon = ';';
+ gzfp = gzopen(vmsname, "rb");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadFile: gzopen of `%s' gives %p\n",
+ vmsname, (void*)gzfp);
+ use_gzread = YES;
+ } else
+#endif /* USE_ZLIB */
+ {
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding));
+ format = HTAtom_for("www/compressed");
+ }
+ } else if ((len = strlen(vmsname)) > 2) {
+ if ((vmsname[len - 1] == 'Z') &&
+ (vmsname[len - 2] == '.' ||
+ vmsname[len - 2] == '-' ||
+ vmsname[len - 2] == '_') &&
+ vmsname[len - 3] != ']' &&
+ vmsname[len - 3] != ':') {
+ StrAllocCopy(cp, vmsname);
+ cp[len - 2] = '\0';
+ format = HTFileFormat(cp, &encoding, NULL);
+ FREE(cp);
+ format = HTCharsetFormat(format, anchor,
+ UCLYhndl_HTFile_for_unspec);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-compress");
+ format = HTAtom_for("www/compressed");
+ } else if ((len > 3) &&
+ !strcasecomp((char *)&vmsname[len - 2], "gz")) {
+ if (vmsname[len - 3] == '.' ||
+ vmsname[len - 3] == '-' ||
+ vmsname[len - 3] == '_') {
+ StrAllocCopy(cp, vmsname);
+ cp[len - 3] = '\0';
+ format = HTFileFormat(cp, &encoding, NULL);
+ FREE(cp);
+ format = HTCharsetFormat(format, anchor,
+ UCLYhndl_HTFile_for_unspec);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-gzip");
+#ifdef USE_ZLIB
+ if (strcmp(format_out->name, "www/download") != 0) {
+ fclose(fp);
+ if (semicolon != NULL)
+ *semicolon = ';';
+ gzfp = gzopen(vmsname, "rb");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadFile: gzopen of `%s' gives %p\n",
+ vmsname, (void*)gzfp);
+ use_gzread = YES;
+ }
+#else /* USE_ZLIB */
+ format = HTAtom_for("www/compressed");
+#endif /* USE_ZLIB */
+ }
+ }
+ }
+ if (semicolon != NULL)
+ *semicolon = ';';
+ FREE(filename);
+ FREE(nodename);
+#ifdef USE_ZLIB
+ if (use_gzread) {
+ if (gzfp) {
+ char * sugfname = NULL;
+ if (anchor->SugFname) {
+ StrAllocCopy(sugfname, anchor->SugFname);
+ } else {
+ char * anchor_path = HTParse(anchor->address, "",
+ PARSE_PATH + PARSE_PUNCTUATION);
+ char * lastslash;
+ HTUnEscape(anchor_path);
+ lastslash = strrchr(anchor_path, '/');
+ if (lastslash)
+ StrAllocCopy(sugfname, lastslash + 1);
+ FREE(anchor_path);
+ }
+ FREE(anchor->content_encoding);
+ if (sugfname && *sugfname)
+ HTCheckFnameForCompression(&sugfname, anchor,
+ TRUE);
+ if (sugfname && *sugfname)
+ StrAllocCopy(anchor->SugFname, sugfname);
+ FREE(sugfname);
+ status = HTParseGzFile(format, format_out,
+ anchor,
+ gzfp, sink);
+ } else {
+ status = HTLoadError(NULL,
+ -(HT_ERROR),
+ "Could not open file for decompression!");
+ }
+ } else
+#endif /* USE_ZLIB */
+ {
+ status = HTParseFile(format, format_out, anchor, fp, sink);
+ fclose(fp);
+ }
+ return status;
+ } /* If successful open */
+ FREE(filename);
+ }
+
+#else /* Unix: */
+
+ FREE(filename);
+
+ /*
+ ** For unix, we try to translate the name into the name of a
+ ** transparently mounted file.
+ **
+ ** Not allowed in secure (HTClienntHost) situations. TBL 921019
+ */
+#ifndef NO_UNIX_IO
+ /* Need protection here for telnet server but not httpd server. */
+
+ if (!HTSecure) { /* try local file system */
+ char * localname = HTLocalName(addr);
+ struct stat dir_info;
+
+#ifdef HAVE_READDIR
+ /*
+ ** Multiformat handling.
+ **
+ ** If needed, scan directory to find a good file.
+ ** Bug: We don't stat the file to find the length.
+ */
+ if ((strlen(localname) > strlen(MULTI_SUFFIX)) &&
+ (0 == strcmp(localname + strlen(localname) - strlen(MULTI_SUFFIX),
+ MULTI_SUFFIX))) {
+ DIR *dp;
+ BOOL forget_multi = NO;
+
+ STRUCT_DIRENT * dirbuf;
+ float best = NO_VALUE_FOUND; /* So far best is bad */
+ HTFormat best_rep = NULL; /* Set when rep found */
+ HTAtom * best_enc = NULL;
+ char * best_name = NULL; /* Best dir entry so far */
+
+ char *base = strrchr(localname, '/');
+ int baselen = 0;
+
+ if (!base || base == localname) {
+ forget_multi = YES;
+ } else {
+ *base++ = '\0'; /* Just got directory name */
+ baselen = strlen(base)- strlen(MULTI_SUFFIX);
+ base[baselen] = '\0'; /* Chop off suffix */
+
+ dp = opendir(localname);
+ }
+ if (forget_multi || !dp) {
+ FREE(localname);
+ FREE(nodename);
+ return HTLoadError(sink, 500,
+ "Multiformat: directory scan failed.");
+ }
+
+ while ((dirbuf = readdir(dp)) != NULL) {
+ /*
+ ** While there are directory entries to be read...
+ */
+#ifndef DOSPATH
+ if (dirbuf->d_ino == 0)
+ continue; /* if the entry is not being used, skip it */
+#endif
+ if ((int)strlen(dirbuf->d_name) > baselen && /* Match? */
+ !strncmp(dirbuf->d_name, base, baselen)) {
+ HTAtom * enc;
+ HTFormat rep = HTFileFormat(dirbuf->d_name, &enc, NULL);
+ float filevalue = HTFileValue(dirbuf->d_name);
+ float value = HTStackValue(rep, format_out,
+ filevalue,
+ 0L /* @@@@@@ */);
+ if (value <= 0.0) {
+ char * cp = NULL;
+ int len = strlen(dirbuf->d_name);
+ enc = NULL;
+ if (len > 2 &&
+ dirbuf->d_name[len - 1] == 'Z' &&
+ dirbuf->d_name[len - 2] == '.') {
+ StrAllocCopy(cp, dirbuf->d_name);
+ cp[len - 2] = '\0';
+ format = HTFileFormat(cp, NULL, NULL);
+ FREE(cp);
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ if (value <= 0.0) {
+ format = HTAtom_for("application/x-compressed");
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ }
+ if (value <= 0.0) {
+ format = HTAtom_for("www/compressed");
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ }
+ } else if ((len > 3) &&
+ !strcasecomp((char *)&dirbuf->d_name[len - 2],
+ "gz") &&
+ dirbuf->d_name[len - 3] == '.') {
+ StrAllocCopy(cp, dirbuf->d_name);
+ cp[len - 3] = '\0';
+ format = HTFileFormat(cp, NULL, NULL);
+ FREE(cp);
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ if (value <= 0.0) {
+ format = HTAtom_for("application/x-gzip");
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ }
+ if (value <= 0.0) {
+ format = HTAtom_for("www/compressed");
+ value = HTStackValue(format, format_out,
+ filevalue, 0);
+ }
+ }
+ }
+ if (value != NO_VALUE_FOUND) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadFile: value of presenting %s is %f\n",
+ HTAtom_name(rep), value);
+ if (value > best) {
+ best_rep = rep;
+ best_enc = enc;
+ best = value;
+ StrAllocCopy(best_name, dirbuf->d_name);
+ }
+ } /* if best so far */
+ } /* if match */
+
+ } /* end while directory entries left to read */
+ closedir(dp);
+
+ if (best_rep) {
+ format = best_rep;
+ myEncoding = best_enc;
+ base[-1] = '/'; /* Restore directory name */
+ base[0] = '\0';
+ StrAllocCat(localname, best_name);
+ FREE(best_name);
+ } else { /* If not found suitable file */
+ FREE(localname);
+ FREE(nodename);
+ return HTLoadError(sink, 403, /* List formats? */
+ "Could not find suitable representation for transmission.");
+ }
+ /*NOTREACHED*/
+ } /* if multi suffix */
+
+ /*
+ ** Check to see if the 'localname' is in fact a directory. If it
+ ** is create a new hypertext object containing a list of files and
+ ** subdirectories contained in the directory. All of these are
+ ** links to the directories or files listed.
+ ** NB This assumes the existence of a type 'STRUCT_DIRENT', which
+ ** will hold the directory entry, and a type 'DIR' which is used
+ ** to point to the current directory being read.
+ */
+#ifdef _WINDOWS
+ if (!exists(localname))
+#else
+ if (stat(localname,&dir_info) == -1) /* get file information */
+#endif
+ {
+ /* if can't read file information */
+ if (TRACE)
+ fprintf(stderr, "HTLoadFile: can't stat %s\n", localname);
+
+ } else { /* Stat was OK */
+
+#ifdef _WINDOWS
+ if (stat(localname,&dir_info) == -1) dir_info.st_mode = S_IFDIR;
+#endif
+
+ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR) {
+ /*
+ ** If localname is a directory.
+ */
+ HTStructured *target; /* HTML object */
+ HTStructuredClass targetClass;
+ DIR *dp;
+ STRUCT_DIRENT * dirbuf;
+ char *logical = NULL;
+ char *pathname = NULL;
+ char *tail = NULL;
+ BOOL present[HTML_A_ATTRIBUTES];
+ char * tmpfilename = NULL;
+ BOOL need_parent_link = FALSE;
+ struct stat file_info;
+
+ if (TRACE)
+ fprintf(stderr, "%s is a directory\n", localname);
+
+ /*
+ ** Check directory access.
+ ** Selective access means only those directories containing
+ ** a marker file can be browsed.
+ */
+ if (HTDirAccess == HT_DIR_FORBID) {
+ FREE(localname);
+ FREE(nodename);
+ return HTLoadError(sink, 403,
+ "Directory browsing is not allowed.");
+ }
+
+
+ if (HTDirAccess == HT_DIR_SELECTIVE) {
+ char * enable_file_name =
+ malloc(strlen(localname)+ 1 +
+ strlen(HT_DIR_ENABLE_FILE) + 1);
+ if (enable_file_name == NULL)
+ outofmem(__FILE__, "HTLoadFile");
+ strcpy(enable_file_name, localname);
+ strcat(enable_file_name, "/");
+ strcat(enable_file_name, HT_DIR_ENABLE_FILE);
+ if (stat(enable_file_name, &file_info) != 0) {
+ FREE(localname);
+ FREE(nodename);
+ return HTLoadError(sink, 403,
+ "Selective access is not enabled for this directory");
+ }
+ }
+
+ dp = opendir(localname);
+ if (!dp) {
+ FREE(localname);
+ FREE(nodename);
+ return HTLoadError(sink, 403,
+ "This directory is not readable.");
+ }
+
+ /*
+ ** Directory access is allowed and possible.
+ */
+ logical = HTAnchor_address((HTAnchor*)anchor);
+ pathname = HTParse(logical, "",
+ PARSE_PATH + PARSE_PUNCTUATION);
+
+ if (!strcmp(pathname,"/")) {
+ /*
+ ** Root path.
+ */
+ StrAllocCopy (tail, "/foo/..");
+ } else {
+ char *p = strrchr(pathname, '/'); /* find last slash */
+
+ if (!p) {
+ /*
+ ** This probably should not happen,
+ ** but be prepared if it does. - KW
+ */
+ StrAllocCopy (tail, "/foo/..");
+ } else {
+ /*
+ ** Take slash off the beginning.
+ */
+ StrAllocCopy(tail, (p + 1));
+ }
+ }
+ FREE(pathname);
+
+ if (UCLYhndl_HTFile_for_unspec >= 0) {
+ HTAnchor_setUCInfoStage(anchor,
+ UCLYhndl_HTFile_for_unspec,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT);
+ }
+
+ target = HTML_new(anchor, format_out, sink);
+ targetClass = *target->isa; /* Copy routine entry points */
+
+ { int i;
+ for (i = 0; i < HTML_A_ATTRIBUTES; i++)
+ present[i] = (i == HTML_A_HREF);
+ }
+
+ /*
+ ** The need_parent_link flag will be set if an
+ ** "Up to <parent>" link was not created for a
+ ** readable parent in HTDirTitles() because
+ ** LONG_LIST is defined and NO_PARENT_DIR_REFERENCE
+ ** is not defined so that need we to create the
+ ** link via an LYListFmtParse() call. - FM
+ */
+ need_parent_link = HTDirTitles(target,
+ (HTAnchor *)anchor, FALSE);
+
+#ifdef DIRED_SUPPORT
+ if (strncmp(anchor->address, "lynxcgi:", 8)) {
+ HTAnchor_setFormat((HTParentAnchor *) anchor, WWW_DIRED);
+ lynx_edit_mode = TRUE;
+ }
+#endif /* DIRED_SUPPORT */
+ if (HTDirReadme == HT_DIR_README_TOP)
+ do_readme(target, localname);
+ {
+ HTBTree * bt = HTBTree_new((HTComparer)strcmp);
+
+ while ((dirbuf = readdir(dp)) != NULL) {
+ /*
+ ** While there are directory entries to be read...
+ */
+ char * dirname = NULL;
+
+#ifndef DOSPATH
+ if (dirbuf->d_ino == 0)
+ /*
+ ** If the entry is not being used, skip it.
+ */
+ continue;
+#endif
+ /*
+ ** Skip self, parent if handled in HTDirTitles()
+ ** or if NO_PARENT_DIR_REFERENCE is not defined,
+ ** and any dot files if no_dotfiles is set or
+ ** show_dotfiles is not set. - FM
+ */
+ if (!strcmp(dirbuf->d_name, ".") /* self */ ||
+ (!strcmp(dirbuf->d_name, "..") /* parent */ &&
+ need_parent_link == FALSE) ||
+ ((strcmp(dirbuf->d_name, "..")) &&
+ (dirbuf->d_name[0] == '.' &&
+ (no_dotfiles || !show_dotfiles))))
+ continue;
+
+ dirname = (char *)malloc(strlen(dirbuf->d_name) + 4);
+ if (dirname == NULL)
+ outofmem(__FILE__, "HTLoadFile");
+ StrAllocCopy(tmpfilename, localname);
+ if (strcmp(localname, "/"))
+ /*
+ ** If filename is not root directory.
+ */
+ StrAllocCat(tmpfilename, "/");
+
+ StrAllocCat(tmpfilename, dirbuf->d_name);
+ stat(tmpfilename, &file_info);
+ if (((file_info.st_mode) & S_IFMT) == S_IFDIR)
+#ifndef DIRED_SUPPORT
+ sprintf((char *)dirname, "D%s",dirbuf->d_name);
+ else
+ sprintf((char *)dirname, "F%s",dirbuf->d_name);
+ /* D & F to have first directories, then files */
+#else
+ if (dir_list_style == MIXED_STYLE)
+ sprintf((char *)dirname,
+ " %s/", dirbuf->d_name);
+ else if (!strcmp(dirbuf->d_name, ".."))
+ sprintf((char *)dirname,
+ "A%s", dirbuf->d_name);
+ else
+ sprintf((char *)dirname,
+ "D%s", dirbuf->d_name);
+ else if (dir_list_style == MIXED_STYLE)
+ sprintf((char *)dirname, " %s", dirbuf->d_name);
+ else if (dir_list_style == FILES_FIRST)
+ sprintf((char *)dirname, "C%s", dirbuf->d_name);
+ /* C & D to have first files, then directories */
+ else
+ sprintf((char *)dirname, "F%s", dirbuf->d_name);
+#endif /* !DIRED_SUPPORT */
+ /*
+ ** Sort dirname in the tree bt.
+ */
+ HTBTree_add(bt, dirname);
+ }
+
+ /*
+ ** Run through tree printing out in order.
+ */
+ {
+ HTBTElement * next_element = HTBTree_next(bt,NULL);
+ /* pick up the first element of the list */
+ char state;
+ /* I for initial (.. file),
+ D for directory file,
+ F for file */
+
+#ifdef DIRED_SUPPORT
+ char test;
+#endif /* DIRED_SUPPORT */
+ state = 'I';
+
+ while (next_element != NULL) {
+ char *entry, *file_extra;
+
+ StrAllocCopy(tmpfilename,localname);
+ if (strcmp(localname, "/"))
+ /*
+ ** If filename is not root directory.
+ */
+ StrAllocCat(tmpfilename, "/");
+
+ StrAllocCat(tmpfilename,
+ (char *)HTBTree_object(next_element)+1);
+ /*
+ ** Append the current entry's filename
+ ** to the path.
+ */
+ HTSimplify(tmpfilename);
+ /*
+ ** Output the directory entry.
+ */
+ if (strcmp((char *)
+ (HTBTree_object(next_element)), "D..") &&
+ strcmp((char *)
+ (HTBTree_object(next_element)), "A.."))
+ {
+#ifdef DIRED_SUPPORT
+ test = (*(char *)(HTBTree_object(next_element))
+ == 'D' ? 'D' : 'F');
+ if (state != test) {
+#ifndef LONG_LIST
+ if (dir_list_style == FILES_FIRST) {
+ if (state == 'F')
+ END(HTML_DIR);
+ } else if (dir_list_style != MIXED_STYLE)
+ if (state == 'D')
+ END(HTML_DIR);
+#endif /* !LONG_LIST */
+ state =
+ (*(char *)(HTBTree_object(next_element))
+ == 'D' ? 'D' : 'F');
+ START(HTML_H2);
+ if (dir_list_style != MIXED_STYLE) {
+ START(HTML_EM);
+ PUTS(state == 'D' ?
+ "Subdirectories:" : "Files:");
+ END(HTML_EM);
+ }
+ END(HTML_H2);
+#ifndef LONG_LIST
+ START(HTML_DIR);
+#endif /* !LONG_LIST */
+ }
+#else
+ if (state != *(char *)(HTBTree_object(
+ next_element))) {
+#ifndef LONG_LIST
+ if (state == 'D')
+ END(HTML_DIR);
+#endif /* !LONG_LIST */
+ state =
+ (*(char *)(HTBTree_object(next_element))
+ == 'D' ? 'D' : 'F');
+ START(HTML_H2);
+ START(HTML_EM);
+ PUTS(state == 'D' ?
+ "Subdirectories:" : "Files:");
+ END(HTML_EM);
+ END(HTML_H2);
+#ifndef LONG_LIST
+ START(HTML_DIR);
+#endif /* !LONG_LIST */
+ }
+#endif /* DIRED_SUPPORT */
+#ifndef LONG_LIST
+ START(HTML_LI);
+#endif /* !LONG_LIST */
+ }
+ entry = (char*)HTBTree_object(next_element)+1;
+ file_extra = NULL;
+
+#ifdef LONG_LIST
+ LYListFmtParse(list_format, tmpfilename, target,
+ entry, tail);
+#else
+ HTDirEntry(target, tail, entry);
+ PUTS(entry);
+ END(HTML_A);
+ if (file_extra) {
+ PUTS(file_extra);
+ FREE(file_extra);
+ }
+ MAYBE_END(HTML_LI);
+#endif /* LONG_LIST */
+
+ next_element = HTBTree_next(bt, next_element);
+ /* pick up the next element of the list;
+ if none, return NULL*/
+ }
+ if (state == 'I') {
+ START(HTML_P);
+ PUTS("Empty Directory");
+ }
+#ifndef LONG_LIST
+ else
+ END(HTML_DIR);
+#endif /* !LONG_LIST */
+ }
+ /* end while directory entries left to read */
+ closedir(dp);
+ FREE(logical);
+ FREE(tmpfilename);
+ FREE(tail);
+ HTBTreeAndObject_free(bt);
+
+ if (HTDirReadme == HT_DIR_README_BOTTOM)
+ do_readme(target, localname);
+ FREE_TARGET;
+ FREE(localname);
+ FREE(nodename);
+ return HT_LOADED; /* document loaded */
+ }
+
+ } /* end if localname is directory */
+
+ } /* end if file stat worked */
+
+/* End of directory reading section
+*/
+#endif /* HAVE_READDIR */
+ {
+ FILE * fp = fopen(localname, "r");
+
+ if (TRACE)
+ fprintf (stderr, "HTLoadFile: Opening `%s' gives %p\n",
+ localname, (void*)fp);
+ if (fp) { /* Good! */
+ int len;
+ char *cp = NULL;
+
+ if (HTEditable(localname)) {
+ HTAtom * put = HTAtom_for("PUT");
+ HTList * methods = HTAnchor_methods(anchor);
+ if (HTList_indexOf(methods, put) == (-1)) {
+ HTList_addObject(methods, put);
+ }
+ }
+ /*
+ ** Fake a Content-Encoding for compressed files. - FM
+ */
+ if (!IsUnityEnc(myEncoding)) {
+ /*
+ * We already know from the call to HTFileFormat above
+ * that this is a compressed file, no need to look at
+ * the filename again. - kw
+ */
+#ifdef USE_ZLIB
+ if (strcmp(format_out->name, "www/download") != 0 &&
+ (!strcmp(HTAtom_name(myEncoding), "gzip") ||
+ !strcmp(HTAtom_name(myEncoding), "x-gzip"))) {
+ fclose(fp);
+ gzfp = gzopen(localname, "rb");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadFile: gzopen of `%s' gives %p\n",
+ localname, (void*)gzfp);
+ use_gzread = YES;
+ } else
+#endif /* USE_ZLIB */
+ {
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding));
+ format = HTAtom_for("www/compressed");
+ }
+ } else if ((len = strlen(localname)) > 2) {
+ if (localname[len - 1] == 'Z' &&
+ localname[len - 2] == '.') {
+ StrAllocCopy(cp, localname);
+ cp[len - 2] = '\0';
+ format = HTFileFormat(cp, &encoding, NULL);
+ FREE(cp);
+ format = HTCharsetFormat(format, anchor,
+ UCLYhndl_HTFile_for_unspec);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-compress");
+ format = HTAtom_for("www/compressed");
+ } else if ((len > 3) &&
+ !strcasecomp((char *)&localname[len - 2],
+ "gz") &&
+ localname[len - 3] == '.') {
+ StrAllocCopy(cp, localname);
+ cp[len - 3] = '\0';
+ format = HTFileFormat(cp, &encoding, NULL);
+ FREE(cp);
+ format = HTCharsetFormat(format, anchor,
+ UCLYhndl_HTFile_for_unspec);
+ StrAllocCopy(anchor->content_type, format->name);
+ StrAllocCopy(anchor->content_encoding, "x-gzip");
+#ifdef USE_ZLIB
+ if (strcmp(format_out->name, "www/download") != 0) {
+ fclose(fp);
+ gzfp = gzopen(localname, "rb");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadFile: gzopen of `%s' gives %p\n",
+ localname, (void*)gzfp);
+ use_gzread = YES;
+ }
+#else /* USE_ZLIB */
+ format = HTAtom_for("www/compressed");
+#endif /* USE_ZLIB */
+ }
+ }
+ FREE(localname);
+ FREE(nodename);
+#ifdef USE_ZLIB
+ if (use_gzread) {
+ if (gzfp) {
+ char * sugfname = NULL;
+ if (anchor->SugFname) {
+ StrAllocCopy(sugfname, anchor->SugFname);
+ } else {
+ char * anchor_path = HTParse(anchor->address, "",
+ PARSE_PATH + PARSE_PUNCTUATION);
+ char * lastslash;
+ HTUnEscape(anchor_path);
+ lastslash = strrchr(anchor_path, '/');
+ if (lastslash)
+ StrAllocCopy(sugfname, lastslash + 1);
+ FREE(anchor_path);
+ }
+ FREE(anchor->content_encoding);
+ if (sugfname && *sugfname)
+ HTCheckFnameForCompression(&sugfname, anchor,
+ TRUE);
+ if (sugfname && *sugfname)
+ StrAllocCopy(anchor->SugFname, sugfname);
+ FREE(sugfname);
+ status = HTParseGzFile(format, format_out,
+ anchor,
+ gzfp, sink);
+ } else {
+ status = HTLoadError(NULL,
+ -(HT_ERROR),
+ "Could not open file for decompression!");
+ }
+ } else
+#endif /* USE_ZLIB */
+ {
+ status = HTParseFile(format, format_out, anchor, fp, sink);
+ fclose(fp);
+ }
+ return status;
+ } /* If successful open */
+ FREE(localname);
+ } /* scope of fp */
+ } /* local unix file system */
+#endif /* !NO_UNIX_IO */
+#endif /* VMS */
+
+#ifndef DECNET
+ /*
+ ** Now, as transparently mounted access has failed, we try FTP.
+ */
+ {
+ /*
+ ** Deal with case-sensitivity differences on VMS versus Unix.
+ */
+#ifdef VMS
+ if (strcasecomp(nodename, HTHostName()) != 0)
+#else
+ if (strcmp(nodename, HTHostName()) != 0)
+#endif /* VMS */
+ {
+ FREE(nodename);
+ if (!strncmp(addr, "file://localhost", 16)) {
+ return -1; /* never go to ftp site when URL
+ * is file://localhost
+ */
+ } else {
+ return HTFTPLoad(addr, anchor, format_out, sink);
+ }
+ }
+ FREE(nodename);
+ }
+#endif /* !DECNET */
+
+ /*
+ ** All attempts have failed.
+ */
+ {
+ if (TRACE)
+ fprintf(stderr, "Can't open `%s', errno=%d\n", addr, SOCKET_ERRNO);
+
+ return HTLoadError(sink, 403, "Can't access requested file.");
+ }
+}
+
+/*
+** Protocol descriptors
+*/
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTFILE_C_1_INIT { "ftp", HTLoadFile, 0 }
+GLOBALDEF (HTProtocol,HTFTP,_HTFILE_C_1_INIT);
+#define _HTFILE_C_2_INIT { "file", HTLoadFile, HTFileSaveStream }
+GLOBALDEF (HTProtocol,HTFile,_HTFILE_C_2_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTFTP = { "ftp", HTLoadFile, 0 };
+GLOBALDEF PUBLIC HTProtocol HTFile = { "file", HTLoadFile, HTFileSaveStream };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.h
new file mode 100644
index 00000000000..b65c17e73f4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFile.h
@@ -0,0 +1,210 @@
+/* File access in libwww
+** FILE ACCESS
+**
+** These are routines for local file access used by WWW browsers and servers.
+** Implemented by HTFile.c.
+**
+** If the file is not a local file, then we pass it on to HTFTP in case it
+** can be reached by FTP.
+*/
+#ifndef HTFILE_H
+#define HTFILE_H
+
+#include "HTFormat.h"
+#include "HTAccess.h"
+#ifndef HTML_H
+#include "HTML.h" /* SCW */
+#endif /* HTML_H */
+
+/*
+** Controlling globals
+**
+** These flags control how directories and files are represented as
+** hypertext, and are typically set by the application from command
+** line options, etc.
+*/
+extern int HTDirAccess; /* Directory access level */
+
+#define HT_DIR_FORBID 0 /* Altogether forbidden */
+#define HT_DIR_SELECTIVE 1 /* If HT_DIR_ENABLE_FILE exists */
+#define HT_DIR_OK 2 /* Any accesible directory */
+
+#define HT_DIR_ENABLE_FILE ".www_browsable" /* If exists, can browse */
+
+extern int HTDirReadme; /* Include readme files in listing? */
+ /* Values: */
+#define HT_DIR_README_NONE 0 /* No */
+#define HT_DIR_README_TOP 1 /* Yes, first */
+#define HT_DIR_README_BOTTOM 2 /* Yes, at the end */
+
+#define HT_DIR_README_FILE "README"
+
+/*
+** Convert filenames between local and WWW formats
+*/
+extern char * HTLocalName PARAMS((CONST char * name));
+
+/*
+** Make a WWW name from a full local path name
+*/
+extern char * WWW_nameOfFile PARAMS((const char * name));
+
+/*
+** Generate the name of a cache file
+*/
+extern char * HTCacheFileName PARAMS((CONST char * name));
+
+/*
+** Output directory titles
+**
+** This is (like the next one) used by HTFTP. It is common code to generate
+** the title and heading 1 and the parent directory link for any anchor.
+**
+** changed to return TRUE if parent directory link was generated,
+** FALSE otherwise - KW
+*/
+extern BOOL HTDirTitles PARAMS((
+ HTStructured * target,
+ HTAnchor * anchor,
+ BOOL tildeIsTop));
+
+/* Load a document.
+** ----------------
+*/
+extern int HTLoadFile PARAMS((
+ CONST char * addr,
+ HTParentAnchor * anchor,
+ HTFormat format_out,
+ HTStream * sink));
+
+/*
+** Output a directory entry
+**
+** This is used by HTFTP.c for example -- it is a common routine for
+** generating a linked directory entry.
+*/
+extern void HTDirEntry PARAMS((
+ HTStructured * target, /* in which to put the linked text */
+ CONST char * tail, /* last part of directory name */
+ CONST char * entry)); /* name of this entry */
+
+/*
+** HTSetSuffix: Define the representation for a file suffix
+**
+** This defines a mapping between local file suffixes and file content
+** types and encodings.
+**
+** ON ENTRY,
+**
+** suffix includes the "." if that is important (normally, yes!)
+**
+** representation is MIME-style content-type
+**
+** encoding is MIME-style content-transfer-encoding
+** (8bit, 7bit, etc) or HTTP-style content-encoding
+** (gzip, compress etc.)
+**
+** quality an a priori judgement of the quality of such files
+** (0.0..1.0)
+**
+** HTSetSuffix5 has one more parameter for a short description of the type
+** which is otherwise derived from the representation:
+**
+** desc is a short textual description, or NULL
+**
+** Examples: HTSetSuffix(".ps", "application/postscript", "8bit", 1.0);
+** Examples: HTSetSuffix(".psz", "application/postscript", "gzip", 1.0);
+** A MIME type could also indicate a non-trivial encoding on its own
+** ("application/x-compressed-tar"), but in that case don't use enconding
+** to also indicate it but use "binary" etc.
+*/
+extern void HTSetSuffix5 PARAMS((
+ CONST char * suffix,
+ CONST char * representation,
+ CONST char * encoding,
+ CONST char * desc,
+ float quality));
+
+#define HTSetSuffix(suff,rep,enc,q) HTSetSuffix5(suff, rep, enc, NULL, q)
+
+/*
+** HTFileFormat: Get Representation and Encoding from file name.
+**
+** ON EXIT,
+**
+** return The represntation it imagines the file is in.
+**
+** *pEncoding The encoding (binary, 7bit, etc). See HTSetSuffix.
+*/
+extern HTFormat HTFileFormat PARAMS((
+ CONST char * filename,
+ HTAtom ** pEncoding,
+ CONST char ** pDesc));
+
+/*
+** HTCharsetFormat: Revise the file format in relation to the Lynx charset.
+**
+** This checks the format associated with an anchor for
+** for an extended MIME Content-Type, and if a charset is
+** indicated, sets Lynx up for proper handling in relation
+** to the currently selected character set. - FM
+*/
+extern HTFormat HTCharsetFormat PARAMS((
+ HTFormat format,
+ HTParentAnchor * anchor,
+ int default_LYhndl));
+
+/*
+** Determine file value from file name.
+*/
+extern float HTFileValue PARAMS((
+ CONST char * filename));
+
+/*
+** Determine write access to a file.
+**
+** ON EXIT,
+**
+** return value YES if file can be accessed and can be written to.
+**
+** BUGS
+**
+** Isn't there a quicker way?
+*/
+extern BOOL HTEditable PARAMS((CONST char * filename));
+
+/* Make a save stream.
+** -------------------
+*/
+extern HTStream * HTFileSaveStream PARAMS((
+ HTParentAnchor * anchor));
+
+/*
+** Determine a suitable suffix, given the representation.
+**
+** ON ENTRY,
+**
+** rep is the atomized MIME style representation
+** enc is an encoding (8bit, binary, gzip, compress,..)
+**
+** ON EXIT,
+**
+** returns a pointer to a suitable suffix string if one has
+** been found, else NULL.
+*/
+extern CONST char * HTFileSuffix PARAMS((
+ HTAtom* rep,
+ CONST char* enc));
+
+/*
+** The Protocols
+*/
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol,HTFTP);
+extern GLOBALREF (HTProtocol,HTFile);
+#else
+GLOBALREF HTProtocol HTFTP, HTFile;
+#endif /* GLOBALREF_IS_MACRO */
+#endif /* HTFILE_H */
+
+/* end of HTFile */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c
new file mode 100644
index 00000000000..e714e0d20f0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.c
@@ -0,0 +1,441 @@
+/* FINGER ACCESS HTFinger.c
+** =============
+** Authors:
+** ARB Andrew Brooks
+**
+** History:
+** 21 Apr 94 First version (ARB, from HTNews.c by TBL)
+** 12 Mar 96 Made the URL and command buffering secure from
+** stack modifications, beautified the HTLoadFinger()
+** and response() functions, and added support for the
+** following URL formats for sending a "", "/w",
+** "username[@host]", or "/w username[@host]" command
+** to the server:
+** finger://host
+** finger://host/
+** finger://host/%2fw
+** finger://host/%2fw%20username[@host]
+** finger://host/w/username[@host]
+** finger://host/username[@host]
+** finger://host/username[@host]/w
+** finger://username@host
+** finger://username@host/
+** finger://username@host/w
+** 15 Mar 96 Added support for port 79 gtype 0 gopher URLs
+** relayed from HTLoadGopher. - FM
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "HTML.h"
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTTCP.h"
+#include "HTString.h"
+#include "HTFinger.h"
+
+#include "LYLeaks.h"
+
+/* #define TRACE 1 */
+
+#define FINGER_PORT 79 /* See rfc742 */
+#define BIG 1024 /* Bug */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET (*targetClass._free)(target)
+#define NEXT_CHAR HTGetCharacter()
+
+
+/* Module-wide variables
+*/
+PRIVATE int s; /* Socket for FingerHost */
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa; /* For gopher streams */
+ /* ... */
+};
+
+PRIVATE HTStructured * target; /* The output sink */
+PRIVATE HTStructuredClass targetClass; /* Copy of fn addresses */
+
+/* Initialisation for this module
+** ------------------------------
+*/
+PRIVATE BOOL initialized = NO;
+PRIVATE BOOL initialize NOARGS
+{
+ s = -1; /* Disconnected */
+ return YES;
+}
+
+
+
+/* Start anchor element
+** --------------------
+*/
+PRIVATE void start_anchor ARGS1(CONST char *, href)
+{
+ BOOL present[HTML_A_ATTRIBUTES];
+ CONST char* value[HTML_A_ATTRIBUTES];
+
+ {
+ int i;
+ for(i=0; i<HTML_A_ATTRIBUTES; i++)
+ present[i] = (i==HTML_A_HREF);
+ }
+ ((CONST char **)value)[HTML_A_HREF] = href;
+ (*targetClass.start_element)(target, HTML_A, present,
+ (CONST char **)value, -1, 0);
+
+}
+
+/* Send Finger Command line to remote host & Check Response
+** --------------------------------------------------------
+**
+** On entry,
+** command points to the command to be sent, including CRLF, or is null
+** pointer if no command to be sent.
+** On exit,
+** Negative status indicates transmission error, socket closed.
+** Positive status is a Finger status.
+*/
+
+
+PRIVATE int response ARGS5(
+ CONST char *, command,
+ char *, sitename,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ int status;
+ int length = strlen(command);
+ int ch, i;
+ char line[BIG], *l, *cmd=NULL;
+ char *p = line, *href=NULL;
+
+ if (length == 0)
+ return(-1);
+
+ /* Set up buffering.
+ */
+ HTInitInput(s);
+
+ /* Send the command.
+ */
+ if (TRACE)
+ fprintf(stderr, "HTFinger command to be sent: %s", command);
+ status = NETWRITE(s, (char *)command, length);
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTFinger: Unable to send command. Disconnecting.\n");
+ NETCLOSE(s);
+ s = -1;
+ return status;
+ } /* if bad status */
+
+ /* Make a hypertext object with an anchor list.
+ */
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa; /* Copy routine entry points */
+
+ /* Create the results report.
+ */
+ if (TRACE)
+ fprintf(stderr,"HTFinger: Reading finger information\n");
+ START(HTML_HTML);
+ PUTS("\n");
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ PUTS("Finger server on ");
+ PUTS(sitename);
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_BODY);
+ PUTS("\n");
+ START(HTML_H1);
+ PUTS("Finger server on ");
+ START(HTML_EM);
+ PUTS(sitename);
+ END(HTML_EM);
+ PUTS(": ");
+ if (command) {
+ StrAllocCopy(cmd, command);
+ } else {
+ StrAllocCopy(cmd, "");
+ }
+ for (i = (strlen(cmd) - 1); i >= 0; i--) {
+ if (cmd[i] == LF || cmd[i] == CR) {
+ cmd[i] = '\0';
+ } else {
+ break;
+ }
+ }
+ PUTS(cmd);
+ FREE(cmd);
+ END(HTML_H1);
+ PUTS("\n");
+ START(HTML_PRE);
+
+ while ((ch=NEXT_CHAR) != (char)EOF) {
+
+ if (interrupted_in_htgetcharacter) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTFinger: Interrupted in HTGetCharacter, apparently.\n");
+ }
+ _HTProgress ("Connection interrupted.");
+ goto end_html;
+ }
+
+ if (ch != LF) {
+ *p = ch; /* Put character in line */
+ if (p < &line[BIG-1]) {
+ p++;
+ }
+ } else {
+ *p = '\0'; /* Terminate line */
+ /*
+ * OK we now have a line.
+ * Load it as 'l' and parse it.
+ */
+ p = l = line;
+ while (*l) {
+ if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9))
+ PUTC(*l++);
+ else {
+ StrAllocCopy(href, l);
+ start_anchor(strtok(href, " \r\n\t,>)\""));
+ while (*l && !strchr(" \r\n\t,>)\"", *l))
+ PUTC(*l++);
+ END(HTML_A);
+ FREE(href);
+ }
+ }
+ PUTC('\n');
+ }
+ }
+ NETCLOSE(s);
+ s = -1;
+
+end_html:
+ END(HTML_PRE);
+ PUTS("\n");
+ END(HTML_BODY);
+ PUTS("\n");
+ END(HTML_HTML);
+ PUTS("\n");
+ FREE_TARGET;
+ return(0);
+}
+
+
+/* Load by name HTLoadFinger
+** ============
+*/
+PUBLIC int HTLoadFinger ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, stream)
+{
+ char *username, *sitename, *colon; /* Fields extracted from URL */
+ char *slash, *at_sign; /* Fields extracted from URL */
+ char *command, *str; /* Buffers */
+ int port; /* Port number from URL */
+ int status; /* tcp return */
+
+ if (TRACE) {
+ fprintf(stderr, "HTFinger: Looking for %s\n", (arg ? arg : "NULL"));
+ }
+
+ if (!(arg && *arg)) {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* Ignore if no name */
+ }
+
+ if (!initialized)
+ initialized = initialize();
+ if (!initialized) {
+ HTAlert ("Could not set up finger connection.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+
+ {
+ CONST char * p1=arg;
+ BOOL IsGopherURL = FALSE;
+
+ /* Set up the host and command fields.
+ */
+ if (!strncasecomp(arg, "finger://", 9)) {
+ p1 = arg + 9; /* Skip "finger://" prefix */
+ } else if (!strncasecomp(arg, "gopher://", 9)) {
+ p1 = arg + 9; /* Skip "gopher://" prefix */
+ IsGopherURL = TRUE;
+ }
+ sitename = (char *)p1;
+
+ if ((slash = strchr(sitename, '/')) != NULL) {
+ *slash++ = '\0';
+ HTUnEscape(slash);
+ if (IsGopherURL) {
+ if (*slash != '0') {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ *slash++ = '\0';
+ }
+ }
+ if ((at_sign = strchr(sitename, '@')) != NULL) {
+ if (IsGopherURL) {
+ HTAlert("Could not load data.");
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ *at_sign++ = '\0';
+ username = sitename;
+ sitename = at_sign;
+ HTUnEscape(username);
+ } else if (slash) {
+ username = slash;
+ } else {
+ username = "";
+ }
+
+ if (*sitename == '\0') {
+ HTAlert("Could not load data (no sitename in finger URL)");
+ return HT_NOT_LOADED; /* Ignore if no name */
+ }
+
+ if ((colon = strchr(sitename, ':')) != NULL) {
+ *colon++ = '\0';
+ port = atoi(colon);
+ if (port != 79) {
+ HTAlert("Invalid port number - will only use port 79!");
+ return HT_NOT_LOADED; /* Ignore if wrong port */
+ }
+ }
+
+ /* Load the string for making a connection/
+ */
+ str = (char *)calloc(1, (strlen(sitename) + 10));
+ if (str == NULL)
+ outofmem(__FILE__, "HTLoadFinger");
+ sprintf(str, "lose://%s/", sitename);
+
+ /* Load the command for the finger server.
+ */
+ command = (char *)calloc(1, (strlen(username) + 10));
+ if (command == NULL)
+ outofmem(__FILE__, "HTLoadFinger");
+ if (at_sign && slash) {
+ if (*slash == 'w' || *slash == 'W') {
+ sprintf(command, "/w %s%c%c", username, CR, LF);
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } else if (at_sign) {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ } else if (*username == '/') {
+ if ((slash = strchr((username+1), '/')) != NULL) {
+ *slash = ' ';
+ }
+ sprintf(command, "%s%c%c", username, CR, LF);
+ } else if ((*username == 'w' || *username == 'W') &&
+ *(username+1) == '/') {
+ if (*username+2 != '\0') {
+ *(username+1) = ' ';
+ } else {
+ *(username+1) = '\0';
+ }
+ sprintf(command, "/%s%c%c", username, CR, LF);
+ } else if ((*username == 'w' || *username == 'W') &&
+ *(username+1) == '\0') {
+ sprintf(command, "/%s%c%c", username, CR, LF);
+ } else if ((slash = strchr(username, '/')) != NULL) {
+ *slash++ = '\0';
+ if (*slash == 'w' || *slash == 'W') {
+ sprintf(command, "/w %s%c%c", username, CR, LF);
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } else {
+ sprintf(command, "%s%c%c", username, CR, LF);
+ }
+ } /* scope of p1 */
+
+ /* Now, let's get a stream setup up from the FingerHost:
+ ** CONNECTING to finger host
+ */
+ if (TRACE)
+ fprintf(stderr, "HTFinger: doing HTDoConnect on '%s'\n", str);
+ status = HTDoConnect(str, "finger", FINGER_PORT, &s);
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Done DoConnect; status %d\n", status);
+
+ if (status == HT_INTERRUPTED) {
+ /* Interrupt cleanly */
+ if (TRACE)
+ fprintf(stderr,
+ "HTFinger: Interrupted on connect; recovering cleanly.\n");
+ HTProgress ("Connection interrupted.");
+ FREE(str);
+ FREE(command);
+ return HT_NOT_LOADED;
+ }
+ if (status < 0) {
+ NETCLOSE(s);
+ s = -1;
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Unable to connect to finger host.\n");
+ HTAlert("Could not access finger host.");
+ FREE(str);
+ FREE(command);
+ return HT_NOT_LOADED; /* FAIL */
+ }
+ if (TRACE)
+ fprintf(stderr, "HTFinger: Connected to finger host '%s'.\n", str);
+ FREE(str);
+
+ /* Send the command, and process response if successful.
+ */
+ if (response(command, sitename, anAnchor, format_out, stream) != 0) {
+ HTAlert("No response from finger server.");
+ FREE(command);
+ return HT_NOT_LOADED;
+ }
+
+ FREE(command);
+ return HT_LOADED;
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTFINGER_C_1_INIT { "finger", HTLoadFinger, NULL }
+GLOBALDEF (HTProtocol, HTFinger, _HTFINGER_C_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTFinger = { "finger", HTLoadFinger, NULL };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.h
new file mode 100644
index 00000000000..98d98070900
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFinger.h
@@ -0,0 +1,24 @@
+/* Finger protocol module for the WWW library */
+/* History:
+** 21 Apr 94 Andrew Brooks
+*/
+
+#ifndef HTFINGER_H
+#define HTFINGER_H
+
+#include "HTAccess.h"
+#include "HTAnchor.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol, HTFinger);
+#else
+GLOBALREF HTProtocol HTFinger;
+#endif /* GLOBALREF_IS_MACRO */
+
+extern int HTLoadFinger PARAMS((
+ CONST char * arg,
+ HTParentAnchor * anAnchor,
+ HTFormat format_out,
+ HTStream * stream));
+
+#endif /* HTFINGER_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.c
new file mode 100644
index 00000000000..c05af1fa255
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.c
@@ -0,0 +1,1093 @@
+/* Manage different file formats HTFormat.c
+** =============================
+**
+** Bugs:
+** Not reentrant.
+**
+** Assumes the incoming stream is ASCII, rather than a local file
+** format, and so ALWAYS converts from ASCII on non-ASCII machines.
+** Therefore, non-ASCII machines can't read local files.
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAccess.h"
+
+/* Implements:
+*/
+#include "HTFormat.h"
+
+PUBLIC float HTMaxSecs = 1e10; /* No effective limit */
+PUBLIC float HTMaxLength = 1e10; /* No effective limit */
+PUBLIC long int HTMaxBytes = 0; /* No effective limit */
+
+#ifdef unix
+#ifdef NeXT
+#define PRESENT_POSTSCRIPT "open %s; /bin/rm -f %s\n"
+#else
+#define PRESENT_POSTSCRIPT "(ghostview %s ; /bin/rm -f %s)&\n"
+ /* Full pathname would be better! */
+#endif /* NeXT */
+#endif /* unix */
+
+#include "HTML.h"
+#include "HTMLDTD.h"
+#include "HText.h"
+#include "HTAlert.h"
+#include "HTList.h"
+#include "HTInit.h"
+#include "HTTCP.h"
+/* Streams and structured streams which we use:
+*/
+#include "HTFWriter.h"
+#include "HTPlain.h"
+#include "SGML.h"
+#include "HTML.h"
+#include "HTMLGen.h"
+
+#include "LYexit.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern int HTCheckForInterrupt NOPARAMS;
+
+PUBLIC BOOL HTOutputSource = NO; /* Flag: shortcut parser to stdout */
+/* extern BOOL interactive; LJM */
+
+#ifdef ORIGINAL
+struct _HTStream {
+ CONST HTStreamClass* isa;
+ /* ... */
+};
+#endif /* ORIGINAL */
+
+/* this version used by the NetToText stream */
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ BOOL had_cr;
+ HTStream * sink;
+};
+
+/* Presentation methods
+** --------------------
+*/
+PUBLIC HTList * HTPresentations = NULL;
+PUBLIC HTPresentation * default_presentation = NULL;
+
+/*
+ * To free off the presentation list.
+ */
+PRIVATE void HTFreePresentations NOPARAMS;
+
+/* Define a presentation system command for a content-type
+** -------------------------------------------------------
+*/
+PUBLIC void HTSetPresentation ARGS6(
+ CONST char *, representation,
+ CONST char *, command,
+ float, quality,
+ float, secs,
+ float, secs_per_byte,
+ long int, maxbytes)
+{
+ HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
+ if (pres == NULL)
+ outofmem(__FILE__, "HTSetPresentation");
+
+ pres->rep = HTAtom_for(representation);
+ pres->rep_out = WWW_PRESENT; /* Fixed for now ... :-) */
+ pres->converter = HTSaveAndExecute; /* Fixed for now ... */
+ pres->quality = quality;
+ pres->secs = secs;
+ pres->secs_per_byte = secs_per_byte;
+ pres->maxbytes = maxbytes;
+ pres->command = NULL;
+ StrAllocCopy(pres->command, command);
+
+ /*
+ * Memory leak fixed.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ if (!HTPresentations) {
+ HTPresentations = HTList_new();
+ atexit(HTFreePresentations);
+ }
+
+ if (strcmp(representation, "*")==0) {
+ FREE(default_presentation);
+ default_presentation = pres;
+ } else {
+ HTList_addObject(HTPresentations, pres);
+ }
+}
+
+/* Define a built-in function for a content-type
+** ---------------------------------------------
+*/
+PUBLIC void HTSetConversion ARGS7(
+ CONST char *, representation_in,
+ CONST char *, representation_out,
+ HTConverter*, converter,
+ float, quality,
+ float, secs,
+ float, secs_per_byte,
+ long int, maxbytes)
+{
+ HTPresentation * pres = (HTPresentation *)malloc(sizeof(HTPresentation));
+ if (pres == NULL)
+ outofmem(__FILE__, "HTSetConversion");
+
+ pres->rep = HTAtom_for(representation_in);
+ pres->rep_out = HTAtom_for(representation_out);
+ pres->converter = converter;
+ pres->command = NULL; /* Fixed */
+ pres->quality = quality;
+ pres->secs = secs;
+ pres->secs_per_byte = secs_per_byte;
+ pres->maxbytes = maxbytes;
+ pres->command = NULL;
+
+ /*
+ * Memory Leak fixed.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ if (!HTPresentations) {
+ HTPresentations = HTList_new();
+ atexit(HTFreePresentations);
+ }
+
+ HTList_addObject(HTPresentations, pres);
+}
+
+/*
+** Purpose: Free the presentation list.
+** Arguments: void
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** Made to clean up Lynx's bad leakage.
+** Revision History:
+** 05-28-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void HTFreePresentations NOARGS
+{
+ HTPresentation * pres = NULL;
+
+ /*
+ * Loop through the list.
+ */
+ while (!HTList_isEmpty(HTPresentations)) {
+ /*
+ * Free off each item.
+ * May also need to free off it's items, but not sure
+ * as of yet.
+ */
+ pres = (HTPresentation *)HTList_removeLastObject(HTPresentations);
+ FREE(pres->command);
+ FREE(pres);
+ }
+ /*
+ * Free the list itself.
+ */
+ HTList_delete(HTPresentations);
+ HTPresentations = NULL;
+}
+
+/* File buffering
+** --------------
+**
+** The input file is read using the macro which can read from
+** a socket or a file.
+** The input buffer size, if large will give greater efficiency and
+** release the server faster, and if small will save space on PCs etc.
+*/
+#define INPUT_BUFFER_SIZE 4096 /* Tradeoff */
+PRIVATE char input_buffer[INPUT_BUFFER_SIZE];
+PRIVATE char * input_pointer;
+PRIVATE char * input_limit;
+PRIVATE int input_file_number;
+
+/* Set up the buffering
+**
+** These routines are public because they are in fact needed by
+** many parsers, and on PCs and Macs we should not duplicate
+** the static buffer area.
+*/
+PUBLIC void HTInitInput ARGS1 (int,file_number)
+{
+ input_file_number = file_number;
+ input_pointer = input_limit = input_buffer;
+}
+
+PUBLIC int interrupted_in_htgetcharacter = 0;
+PUBLIC char HTGetCharacter NOARGS
+{
+ char ch;
+ interrupted_in_htgetcharacter = 0;
+ do {
+ if (input_pointer >= input_limit) {
+ int status = NETREAD(input_file_number,
+ input_buffer, INPUT_BUFFER_SIZE);
+ if (status <= 0) {
+ if (status == 0)
+ return (char)EOF;
+ if (status == HT_INTERRUPTED) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTFormat: Interrupted in HTGetCharacter\n");
+ interrupted_in_htgetcharacter = 1;
+ return (char)EOF;
+ }
+ if (TRACE)
+ fprintf(stderr, "HTFormat: File read error %d\n", status);
+ return (char)EOF; /* -1 is returned by UCX
+ at end of HTTP link */
+ }
+ input_pointer = input_buffer;
+ input_limit = input_buffer + status;
+ }
+ ch = *input_pointer++;
+ } while (ch == (char) 13); /* Ignore ASCII carriage return */
+
+ return FROMASCII(ch);
+}
+
+/* Match maintype to any MIME type starting with maintype,
+ * for example: image/gif should match image
+ */
+PRIVATE int half_match ARGS2(char *,trial_type, char *,target)
+{
+ char *cp=strchr(trial_type,'/');
+
+ /* if no '/' or no '*' */
+ if (!cp || *(cp+1) != '*')
+ return 0;
+
+ if (TRACE)
+ fprintf(stderr,"HTFormat: comparing %s and %s for half match\n",
+ trial_type, target);
+
+ /* main type matches */
+ if (!strncmp(trial_type, target, (cp-trial_type)-1))
+ return 1;
+
+ return 0;
+}
+
+/* Look up a presentation
+** ----------------------
+**
+** If fill_in is NULL, only look for an exact match.
+** If a wildcard match is made, *fill_in is used to store
+** a possibly modified presentation, and a pointer to it is
+** returned. For an exact match, a pointer to the presentation
+** in the HTPresentations list is returned. Returns NULL if
+** nothing found. - kw
+**
+*/
+PRIVATE HTPresentation * HTFindPresentation ARGS3(
+ HTFormat, rep_in,
+ HTFormat, rep_out,
+ HTPresentation*, fill_in)
+{
+ HTAtom * wildcard = HTAtom_for("*");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTFormat: Looking up presentation for %s to %s\n",
+ HTAtom_name(rep_in), HTAtom_name(rep_out));
+
+ /* don't do anymore do it in the Lynx code at startup LJM */
+ /* if (!HTPresentations) HTFormatInit(); */ /* set up the list */
+
+ {
+ int n = HTList_count(HTPresentations);
+ int i;
+ HTPresentation * pres, *match,
+ *strong_wildcard_match=0,
+ *weak_wildcard_match=0,
+ *last_default_match=0,
+ *strong_subtype_wildcard_match=0;
+
+ for (i = 0; i < n; i++) {
+ pres = (HTPresentation *)HTList_objectAt(HTPresentations, i);
+ if (pres->rep == rep_in) {
+ if (pres->rep_out == rep_out) {
+ if (TRACE)
+ fprintf(stderr,
+ "FindPresentation: found exact match: %s\n",
+ HTAtom_name(pres->rep));
+ return pres;
+
+ } else if (!fill_in) {
+ continue;
+ } else if (pres->rep_out == wildcard) {
+ if (!strong_wildcard_match)
+ strong_wildcard_match = pres;
+ /* otherwise use the first one */
+ if (TRACE)
+ fprintf(stderr,
+ "StreamStack: found strong wildcard match: %s\n",
+ HTAtom_name(pres->rep));
+ }
+
+ } else if (!fill_in) {
+ continue;
+
+ } else if (half_match(HTAtom_name(pres->rep),
+ HTAtom_name(rep_in))) {
+ if (pres->rep_out == rep_out) {
+ if (!strong_subtype_wildcard_match)
+ strong_subtype_wildcard_match = pres;
+ /* otherwise use the first one */
+ if (TRACE)
+ fprintf(stderr,
+ "StreamStack: found strong subtype wildcard match: %s\n",
+ HTAtom_name(pres->rep));
+ }
+ }
+
+ if (pres->rep == WWW_SOURCE) {
+ if (pres->rep_out == rep_out) {
+ if (!weak_wildcard_match)
+ weak_wildcard_match = pres;
+ /* otherwise use the first one */
+ if (TRACE)
+ fprintf(stderr,
+ "StreamStack: found weak wildcard match: %s\n",
+ HTAtom_name(pres->rep_out));
+ }
+ if (pres->rep_out == wildcard) {
+ if (!last_default_match)
+ last_default_match = pres;
+ /* otherwise use the first one */
+ }
+ }
+ }
+
+ match = strong_subtype_wildcard_match ? strong_subtype_wildcard_match :
+ strong_wildcard_match ? strong_wildcard_match :
+ weak_wildcard_match ? weak_wildcard_match :
+ last_default_match;
+
+ if (match) {
+ *fill_in = *match; /* Specific instance */
+ fill_in->rep = rep_in; /* yuk */
+ fill_in->rep_out = rep_out; /* yuk */
+ return fill_in;
+ }
+ }
+
+ return NULL;
+}
+
+/* Create a filter stack
+** ---------------------
+**
+** If a wildcard match is made, a temporary HTPresentation
+** structure is made to hold the destination format while the
+** new stack is generated. This is just to pass the out format to
+** MIME so far. Storing the format of a stream in the stream might
+** be a lot neater.
+**
+*/
+PUBLIC HTStream * HTStreamStack ARGS4(
+ HTFormat, rep_in,
+ HTFormat, rep_out,
+ HTStream*, sink,
+ HTParentAnchor*, anchor)
+{
+ HTPresentation temp;
+ HTPresentation *match;
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTFormat: Constructing stream stack for %s to %s\n",
+ HTAtom_name(rep_in), HTAtom_name(rep_out));
+
+ /* don't return on WWW_SOURCE some people might like
+ * to make use of the source!!!! LJM
+ *//*
+ if (rep_out == WWW_SOURCE || rep_out == rep_in)
+ return sink; LJM */
+
+ if (rep_out == rep_in)
+ return sink;
+
+ if ((match = HTFindPresentation(rep_in, rep_out, &temp))) {
+ if (match == &temp) {
+ if (TRACE)
+ fprintf(stderr,
+ "StreamStack: Using %s\n", HTAtom_name(temp.rep_out));
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "StreamStack: found exact match: %s\n",
+ HTAtom_name(match->rep));
+ }
+ return (*match->converter)(match, anchor, sink);
+ } else {
+ return NULL;
+ }
+}
+
+/* Put a presentation near start of list
+** -------------------------------------
+**
+** Look up a presentation (exact match only) and, if found, reorder
+** it to the start of the HTPresentations list. - kw
+*/
+PUBLIC void HTReorderPresentation ARGS2(
+ HTFormat, rep_in,
+ HTFormat, rep_out)
+{
+ HTPresentation *match;
+ if ((match = HTFindPresentation(rep_in, rep_out, NULL))) {
+ HTList_removeObject(HTPresentations, match);
+ HTList_addObject(HTPresentations, match);
+ }
+}
+/* Find the cost of a filter stack
+** -------------------------------
+**
+** Must return the cost of the same stack which StreamStack would set up.
+**
+** On entry,
+** length The size of the data to be converted
+*/
+PUBLIC float HTStackValue ARGS4(
+ HTFormat, rep_in,
+ HTFormat, rep_out,
+ float, initial_value,
+ long int, length)
+{
+ HTAtom * wildcard = HTAtom_for("*");
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTFormat: Evaluating stream stack for %s worth %.3f to %s\n",
+ HTAtom_name(rep_in), initial_value, HTAtom_name(rep_out));
+
+ if (rep_out == WWW_SOURCE || rep_out == rep_in)
+ return 0.0;
+
+ /* don't do anymore do it in the Lynx code at startup LJM */
+ /* if (!HTPresentations) HTFormatInit(); */ /* set up the list */
+
+ {
+ int n = HTList_count(HTPresentations);
+ int i;
+ HTPresentation * pres;
+ for (i = 0; i < n; i++) {
+ pres = (HTPresentation *)HTList_objectAt(HTPresentations, i);
+ if (pres->rep == rep_in &&
+ (pres->rep_out == rep_out || pres->rep_out == wildcard)) {
+ float value = initial_value * pres->quality;
+ if (HTMaxSecs != 0.0)
+ value = value - (length*pres->secs_per_byte + pres->secs)
+ /HTMaxSecs;
+ return value;
+ }
+ }
+ }
+
+ return -1e30; /* Really bad */
+
+}
+
+/* Push data from a socket down a stream
+** -------------------------------------
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the file.
+**
+** The file number given is assumed to be a TELNET stream ie containing
+** CRLF at the end of lines which need to be stripped to LF for unix
+** when the format is textual.
+**
+*/
+PUBLIC int HTCopy ARGS4(
+ HTParentAnchor *, anchor,
+ int, file_number,
+ void*, handle GCC_UNUSED,
+ HTStream*, sink)
+{
+ HTStreamClass targetClass;
+ char line[256];
+ int bytes = 0;
+ int rv = 0;
+
+ /* Push the data down the stream
+ */
+ targetClass = *(sink->isa); /* Copy pointers to procedures */
+
+ /* Push binary from socket down sink
+ **
+ ** This operation could be put into a main event loop
+ */
+ for (;;) {
+ int status;
+
+ if (LYCancelDownload) {
+ LYCancelDownload = FALSE;
+ (*targetClass._abort)(sink, NULL);
+ rv = -1;
+ goto finished;
+ }
+
+ if (HTCheckForInterrupt()) {
+ _HTProgress ("Data transfer interrupted.");
+ (*targetClass._abort)(sink, NULL);
+ if (bytes)
+ rv = HT_INTERRUPTED;
+ else
+ rv = -1;
+ goto finished;
+ }
+
+ status = NETREAD(file_number, input_buffer, INPUT_BUFFER_SIZE);
+
+ if (status <= 0) {
+ if (status == 0) {
+ break;
+ } else if (status == HT_INTERRUPTED) {
+ _HTProgress ("Data transfer interrupted.");
+ (*targetClass._abort)(sink, NULL);
+ if (bytes)
+ rv = HT_INTERRUPTED;
+ else
+ rv = -1;
+ goto finished;
+ } else if (SOCKET_ERRNO == ENOTCONN ||
+ SOCKET_ERRNO == ECONNRESET ||
+ SOCKET_ERRNO == EPIPE) {
+ /*
+ * Arrrrgh, HTTP 0/1 compability problem, maybe.
+ */
+ if (bytes <= 0) {
+ /*
+ * Don't have any data, so let the calling
+ * function decide what to do about it. - FM
+ */
+ rv = -2;
+ goto finished;
+ } else {
+ /*
+ * Treat what we've gotten already
+ * as the complete transmission. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTCopy: Unexpected server disconnect. Treating as completed.\n");
+ status = 0;
+ break;
+ }
+ }
+ break;
+ }
+
+#ifdef NOT_ASCII
+ {
+ char * p;
+ for (p = input_buffer; p < input_buffer+status; p++) {
+ *p = FROMASCII(*p);
+ }
+ }
+#endif /* NOT_ASCII */
+
+ (*targetClass.put_block)(sink, input_buffer, status);
+
+ bytes += status;
+ if (anchor && anchor->content_length > 0)
+ sprintf(line, "Read %d of %d bytes of data.",
+ bytes, anchor->content_length);
+ else
+ sprintf(line, "Read %d bytes of data.", bytes);
+ HTProgress(line);
+
+ } /* next bufferload */
+
+ _HTProgress("Data transfer complete");
+ (void)NETCLOSE(file_number);
+ rv = HT_LOADED;
+
+finished:
+ return(rv);
+}
+
+/* Push data from a file pointer down a stream
+** -------------------------------------
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the file.
+**
+**
+*/
+PUBLIC int HTFileCopy ARGS2(
+ FILE *, fp,
+ HTStream*, sink)
+{
+ HTStreamClass targetClass;
+ char line[256];
+ int status, bytes = 0, nreads = 0, nprogr = 0;
+ int rv = HT_OK;
+
+ /* Push the data down the stream
+ */
+ targetClass = *(sink->isa); /* Copy pointers to procedures */
+
+ /* Push binary from socket down sink
+ */
+ for (;;) {
+ status = fread(input_buffer, 1, INPUT_BUFFER_SIZE, fp);
+ nreads++;
+ if (status == 0) { /* EOF or error */
+ if (ferror(fp) == 0) {
+ rv = HT_LOADED;
+ break;
+ }
+ if (TRACE)
+ fprintf(stderr,
+ "HTFormat: Read error, read returns %d\n",
+ ferror(fp));
+ if (bytes) {
+ rv = HT_PARTIAL_CONTENT;
+ } else {
+ rv = -1;
+ }
+ break;
+ }
+ (*targetClass.put_block)(sink, input_buffer, status);
+
+ bytes += status;
+ if (nreads >= 100) {
+ /*
+ ** Show progress messages for local files, and check for
+ ** user interruption. Start doing so only after a certain
+ ** number of reads have been done, and don't update it on
+ ** every read (normally reading in a local file should be
+ ** speedy). - KW
+ */
+ if (nprogr == 0) {
+ if (bytes < 1024000) {
+ sprintf(line, "Read %d bytes of data.", bytes);
+ } else {
+ sprintf(line, "Read %d KB of data. %s",
+ bytes/1024,
+ "(Press 'z' if you want to abort loading.)");
+ }
+ HTProgress(line);
+ if (HTCheckForInterrupt()) {
+ _HTProgress ("Data transfer interrupted.");
+ if (bytes) {
+ rv = HT_INTERRUPTED;
+ } else {
+ rv = -1;
+ }
+ break;
+ }
+ nprogr++;
+ } else if (nprogr == 25) {
+ nprogr = 0;
+ } else {
+ nprogr++;
+ }
+ }
+ } /* next bufferload */
+
+ return rv;
+}
+
+#ifdef USE_ZLIB
+/* Push data from a gzip file pointer down a stream
+** -------------------------------------
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the file.
+**
+**
+*/
+PRIVATE int HTGzFileCopy ARGS2(
+ gzFile, gzfp,
+ HTStream*, sink)
+{
+ HTStreamClass targetClass;
+ char line[256];
+ int status, bytes = 0, nreads = 0, nprogr = 0;
+ int gzerrnum;
+ int rv = HT_OK;
+
+ /* Push the data down the stream
+ */
+ targetClass = *(sink->isa); /* Copy pointers to procedures */
+
+ /* read and inflate gzipped file, and push binary down sink
+ */
+ for (;;) {
+ status = gzread(gzfp, input_buffer, INPUT_BUFFER_SIZE);
+ nreads++;
+ if (status <= 0) { /* EOF or error */
+ if (status == 0) {
+ rv = HT_LOADED;
+ break;
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "HTGzFileCopy: Read error, gzread returns %d\n",
+ status);
+ fprintf(stderr,
+ "gzerror : %s\n",
+ gzerror(gzfp, &gzerrnum));
+ if (gzerrnum == Z_ERRNO)
+ perror("gzerror ");
+ }
+ if (bytes) {
+ rv = HT_PARTIAL_CONTENT;
+ } else {
+ rv = -1;
+ }
+ break;
+ }
+ (*targetClass.put_block)(sink, input_buffer, status);
+
+ bytes += status;
+ if (nreads >= 100) {
+ /*
+ ** Show progress messages for local files, and check for
+ ** user interruption. Start doing so only after a certain
+ ** number of reads have been done, and don't update it on
+ ** every read (normally reading in a local file should be
+ ** speedy). - KW
+ */
+ if (nprogr == 0) {
+ if (bytes < 1024000) {
+ sprintf(line,
+ "Read %d uncompressed bytes of data.", bytes);
+ } else {
+ sprintf(line, "Read %d uncompressed KB of data. %s",
+ bytes/1024,
+ "(Press 'z' to abort.)");
+ }
+ HTProgress(line);
+ if (HTCheckForInterrupt()) {
+ _HTProgress ("Data transfer interrupted.");
+ if (bytes) {
+ rv = HT_INTERRUPTED;
+ } else {
+ rv = -1;
+ }
+ break;
+ }
+ nprogr++;
+ } else if (nprogr == 25) {
+ nprogr = 0;
+ } else {
+ nprogr++;
+ }
+ }
+ } /* next bufferload */
+
+ return rv;
+}
+#endif /* USE_ZLIB */
+
+/* Push data from a socket down a stream STRIPPING CR
+** --------------------------------------------------
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the socket.
+**
+** The file number given is assumed to be a TELNET stream ie containing
+** CRLF at the end of lines which need to be stripped to LF for unix
+** when the format is textual.
+**
+*/
+PUBLIC void HTCopyNoCR ARGS3(
+ HTParentAnchor *, anchor GCC_UNUSED,
+ int, file_number,
+ HTStream*, sink)
+{
+ HTStreamClass targetClass;
+ char character;
+
+ /* Push the data, ignoring CRLF, down the stream
+ */
+ targetClass = *(sink->isa); /* Copy pointers to procedures */
+
+ /* Push text from telnet socket down sink
+ **
+ ** @@@@@ To push strings could be faster? (especially is we
+ ** cheat and don't ignore CR! :-}
+ */
+ HTInitInput(file_number);
+ for (;;) {
+ character = HTGetCharacter();
+ if (character == (char)EOF)
+ break;
+ (*targetClass.put_character)(sink, character);
+ }
+}
+
+/* Parse a socket given format and file number
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the file.
+**
+** The file number given is assumed to be a TELNET stream ie containing
+** CRLF at the end of lines which need to be stripped to LF for unix
+** when the format is textual.
+**
+*/
+PUBLIC int HTParseSocket ARGS5(
+ HTFormat, rep_in,
+ HTFormat, format_out,
+ HTParentAnchor *, anchor,
+ int, file_number,
+ HTStream*, sink)
+{
+ HTStream * stream;
+ HTStreamClass targetClass;
+ int rv;
+
+ stream = HTStreamStack(rep_in, format_out, sink, anchor);
+
+ if (!stream) {
+ char buffer[1024]; /* @@@@@@@@ */
+ if (LYCancelDownload) {
+ LYCancelDownload = FALSE;
+ return -1;
+ }
+ sprintf(buffer, "Sorry, can't convert from %s to %s.",
+ HTAtom_name(rep_in), HTAtom_name(format_out));
+ if (TRACE)
+ fprintf(stderr, "HTFormat: %s\n", buffer);
+ return HTLoadError(sink, 501, buffer); /* returns -501 */
+ }
+
+ /*
+ ** Push the data, don't worry about CRLF we can strip them later.
+ */
+ targetClass = *(stream->isa); /* Copy pointers to procedures */
+ rv = HTCopy(anchor, file_number, NULL, stream);
+ if (rv != -1 && rv != HT_INTERRUPTED)
+ (*targetClass._free)(stream);
+
+ return rv; /* full: HT_LOADED; partial: HT_INTERRUPTED; no bytes: -1 */
+}
+
+/* Parse a file given format and file pointer
+**
+** This routine is responsible for creating and PRESENTING any
+** graphic (or other) objects described by the file.
+**
+** The file number given is assumed to be a TELNET stream ie containing
+** CRLF at the end of lines which need to be stripped to \n for unix
+** when the format is textual.
+**
+*/
+PUBLIC int HTParseFile ARGS5(
+ HTFormat, rep_in,
+ HTFormat, format_out,
+ HTParentAnchor *, anchor,
+ FILE *, fp,
+ HTStream*, sink)
+{
+ HTStream * stream;
+ HTStreamClass targetClass;
+ int rv;
+
+ stream = HTStreamStack(rep_in,
+ format_out,
+ sink , anchor);
+
+ if (!stream) {
+ char buffer[1024]; /* @@@@@@@@ */
+ if (LYCancelDownload) {
+ LYCancelDownload = FALSE;
+ return -1;
+ }
+ sprintf(buffer, "Sorry, can't convert from %s to %s.",
+ HTAtom_name(rep_in), HTAtom_name(format_out));
+ if (TRACE)
+ fprintf(stderr, "HTFormat(in HTParseFile): %s\n", buffer);
+ return HTLoadError(sink, 501, buffer);
+ }
+
+ /* Push the data down the stream
+ **
+ ** @@ Bug: This decision ought to be made based on "encoding"
+ ** rather than on content-type. @@@ When we handle encoding.
+ ** The current method smells anyway.
+ */
+ targetClass = *(stream->isa); /* Copy pointers to procedures */
+ rv = HTFileCopy(fp, stream);
+ if (rv == -1 || rv == HT_INTERRUPTED) {
+ (*targetClass._abort)(stream, NULL);
+ } else {
+ (*targetClass._free)(stream);
+ }
+
+ if (rv == -1)
+ return HT_NO_DATA;
+ else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED))
+ return HT_PARTIAL_CONTENT;
+ else
+ return HT_LOADED;
+}
+
+#ifdef USE_ZLIB
+PRIVATE int HTCloseGzFile ARGS1(
+ gzFile, gzfp)
+{
+ int gzres;
+ if (gzfp == NULL)
+ return 0;
+ gzres = gzclose(gzfp);
+ if (TRACE) {
+ if (gzres == Z_ERRNO) {
+ perror("gzclose ");
+ } else if (gzres != Z_OK) {
+ fprintf(stderr, "gzclose : error number %d\n", gzres);
+ }
+ }
+ return(gzres);
+}
+
+PUBLIC int HTParseGzFile ARGS5(
+ HTFormat, rep_in,
+ HTFormat, format_out,
+ HTParentAnchor *, anchor,
+ gzFile, gzfp,
+ HTStream*, sink)
+{
+ HTStream * stream;
+ HTStreamClass targetClass;
+ int rv;
+
+ stream = HTStreamStack(rep_in,
+ format_out,
+ sink , anchor);
+
+ if (!stream) {
+ char buffer[1024]; /* @@@@@@@@ */
+ extern char LYCancelDownload;
+ HTCloseGzFile(gzfp);
+ if (LYCancelDownload) {
+ LYCancelDownload = FALSE;
+ return -1;
+ }
+ sprintf(buffer, "Sorry, can't convert from %s to %s.",
+ HTAtom_name(rep_in), HTAtom_name(format_out));
+ if (TRACE)
+ fprintf(stderr, "HTFormat(in HTParseGzFile): %s\n", buffer);
+ return HTLoadError(sink, 501, buffer);
+ }
+
+ /* Push the data down the stream
+ **
+ ** @@ Bug: This decision ought to be made based on "encoding"
+ ** rather than on content-type. @@@ When we handle encoding.
+ ** The current method smells anyway.
+ */
+ targetClass = *(stream->isa); /* Copy pointers to procedures */
+ rv = HTGzFileCopy(gzfp, stream);
+ if (rv == -1 || rv == HT_INTERRUPTED) {
+ (*targetClass._abort)(stream, NULL);
+ } else {
+ (*targetClass._free)(stream);
+ }
+
+ HTCloseGzFile(gzfp);
+ if (rv == -1)
+ return HT_NO_DATA;
+ else if (rv == HT_INTERRUPTED || (rv > 0 && rv != HT_LOADED))
+ return HT_PARTIAL_CONTENT;
+ else
+ return HT_LOADED;
+}
+#endif /* USE_ZLIB */
+
+/* Converter stream: Network Telnet to internal character text
+** -----------------------------------------------------------
+**
+** The input is assumed to be in ASCII, with lines delimited
+** by (13,10) pairs, These pairs are converted into (CR,LF)
+** pairs in the local representation. The (CR,LF) sequence
+** when found is changed to a '\n' character, the internal
+** C representation of a new line.
+*/
+
+PRIVATE void NetToText_put_character ARGS2(HTStream *, me, char, net_char)
+{
+ char c = FROMASCII(net_char);
+ if (me->had_cr) {
+ if (c == LF) {
+ me->sink->isa->put_character(me->sink, '\n'); /* Newline */
+ me->had_cr = NO;
+ return;
+ } else {
+ me->sink->isa->put_character(me->sink, CR); /* leftover */
+ }
+ }
+ me->had_cr = (c == CR);
+ if (!me->had_cr)
+ me->sink->isa->put_character(me->sink, c); /* normal */
+}
+
+PRIVATE void NetToText_put_string ARGS2(HTStream *, me, CONST char *, s)
+{
+ CONST char * p;
+
+ for (p = s; *p; p++)
+ NetToText_put_character(me, *p);
+}
+
+PRIVATE void NetToText_put_block ARGS3(HTStream *, me, CONST char*, s, int, l)
+{
+ CONST char * p;
+
+ for (p = s; p < (s+l); p++)
+ NetToText_put_character(me, *p);
+}
+
+PRIVATE void NetToText_free ARGS1(HTStream *, me)
+{
+ (me->sink->isa->_free)(me->sink); /* Close rest of pipe */
+ FREE(me);
+}
+
+PRIVATE void NetToText_abort ARGS2(HTStream *, me, HTError, e)
+{
+ me->sink->isa->_abort(me->sink,e); /* Abort rest of pipe */
+ FREE(me);
+}
+
+/* The class structure
+*/
+PRIVATE HTStreamClass NetToTextClass = {
+ "NetToText",
+ NetToText_free,
+ NetToText_abort,
+ NetToText_put_character,
+ NetToText_put_string,
+ NetToText_put_block
+};
+
+/* The creation method
+*/
+PUBLIC HTStream * HTNetToText ARGS1(HTStream *, sink)
+{
+ HTStream* me = (HTStream*)malloc(sizeof(*me));
+
+ if (me == NULL)
+ outofmem(__FILE__, "NetToText");
+ me->isa = &NetToTextClass;
+
+ me->had_cr = NO;
+ me->sink = sink;
+ return me;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.h
new file mode 100644
index 00000000000..225456b6eca
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTFormat.h
@@ -0,0 +1,441 @@
+/* HTFormat: The format manager in the WWW Library
+ MANAGE DIFFERENT DOCUMENT FORMATS
+
+ Here we describe the functions of the HTFormat module which handles conversion between
+ different data representations. (In MIME parlance, a representation is known as a
+ content-type. In WWW the term "format" is often used as it is shorter).
+
+ This module is implemented by HTFormat.c . This hypertext document is used to generate
+ the HTFormat.h include file. Part of the WWW library .
+
+Preamble
+
+ */
+#ifndef HTFORMAT_H
+#define HTFORMAT_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTStream.h"
+#include "HTAtom.h"
+#include "HTList.h"
+
+#ifdef SHORT_NAMES
+#define HTOutputSource HTOuSour
+#define HTOutputBinary HTOuBina
+#endif
+
+/*
+
+The HTFormat type
+
+ We use the HTAtom object for holding representations. This allows faster manipulation
+ (comparison and copying) that if we stayed with strings.
+
+ */
+typedef HTAtom * HTFormat;
+
+/*
+
+ These macros (which used to be constants) define some basic internally referenced
+ representations. The www/xxx ones are of course not MIME standard.
+
+ www/source is an output format which leaves the input untouched. It is useful for
+ diagnostics, and for users who want to see the original, whatever it is.
+
+ */
+ /* Internal ones */
+#define WWW_SOURCE HTAtom_for("www/source") /* Whatever it was originally*/
+
+/*
+
+ www/present represents the user's perception of the document. If you convert to
+ www/present, you present the material to the user.
+
+ */
+#define WWW_PRESENT HTAtom_for("www/present") /* The user's perception */
+
+/*
+
+ The message/rfc822 format means a MIME message or a plain text message with no MIME
+ header. This is what is returned by an HTTP server.
+
+ */
+#define WWW_MIME HTAtom_for("www/mime") /* A MIME message */
+
+/*
+
+ www/print is like www/present except it represents a printed copy.
+
+ */
+#define WWW_PRINT HTAtom_for("www/print") /* A printed copy */
+
+/*
+
+ www/unknown is a really unknown type. Some default action is appropriate.
+
+ */
+#define WWW_UNKNOWN HTAtom_for("www/unknown")
+
+#ifdef DIRED_SUPPORT
+/*
+ www/dired signals directory edit mode.
+*/
+#define WWW_DIRED HTAtom_for("www/dired")
+#endif
+
+/*
+
+ These are regular MIME types. HTML is assumed to be added by the W3 code.
+ application/octet-stream was mistakenly application/binary in earlier libwww versions
+ (pre 2.11).
+
+ */
+#define WWW_PLAINTEXT HTAtom_for("text/plain")
+#define WWW_POSTSCRIPT HTAtom_for("application/postscript")
+#define WWW_RICHTEXT HTAtom_for("application/rtf")
+#define WWW_AUDIO HTAtom_for("audio/basic")
+#define WWW_HTML HTAtom_for("text/html")
+#define WWW_BINARY HTAtom_for("application/octet-stream")
+
+/*
+
+ We must include the following file after defining HTFormat, to which it makes
+ reference.
+
+The HTEncoding type
+
+ */
+typedef HTAtom* HTEncoding;
+
+/*
+
+ The following are values for the MIME types:
+
+ */
+#define WWW_ENC_7BIT HTAtom_for("7bit")
+#define WWW_ENC_8BIT HTAtom_for("8bit")
+#define WWW_ENC_BINARY HTAtom_for("binary")
+
+/*
+
+ We also add
+
+ */
+#define WWW_ENC_COMPRESS HTAtom_for("compress")
+
+/*
+ Does a string designate a real encoding, or is it just
+ a "dummy" as for example 7bit, 8bit, and binary?
+ */
+#define IsUnityEncStr(senc) \
+ ((senc)==NULL || *(senc)=='\0' || !strcmp(senc,"identity") ||\
+ !strcmp(senc,"8bit") || !strcmp(senc,"binary") || !strcmp(senc,"7bit"))
+
+#define IsUnityEnc(enc) \
+ ((enc)==NULL || (enc)==HTAtom_for("identity") ||\
+ (enc)==WWW_ENC_8BIT || (enc)==WWW_ENC_BINARY || (enc)==WWW_ENC_7BIT)
+
+
+#include "HTAnchor.h"
+
+/*
+
+The HTPresentation and HTConverter types
+
+ This HTPresentation structure represents a possible conversion algorithm from one
+ format to annother. It includes a pointer to a conversion routine. The conversion
+ routine returns a stream to which data should be fed. See also HTStreamStack which
+ scans the list of registered converters and calls one. See the initialisation module
+ for a list of conversion routines.
+
+ */
+typedef struct _HTPresentation HTPresentation;
+
+typedef HTStream * HTConverter PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+struct _HTPresentation {
+ HTAtom * rep; /* representation name atmoized */
+ HTAtom * rep_out; /* resulting representation */
+ HTConverter * converter; /* The routine to gen the stream stack */
+ char * command; /* MIME-format string */
+ float quality; /* Between 0 (bad) and 1 (good) */
+ float secs;
+ float secs_per_byte;
+ long int maxbytes;
+};
+
+/*
+
+ The list of presentations is kept by this module. It is also scanned by modules which
+ want to know the set of formats supported. for example.
+
+ */
+extern HTList * HTPresentations;
+
+/*
+
+ The default presentation is used when no other is appriporate
+
+ */
+extern HTPresentation* default_presentation;
+
+/*
+
+HTSetPresentation: Register a system command to present a format
+
+ ON ENTRY,
+
+ rep is the MIME - style format name
+
+ command is the MAILCAP - style command template
+
+ quality A degradation faction 0..1.0
+
+ secs A limit on the time user will wait (0.0 for infinity)
+ secs_per_byte
+
+ maxbytes A limit on the length acceptable as input (0 infinite)
+
+ */
+extern void HTSetPresentation PARAMS((
+ CONST char * representation,
+ CONST char * command,
+ float quality,
+ float secs,
+ float secs_per_byte,
+ long int maxbytes
+));
+
+
+/*
+
+HTSetConversion: Register a converstion routine
+
+ ON ENTRY,
+
+ rep_in is the content-type input
+
+ rep_out is the resulting content-type
+
+ converter is the routine to make the stream to do it
+
+ */
+
+extern void HTSetConversion PARAMS((
+ CONST char * rep_in,
+ CONST char * rep_out,
+ HTConverter * converter,
+ float quality,
+ float secs,
+ float secs_per_byte,
+ long int maxbytes
+));
+
+
+/*
+
+HTStreamStack: Create a stack of streams
+
+ This is the routine which actually sets up the conversion. It currently checks only for
+ direct conversions, but multi-stage conversions are forseen. It takes a stream into
+ which the output should be sent in the final format, builds the conversion stack, and
+ returns a stream into which the data in the input format should be fed. The anchor is
+ passed because hypertxet objects load information into the anchor object which
+ represents them.
+
+ */
+extern HTStream * HTStreamStack PARAMS((
+ HTFormat format_in,
+ HTFormat format_out,
+ HTStream* stream_out,
+ HTParentAnchor* anchor));
+
+/*
+HTReorderPresentation: put presentation near head of list
+
+ Look up a presentation (exact match only) and, if found, reorder
+ it to the start of the HTPresentations list. - kw
+ */
+
+extern void HTReorderPresentation PARAMS((
+ HTFormat format_in,
+ HTFormat format_out));
+
+/*
+
+HTStackValue: Find the cost of a filter stack
+
+ Must return the cost of the same stack which HTStreamStack would set up.
+
+ ON ENTRY,
+
+ format_in The fomat of the data to be converted
+
+ format_out The format required
+
+ initial_value The intrinsic "value" of the data before conversion on a scale
+ from 0 to 1
+
+ length The number of bytes expected in the input format
+
+ */
+extern float HTStackValue PARAMS((
+ HTFormat format_in,
+ HTFormat rep_out,
+ float initial_value,
+ long int length));
+
+#define NO_VALUE_FOUND -1e20 /* returned if none found */
+
+/*
+
+HTCopy: Copy a socket to a stream
+
+ This is used by the protocol engines to send data down a stream, typically one which
+ has been generated by HTStreamStack.
+
+ */
+extern int HTCopy PARAMS((
+ HTParentAnchor * anchor,
+ int file_number,
+ void* handle,
+ HTStream* sink));
+
+
+/*
+
+HTFileCopy: Copy a file to a stream
+
+ This is used by the protocol engines to send data down a stream, typically one which
+ has been generated by HTStreamStack. It is currently called by HTParseFile
+
+ */
+extern int HTFileCopy PARAMS((
+ FILE* fp,
+ HTStream* sink));
+
+
+/*
+
+HTCopyNoCR: Copy a socket to a stream, stripping CR characters.
+
+ It is slower than HTCopy .
+
+ */
+
+extern void HTCopyNoCR PARAMS((
+ HTParentAnchor * anchor,
+ int file_number,
+ HTStream* sink));
+
+
+/*
+
+Clear input buffer and set file number
+
+ This routine and the one below provide simple character input from sockets. (They are
+ left over from the older architecure and may not be used very much.) The existence of
+ a common routine and buffer saves memory space in small implementations.
+
+ */
+extern void HTInitInput PARAMS((int file_number));
+
+/*
+
+Get next character from buffer
+
+ */
+extern int interrupted_in_htgetcharacter;
+extern char HTGetCharacter NOPARAMS;
+
+
+/*
+
+HTParseSocket: Parse a socket given its format
+
+ This routine is called by protocol modules to load an object. uses HTStreamStack and
+ the copy routines above. Returns HT_LOADED if succesful, <0 if not.
+
+ */
+extern int HTParseSocket PARAMS((
+ HTFormat format_in,
+ HTFormat format_out,
+ HTParentAnchor *anchor,
+ int file_number,
+ HTStream* sink));
+
+/*
+
+HTParseFile: Parse a File through a file pointer
+
+ This routine is called by protocols modules to load an object. uses HTStreamStack and
+ HTFileCopy . Returns HT_LOADED if succesful, <0 if not.
+
+ */
+extern int HTParseFile PARAMS((
+ HTFormat format_in,
+ HTFormat format_out,
+ HTParentAnchor *anchor,
+ FILE *fp,
+ HTStream* sink));
+
+#ifdef USE_ZLIB
+
+#ifdef USE_ZLIB
+#include <zlib.h>
+#endif /* USE_ZLIB */
+/*
+HTParseGzFile: Parse a gzipped File through a file pointer
+
+ This routine is called by protocols modules to load an object. uses HTStreamStack and
+ HTGzFileCopy . Returns HT_LOADED if succesful, <0 if not.
+ */
+extern int HTParseGzFile PARAMS((
+ HTFormat format_in,
+ HTFormat format_out,
+ HTParentAnchor *anchor,
+ gzFile gzfp,
+ HTStream* sink));
+
+#endif /* USE_ZLIB */
+
+/*
+
+HTNetToText: Convert Net ASCII to local representation
+
+ This is a filter stream suitable for taking text from a socket and passing it into a
+ stream which expects text in the local C representation. It does ASCII and newline
+ conversion. As usual, pass its output stream to it when creating it.
+
+ */
+extern HTStream * HTNetToText PARAMS ((HTStream * sink));
+
+/*
+
+HTFormatInit: Set up default presentations and conversions
+
+ These are defined in HTInit.c or HTSInit.c if these have been replaced. If you don't
+ call this routine, and you don't define any presentations, then this routine will
+ automatically be called the first time a conversion is needed. However, if you
+ explicitly add some conversions (eg using HTLoadRules) then you may want also to
+ explicitly call this to get the defaults as well.
+
+ */
+extern void HTFormatInit NOPARAMS;
+
+/*
+
+Epilogue
+
+ */
+extern BOOL HTOutputSource; /* Flag: shortcut parser */
+#endif
+
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.c
new file mode 100644
index 00000000000..23e8f9d07b7
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.c
@@ -0,0 +1,2004 @@
+/* GOPHER ACCESS HTGopher.c
+** =============
+**
+** History:
+** 26 Sep 90 Adapted from other accesses (News, HTTP) TBL
+** 29 Nov 91 Downgraded to C, for portable implementation.
+** 10 Mar 96 Foteos Macrides (macrides@sci.wfbr.edu). Added a
+** form-based CSO/PH gateway. Can be invoked via a
+** "cso://host[:port]/" or "gopher://host:105/2"
+** URL. If a gopher URL is used with a query token
+** ('?'), the old ISINDEX procedure will be used
+** instead of the form-based gateway.
+** 15 Mar 96 Foteos Macrides (macrides@sci.wfbr.edu). Pass
+** port 79, gtype 0 gopher URLs to the finger
+** gateway.
+*/
+
+#include "HTUtils.h" /* Coding convention macros */
+#include "tcp.h"
+#include "HTAlert.h"
+#include "HTParse.h"
+#include "HTTCP.h"
+#include "HTFinger.h"
+
+/*
+** Implements.
+*/
+#include "HTGopher.h"
+
+#define HT_EM_SPACE ((char)2) /* For now */
+
+#define GOPHER_PORT 70 /* See protocol spec */
+#define CSO_PORT 105 /* See protocol spec */
+#define BIG 1024 /* Bug */
+#define LINE_LENGTH 256 /* Bug */
+
+/*
+** Gopher entity types.
+*/
+#define GOPHER_TEXT '0'
+#define GOPHER_MENU '1'
+#define GOPHER_CSO '2'
+#define GOPHER_ERROR '3'
+#define GOPHER_MACBINHEX '4'
+#define GOPHER_PCBINARY '5'
+#define GOPHER_UUENCODED '6'
+#define GOPHER_INDEX '7'
+#define GOPHER_TELNET '8'
+#define GOPHER_BINARY '9'
+#define GOPHER_GIF 'g'
+#define GOPHER_HTML 'h' /* HTML */
+#define GOPHER_CHTML 'H' /* HTML */
+#define GOPHER_SOUND 's'
+#define GOPHER_WWW 'w' /* W3 address */
+#define GOPHER_IMAGE 'I'
+#define GOPHER_TN3270 'T'
+#define GOPHER_INFO 'i'
+#define GOPHER_DUPLICATE '+'
+#define GOPHER_PLUS_IMAGE ':' /* Addition from Gopher Plus */
+#define GOPHER_PLUS_MOVIE ';'
+#define GOPHER_PLUS_SOUND '<'
+#define GOPHER_PLUS_PDF 'P'
+
+#include <ctype.h>
+
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTTCP.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+** Hypertext object building machinery.
+*/
+#include "HTML.h"
+
+#include "LYLeaks.h"
+
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET (*targetClass._free)(target)
+
+#define GOPHER_PROGRESS(foo) HTAlert(foo)
+
+#define NEXT_CHAR HTGetCharacter()
+
+/*
+** Module-wide variables.
+*/
+PRIVATE int s; /* Socket for gopher or CSO host */
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa; /* For gopher streams */
+ /* ... */
+};
+
+PRIVATE HTStructured *target; /* the new gopher hypertext */
+PRIVATE HTStructuredClass targetClass; /* Its action routines */
+
+struct _HTStream
+{
+ HTStreamClass * isa; /* For form-based CSO gateway - FM */
+};
+
+typedef struct _CSOfield_info { /* For form-based CSO gateway - FM */
+ struct _CSOfield_info * next;
+ char * name;
+ char * attributes;
+ char * description;
+ int id;
+ int lookup;
+ int indexed;
+ int url;
+ int max_size;
+ int defreturn;
+ int explicit_return;
+ int reserved;
+ int public;
+ char name_buf[16]; /* Avoid malloc if we can */
+ char desc_buf[32]; /* Avoid malloc if we can */
+ char attr_buf[80]; /* Avoid malloc if we can */
+} CSOfield_info;
+
+PRIVATE CSOfield_info *CSOfields = NULL; /* For form-based CSO gateway - FM */
+
+typedef struct _CSOformgen_context { /* For form-based CSO gateway - FM */
+ char * host;
+ char * seek;
+ CSOfield_info * fld;
+ int port;
+ int cur_line;
+ int cur_off;
+ int rep_line;
+ int rep_off;
+ int public_override;
+ int field_select;
+} CSOformgen_context;
+
+/* Matrix of allowed characters in filenames
+** =========================================
+*/
+PRIVATE BOOL acceptable[256];
+PRIVATE BOOL acceptable_inited = NO;
+
+PRIVATE void init_acceptable NOARGS
+{
+ unsigned int i;
+ char * good =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
+ for(i = 0; i < 256; i++)
+ acceptable[i] = NO;
+ for(; *good; good++)
+ acceptable[(unsigned int)*good] = YES;
+ acceptable_inited = YES;
+}
+
+/* Decode one hex character
+** ========================
+*/
+PRIVATE CONST char hex[17] = "0123456789abcdef";
+
+PRIVATE char from_hex ARGS1(char, c)
+{
+ return (c>='0')&&(c<='9') ? c-'0'
+ : (c>='A')&&(c<='F') ? c-'A'+10
+ : (c>='a')&&(c<='f') ? c-'a'+10
+ : 0;
+}
+
+/* Paste in an Anchor
+** ==================
+**
+** The title of the destination is set, as there is no way
+** of knowing what the title is when we arrive.
+**
+** On entry,
+** HT is in append mode.
+** text points to the text to be put into the file, 0 terminated.
+** addr points to the hypertext refernce address 0 terminated.
+*/
+PUBLIC BOOLEAN HT_Is_Gopher_URL=FALSE;
+
+PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr)
+{
+ BOOL present[HTML_A_ATTRIBUTES];
+ CONST char * value[HTML_A_ATTRIBUTES];
+
+ int i;
+
+ for (i = 0; i < HTML_A_ATTRIBUTES; i++)
+ present[i] = 0;
+ present[HTML_A_HREF] = YES;
+ ((CONST char **)value)[HTML_A_HREF] = addr;
+ present[HTML_A_TITLE] = YES;
+ ((CONST char **)value)[HTML_A_TITLE] = text;
+
+ if(TRACE)
+ fprintf(stderr,"HTGopher: adding URL: %s\n",addr);
+
+ HT_Is_Gopher_URL = TRUE; /* tell HTML.c that this is a Gopher URL */
+ (*targetClass.start_element)(target, HTML_A, present,
+ (CONST char **)value, -1, 0);
+
+ PUTS(text);
+ END(HTML_A);
+}
+
+/* Parse a Gopher Menu document
+** ============================
+*/
+PRIVATE void parse_menu ARGS2(
+ CONST char *, arg GCC_UNUSED,
+ HTParentAnchor *, anAnchor)
+{
+ char gtype;
+ char ch;
+ char line[BIG];
+ char address[BIG];
+ char *name = NULL, *selector = NULL; /* Gopher menu fields */
+ char *host = NULL;
+ char *port;
+ char *p = line;
+ CONST char *title;
+ int bytes = 0;
+ int BytesReported = 0;
+ char buffer[128];
+
+#define TAB '\t'
+#define HEX_ESCAPE '%'
+
+
+ START(HTML_HTML);
+ PUTS("\n");
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else
+ PUTS("Gopher Menu");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+
+ START(HTML_BODY);
+ PUTS("\n");
+ START(HTML_H1);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else
+ PUTS("Gopher Menu");
+ END(HTML_H1);
+ PUTS("\n");
+ START(HTML_PRE);
+ while ((ch=NEXT_CHAR) != (char)EOF) {
+
+ if (interrupted_in_htgetcharacter) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTGopher: Interrupted in HTGetCharacter, apparently.\n");
+ goto end_html;
+ }
+
+ if (ch != LF) {
+ *p = ch; /* Put character in line */
+ if (p< &line[BIG-1]) p++;
+
+ } else {
+ *p++ = '\0'; /* Terminate line */
+ bytes += p-line; /* add size */
+ p = line; /* Scan it to parse it */
+ port = 0; /* Flag "not parsed" */
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Menu item: %s\n", line);
+ gtype = *p++;
+
+ if (bytes > BytesReported + 1024) {
+ sprintf(buffer, "Transferred %d bytes", bytes);
+ HTProgress(buffer);
+ BytesReported = bytes;
+ }
+
+ /* Break on line with a dot by itself */
+ if ((gtype=='.') && ((*p=='\r') || (*p==0)))
+ break;
+
+ if (gtype && *p) {
+ name = p;
+ selector = strchr(name, TAB);
+ if (selector) {
+ *selector++ = '\0'; /* Terminate name */
+ /*
+ * Gopher+ Type=0+ objects can be binary, and will
+ * have 9 or 5 beginning their selector. Make sure
+ * we don't trash the terminal by treating them as
+ * text. - FM
+ */
+ if (gtype == GOPHER_TEXT && (*selector == GOPHER_BINARY ||
+ *selector == GOPHER_PCBINARY))
+ gtype = *selector;
+ host = strchr(selector, TAB);
+ if (host) {
+ *host++ = '\0'; /* Terminate selector */
+ port = strchr(host, TAB);
+ if (port) {
+ char *junk;
+ port[0] = ':'; /* delimit host a la W3 */
+ junk = strchr(port, TAB);
+ if (junk) *junk++ = '\0'; /* Chop port */
+ if ((port[1]=='0') && (!port[2]))
+ port[0] = '\0'; /* 0 means none */
+ } /* no port */
+ } /* host ok */
+ } /* selector ok */
+ } /* gtype and name ok */
+
+ /* Nameless files are a separator line */
+ if (gtype == GOPHER_TEXT) {
+ int i = strlen(name)-1;
+ while (name[i] == ' ' && i >= 0)
+ name[i--] = '\0';
+ if (i < 0)
+ gtype = GOPHER_INFO;
+ }
+
+ if (gtype == GOPHER_WWW) { /* Gopher pointer to W3 */
+ PUTS("(HTML) ");
+ write_anchor(name, selector);
+
+ } else if (gtype == GOPHER_INFO) {
+ /* Information or separator line */
+ PUTS(" ");
+ PUTS(name);
+
+ } else if (port) { /* Other types need port */
+ if (gtype == GOPHER_TELNET) {
+ PUTS(" (TEL) ");
+ if (*selector) sprintf(address, "telnet://%s@%s/",
+ selector, host);
+ else sprintf(address, "telnet://%s/", host);
+ }
+ else if (gtype == GOPHER_TN3270)
+ {
+ PUTS("(3270) ");
+ if (*selector)
+ sprintf(address, "tn3270://%s@%s/",
+ selector, host);
+ else
+ sprintf(address, "tn3270://%s/", host);
+ }
+ else { /* If parsed ok */
+ char *q;
+ char *r;
+
+ switch(gtype) {
+ case GOPHER_TEXT:
+ PUTS("(FILE) ");
+ break;
+ case GOPHER_MENU:
+ PUTS(" (DIR) ");
+ break;
+ case GOPHER_CSO:
+ PUTS(" (CSO) ");
+ break;
+ case GOPHER_PCBINARY:
+ PUTS(" (BIN) ");
+ break;
+ case GOPHER_UUENCODED:
+ PUTS(" (UUE) ");
+ break;
+ case GOPHER_INDEX:
+ PUTS(" (?) ");
+ break;
+ case GOPHER_BINARY:
+ PUTS(" (BIN) ");
+ break;
+ case GOPHER_GIF:
+ case GOPHER_IMAGE:
+ case GOPHER_PLUS_IMAGE:
+ PUTS(" (IMG) ");
+ break;
+ case GOPHER_SOUND:
+ case GOPHER_PLUS_SOUND:
+ PUTS(" (SND) ");
+ break;
+ case GOPHER_MACBINHEX:
+ PUTS(" (HQX) ");
+ break;
+ case GOPHER_HTML:
+ case GOPHER_CHTML:
+ PUTS("(HTML) ");
+ break;
+ case 'm':
+ PUTS("(MIME) ");
+ break;
+ case GOPHER_PLUS_MOVIE:
+ PUTS(" (MOV) ");
+ break;
+ case GOPHER_PLUS_PDF:
+ PUTS(" (PDF) ");
+ break;
+ default:
+ PUTS("(UNKN) ");
+ break;
+ }
+
+ sprintf(address, "//%s/%c", host, gtype);
+
+ q = address+ strlen(address);
+ for(r=selector; *r; r++) { /* Encode selector string */
+ if (acceptable[(unsigned char)*r]) *q++ = *r;
+ else {
+ *q++ = HEX_ESCAPE; /* Means hex coming */
+ *q++ = hex[(TOASCII(*r)) >> 4];
+ *q++ = hex[(TOASCII(*r)) & 15];
+ }
+ }
+
+ *q++ = '\0'; /* terminate address */
+ }
+ /* Error response from Gopher doesn't deserve to
+ be a hyperlink. */
+ if (strcmp (address, "gopher://error.host:1/0"))
+ write_anchor(name, address);
+ else
+ PUTS(name);
+ } else { /* parse error */
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Bad menu item.\n");
+ PUTS(line);
+
+ } /* parse error */
+
+ PUTS("\n");
+ p = line; /* Start again at beginning of line */
+
+ } /* if end of line */
+
+ } /* Loop over characters */
+
+end_html:
+ END(HTML_PRE);
+ PUTS("\n");
+ END(HTML_BODY);
+ PUTS("\n");
+ END(HTML_HTML);
+ PUTS("\n");
+ FREE_TARGET;
+
+ return;
+}
+
+/* Parse a Gopher CSO document from an ISINDEX query.
+** ==================================================
+**
+** Accepts an open socket to a CSO server waiting to send us
+** data and puts it on the screen in a reasonable manner.
+**
+** Perhaps this data can be automatically linked to some
+** other source as well???
+**
+** Taken from hacking by Lou Montulli@ukanaix.cc.ukans.edu
+** on XMosaic-1.1, and put on libwww 2.11 by Arthur Secret,
+** secret@dxcern.cern.ch .
+*/
+PRIVATE void parse_cso ARGS2(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor)
+{
+ char ch;
+ char line[BIG];
+ char *p = line;
+ char *second_colon, last_char='\0';
+ CONST char *title;
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else
+ PUTS("CSO Search Results");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_H1);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else {
+ PUTS(arg);
+ PUTS(" Search Results");
+ }
+ END(HTML_H1);
+ PUTS("\n");
+ START(HTML_PRE);
+
+ /*
+ ** Start grabbing chars from the network.
+ */
+ while ((ch=NEXT_CHAR) != (char)EOF)
+ {
+ if (ch != LF)
+ {
+ *p = ch; /* Put character in line */
+ if (p< &line[BIG-1]) p++;
+ }
+ else
+ {
+ *p = '\0'; /* Terminate line */
+ p = line; /* Scan it to parse it */
+ /*
+ ** OK we now have a line in 'p'.
+ ** Lets parse it and print it.
+ */
+
+ /*
+ ** Break on line that begins with a 2.
+ ** It's the end of data.
+ */
+ if (*p == '2')
+ break;
+
+ /*
+ ** Lines beginning with 5 are errors.
+ ** Print them and quit.
+ */
+ if (*p == '5') {
+ START(HTML_H2);
+ PUTS(p+4);
+ END(HTML_H2);
+ break;
+ }
+
+ if (*p == '-') {
+ /*
+ ** Data lines look like -200:#:
+ ** where # is the search result number and can be
+ ** multiple digits (infinite?).
+ ** Find the second colon and check the digit to the
+ ** left of it to see if they are diferent.
+ ** If they are then a different person is starting.
+ ** Make this line an <h2>.
+ */
+
+ /*
+ ** Find the second_colon.
+ */
+ second_colon = strchr( strchr(p,':')+1, ':');
+
+ if(second_colon != NULL) { /* error check */
+
+ if (*(second_colon-1) != last_char)
+ /* print seperator */
+ {
+ END(HTML_PRE);
+ START(HTML_H2);
+ }
+
+
+ /*
+ ** Right now the record appears with the alias
+ ** (first line) as the header and the rest as
+ ** <pre> text.
+ ** It might look better with the name as the
+ ** header and the rest as a <ul> with <li> tags.
+ ** I'm not sure whether the name field comes in
+ ** any special order or if its even required in
+ ** a record, so for now the first line is the
+ ** header no matter what it is (it's almost
+ ** always the alias).
+ ** A <dl> with the first line as the <DT> and
+ ** the rest as some form of <DD> might good also?
+ */
+
+ /*
+ ** Print data.
+ */
+ PUTS(second_colon+1);
+ PUTS("\n");
+
+ if (*(second_colon-1) != last_char)
+ /* end seperator */
+ {
+ END(HTML_H2);
+ START(HTML_PRE);
+ }
+
+ /*
+ ** Save the char before the second colon
+ ** for comparison on the next pass.
+ */
+ last_char = *(second_colon-1) ;
+
+ } /* end if second_colon */
+ } /* end if *p == '-' */
+ } /* if end of line */
+
+ } /* Loop over characters */
+
+ /* end the text block */
+ PUTS("\n");
+ END(HTML_PRE);
+ PUTS("\n");
+ FREE_TARGET;
+
+ return; /* all done */
+} /* end of procedure */
+
+/* Display a Gopher CSO ISINDEX cover page.
+** ========================================
+*/
+PRIVATE void display_cso ARGS2(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor)
+{
+ CONST char * title;
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else
+ PUTS("CSO index");
+ END(HTML_TITLE);
+ PUTS("\n");
+ START(HTML_ISINDEX);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_H1);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else {
+ PUTS(arg);
+ PUTS(" index");
+ }
+ END(HTML_H1);
+ PUTS("\nThis is a searchable index of a CSO database.\n");
+ START(HTML_P);
+ PUTS("\nPress the 's' key and enter search keywords.\n");
+ START(HTML_P);
+ PUTS("\nThe keywords that you enter will allow you to search on a");
+ PUTS(" person's name in the database.\n");
+
+ if (!HTAnchor_title(anAnchor))
+ HTAnchor_setTitle(anAnchor, arg);
+
+ FREE_TARGET;
+ return;
+}
+
+/* Display a Gopher Index document.
+** ================================
+*/
+PRIVATE void display_index ARGS2(
+ CONST char *, arg,
+ HTParentAnchor *,anAnchor)
+{
+ CONST char * title;
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ PUTS("\n");
+ START(HTML_TITLE);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else
+ PUTS("Gopher index");
+ END(HTML_TITLE);
+ PUTS("\n");
+ START(HTML_ISINDEX);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_H1);
+ if ((title = HTAnchor_title(anAnchor)))
+ PUTS(title);
+ else {
+ PUTS(arg);
+ PUTS(" index");
+ }
+ END(HTML_H1);
+ PUTS("\nThis is a searchable Gopher index.\n");
+ START(HTML_P);
+ PUTS("\nPlease enter search keywords.\n");
+
+ if (!HTAnchor_title(anAnchor))
+ HTAnchor_setTitle(anAnchor, arg);
+
+ FREE_TARGET;
+ return;
+}
+
+/* De-escape a selector into a command.
+** ====================================
+**
+** The % hex escapes are converted. Otheriwse, the string is copied.
+*/
+PRIVATE void de_escape ARGS2(char *, command, CONST char *, selector)
+{
+ CONST char * p = selector;
+ char * q = command;
+ if (command == NULL)
+ outofmem(__FILE__, "HTLoadGopher");
+ while (*p) { /* Decode hex */
+ if (*p == HEX_ESCAPE) {
+ char c;
+ unsigned int b;
+ p++;
+ c = *p++;
+ b = from_hex(c);
+ c = *p++;
+ if (!c) break; /* Odd number of chars! */
+ *q++ = FROMASCII((b<<4) + from_hex(c));
+ } else {
+ *q++ = *p++; /* Record */
+ }
+ }
+ *q++ = '\0'; /* Terminate command */
+}
+
+
+/* Free the CSOfields structures. - FM
+** ===================================
+*/
+PRIVATE void free_CSOfields NOPARAMS
+{
+ CSOfield_info *cur = CSOfields;
+ CSOfield_info *prev;
+
+ while (cur) {
+ if (cur->name != cur->name_buf)
+ FREE(cur->name);
+ if (cur->attributes != cur->attr_buf)
+ FREE(cur->attributes);
+ if (cur->description != cur->desc_buf)
+ FREE(cur->description);
+ prev = cur;
+ cur = cur->next;
+ FREE(prev);
+ }
+
+ return;
+}
+
+/* Interpret CSO/PH form template keys. - FM
+** =========================================
+*/
+PRIVATE int interpret_cso_key ARGS5(
+ char *, key,
+ char *, buf,
+ int *, length,
+ CSOformgen_context *, ctx,
+ HTStream *, Target)
+{
+ CSOfield_info *fld;
+
+ if ((fld = ctx->fld) != 0) {
+ /*
+ ** Most substitutions only recognized inside of loops.
+ */
+ int error = 0;
+ if (0 == strncmp(key, "$(FID)", 6)) {
+ sprintf(buf, "%d", fld->id);
+ } else if (0 == strncmp(key, "$(FDESC)", 8)) {
+ sprintf(buf, "%s%s%s", fld->description,
+ ctx->public_override ? /***" "***/"" : "",
+ ctx->public_override ? /***fld->attributes***/"" : "");
+ } else if (0 == strncmp(key, "$(FDEF)", 7)) {
+ strcpy(buf, fld->defreturn ? " checked" : "");
+ } else if (0 == strncmp(key, "$(FNDX)", 7)) {
+ strcpy(buf, fld->indexed ? "*" : "");
+ } else if (0 == strncmp(key, "$(FSIZE)", 8)) {
+ sprintf(buf, " size=%d maxlength=%d",
+ fld->max_size > 55 ? 55 : fld->max_size,
+ fld->max_size);
+ } else if (0 == strncmp(key, "$(FSIZE2)", 9)) {
+ sprintf(buf, " maxlength=%d", fld->max_size);
+ } else {
+ error = 1;
+ }
+ if (!error) {
+ *length = strlen(buf);
+ return -1;
+ }
+ }
+ buf[0] = '\0';
+ if (0 == strncmp(key, "$(NEXTFLD)", 10)) {
+ if (!ctx->fld)
+ fld = CSOfields;
+ else
+ fld = ctx->fld->next;
+ switch (ctx->field_select) {
+ case 0:
+ /*
+ ** 'Query' fields, public and lookup attributes.
+ */
+ for (; fld; fld = fld->next)
+ if (fld->public && (fld->lookup==1))
+ break;
+ break;
+ case 1:
+ /*
+ ** 'Query' fields, accept lookup attribute.
+ */
+ for (; fld; fld = fld->next)
+ if (fld->lookup == 1)
+ break;
+ break;
+ case 2:
+ /*
+ ** 'Return' fields, public only.
+ */
+ for (; fld; fld = fld->next)
+ if (fld->public)
+ break;
+ break;
+ case 3:
+ /*
+ ** All fields.
+ */
+ break;
+ }
+ if (fld) {
+ ctx->cur_line = ctx->rep_line;
+ ctx->cur_off = ctx->rep_off;
+ }
+ ctx->fld = fld;
+
+ } else if ((0 == strncmp(key, "$(QFIELDS)", 10)) ||
+ (0 == strncmp(key, "$(RFIELDS)", 10))) {
+ /*
+ ** Begin iteration sequence.
+ */
+ ctx->rep_line = ctx->cur_line;
+ ctx->rep_off = ctx->cur_off;
+ ctx->fld = (CSOfield_info *) 0;
+ ctx->seek = "$(NEXTFLD)";
+ ctx->field_select = (key[2] == 'Q') ? 0 : 2;
+ if (ctx->public_override)
+ ctx->field_select++;
+
+ } else if (0 == strncmp(key, "$(NAMEFLD)", 10)) {
+ /*
+ ** Special, locate name field. Flag lookup so QFIELDS will skip it.
+ */
+ for (fld = CSOfields; fld; fld = fld->next)
+ if (strcmp(fld->name, "name") == 0 ||
+ strcmp(fld->name, "Name") == 0) {
+ if (fld->lookup)
+ fld->lookup = 2;
+ break;
+ }
+ ctx->fld = fld;
+ } else if (0 == strncmp (key, "$(HOST)", 7)) {
+ strcpy (buf, ctx->host);
+ } else if (0 == strncmp (key, "$(PORT)", 7)) {
+ sprintf(buf, "%d", ctx->port);
+ } else {
+ /*
+ ** No match, dump key to buffer so client sees it for debugging.
+ */
+ size_t out = 0;
+ while (*key && (*key != ')')) {
+ buf[out++] = (*key++);
+ if (out > sizeof(buf)-2) {
+ buf[out] = '\0';
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ out = 0;
+ }
+ }
+ buf[out++] = ')';
+ buf[out] = '\0';
+ *length = strlen(buf);
+ return -1;
+ }
+ *length = strlen(buf);
+ return 0;
+}
+
+/* Parse the elements in a CSO/PH fields structure. - FM
+** =====================================================
+*/
+PRIVATE int parse_cso_field_info ARGS1(
+ CSOfield_info *, blk)
+{
+ int i;
+ char *info, *max_spec;
+
+ /*
+ ** Initialize all fields to default values.
+ */
+ blk->indexed = blk->lookup = blk->reserved = blk->max_size = blk->url = 0;
+ blk->defreturn = blk->explicit_return = blk->public = 0;
+
+ /*
+ ** Search for keywords in info string and set values. Attributes
+ ** are converted to all lower-case for comparison.
+ */
+ info = blk->attributes;
+ for (i = 0; info[i]; i++)
+ info[i] = TOLOWER(info[i]);
+ if (strstr(info, "indexed "))
+ blk->indexed = 1;
+ if (strstr(info, "default "))
+ blk->defreturn = 1;
+ if (strstr(info, "public "))
+ blk->public = 1;
+ if (strstr(info, "lookup "))
+ blk->lookup = 1;
+ if (strstr(info, "url ")) {
+ blk->url = 1;
+ blk->defreturn = 1;
+ }
+ max_spec = strstr(info, "max ");
+ if (max_spec) {
+ sscanf(&max_spec[4], "%d", &blk->max_size);
+ } else {
+ blk->max_size = 32;
+ }
+
+ return 0;
+}
+
+/* Parse a reply from a CSO/PH fields request. - FM
+** ================================================
+*/
+PRIVATE int parse_cso_fields ARGS2(
+ char *, buf,
+ int, size)
+{
+ char ch;
+ char *p = buf;
+ int i, code = 0, prev_code;
+ size_t alen;
+ char *indx, *name;
+ CSOfield_info *last, *new;
+
+ last = CSOfields = (CSOfield_info *) 0;
+ prev_code = -2555;
+ buf[0] = '\0';
+
+ /*
+ ** Start grabbing chars from the network.
+ */
+ while ((ch = NEXT_CHAR) != (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTLoadCSO: Interrupted in HTGetCharacter, apparently.\n");
+ }
+ free_CSOfields();
+ buf[0] = '\0';
+ return HT_INTERRUPTED;
+ }
+
+ if (ch != LF) {
+ *p = ch; /* Put character in buffer */
+ if (p < &buf[size-1]) {
+ p++;
+ }
+ } else {
+ *p = '\0'; /* Terminate line */
+ p = buf; /* Scan it to parse it */
+
+ /* OK we now have a line in 'p' lets parse it.
+ */
+
+ /*
+ ** Break on line that begins with a 2.
+ ** It's the end of data.
+ */
+ if (*p == '2')
+ break;
+
+ /*
+ ** Lines beginning with 5 are errors.
+ ** Print them and quit.
+ */
+ if (*p == '5') {
+ strcpy (buf, p);
+ return 5;
+ }
+
+ if (*p == '-') {
+ /*
+ ** Data lines look like -200:#:
+ ** where # is the search result number and can be
+ ** multiple digits (infinite?).
+ */
+
+ /*
+ ** Check status, ignore any non-success.
+ */
+ if (p[1] != '2' )
+ continue;
+
+ /*
+ ** Parse fields within returned line into status, ndx, name, data.
+ */
+ indx = NULL;
+ name = NULL;
+ for (i = 0; p[i]; i++)
+ if (p[i] == ':' ) {
+ p[i] = '\0';
+ if (!indx) {
+ indx = (char *)&p[i+1];
+ code = atoi (indx);
+ } else if (!name) {
+ name = (char *)&p[i+1];
+ } else {
+ i++;
+ break;
+ }
+ }
+ /*
+ ** Add data to field structure.
+ */
+ if (name) {
+ if (code == prev_code) {
+ /*
+ ** Remaining data are description.
+ ** Save in current info block.
+ */
+ alen = strlen((char *)&p[i]) + 1;
+ if (alen > sizeof(last->desc_buf)) {
+ if (last->description != last->desc_buf)
+ FREE(last->description);
+ if (!(last->description = (char *)malloc(alen))) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ }
+ strcpy(last->description, (char *)&p[i]);
+ } else {
+ /*
+ ** Initialize new block, append to end of list
+ ** to preserve order.
+ */
+ new = (CSOfield_info *)calloc(1, sizeof(CSOfield_info));
+ if (!new) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ if (last)
+ last->next = new;
+ else
+ CSOfields = new;
+ last = new;
+
+ new->next = (CSOfield_info *) 0;
+ new->name = new->name_buf;
+ alen = strlen(name) + 1;
+ if (alen > sizeof(new->name_buf)) {
+ if (!(new->name = (char *)malloc(alen))) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ }
+ strcpy (new->name, name);
+
+ new->attributes = new->attr_buf;
+ alen = strlen((char *)&p[i]) + 2;
+ if (alen > sizeof(new->attr_buf)) {
+ if (!(new->attributes = (char *)malloc(alen))) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ }
+ strcpy(new->attributes, (char *)&p[i]);
+ strcpy((char *)&new->attributes[alen-2], " ");
+ new->description = new->desc_buf;
+ new->desc_buf[0] = '\0';
+ new->id = atoi(indx);
+ /*
+ ** Scan for keywords.
+ */
+ parse_cso_field_info(new);
+ }
+ prev_code = code;
+ } else
+ break;
+ } /* end if *p == '-' */
+ } /* if end of line */
+
+ } /* Loop over characters */
+
+ /* end the text block */
+
+ if (buf[0] == '\0') {
+ return -1; /* no response */
+ }
+ buf[0] = '\0';
+ return 0; /* all done */
+} /* end of procedure */
+
+/* Generate a form for submitting CSO/PH searches. - FM
+** ====================================================
+*/
+PRIVATE int generate_cso_form ARGS4(
+ char *, host,
+ int, port,
+ char *, buf,
+ HTStream *, Target)
+{
+ int i, j, length;
+ size_t out;
+ int full_flag = 1;
+ char *key, *line;
+ CSOformgen_context ctx;
+ static char *template[] = {
+ "<HEAD>\n<TITLE>CSO/PH Query Form for $(HOST)</TITLE>\n</HEAD>\n<BODY>",
+ "<H2><I>CSO/PH Query Form</I> for <EM>$(HOST)</EM></H2>",
+ "To search the database for a name, fill in one or more of the fields",
+ "in the form below and activate the 'Submit query' button. At least",
+ "one of the entered fields must be flagged as indexed.",
+ "<HR><FORM method=\"POST\" action=\"cso://$(HOST)/\">",
+ "[ <input type=\"submit\" value=\"Submit query\"> | ",
+ "<input type=\"reset\" value=\"Clear fields\"> ]",
+ "<P><DL>",
+ " <DT>Search parameters (* indicates indexed field):",
+ " <DD>", "$(NAMEFLD) <DL COMPACT>\n <DT><I>$(FDESC)</I>$(FNDX)",
+ " <DD>Last: <input name=\"q_$(FID)\" type=\"text\" size=49$(FSIZE2)>",
+ " <DD>First: <input name=\"q_$(FID)\" type=\"text\" size=48$(FSIZE2)>",
+ "$(QFIELDS) <DT><I>$(FDESC)</I>$(FNDX)",
+ " <DD><input name=\"q_$(FID)\" type=\"text\" $(FSIZE)>\n$(NEXTFLD)",
+ " </DL>",
+ " </DL>\n<P><DL>",
+ " <DT>Output format:",
+ " <DD>Returned data option: <select name=\"return\">",
+ " <option>default<option selected>all<option>selected</select><BR>",
+ "$(RFIELDS) <input type=\"checkbox\" name=\"r_$(FID)\"$(FDEF)> $(FDESC)<BR>",
+ "$(NEXTFLD) ",
+ " </DL></FORM><HR>\n</BODY>\n</HTML>",
+ (char *) 0
+ };
+
+ out = 0;
+ ctx.host = host;
+ ctx.seek = (char *) 0;
+ ctx.port = port;
+ ctx.fld = (CSOfield_info *) 0;
+ ctx.public_override = full_flag;
+ /*
+ ** Parse the strings in the template array to produce HTML document
+ ** to send to client. First line is skipped for 'full' lists.
+ */
+ out = 0;
+ buf[out] = '\0';
+ for (i = full_flag ? /***1***/ 0 : 0; template[i]; i++) {
+ /*
+ ** Search the current string for substitution, flagged by $(
+ */
+ for (line=template[i], j = 0; line[j]; j++) {
+ if ((line[j] == '$') && (line[j+1] == '(')) {
+ /*
+ ** Command detected, flush output buffer and find closing ')'
+ ** that delimits the command.
+ */
+ buf[out] = '\0';
+ if (out > 0)
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ out = 0;
+ for (key = &line[j]; line[j+1] && (line[j] != ')'); j++)
+ ;
+ /*
+ ** Save context, interpet command and restore updated context.
+ */
+ ctx.cur_line = i;
+ ctx.cur_off = j;
+ interpret_cso_key(key, buf, &length, &ctx, Target);
+ i = ctx.cur_line;
+ j = ctx.cur_off;
+ line = template[i];
+ out = length;
+
+ if (ctx.seek) {
+ /*
+ ** Command wants us to skip (forward) to indicated token.
+ ** Start at current position.
+ */
+ int slen = strlen(ctx.seek);
+ for (; template[i]; i++) {
+ for (line = template[i]; line[j]; j++) {
+ if (line[j] == '$')
+ if (0 == strncmp(ctx.seek, &line[j], slen)) {
+ if (j == 0)
+ j = strlen(template[--i])-1;
+ else
+ --j;
+ line = template[i];
+ ctx.seek = (char *) 0;
+ break;
+ }
+ }
+ if (!ctx.seek)
+ break;
+ j = 0;
+ }
+ if (ctx.seek) {
+ char *temp = (char *)malloc(strlen(ctx.seek) + 20);
+ if (temp) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ sprintf(temp, "Seek fail on %s\n", ctx.seek);
+ (*Target->isa->put_block)(Target, temp, strlen(temp));
+ FREE(temp);
+ }
+ }
+ } else {
+ /*
+ ** Non-command text, add to output buffer.
+ */
+ buf[out++] = line[j];
+ if (out > (sizeof(buf)-3)) {
+ buf[out] = '\0';
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ out = 0;
+ }
+ }
+ }
+ buf[out++] = '\n';
+ buf[out] = '\0';
+ }
+ if (out > 0)
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+
+ return 0;
+}
+
+/* Generate a results report for CSO/PH form-based searches. - FM
+** ==============================================================
+*/
+PRIVATE int generate_cso_report ARGS2(
+ char *, buf,
+ HTStream *, Target)
+{
+ char ch;
+ char line[BIG];
+ char *p = line, *href = NULL;
+ int len, i, prev_ndx, ndx;
+ char *rcode, *ndx_str, *fname, *fvalue, *l;
+ CSOfield_info *fld;
+ BOOL stop = FALSE;
+
+ /*
+ ** Read lines until non-negative status.
+ */
+ prev_ndx = -100;
+ /*
+ ** Start grabbing chars from the network.
+ */
+ while (!stop && (ch = NEXT_CHAR) != (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ buf[0] = '\0';
+ if (TRACE) {
+ fprintf(stderr,
+ "HTLoadCSO: Interrupted in HTGetCharacter, apparently.\n");
+ }
+ _HTProgress ("Connection interrupted.");
+ goto end_CSOreport;
+ }
+
+ if (ch != LF) {
+ *p = ch; /* Put character in line */
+ if (p < &line[BIG-1]) {
+ p++;
+ }
+ } else {
+ *p = '\0'; /* Terminate line */
+ /*
+ ** OK we now have a line.
+ ** Load it as 'p' and parse it.
+ */
+ p = line;
+ if (p[0] != '-' && p[0] != '1') {
+ stop = TRUE;
+ }
+ rcode = (p[0] == '-') ? &p[1] : p;
+ ndx_str = fname = NULL;
+ len = strlen(p);
+ for (i = 0; i < len; i++) {
+ if (p[i] == ':') {
+ p[i] = '\0';
+ if (!ndx_str) {
+ fname = ndx_str = &p[i+1];
+ } else {
+ fname = &p[i+1];
+ break;
+ }
+ }
+ }
+ if (ndx_str) {
+ ndx = atoi(ndx_str);
+ if (prev_ndx != ndx) {
+ if (prev_ndx != -100) {
+ strcpy(buf, "</DL></DL>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ if (ndx == 0) {
+ strcpy(buf,
+ "<HR><DL><DT>Information/status<DD><DL><DT>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ } else {
+ sprintf(buf,
+ "<HR><DL><DT>Entry %d:<DD><DL COMPACT><DT>\n", ndx);
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ prev_ndx = ndx;
+ }
+ } else {
+ sprintf(buf, "<DD>%s\n", rcode);
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ continue;
+ }
+ if ((*rcode >= '2') && (*rcode <= '5') && (fname != ndx_str)) {
+ while (*fname == ' ') {
+ fname++; /* trim leading spaces */
+ }
+ for (fvalue = fname; *fvalue; fvalue++) {
+ if (*fvalue == ':') {
+ *fvalue++ = '\0';
+ i = strlen(fname) - 1;
+ while (i >= 0 && fname[i] == ' ') {
+ fname[i--] = '\0'; /* trim trailing */
+ }
+ break;
+ }
+ }
+ if (fvalue) {
+ while (*fvalue == ' ') {
+ fvalue++; /* trim leading spaces */
+ }
+ }
+ if (*fname) {
+ for (fld = CSOfields; fld; fld = fld->next) {
+ if (!strcmp(fld->name, fname)) {
+ if (fld->description) {
+ fname = fld->description;
+ }
+ break;
+ }
+ }
+ if (fld && fld->url) {
+ sprintf(buf,
+ "<DT><I>%s</I><DD><A HREF=\"%s\">%s</A>\n",
+ fname, fvalue, fvalue);
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ } else {
+ sprintf(buf, "<DT><I>%s</I><DD>", fname);
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ i = 0;
+ buf[i] = '\0';
+ l = fvalue;
+ while (*l) {
+ if (*l == '<') {
+ strcat(buf, "&lt;");
+ l++;
+ i += 4;
+ buf[i] = '\0';
+ } else if (*l == '>') {
+ strcat(buf, "&gt;");
+ l++;
+ i += 4;
+ buf[i] = '\0';
+ } else if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9)) {
+ buf[i++] = *l++;
+ buf[i] = '\0';
+ } else {
+ strcat(buf, "<a href=\"");
+ i += 9;
+ buf[i] = '\0';
+ StrAllocCopy(href, l);
+ strcat(buf, strtok(href, " \r\n\t,>)\""));
+ strcat(buf, "\">");
+ i = strlen(buf);
+ while (*l && !strchr(" \r\n\t,>)\"", *l)) {
+ buf[i++] = *l++;
+ }
+ buf[i] = '\0';
+ strcat(buf, "</a>");
+ i += 4;
+ FREE(href);
+ }
+ }
+ strcat(buf, "\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ } else {
+ sprintf(buf, "<DD>");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ i = 0;
+ buf[i] = '\0';
+ l = fvalue;
+ while (*l) {
+ if (*l == '<') {
+ strcat(buf, "&lt;");
+ l++;
+ i += 4;
+ buf[i] = '\0';
+ } else if (*l == '>') {
+ strcat(buf, "&gt;");
+ l++;
+ i += 4;
+ buf[i] = '\0';
+ } else if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9)) {
+ buf[i++] = *l++;
+ buf[i] = '\0';
+ } else {
+ strcat(buf, "<a href=\"");
+ i += 9;
+ buf[i] = '\0';
+ StrAllocCopy(href, l);
+ strcat(buf, strtok(href, " \r\n\t,>)\""));
+ strcat(buf, "\">");
+ i = strlen(buf);
+ while (*l && !strchr(" \r\n\t,>)\"", *l)) {
+ buf[i++] = *l++;
+ }
+ buf[i] = '\0';
+ strcat(buf, "</a>");
+ i += 4;
+ FREE(href);
+ }
+ }
+ strcat(buf, "\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ } else {
+ sprintf(buf, "<DD>%s\n", fname ? fname : rcode );
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ }
+ }
+end_CSOreport:
+ if (prev_ndx != -100) {
+ sprintf(buf, "</DL></DL>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ }
+ return 0;
+}
+
+/* CSO/PH form-based search gateway - FM HTLoadCSO
+** =====================================
+*/
+PRIVATE int HTLoadCSO ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ char *host, *cp;
+ int port = CSO_PORT;
+ int status; /* tcp return */
+ char *command = NULL;
+ char *content = NULL;
+ int len, i, j, start, finish, flen, ndx, clen;
+ int return_type, has_indexed;
+ CSOfield_info *fld;
+ char buf[2048];
+ HTFormat format_in = WWW_HTML;
+ HTStream *Target = NULL;
+
+ if (!acceptable_inited)
+ init_acceptable();
+
+ if (!arg)
+ return -3; /* Bad if no name sepcified */
+ if (!*arg)
+ return -2; /* Bad if name had zero length */
+ if (TRACE)
+ fprintf(stderr, "HTLoadCSO: Looking for %s\n", arg);
+
+ /*
+ ** Set up a socket to the server for the data.
+ */
+ status = HTDoConnect (arg, "cso", CSO_PORT, &s);
+ if (status == HT_INTERRUPTED) {
+ /*
+ ** Interrupt cleanly.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadCSO: Interrupted on connect; recovering cleanly.\n");
+ _HTProgress ("Connection interrupted.");
+ return HT_NOT_LOADED;
+ }
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadCSO: Unable to connect to remote host for `%s'.\n",
+ arg);
+ return HTInetStatus("connect");
+ }
+
+ HTInitInput(s); /* Set up input buffering */
+
+ if ((command = (char *)malloc(12)) == NULL)
+ outofmem(__FILE__, "HTLoadCSO");
+ sprintf(command, "fields%c%c", CR, LF);
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadCSO: Connected, writing command `%s' to socket %d\n",
+ command, s);
+ _HTProgress ("Sending CSO/PH request.");
+ status = NETWRITE(s, command, (int)strlen(command));
+ FREE(command);
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr, "HTLoadCSO: Unable to send command.\n");
+ return HTInetStatus("send");
+ }
+ _HTProgress ("CSO/PH request sent; waiting for response.");
+
+ /*
+ ** Now read the data from the socket.
+ */
+ status = parse_cso_fields(buf, sizeof(buf));
+ if (status) {
+ NETCLOSE(s);
+ if (status == HT_INTERRUPTED) {
+ _HTProgress ("Connection interrupted.");
+ } else if (buf[0] != '\0') {
+ HTAlert(buf);
+ } else {
+ HTAlert("No response from server!");
+ }
+ return HT_NOT_LOADED;
+ }
+ Target = HTStreamStack(format_in,
+ format_out,
+ sink, anAnchor);
+ if (!Target || Target == NULL) {
+ char *temp = (char *)malloc(256);
+ if (!temp) {
+ outofmem(__FILE__, "HTLoadCSO");
+ }
+ sprintf(temp, "Sorry, no known way of converting %s to %s.",
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ HTAlert(temp);
+ FREE(temp);
+ NETCLOSE(s);
+ return HT_NOT_LOADED;
+ }
+ host = HTParse(arg, "", PARSE_HOST);
+ if ((cp=strchr(host, ':')) != NULL) {
+ if (cp[1] >= '0' && cp[1] <= '9') {
+ port = atoi((cp+1));
+ if (port == CSO_PORT) {
+ *cp = '\0';
+ }
+ }
+ }
+ anAnchor->safe = TRUE;
+ if (!(anAnchor->post_data && *anAnchor->post_data)) {
+ generate_cso_form(host, port, buf, Target);
+ (*Target->isa->_free)(Target);
+ FREE(host);
+ NETCLOSE(s);
+ free_CSOfields();
+ return HT_LOADED;
+ }
+ sprintf(buf,
+ "<HTML>\n<HEAD>\n<TITLE>CSO/PH Results on %s</TITLE>\n</HEAD>\n<BODY>\n",
+ host);
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ FREE(host);
+ StrAllocCopy(content, anAnchor->post_data);
+ if (content[strlen(content)-1] != '&')
+ StrAllocCat(content, "&");
+ len = strlen(content);
+ for (i = 0; i < len; i++) {
+ if (content[i] == '+') {
+ content[i] = ' ';
+ }
+ }
+ HTUnEscape(content);
+ len = strlen(content);
+ return_type = 0;
+ has_indexed = 0;
+ start = finish = clen = 0;
+ for (i = 0; i < len; i++) {
+ if (!content[i] || content[i] == '&') {
+ /*
+ ** Value parsed. Unescape characters and look for first '='
+ ** to delimit field name from value.
+ */
+ flen = i - start;
+ finish = start + flen;
+ content[finish] = '\0';
+ for (j = start; j < finish; j++) {
+ if (content[j] == '=') {
+ /*
+ ** content[start..j-1] is field name,
+ ** [j+1..finish-1] is value.
+ */
+ if ((content[start+1] == '_') &&
+ ((content[start] == 'r') || (content[start] == 'q'))) {
+ /*
+ ** Decode fields number and lookup field info.
+ */
+ sscanf (&content[start+2], "%d=", &ndx);
+ for (fld = CSOfields; fld; fld = fld->next) {
+ if (ndx==fld->id) {
+ if ((j+1) >= finish)
+ break; /* ignore nulls */
+ if (content[start] == 'q') {
+ /*
+ * Append field to query line.
+ */
+ if (fld->lookup) {
+ if (fld->indexed)
+ has_indexed = 1;
+ if (clen == 0) {
+ StrAllocCopy(command, "query ");
+ clen = 6;
+ } else {
+ StrAllocCat(command, " ");
+ clen++;
+ }
+ sprintf(buf, "%s=\"%s\"",
+ fld->name, &content[j+1]);
+ StrAllocCat(command, buf);
+ clen += strlen(buf);
+ } else {
+ strcpy(buf,
+ "Warning: non-lookup field ignored<BR>\n");
+ (*Target->isa->put_block)(Target,
+ buf,
+ strlen(buf));
+ }
+ } else if (content[start] == 'r') {
+ fld->explicit_return = 1;
+ }
+ break;
+ }
+ }
+ } else if (!strncmp(&content[start],"return=",7)) {
+ if (!strcmp(&content[start+7],"all")) {
+ return_type = 1;
+ } else if (!strcmp(&content[start+7],"selected")) {
+ return_type = 2;
+ }
+ }
+ }
+ }
+ start = i + 1;
+ }
+ }
+ FREE(content);
+ if ((clen == 0) || !has_indexed) {
+ NETCLOSE(s);
+ strcpy(buf,
+ "<EM>Error:</EM> At least one indexed field value must be specified!\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ strcpy(buf, "</BODY>\n</HTML>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ (*Target->isa->_free)(Target);
+ free_CSOfields();
+ return HT_LOADED;
+ }
+ /*
+ ** Append return fields.
+ */
+ if (return_type == 1) {
+ StrAllocCat(command, " return all");
+ clen += 11;
+ } else if (return_type == 2) {
+ StrAllocCat(command, " return");
+ clen += 7;
+ for (fld = CSOfields; fld; fld = fld->next) {
+ if (fld->explicit_return) {
+ sprintf(buf, " %s", fld->name);
+ StrAllocCat(command, buf);
+ clen += strlen(buf);
+ }
+ }
+ }
+ sprintf(buf, "%c%c", CR, LF);
+ StrAllocCat(command, buf);
+ clen += strlen(buf);
+ strcpy(buf, "<H2>\n<EM>CSO/PH command:</EM> ");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ (*Target->isa->put_block)(Target, command, clen);
+ strcpy(buf, "</H2>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadCSO: Writing command `%s' to socket %d\n",
+ command, s);
+ status = NETWRITE(s, command, clen);
+ FREE(command);
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr, "HTLoadCSO: Unable to send command.\n");
+ free_CSOfields();
+ return HTInetStatus("send");
+ }
+ generate_cso_report(buf, Target);
+ NETCLOSE(s);
+ strcpy(buf, "</BODY>\n</HTML>\n");
+ (*Target->isa->put_block)(Target, buf, strlen(buf));
+ (*Target->isa->_free)(Target);
+ FREE(host);
+ free_CSOfields();
+ return HT_LOADED;
+}
+
+/* Load by name. HTLoadGopher
+** =============
+**
+** Bug: No decoding of strange data types as yet.
+**
+*/
+PRIVATE int HTLoadGopher ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ char *command; /* The whole command */
+ int status; /* tcp return */
+ char gtype; /* Gopher Node type */
+ char * selector; /* Selector string */
+
+ if (!acceptable_inited)
+ init_acceptable();
+
+ if (!arg)
+ return -3; /* Bad if no name sepcified */
+ if (!*arg)
+ return -2; /* Bad if name had zero length */
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Looking for %s\n", arg);
+
+ /*
+ ** If it's a port 105 GOPHER_CSO gtype with no ISINDEX token ('?'),
+ ** use the form-based CSO gateway (otherwise, return an ISINDEX
+ ** cover page or do the ISINDEX search). - FM
+ */
+ {
+ int len;
+
+ if ((len = strlen(arg)) > 5) {
+ if (0 == strcmp((CONST char *)&arg[len-6], ":105/2")) {
+ /* Use CSO gateway. */
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Passing to CSO/PH gateway.\n");
+ return HTLoadCSO(arg, anAnchor, format_out, sink);
+ }
+ }
+ }
+
+ /*
+ ** If it's a port 79/0[/...] URL, use the finger gateway. - FM
+ */
+ if (strstr(arg, ":79/0") != NULL) {
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Passing to finger gateway.\n");
+ return HTLoadFinger(arg, anAnchor, format_out, sink);
+ }
+
+ /*
+ ** Get entity type, and selector string.
+ */
+ {
+ char * p1 = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
+ gtype = '1'; /* Default = menu */
+ selector = p1;
+ if ((*selector++=='/') && (*selector)) { /* Skip first slash */
+ gtype = *selector++; /* Pick up gtype */
+ }
+ if (gtype == GOPHER_INDEX) {
+ char * query;
+ /*
+ ** Search is allowed.
+ */
+ HTAnchor_setIndex(anAnchor, anAnchor->address);
+ query = strchr(selector, '?'); /* Look for search string */
+ if (!query || !query[1]) { /* No search required */
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa;
+ display_index(arg, anAnchor); /* Display "cover page" */
+ return HT_LOADED; /* Local function only */
+ }
+ *query++ = '\0'; /* Skip '?' */
+ command =
+ (char *)malloc(strlen(selector)+ 1 + strlen(query)+ 2 + 1);
+ if (command == NULL)
+ outofmem(__FILE__, "HTLoadGopher");
+
+ de_escape(command, selector); /* Bug fix TBL 921208 */
+
+ strcat(command, "\t");
+
+ { /* Remove plus signs 921006 */
+ char *p;
+ for (p=query; *p; p++) {
+ if (*p == '+') *p = ' ';
+ }
+ }
+
+ de_escape(&command[strlen(command)], query);/* bug fix LJM 940415 */
+ } else if (gtype == GOPHER_CSO) {
+ char * query;
+ /*
+ ** Search is allowed.
+ */
+ query = strchr(selector, '?'); /* Look for search string */
+ if (!query || !query[1]) { /* No search required */
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa;
+ display_cso(arg, anAnchor); /* Display "cover page" */
+ return HT_LOADED; /* Local function only */
+ }
+ HTAnchor_setIndex(anAnchor, anAnchor->address);
+ *query++ = '\0'; /* Skip '?' */
+ command = (char *)malloc(strlen("query")+1 + strlen(query)+2+1);
+ if (command == NULL)
+ outofmem(__FILE__, "HTLoadGopher");
+
+ de_escape(command, selector); /* Bug fix TBL 921208 */
+
+ strcpy(command, "query ");
+
+ { /* Remove plus signs 921006 */
+ char *p;
+ for (p=query; *p; p++) {
+ if (*p == '+') *p = ' ';
+ }
+ }
+ de_escape(&command[strlen(command)], query);/* bug fix LJM 940415 */
+
+ } else { /* Not index */
+ command = (char *)malloc(strlen(selector)+2+1);
+ de_escape(command, selector);
+ }
+ FREE(p1);
+ }
+
+ {
+ char * p = command + strlen(command);
+ *p++ = CR; /* Macros to be correct on Mac */
+ *p++ = LF;
+ *p++ = '\0';
+ }
+
+ /*
+ ** Set up a socket to the server for the data.
+ */
+ status = HTDoConnect (arg, "gopher", GOPHER_PORT, &s);
+ if (status == HT_INTERRUPTED) {
+ /*
+ ** Interrupt cleanly.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTGopher: Interrupted on connect; recovering cleanly.\n");
+ _HTProgress ("Connection interrupted.");
+ FREE(command);
+ return HT_NOT_LOADED;
+ }
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTGopher: Unable to connect to remote host for `%s'.\n",
+ arg);
+ FREE(command);
+ return HTInetStatus("connect");
+ }
+
+ HTInitInput(s); /* Set up input buffering */
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTGopher: Connected, writing command `%s' to socket %d\n",
+ command, s);
+
+#ifdef NOT_ASCII
+ {
+ char * p;
+ for (p = command; *p; p++) {
+ *p = TOASCII(*p);
+ }
+ }
+#endif
+
+ _HTProgress ("Sending Gopher request.");
+
+ status = NETWRITE(s, command, (int)strlen(command));
+ FREE(command);
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr, "HTGopher: Unable to send command.\n");
+ return HTInetStatus("send");
+ }
+
+ _HTProgress ("Gopher request sent; waiting for response.");
+
+ /*
+ ** Now read the data from the socket.
+ */
+ switch (gtype) {
+
+ case GOPHER_TEXT :
+ HTParseSocket(WWW_PLAINTEXT, format_out, anAnchor, s, sink);
+ break;
+
+ case GOPHER_HTML :
+ case GOPHER_CHTML :
+ HTParseSocket(WWW_HTML, format_out, anAnchor, s, sink);
+ break;
+
+ case GOPHER_GIF:
+ case GOPHER_IMAGE:
+ case GOPHER_PLUS_IMAGE:
+ HTParseSocket(HTAtom_for("image/gif"),
+ format_out, anAnchor, s, sink);
+ break;
+
+ case GOPHER_MENU :
+ case GOPHER_INDEX :
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa;
+ parse_menu(arg, anAnchor);
+ break;
+
+ case GOPHER_CSO:
+ target = HTML_new(anAnchor, format_out, sink);
+ targetClass = *target->isa;
+ parse_cso(arg, anAnchor);
+ break;
+
+ case GOPHER_SOUND :
+ case GOPHER_PLUS_SOUND :
+ HTParseSocket(WWW_AUDIO, format_out, anAnchor, s, sink);
+ break;
+
+ case GOPHER_PLUS_MOVIE:
+ HTParseSocket(HTAtom_for("video/mpeg"), format_out, anAnchor, s, sink);
+ break;
+
+ case GOPHER_PLUS_PDF:
+ HTParseSocket(HTAtom_for("application/pdf"), format_out, anAnchor,
+ s, sink);
+ break;
+
+ case GOPHER_MACBINHEX:
+ case GOPHER_PCBINARY:
+ case GOPHER_UUENCODED:
+ case GOPHER_BINARY:
+ default:
+ /*
+ ** Specifying WWW_UNKNOWN forces dump to local disk.
+ */
+ HTParseSocket (WWW_UNKNOWN, format_out, anAnchor, s, sink);
+ break;
+
+ } /* switch(gtype) */
+
+ NETCLOSE(s);
+ return HT_LOADED;
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTGOPHER_C_1_INIT { "gopher", HTLoadGopher, NULL }
+GLOBALDEF (HTProtocol, HTGopher, _HTGOPHER_C_1_INIT);
+#define _HTCSO_C_1_INIT { "cso", HTLoadCSO, NULL }
+GLOBALDEF (HTProtocol, HTCSO, _HTCSO_C_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTGopher = { "gopher", HTLoadGopher, NULL };
+GLOBALDEF PUBLIC HTProtocol HTCSO = { "cso", HTLoadCSO, NULL };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.h
new file mode 100644
index 00000000000..947bd3e93c6
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGopher.h
@@ -0,0 +1,27 @@
+/* Gopher protocol module for libwww
+ GOPHER ACCESS
+
+ HISTORY:
+
+ 8 Jan 92 Adapted from HTTP TBL
+
+ */
+
+
+#ifndef HTGOPHER_H
+#define HTGOPHER_H
+
+#include "HTAccess.h"
+#include "HTAnchor.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol, HTGopher);
+#else
+GLOBALREF HTProtocol HTGopher;
+#endif /* GLOBALREF_IS_MACRO */
+
+#endif /* HTGOPHER_H */
+
+/*
+
+ end of gopher module */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.c
new file mode 100644
index 00000000000..f6b1757868a
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.c
@@ -0,0 +1,772 @@
+
+/* MODULE HTGroup.c
+** GROUP FILE ROUTINES
+**
+** Contains group file parser and routines to match IP
+** address templates and to find out group membership.
+**
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+**
+**
+** BUGS:
+**
+**
+**
+** GROUP DEFINITION GRAMMAR:
+**
+** string = "sequence of alphanumeric characters"
+** user_name ::= string
+** group_name ::= string
+** group_ref ::= group_name
+** user_def ::= user_name | group_ref
+** user_def_list ::= user_def { ',' user_def }
+** user_part = user_def | '(' user_def_list ')'
+**
+** templ = "sequence of alphanumeric characters and '*'s"
+** ip_number_mask ::= templ '.' templ '.' templ '.' templ
+** domain_name_mask ::= templ { '.' templ }
+** address ::= ip_number_mask | domain_name_mask
+** address_def ::= address
+** address_def_list ::= address_def { ',' address_def }
+** address_part = address_def | '(' address_def_list ')'
+**
+** item ::= [user_part] ['@' address_part]
+** item_list ::= item { ',' item }
+** group_def ::= item_list
+** group_decl ::= group_name ':' group_def
+**
+*/
+
+
+
+#include "HTUtils.h"
+#include <string.h>
+#include "HTAAUtil.h"
+#include "HTLex.h" /* Lexical analysor */
+#include "HTGroup.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+/*
+** Group file parser
+*/
+
+typedef HTList UserDefList;
+typedef HTList AddressDefList;
+
+typedef struct {
+ UserDefList * user_def_list;
+ AddressDefList * address_def_list;
+} Item;
+
+typedef struct {
+ char * name;
+ GroupDef * translation;
+} Ref;
+
+
+
+PRIVATE void syntax_error ARGS3(FILE *, fp,
+ char *, msg,
+ LexItem, lex_item)
+{
+ char buffer[41];
+ int cnt = 0;
+ int ch;
+
+ while ((ch = getc(fp)) != EOF && ch != '\n')
+ if (cnt < 40) buffer[cnt++] = ch;
+ buffer[cnt] = (char)0;
+
+ if (TRACE)
+ fprintf(stderr, "%s %d before: '%s'\nHTGroup.c: %s (got %s)\n",
+ "HTGroup.c: Syntax error in rule file at line",
+ HTlex_line, buffer, msg, lex_verbose(lex_item));
+ HTlex_line++;
+}
+
+
+PRIVATE AddressDefList *parse_address_part ARGS1(FILE *, fp)
+{
+ AddressDefList *address_def_list = NULL;
+ LexItem lex_item;
+ BOOL only_one = NO;
+
+ lex_item = lex(fp);
+ if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR)
+ only_one = YES;
+ else if (lex_item != LEX_OPEN_PAREN ||
+ ((lex_item = lex(fp)) != LEX_ALPH_STR &&
+ lex_item != LEX_TMPL_STR)) {
+ syntax_error(fp, "Expecting a single address or '(' beginning list",
+ lex_item);
+ return NULL;
+ }
+ address_def_list = HTList_new();
+
+ for(;;) {
+ Ref *ref = (Ref*)calloc(1, sizeof(Ref));
+ ref->name = NULL;
+ ref->translation = NULL;
+ StrAllocCopy(ref->name, HTlex_buffer);
+
+ HTList_addObject(address_def_list, (void*)ref);
+
+ if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
+ break;
+ /*
+ ** Here lex_item == LEX_ITEM_SEP; after item separator it
+ ** is ok to have one or more newlines (LEX_REC_SEP) and
+ ** they are ignored (continuation line).
+ */
+ do {
+ lex_item = lex(fp);
+ } while (lex_item == LEX_REC_SEP);
+
+ if (lex_item != LEX_ALPH_STR && lex_item != LEX_TMPL_STR) {
+ syntax_error(fp, "Expecting an address template", lex_item);
+ HTList_delete(address_def_list);
+ address_def_list = NULL;
+ return NULL;
+ }
+ }
+
+ if (!only_one && lex_item != LEX_CLOSE_PAREN) {
+ HTList_delete(address_def_list);
+ address_def_list = NULL;
+ syntax_error(fp, "Expecting ')' closing address list", lex_item);
+ return NULL;
+ }
+ return address_def_list;
+}
+
+
+PRIVATE UserDefList *parse_user_part ARGS1(FILE *, fp)
+{
+ UserDefList *user_def_list = NULL;
+ LexItem lex_item;
+ BOOL only_one = NO;
+
+ lex_item = lex(fp);
+ if (lex_item == LEX_ALPH_STR)
+ only_one = YES;
+ else if (lex_item != LEX_OPEN_PAREN ||
+ (lex_item = lex(fp)) != LEX_ALPH_STR) {
+ syntax_error(fp, "Expecting a single name or '(' beginning list",
+ lex_item);
+ return NULL;
+ }
+ user_def_list = HTList_new();
+
+ for (;;) {
+ Ref *ref = (Ref*)calloc(1, sizeof(Ref));
+ ref->name = NULL;
+ ref->translation = NULL;
+ StrAllocCopy(ref->name, HTlex_buffer);
+
+ HTList_addObject(user_def_list, (void*)ref);
+
+ if (only_one || (lex_item = lex(fp)) != LEX_ITEM_SEP)
+ break;
+ /*
+ ** Here lex_item == LEX_ITEM_SEP; after item separator it
+ ** is ok to have one or more newlines (LEX_REC_SEP) and
+ ** they are ignored (continuation line).
+ */
+ do {
+ lex_item = lex(fp);
+ } while (lex_item == LEX_REC_SEP);
+
+ if (lex_item != LEX_ALPH_STR) {
+ syntax_error(fp, "Expecting user or group name", lex_item);
+ HTList_delete(user_def_list);
+ user_def_list = NULL;
+ return NULL;
+ }
+ }
+
+ if (!only_one && lex_item != LEX_CLOSE_PAREN) {
+ HTList_delete(user_def_list);
+ user_def_list = NULL;
+ syntax_error(fp, "Expecting ')' closing user/group list", lex_item);
+ return NULL;
+ }
+ return user_def_list;
+}
+
+
+PRIVATE Item *parse_item ARGS1(FILE *, fp)
+{
+ Item *item = NULL;
+ UserDefList *user_def_list = NULL;
+ AddressDefList *address_def_list = NULL;
+ LexItem lex_item;
+
+ lex_item = lex(fp);
+ if (lex_item == LEX_ALPH_STR || lex_item == LEX_OPEN_PAREN) {
+ unlex(lex_item);
+ user_def_list = parse_user_part(fp);
+ lex_item = lex(fp);
+ }
+
+ if (lex_item == LEX_AT_SIGN) {
+ lex_item = lex(fp);
+ if (lex_item == LEX_ALPH_STR || lex_item == LEX_TMPL_STR ||
+ lex_item == LEX_OPEN_PAREN) {
+ unlex(lex_item);
+ address_def_list = parse_address_part(fp);
+ }
+ else {
+ if (user_def_list) {
+ HTList_delete(user_def_list); /* @@@@ */
+ user_def_list = NULL;
+ }
+ syntax_error(fp, "Expected address part (single address or list)",
+ lex_item);
+ return NULL;
+ }
+ }
+ else unlex(lex_item);
+
+ if (!user_def_list && !address_def_list) {
+ syntax_error(fp, "Empty item not allowed", lex_item);
+ return NULL;
+ }
+ item = (Item*)calloc(1, sizeof(Item));
+ item->user_def_list = user_def_list;
+ item->address_def_list = address_def_list;
+ return item;
+}
+
+
+PRIVATE ItemList *parse_item_list ARGS1(FILE *, fp)
+{
+ ItemList *item_list = HTList_new();
+ Item *item;
+ LexItem lex_item;
+
+ for(;;) {
+ if (!(item = parse_item(fp))) {
+ HTList_delete(item_list); /* @@@@ */
+ item_list = NULL;
+ return NULL;
+ }
+ HTList_addObject(item_list, (void*)item);
+ lex_item = lex(fp);
+ if (lex_item != LEX_ITEM_SEP) {
+ unlex(lex_item);
+ return item_list;
+ }
+ /*
+ ** Here lex_item == LEX_ITEM_SEP; after item separator it
+ ** is ok to have one or more newlines (LEX_REC_SEP) and
+ ** they are ignored (continuation line).
+ */
+ do {
+ lex_item = lex(fp);
+ } while (lex_item == LEX_REC_SEP);
+ unlex(lex_item);
+ }
+}
+
+
+PUBLIC GroupDef *HTAA_parseGroupDef ARGS1(FILE *, fp)
+{
+ ItemList *item_list = NULL;
+ GroupDef *group_def = NULL;
+ LexItem lex_item;
+
+ if (!(item_list = parse_item_list(fp))) {
+ return NULL;
+ }
+ group_def = (GroupDef*)calloc(1, sizeof(GroupDef));
+ group_def->group_name = NULL;
+ group_def->item_list = item_list;
+
+ if ((lex_item = lex(fp)) != LEX_REC_SEP) {
+ syntax_error(fp, "Garbage after group definition", lex_item);
+ }
+
+ return group_def;
+}
+
+
+PRIVATE GroupDef *parse_group_decl ARGS1(FILE *, fp)
+{
+ char *group_name = NULL;
+ GroupDef *group_def = NULL;
+ LexItem lex_item;
+
+ do {
+ lex_item = lex(fp);
+ } while (lex_item == LEX_REC_SEP); /* Ignore empty lines */
+
+ if (lex_item != LEX_ALPH_STR) {
+ if (lex_item != LEX_EOF)
+ syntax_error(fp, "Expecting group name", lex_item);
+ return NULL;
+ }
+ StrAllocCopy(group_name, HTlex_buffer);
+
+ if (LEX_FIELD_SEP != (lex_item = lex(fp))) {
+ syntax_error(fp, "Expecting field separator", lex_item);
+ FREE(group_name);
+ return NULL;
+ }
+
+ if (!(group_def = HTAA_parseGroupDef(fp))) {
+ FREE(group_name);
+ return NULL;
+ }
+ group_def->group_name = group_name;
+
+ return group_def;
+}
+
+
+
+/*
+** Group manipulation routines
+*/
+
+PRIVATE GroupDef *find_group_def ARGS2(GroupDefList *, group_list,
+ CONST char *, group_name)
+{
+ if (group_list && group_name) {
+ GroupDefList *cur = group_list;
+ GroupDef *group_def;
+
+ while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur))) {
+ if (!strcmp(group_name, group_def->group_name)) {
+ return group_def;
+ }
+ }
+ }
+ return NULL;
+}
+
+
+PUBLIC void HTAA_resolveGroupReferences ARGS2(GroupDef *, group_def,
+ GroupDefList *, group_def_list)
+{
+ if (group_def && group_def->item_list && group_def_list) {
+ ItemList *cur1 = group_def->item_list;
+ Item *item;
+
+ while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
+ UserDefList *cur2 = item->user_def_list;
+ Ref *ref;
+
+ while (NULL != (ref = (Ref*)HTList_nextObject(cur2)))
+ ref->translation = find_group_def(group_def_list, ref->name);
+
+ /* Does NOT translate address_def_list */
+ }
+ }
+}
+
+
+PRIVATE void add_group_def ARGS2(GroupDefList *, group_def_list,
+ GroupDef *, group_def)
+{
+ HTAA_resolveGroupReferences(group_def, group_def_list);
+ HTList_addObject(group_def_list, (void*)group_def);
+}
+
+
+PRIVATE GroupDefList *parse_group_file ARGS1(FILE *, fp)
+{
+ GroupDefList *group_def_list = HTList_new();
+ GroupDef *group_def;
+
+ while (NULL != (group_def = parse_group_decl(fp)))
+ add_group_def(group_def_list, group_def);
+
+ return group_def_list;
+}
+
+
+/*
+** Trace functions
+*/
+
+PRIVATE void print_item ARGS1(Item *, item)
+{
+ if (!item)
+ fprintf(stderr, "\tNULL-ITEM\n");
+ else {
+ UserDefList *cur1 = item->user_def_list;
+ AddressDefList *cur2 = item->address_def_list;
+ Ref *user_ref = (Ref*)HTList_nextObject(cur1);
+ Ref *addr_ref = (Ref*)HTList_nextObject(cur2);
+
+ if (user_ref) {
+ fprintf(stderr, "\t[%s%s", user_ref->name,
+ (user_ref->translation ? "*REF*" : ""));
+ while (NULL != (user_ref = (Ref*)HTList_nextObject(cur1)))
+ fprintf(stderr, "; %s%s", user_ref->name,
+ (user_ref->translation ? "*REF*" : ""));
+ fprintf(stderr, "] ");
+ } else fprintf(stderr, "\tANYBODY ");
+
+ if (addr_ref) {
+ fprintf(stderr, "@ [%s", addr_ref->name);
+ while (NULL != (addr_ref = (Ref*)HTList_nextObject(cur2)))
+ fprintf(stderr, "; %s", addr_ref->name);
+ fprintf(stderr, "]\n");
+ } else fprintf(stderr, "@ ANYADDRESS\n");
+ }
+}
+
+
+PRIVATE void print_item_list ARGS1(ItemList *, item_list)
+{
+ ItemList *cur = item_list;
+ Item *item;
+
+ if (!item_list)
+ fprintf(stderr, "EMPTY");
+ else while (NULL != (item = (Item*)HTList_nextObject(cur)))
+ print_item(item);
+}
+
+
+PUBLIC void HTAA_printGroupDef ARGS1(GroupDef *, group_def)
+{
+ if (!group_def) {
+ fprintf(stderr, "\nNULL RECORD\n");
+ return;
+ }
+
+ fprintf(stderr, "\nGroup %s:\n",
+ (group_def->group_name ? group_def->group_name : "NULL"));
+
+ print_item_list(group_def->item_list);
+ fprintf(stderr, "\n");
+}
+
+
+PRIVATE void print_group_def_list ARGS1(GroupDefList *, group_list)
+{
+ GroupDefList *cur = group_list;
+ GroupDef *group_def;
+
+ while (NULL != (group_def = (GroupDef*)HTList_nextObject(cur)))
+ HTAA_printGroupDef(group_def);
+}
+
+
+
+/*
+** IP address template matching
+*/
+
+/* PRIVATE part_match()
+** MATCH ONE PART OF INET ADDRESS AGAIST
+** A PART OF MASK (inet address has 4 parts)
+** ON ENTRY:
+** tcur pointer to the beginning of template part.
+** icur pointer to the beginning of actual inet
+** number part.
+**
+** ON EXIT:
+** returns YES, if match.
+*/
+PRIVATE BOOL part_match ARGS2(CONST char *, tcur,
+ CONST char *, icur)
+{
+ char required[4];
+ char actual[4];
+ CONST char *cur;
+ int cnt;
+
+ if (!tcur || !icur) return NO;
+
+ cur=tcur;
+ cnt=0;
+ while (cnt < 3 && *cur && *cur != '.')
+ required[cnt++] = *(cur++);
+ required[cnt] = (char)0;
+
+ cur=icur;
+ cnt=0;
+ while (cnt < 3 && *cur && *cur != '.')
+ actual[cnt++] = *(cur++);
+ actual[cnt] = (char)0;
+
+ if (TRACE) {
+ BOOL status = HTAA_templateMatch(required, actual);
+ fprintf(stderr, "part_match: req: '%s' act: '%s' match: %s\n",
+ required, actual, (status ? "yes" : "no"));
+ return status;
+ }
+
+ return HTAA_templateMatch(required, actual);
+}
+
+
+
+/* PRIVATE ip_number_match()
+** MATCH INET NUMBER AGAINST AN INET NUMBER MASK
+** ON ENTRY:
+** template mask to match agaist, e.g. 128.141.*.*
+** the_inet_addr actual inet address, e.g. 128.141.201.74
+**
+** ON EXIT:
+** returns YES, if match; NO, if not.
+*/
+PRIVATE BOOL ip_number_match ARGS2(CONST char *, template,
+ CONST char *, the_inet_addr)
+{
+ CONST char *tcur = template;
+ CONST char *icur = the_inet_addr;
+ int cnt;
+
+ for (cnt=0; cnt<4; cnt++) {
+ if (!tcur || !icur || !part_match(tcur, icur))
+ return NO;
+ if (NULL != (tcur = strchr(tcur, '.'))) tcur++;
+ if (NULL != (icur = strchr(icur, '.'))) icur++;
+ }
+ return YES;
+}
+
+
+
+/* PRIVATE is_domain_mask()
+** DETERMINE IF A GIVEN MASK IS A
+** DOMAIN NAME MASK OR AN INET NUMBER MASK
+** ON ENTRY:
+** mask either a domain name mask,
+** e.g.
+** *.cern.ch
+**
+** or an inet number mask,
+** e.g.
+** 128.141.*.*
+**
+** ON EXIT:
+** returns YES, if mask is a domain name mask.
+** NO, if it is an inet number mask.
+*/
+PRIVATE BOOL is_domain_mask ARGS1(CONST char *, mask)
+{
+ CONST char *cur = mask;
+
+ if (!mask) return NO;
+
+ while (*cur) {
+ if (*cur != '.' && *cur != '*' && (*cur < '0' || *cur > '9'))
+ return YES; /* Even one non-digit makes it a domain name mask */
+ cur++;
+ }
+ return NO; /* All digits and dots, so it is an inet number mask */
+}
+
+
+
+/* PRIVATE ip_mask_match()
+** MATCH AN IP NUMBER MASK OR IP NAME MASK
+** AGAINST ACTUAL IP NUMBER OR IP NAME
+**
+** ON ENTRY:
+** mask mask. Mask may be either an inet number
+** mask or a domain name mask,
+** e.g.
+** 128.141.*.*
+** or
+** *.cern.ch
+**
+** ip_number IP number of connecting host.
+** ip_name IP name of the connecting host.
+**
+** ON EXIT:
+** returns YES, if hostname/internet number
+** matches the mask.
+** NO, if no match (no fire).
+*/
+PRIVATE BOOL ip_mask_match ARGS3(CONST char *, mask,
+ CONST char *, ip_number,
+ CONST char *, ip_name)
+{
+ if (mask && (ip_number || ip_name)) {
+ if (is_domain_mask(mask)) {
+ if (HTAA_templateMatch(mask, ip_name))
+ return YES;
+ }
+ else {
+ if (ip_number_match(mask, ip_number))
+ return YES;
+ }
+ }
+ return NO;
+}
+
+
+
+
+PRIVATE BOOL ip_in_def_list ARGS3(AddressDefList *, address_def_list,
+ char *, ip_number,
+ char *, ip_name)
+{
+ if (address_def_list && (ip_number || ip_name)) {
+ AddressDefList *cur = address_def_list;
+ Ref *ref;
+
+ while (NULL != (ref = (Ref*)HTList_nextObject(cur))) {
+ /* Value of ref->translation is ignored, i.e. */
+ /* no recursion for ip address tamplates. */
+ if (ip_mask_match(ref->name, ip_number, ip_name))
+ return YES;
+ }
+ }
+ return NO;
+}
+
+
+/*
+** Group file cached reading
+*/
+
+typedef struct {
+ char * group_filename;
+ GroupDefList * group_list;
+} GroupCache;
+
+typedef HTList GroupCacheList;
+
+PRIVATE GroupCacheList *group_cache_list = NULL;
+
+
+PUBLIC GroupDefList *HTAA_readGroupFile ARGS1(CONST char *, filename)
+{
+ FILE *fp;
+ GroupCache *group_cache;
+
+ if (!filename || !*filename) return NULL;
+
+ if (!group_cache_list)
+ group_cache_list = HTList_new();
+ else {
+ GroupCacheList *cur = group_cache_list;
+
+ while (NULL != (group_cache = (GroupCache*)HTList_nextObject(cur))) {
+ if (!strcmp(filename, group_cache->group_filename)) {
+ if (TRACE) fprintf(stderr, "%s '%s' %s\n",
+ "HTAA_readGroupFile: group file",
+ filename, "already found in cache");
+ return group_cache->group_list;
+ } /* if cache match */
+ } /* while cached files remain */
+ } /* cache exists */
+
+ if (TRACE) fprintf(stderr, "HTAA_readGroupFile: reading group file `%s'\n",
+ filename);
+
+ if (!(fp = fopen(filename, "r"))) {
+ if (TRACE) fprintf(stderr, "%s '%s'\n",
+ "HTAA_readGroupFile: unable to open group file",
+ filename);
+ return NULL;
+ }
+
+ if (!(group_cache = (GroupCache*)calloc(1, sizeof(GroupCache))))
+ outofmem(__FILE__, "HTAA_readGroupFile");
+
+ group_cache->group_filename = NULL;
+ StrAllocCopy(group_cache->group_filename, filename);
+ group_cache->group_list = parse_group_file(fp);
+ HTList_addObject(group_cache_list, (void*)group_cache);
+ fclose(fp);
+
+ if (TRACE) {
+ fprintf(stderr, "Read group file '%s', results follow:\n", filename);
+ print_group_def_list(group_cache->group_list);
+ }
+
+ return group_cache->group_list;
+}
+
+
+/* PUBLIC HTAA_userAndInetInGroup()
+** CHECK IF USER BELONGS TO TO A GIVEN GROUP
+** AND THAT THE CONNECTION COMES FROM AN
+** ADDRESS THAT IS ALLOWED BY THAT GROUP
+** ON ENTRY:
+** group the group definition structure.
+** username connecting user.
+** ip_number browser host IP number, optional.
+** ip_name browser host IP name, optional.
+** However, one of ip_number or ip_name
+** must be given.
+** ON EXIT:
+** returns HTAA_IP_MASK, if IP address mask was
+** reason for failing.
+** HTAA_NOT_MEMBER, if user does not belong
+** to the group.
+** HTAA_OK if both IP address and user are ok.
+*/
+PUBLIC HTAAFailReasonType HTAA_userAndInetInGroup ARGS4(GroupDef *, group,
+ char *, username,
+ char *, ip_number,
+ char *, ip_name)
+{
+ HTAAFailReasonType reason = HTAA_NOT_MEMBER;
+
+ if (group && username) {
+ ItemList *cur1 = group->item_list;
+ Item *item;
+
+ while (NULL != (item = (Item*)HTList_nextObject(cur1))) {
+ if (!item->address_def_list || /* Any address allowed */
+ ip_in_def_list(item->address_def_list, ip_number, ip_name)) {
+
+ if (!item->user_def_list) /* Any user allowed */
+ return HTAA_OK;
+ else {
+ UserDefList *cur2 = item->user_def_list;
+ Ref *ref;
+
+ while (NULL != (ref = (Ref*)HTList_nextObject(cur2))) {
+
+ if (ref->translation) { /* Group, check recursively */
+ reason = HTAA_userAndInetInGroup(ref->translation,
+ username,
+ ip_number,ip_name);
+ if (reason == HTAA_OK)
+ return HTAA_OK;
+ }
+ else { /* Username, check directly */
+ if (username && *username &&
+ 0==strcmp(ref->name, username))
+ return HTAA_OK;
+ }
+ } /* Every user/group name in this group */
+ } /* search for username */
+ } /* IP address ok */
+ else {
+ reason = HTAA_IP_MASK;
+ }
+ } /* while items in group */
+ } /* valid parameters */
+
+ return reason; /* No match, or invalid parameters */
+}
+
+
+PUBLIC void GroupDef_delete ARGS1(GroupDef *, group_def)
+{
+ if (group_def) {
+ FREE(group_def->group_name);
+ if (group_def->item_list) {
+ HTList_delete(group_def->item_list); /* @@@@ */
+ group_def->item_list = NULL;
+ }
+ FREE(group_def);
+ }
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.h
new file mode 100644
index 00000000000..496a5077ad0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTGroup.h
@@ -0,0 +1,189 @@
+/* GROUP FILE ROUTINES
+
+ */
+
+#ifndef HTGROUP_H
+#define HTGROUP_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTList.h"
+
+#ifdef SHORT_NAMES
+#define HTAApGrD HTAA_parseGroupDef
+#define HTAArGrR HTAA_resolveGroupReferences
+#define HTAApGrD HTAA_printGroupDef
+#define HTAAGD_d GroupDef_delete
+#define HTAAuIIG HTAA_userAndInetInGroup
+#endif /* SHORT_NAMES */
+
+typedef HTList GroupDefList;
+typedef HTList ItemList;
+
+typedef struct {
+ char * group_name;
+ ItemList * item_list;
+} GroupDef;
+
+
+/*
+** Access Authorization failure reasons
+*/
+typedef enum {
+ HTAA_OK, /* 200 OK */
+ HTAA_OK_GATEWAY, /* 200 OK, acting as a gateway */
+ HTAA_NO_AUTH, /* 401 Unauthorized, not authenticated */
+ HTAA_NOT_MEMBER, /* 401 Unauthorized, not authorized */
+ HTAA_IP_MASK, /* 403 Forbidden by IP mask */
+ HTAA_BY_RULE, /* 403 Forbidden by rule */
+ HTAA_NO_ACL, /* 403 Forbidden, ACL non-existent */
+ HTAA_NO_ENTRY, /* 403 Forbidden, no ACL entry */
+ HTAA_SETUP_ERROR, /* 403 Forbidden, server setup error */
+ HTAA_DOTDOT, /* 403 Forbidden, URL with /../ illegal */
+ HTAA_HTBIN, /* 403 Forbidden, /htbin not enabled */
+ HTAA_NOT_FOUND /* 404 Not found, or read protected */
+} HTAAFailReasonType;
+
+/*
+
+Group definition grammar
+
+ string
+ "sequence of alphanumeric characters"
+
+ user_name
+ string
+
+ group_name
+ string
+
+ group_ref
+ group_name
+
+ user_def
+ user_name | group_ref
+
+ user_def_list
+ user_def { ',' user_def }
+
+ user_part
+ user_def | '(' user_def_list ')'
+
+ templ
+
+ "sequence of alphanumeric characters and '*'s"
+
+ ip_number_mask
+ templ '.' templ '.' templ '.' templ
+
+ domain_name_mask
+ templ { '.' templ }
+
+ address
+
+ ip_number_mask | domain_name_mask
+
+ address_def
+
+ address
+
+ address_def_list
+ address_def { ',' address_def }
+
+ address_part
+ address_def | '(' address_def_list ')'
+
+ item
+ [user_part] ['@' address_part]
+
+ item_list
+ item { ',' item }
+
+ group_def
+ item_list
+
+ group_decl
+ group_name ':' group_def
+
+ PARSE GROUP DEFINITION
+
+ */
+
+PUBLIC GroupDef *HTAA_parseGroupDef PARAMS((FILE * fp));
+/*
+
+Fill in Pointers to referenced Group Definitions in a Group Definition
+
+ References to groups (by their name) are resolved from group_def_list and pointers to
+ those structures are added to group_def.
+
+ */
+
+PUBLIC void HTAA_resolveGroupReferences PARAMS((GroupDef * group_def,
+ GroupDefList * group_def_list));
+/*
+
+Read Group File (and do caching)
+
+ If group file is already in cache returns a pointer to previously read group definition
+ list.
+
+ */
+
+PUBLIC GroupDefList *HTAA_readGroupFile PARAMS((CONST char * filename));
+/*
+
+Delete Group Definition
+
+ Groups in cache should never be freed by this function. This should only be used to
+ free group definitions read by HTAA_parseGroupDef.
+
+ */
+
+PUBLIC void GroupDef_delete PARAMS((GroupDef * group_def));
+/*
+
+Print Out Group Definition (for trace purposes)
+
+ */
+
+PUBLIC void HTAA_printGroupDef PARAMS((GroupDef * group_def));
+/*
+
+Does a User Belong to a Given Set of Groups
+
+ This function checks both the username and the internet address.
+
+ */
+
+/* PUBLIC HTAA_userAndInetInGroup()
+** CHECK IF USER BELONGS TO TO A GIVEN GROUP
+** AND THAT THE CONNECTION COMES FROM AN
+** ADDRESS THAT IS ALLOWED BY THAT GROUP
+** ON ENTRY:
+** group the group definition structure.
+** username connecting user.
+** ip_number browser host IP number, optional.
+** ip_name browser host IP name, optional.
+** However, one of ip_number or ip_name
+** must be given.
+** ON EXIT:
+** returns HTAA_IP_MASK, if IP address mask was
+** reason for failing.
+** HTAA_NOT_MEMBER, if user does not belong
+** to the group.
+** HTAA_OK if both IP address and user are ok.
+*/
+PUBLIC HTAAFailReasonType HTAA_userAndInetInGroup PARAMS((GroupDef * group,
+ char * username,
+ char * ip_number,
+ char * ip_name));
+/*
+
+ */
+
+#endif /* not HTGROUP_H */
+/*
+
+ End of file HTGroup.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.c
new file mode 100644
index 00000000000..726380a6f02
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.c
@@ -0,0 +1,157 @@
+#include "HTUtils.h"
+#include "tcp.h" /* for standard io */
+
+#include "HTHistory.h"
+
+#include "LYLeaks.h"
+
+static HTList * history; /* List of visited anchors */
+
+
+/* Navigation
+** ==========
+*/
+
+/* Record the jump to an anchor
+** ----------------------------
+*/
+
+void HTHistory_record
+ ARGS1 (HTAnchor *,destination)
+{
+ if (destination) {
+ if (! history)
+ history = HTList_new();
+ HTList_addObject (history, destination);
+ }
+}
+
+/* Go back in history (find the last visited node)
+** ------------------
+*/
+
+HTAnchor * HTHistory_backtrack
+ NOARGS /* FIXME: Should we add a `sticky' option ? */
+{
+ if (HTHistory_canBacktrack())
+ HTList_removeLastObject(history);
+ return(HTAnchor *)HTList_lastObject(history); /* is Home if can't backtrack */
+}
+
+BOOL HTHistory_canBacktrack
+ NOARGS
+{
+ return (HTList_objectAt (history, 1) != NULL);
+}
+
+/* Browse through references in the same parent node
+** -------------------------------------------------
+**
+** Take the n-th child's link after or before the one we took to get here.
+** Positive offset means go towards most recently added children.
+*/
+
+HTAnchor * HTHistory_moveBy
+ ARGS1 (int,offset)
+{
+ HTAnchor * last = (HTAnchor *)HTList_objectAt (history, 1);
+ if (! last)
+ return NULL; /* No last visited node */
+ if (last != (HTAnchor *) last->parent) { /* Was a child */
+ HTList * kids = last->parent->children;
+ int i = HTList_indexOf (kids, last);
+ HTAnchor * nextOne = (HTAnchor *)HTList_objectAt (kids, i - offset);
+ if (nextOne) {
+ HTAnchor * destination = HTAnchor_followMainLink (nextOne);
+ if (destination) {
+ HTList_removeLastObject (history);
+ HTList_removeLastObject (history);
+ HTList_addObject (history, nextOne);
+ HTList_addObject (history, destination);
+ }
+ return destination;
+ } else {
+ if (TRACE) fprintf(stderr,
+ "HTHistory_moveBy: offset by %+d goes out of list %p.\n",
+ offset, (void*)kids);
+ return NULL;
+ }
+ } else { /* Was a parent */
+ return NULL; /* FIXME we could possibly follow the next link... */
+ }
+}
+
+BOOL HTHistory_canMoveBy
+ ARGS1 (int,offset)
+{
+ HTAnchor * last = (HTAnchor *)HTList_objectAt (history, 1);
+ if (! last)
+ return NO; /* No last visited node */
+ if (last != (HTAnchor *) last->parent) { /* Was a child */
+ HTList * kids = last->parent->children;
+ int i = HTList_indexOf (kids, last);
+ return (HTList_objectAt (kids, i - offset) != NULL);
+ } else { /* Was a parent */
+ return NO; /* FIXME we could possibly follow the next link... */
+ }
+}
+
+
+/* Retrieval
+** =========
+*/
+
+/* Read numbered visited anchor (1 is the oldest)
+** ----------------------------
+*/
+
+HTAnchor * HTHistory_read
+ ARGS1 (int,number)
+{
+ return (HTAnchor *)HTList_objectAt(history, HTList_count (history) - number);
+}
+
+
+/* Recall numbered visited anchor (1 is the oldest)
+** ------------------------------
+** This reads the anchor and stores it again in the list, except if last.
+*/
+
+HTAnchor * HTHistory_recall
+ ARGS1 (int,number)
+{
+ HTAnchor * destination =
+ (HTAnchor *)HTList_objectAt (history, HTList_count (history) - number);
+ if (destination && destination != (HTAnchor *)HTList_lastObject (history))
+ HTList_addObject (history, destination);
+ return destination;
+}
+
+/* Number of Anchors stored
+** ------------------------
+**
+** This is needed in order to check the validity of certain commands
+** for menus, etc.
+(not needed for now. Use canBacktrack, etc.)
+int HTHistory_count
+ NOARGS
+{
+ return HTList_count (history);
+}
+*/
+
+/* Change last history entry
+** -------------------------
+**
+** Sometimes we load a node by one anchor but leave by a different
+** one, and it is the one we left from which we want to remember.
+*/
+
+void HTHistory_leavingFrom
+ ARGS1 (HTAnchor *,anchor)
+{
+ if (HTList_removeLastObject (history))
+ HTList_addObject (history, anchor);
+ else
+ if (TRACE) fprintf(stderr, "HTHistory_leavingFrom: empty history !\n");
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.h
new file mode 100644
index 00000000000..a93781e96d5
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTHistory.h
@@ -0,0 +1,112 @@
+/* */
+
+#ifndef HTHISTORY_H
+#define HTHISTORY_H
+
+#include "HTAnchor.h"
+
+#ifdef SHORT_NAMES
+#define HTHistory_record HTHiReco
+#define HTHistory_backtrack HTHiBack
+#define HTHistory_canBacktrack HTHiCaBa
+#define HTHistory_moveBy HTHiMoBy
+#define HTHistory_canMoveBy HTHiCaMo
+#define HTHistory_read HTHiRead
+#define HTHistory_recall HTHiReca
+#define HTHistory_count HTHiCoun
+#define HTHistory_leavingFrom HTHiLeFr
+#endif
+
+/* Navigation
+** ==========
+*/
+
+/* Record the jump to an anchor
+** ----------------------------
+*/
+
+extern void HTHistory_record
+ PARAMS(
+ (HTAnchor * destination)
+ );
+
+/* Go back in history (find the last visited node)
+** ------------------
+*/
+
+extern HTAnchor * HTHistory_backtrack
+ NOPARAMS; /* FIXME: Should we add a `sticky' option ? */
+
+extern BOOL HTHistory_canBacktrack
+ NOPARAMS;
+
+/* Browse through references in the same parent node
+** -------------------------------------------------
+**
+** Take the n-th child's link after or before the one we took to get here.
+** Positive offset means go towards most recently added children.
+*/
+
+extern HTAnchor * HTHistory_moveBy
+ PARAMS(
+ (int offset)
+ );
+
+extern BOOL HTHistory_canMoveBy
+ PARAMS(
+ (int offset)
+ );
+
+#define HTHistory_next (HTHistory_moveBy (+1))
+#define HTHistory_canNext (HTHistory_canMoveBy (+1))
+#define HTHistory_previous (HTHistory_moveBy (-1))
+#define HTHistory_canPrevious (HTHistory_canMoveBy (-1))
+
+
+/* Retrieval
+** =========
+*/
+
+/* Read numbered visited anchor (1 is the oldest)
+** ----------------------------
+*/
+
+extern HTAnchor * HTHistory_read
+ PARAMS(
+ (int number)
+ );
+
+/* Recall numbered visited anchor (1 is the oldest)
+** ------------------------------
+** This reads the anchor and stores it again in the list, except if last.
+*/
+
+extern HTAnchor * HTHistory_recall
+ PARAMS(
+ (int number)
+ );
+
+/* Number of Anchors stored
+** ------------------------
+**
+** This is needed in order to check the validity of certain commands
+** for menus, etc.
+(not needed for now. Use canBacktrack, etc.)
+extern int HTHistory_count NOPARAMS;
+*/
+
+/* Change last history entry
+** -------------------------
+**
+** Sometimes we load a node by one anchor but leave by a different
+** one, and it is the one we left from which we want to remember.
+*/
+extern void HTHistory_leavingFrom
+ PARAMS(
+ (HTAnchor * anchor)
+ );
+
+#endif /* HTHISTORY_H */
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.c
new file mode 100644
index 00000000000..764da7b556d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.c
@@ -0,0 +1,176 @@
+/* Configuration-specific Initialialization HTInit.c
+** ----------------------------------------
+*/
+
+/* Define a basic set of suffixes and presentations
+** ------------------------------------------------
+**
+*/
+
+#include "HTUtils.h"
+
+/* Implements:
+*/
+#include "HTInit.h"
+
+#include "HTML.h"
+#include "HTPlain.h"
+#include "HTMLGen.h"
+#include "HTFile.h"
+#include "HTFormat.h"
+#include "HTMIME.h"
+#include "HTWSRC.h"
+#include "HTFWriter.h"
+
+#include "LYLeaks.h"
+
+PUBLIC void HTFormatInit NOARGS
+{
+#ifdef NeXT
+ HTSetPresentation("application/postscript", "open %s", 1.0, 2.0, 0.0, 0);
+ /* The following needs the GIF previewer -- you might not have it. */
+ HTSetPresentation("image/gif", "open %s", 0.3, 2.0, 0.0, 0);
+ HTSetPresentation("image/x-tiff", "open %s", 1.0, 2.0, 0.0, 0);
+ HTSetPresentation("audio/basic", "open %s", 1.0, 2.0, 0.0, 0);
+ HTSetPresentation("*", "open %s", 1.0, 0.0, 0.0, 0);
+#else
+ if (getenv("DISPLAY")) { /* Must have X11 */
+ HTSetPresentation("application/postscript", "ghostview %s",
+ 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/gif", "xv %s", 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-tiff", "xv %s", 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/jpeg", "xv %s", 1.0, 3.0, 0.0, 0);
+ }
+#endif
+ HTSetConversion("www/mime", "*", HTMIMEConvert,
+ 1.0, 0.0, 0.0, 0);
+ HTSetConversion("application/x-wais-source","*", HTWSRCConvert,
+ 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "text/x-c", HTMLToC,
+ 0.5, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "text/plain", HTMLToPlain,
+ 0.5, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "www/present", HTMLPresent,
+ 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/plain", "text/html", HTPlainToHTML,
+ 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/plain", "www/present", HTPlainPresent,
+ 1.0, 0.0, 0.0, 0);
+ HTSetConversion("application/octet-stream", "www/present", HTSaveLocally,
+ 0.1, 0.0, 0.0, 0);
+ HTSetConversion("www/unknown", "www/present", HTSaveLocally,
+ 0.3, 0.0, 0.0, 0);
+ HTSetConversion("www/source", "www/present", HTSaveLocally,
+ 0.3, 0.0, 0.0, 0);
+}
+
+
+
+/* Define a basic set of suffixes
+** ------------------------------
+**
+** The LAST suffix for a type is that used for temporary files
+** of that type.
+** The quality is an apriori bias as to whether the file should be
+** used. Not that different suffixes can be used to represent files
+** which are of the same format but are originals or regenerated,
+** with different values.
+*/
+
+#ifndef NO_INIT
+PUBLIC void HTFileInit NOARGS
+{
+ /* Suffix Contenet-Type Content-Encoding Quality */
+
+ HTSetSuffix(".mime", "www/mime", "8bit", 1.0); /* Internal -- MIME is */
+ /* not recursive */
+ HTSetSuffix(".bin", "application/octet-stream", "binary", 1.0); /* Uninterpreted binary */
+ HTSetSuffix(".oda", "application/oda", "binary", 1.0);
+ HTSetSuffix(".pdf", "application/pdf", "binary", 1.0);
+ HTSetSuffix(".ai", "application/postscript", "8bit", 0.5); /* Adobe Illustrator */
+ HTSetSuffix(".PS", "application/postscript", "8bit", 0.8); /* PostScript */
+ HTSetSuffix(".eps", "application/postscript", "8bit", 0.8);
+ HTSetSuffix(".ps", "application/postscript", "8bit", 0.8);
+ HTSetSuffix(".rtf", "application/x-rtf", "7bit", 1.0); /* RTF */
+ HTSetSuffix(".Z", "application/x-compressed", "binary", 1.0); /* Compressed data */
+ HTSetSuffix(".csh", "application/x-csh", "7bit", 0.5); /* C-shell script */
+ HTSetSuffix(".dvi", "application/x-dvi", "binary", 1.0); /* TeX DVI */
+ HTSetSuffix(".hdf", "application/x-hdf", "binary", 1.0); /* NCSA HDF data file */
+ HTSetSuffix(".latex", "application/x-latex", "8bit", 1.0); /* LaTeX source */
+ HTSetSuffix(".nc", "application/x-netcdf", "binary", 1.0); /* Unidata netCDF data */
+ HTSetSuffix(".cdf", "application/x-netcdf", "binary", 1.0);
+ HTSetSuffix(".sh", "application/x-sh", "7bit", 0.5); /* Shell-script */
+ HTSetSuffix(".tcl", "application/x-tcl", "7bit", 0.5); /* TCL-script */
+ HTSetSuffix(".tex", "application/x-tex", "8bit", 1.0); /* TeX source */
+ HTSetSuffix(".texi", "application/x-texinfo", "7bit", 1.0); /* Texinfo */
+ HTSetSuffix(".texinfo","application/x-texinfo", "7bit", 1.0);
+ HTSetSuffix(".t", "application/x-troff", "7bit", 0.5); /* Troff */
+ HTSetSuffix(".roff", "application/x-troff", "7bit", 0.5);
+ HTSetSuffix(".tr", "application/x-troff", "7bit", 0.5);
+ HTSetSuffix(".man", "application/x-troff-man", "7bit", 0.5); /* Troff with man macros*/
+ HTSetSuffix(".me", "application/x-troff-me", "7bit", 0.5); /* Troff with me macros */
+ HTSetSuffix(".ms", "application/x-troff-ms", "7bit", 0.5); /* Troff with ms macros */
+ HTSetSuffix(".src", "application/x-wais-source", "7bit", 1.0); /* WAIS source */
+ HTSetSuffix(".zip", "application/zip", "binary", 1.0); /* PKZIP */
+ HTSetSuffix(".bcpio", "application/x-bcpio", "binary", 1.0); /* Old binary CPIO */
+ HTSetSuffix(".cpio", "application/x-cpio", "binary", 1.0); /* POSIX CPIO */
+ HTSetSuffix(".gtar", "application/x-gtar", "binary", 1.0); /* Gnu tar */
+ HTSetSuffix(".shar", "application/x-shar", "8bit", 1.0); /* Shell archive */
+ HTSetSuffix(".sv4cpio","application/x-sv4cpio", "binary", 1.0); /* SVR4 CPIO */
+ HTSetSuffix(".sv4crc", "application/x-sv4crc", "binary", 1.0); /* SVR4 CPIO with CRC */
+ HTSetSuffix(".tar", "application/x-tar", "binary", 1.0); /* 4.3BSD tar */
+ HTSetSuffix(".ustar", "application/x-ustar", "binary", 1.0); /* POSIX tar */
+ HTSetSuffix(".snd", "audio/basic", "binary", 1.0); /* Audio */
+ HTSetSuffix(".au", "audio/basic", "binary", 1.0);
+ HTSetSuffix(".aiff", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".aifc", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".aif", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".wav", "audio/x-wav", "binary", 1.0); /* Windows+ WAVE format */
+ HTSetSuffix(".gif", "image/gif", "binary", 1.0); /* GIF */
+ HTSetSuffix(".ief", "image/ief", "binary", 1.0); /* Image Exchange fmt */
+ HTSetSuffix(".jpg", "image/jpeg", "binary", 1.0); /* JPEG */
+ HTSetSuffix(".JPG", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".JPE", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".jpe", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".JPEG", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".jpeg", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".tif", "image/tiff", "binary", 1.0); /* TIFF */
+ HTSetSuffix(".tiff", "image/tiff", "binary", 1.0);
+ HTSetSuffix(".ras", "image/cmu-raster", "binary", 1.0);
+ HTSetSuffix(".pnm", "image/x-portable-anymap", "binary", 1.0); /* PBM Anymap format */
+ HTSetSuffix(".pbm", "image/x-portable-bitmap", "binary", 1.0); /* PBM Bitmap format */
+ HTSetSuffix(".pgm", "image/x-portable-graymap", "binary", 1.0); /* PBM Graymap format */
+ HTSetSuffix(".ppm", "image/x-portable-pixmap", "binary", 1.0); /* PBM Pixmap format */
+ HTSetSuffix(".rgb", "image/x-rgb", "binary", 1.0);
+ HTSetSuffix(".xbm", "image/x-xbitmap", "binary", 1.0); /* X bitmap */
+ HTSetSuffix(".xpm", "image/x-xpixmap", "binary", 1.0); /* X pixmap format */
+ HTSetSuffix(".xwd", "image/x-xwindowdump", "binary", 1.0); /* X window dump (xwd) */
+ HTSetSuffix(".html", "text/html", "8bit", 1.0); /* HTML */
+ HTSetSuffix(".c", "text/plain", "7bit", 0.5); /* C source */
+ HTSetSuffix(".h", "text/plain", "7bit", 0.5); /* C headers */
+ HTSetSuffix(".C", "text/plain", "7bit", 0.5); /* C++ source */
+ HTSetSuffix(".cc", "text/plain", "7bit", 0.5); /* C++ source */
+ HTSetSuffix(".hh", "text/plain", "7bit", 0.5); /* C++ headers */
+ HTSetSuffix(".m", "text/plain", "7bit", 0.5); /* Objective-C source */
+ HTSetSuffix(".f90", "text/plain", "7bit", 0.5); /* Fortran 90 source */
+ HTSetSuffix(".txt", "text/plain", "7bit", 0.5); /* Plain text */
+ HTSetSuffix(".rtx", "text/richtext", "7bit", 1.0); /* MIME Richtext format */
+ HTSetSuffix(".tsv", "text/tab-separated-values", "7bit", 1.0); /* Tab-separated values */
+ HTSetSuffix(".etx", "text/x-setext", "7bit", 0.9); /* Struct Enchanced Txt */
+ HTSetSuffix(".MPG", "video/mpeg", "binary", 1.0); /* MPEG */
+ HTSetSuffix(".mpg", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".MPE", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".mpe", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".MPEG", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".mpeg", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".qt", "video/quicktime", "binary", 1.0); /* QuickTime */
+ HTSetSuffix(".mov", "video/quicktime", "binary", 1.0);
+ HTSetSuffix(".avi", "video/x-msvideo", "binary", 1.0); /* MS Video for Windows */
+ HTSetSuffix(".movie", "video/x-sgi-movie", "binary", 1.0); /* SGI "moviepalyer" */
+
+ HTSetSuffix("*.*", "application/octet-stream", "binary", 0.1);
+ HTSetSuffix("*", "text/plain", "7bit", 0.5);
+
+}
+#endif /* NO_INIT */
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.h
new file mode 100644
index 00000000000..61c7d776a57
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTInit.h
@@ -0,0 +1,23 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTInit.html
+ INITIALISATION MODULE
+
+ This module resisters all the plug & play software modules which will be used in the
+ program. This is for a browser.
+
+ To override this, just copy it and link in your version befoe you link with the
+ library.
+
+ Implemented by HTInit.c by default.
+
+ */
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+extern void HTFormatInit NOPARAMS;
+extern void HTPreparsedFormatInit NOPARAMS;
+extern void HTFileInit NOPARAMS;
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.c
new file mode 100644
index 00000000000..268701704d1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.c
@@ -0,0 +1,142 @@
+
+/* MODULE HTLex.c
+** LEXICAL ANALYSOR
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+**
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include "HTAAUtil.h"
+#include "HTLex.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+/*
+** Global variables
+*/
+PUBLIC char HTlex_buffer[40]; /* Read lexical string */
+PUBLIC int HTlex_line = 1; /* Line number in source file */
+
+
+/*
+** Module-wide variables
+*/
+PRIVATE int lex_cnt;
+PRIVATE BOOL lex_template;
+PRIVATE LexItem lex_pushed_back = LEX_NONE;
+PRIVATE FILE *cache = NULL;
+
+
+PUBLIC void unlex ARGS1(LexItem, lex_item)
+{
+ lex_pushed_back = lex_item;
+}
+
+
+PUBLIC LexItem lex ARGS1(FILE *, fp)
+{
+ int ch;
+
+ if (fp != cache) { /* This cache doesn't work ok because the system */
+ cache = fp; /* often assign same FILE structure the next open */
+ HTlex_line = 1; /* file. So, if there are syntax errors in setup */
+ } /* files it may confuse things later on. */
+
+ if (lex_pushed_back != LEX_NONE) {
+ LexItem ret = lex_pushed_back;
+ lex_pushed_back = LEX_NONE;
+ return ret;
+ }
+
+ lex_cnt = 0;
+ lex_template = NO;
+
+ for(;;) {
+ switch (ch = getc(fp)) {
+ case EOF:
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ case ':':
+ case ',':
+ case '(':
+ case ')':
+ case '@':
+ if (lex_cnt > 0) {
+ if (ch != EOF) ungetc(ch,fp);
+ if (lex_template) return LEX_TMPL_STR;
+ else return LEX_ALPH_STR;
+ }
+ else switch(ch) {
+ case EOF: return LEX_EOF; break;
+ case '\n':
+ HTlex_line++; return LEX_REC_SEP; break;
+ case ':': return LEX_FIELD_SEP; break;
+ case ',': return LEX_ITEM_SEP; break;
+ case '(': return LEX_OPEN_PAREN; break;
+ case ')': return LEX_CLOSE_PAREN; break;
+ case '@': return LEX_AT_SIGN; break;
+ default: ; /* Leading white space ignored (SP,TAB,CR) */
+ }
+ break;
+ default:
+ HTlex_buffer[lex_cnt++] = ch;
+ HTlex_buffer[lex_cnt] = '\0';
+ if ('*' == ch) lex_template = YES;
+ } /* switch ch */
+ } /* forever */
+}
+
+
+PUBLIC char *lex_verbose ARGS1(LexItem, lex_item)
+{
+ static char msg[100];
+
+ switch (lex_item) {
+ case LEX_NONE: /* Internally used */
+ return "NO-LEX-ITEM";
+ break;
+ case LEX_EOF: /* End of file */
+ return "end-of-file";
+ break;
+ case LEX_REC_SEP: /* Record separator */
+ return "record separator (newline)";
+ break;
+ case LEX_FIELD_SEP: /* Field separator */
+ return "field separator ':'";
+ break;
+ case LEX_ITEM_SEP: /* List item separator */
+ return "item separator ','";
+ break;
+ case LEX_OPEN_PAREN: /* Group start tag */
+ return "'('";
+ break;
+ case LEX_CLOSE_PAREN: /* Group end tag */
+ return "')'";
+ break;
+ case LEX_AT_SIGN: /* Address qualifier */
+ return "address qualifier '@'";
+ break;
+ case LEX_ALPH_STR: /* Alphanumeric string */
+ sprintf(msg, "alphanumeric string '%s'", HTlex_buffer);
+ return msg;
+ break;
+ case LEX_TMPL_STR: /* Template string */
+ sprintf(msg, "template string '%s'", HTlex_buffer);
+ return msg;
+ break;
+ default:
+ return "UNKNOWN-LEX-ITEM";
+ break;
+ }
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.h
new file mode 100644
index 00000000000..5895579bccb
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTLex.h
@@ -0,0 +1,64 @@
+/* LEXICAL ANALYSOR (MAINLY FOR CONFIG FILES)
+
+ */
+
+#ifndef HTLEX_H
+#define HTLEX_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+
+#ifdef SHORT_NAMES
+#define lex_verb lex_verbose
+#endif /*SHORT_NAMES*/
+
+
+typedef enum {
+ LEX_NONE, /* Internally used */
+ LEX_EOF, /* End of file */
+ LEX_REC_SEP, /* Record separator */
+ LEX_FIELD_SEP, /* Field separator */
+ LEX_ITEM_SEP, /* List item separator */
+ LEX_OPEN_PAREN, /* Group start tag */
+ LEX_CLOSE_PAREN, /* Group end tag */
+ LEX_AT_SIGN, /* Address qualifier */
+ LEX_ALPH_STR, /* Alphanumeric string */
+ LEX_TMPL_STR /* Template string */
+} LexItem;
+
+extern char HTlex_buffer[]; /* Read lexical string */
+extern int HTlex_line; /* Line number in source file */
+
+/*
+
+Get Next Lexical Item
+
+ If returns LEX_ALPH_STR or LEX_TMPL_STR the string is in global buffer lex_buffer.
+
+ */
+
+PUBLIC LexItem lex PARAMS((FILE * fp));
+/*
+
+Push Back Latest Item
+
+ */
+
+PUBLIC void unlex PARAMS((LexItem lex_item));
+/*
+
+Get the Name for Lexical Item
+
+ */
+
+PUBLIC char *lex_verbose PARAMS((LexItem lex_item));
+/*
+
+ */
+
+#endif /* not HTLEX_H */
+/*
+
+ End of file HTLex.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.c
new file mode 100644
index 00000000000..839e961ddb5
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.c
@@ -0,0 +1,314 @@
+/* A small List class HTList.c
+** ==================
+**
+** A list is represented as a sequence of linked nodes of type HTList.
+** The first node is a header which contains no object.
+** New nodes are inserted between the header and the rest of the list.
+*/
+
+#include "HTUtils.h"
+#include "HTList.h"
+
+/*#include <stdio.h> included by HTUtils.h -- FM *//* joe@athena, TBL 921019 */
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+
+/* Create list.
+*/
+PUBLIC HTList * HTList_new NOARGS
+{
+ HTList *newList;
+
+ if ((newList = (HTList *)calloc(1, sizeof(HTList))) == NULL)
+ outofmem(__FILE__, "HTList_new");
+
+ newList->object = NULL;
+ newList->next = NULL;
+
+ return newList;
+}
+
+
+/* Delete list.
+*/
+PUBLIC void HTList_delete ARGS1(
+ HTList *, me)
+{
+ HTList *current;
+
+ while ((current = me)) {
+ me = me->next;
+ FREE (current);
+ }
+
+ return;
+}
+
+
+/* Add object to START of list (so it is pointed to by the head).
+*/
+PUBLIC void HTList_addObject ARGS2(
+ HTList *, me,
+ void *, newObject)
+{
+ HTList *newNode;
+
+ if (me) {
+ if ((newNode = (HTList *)calloc(1, sizeof(HTList))) == NULL)
+ outofmem(__FILE__, "HTList_addObject");
+ newNode->object = newObject;
+ newNode->next = me->next;
+ me->next = newNode;
+
+ } else if (TRACE) {
+ fprintf(stderr,
+ "HTList: Trying to add object %p to a nonexisting list\n",
+ newObject);
+ }
+
+ return;
+}
+
+
+/* Append object to END of list (furthest from the head).
+*/
+PUBLIC void HTList_appendObject ARGS2(
+ HTList *, me,
+ void *, newObject)
+{
+ HTList *temp = me;
+
+ if (temp && newObject) {
+ while (temp->next)
+ temp = temp->next;
+ HTList_addObject(temp, newObject);
+ }
+
+ return;
+}
+
+
+/* Insert an object into the list at a specified position.
+** If position is 0, this places the object at the head of the list
+** and is equivalent to HTList_addObject().
+*/
+PUBLIC void HTList_insertObjectAt ARGS3(
+ HTList *, me,
+ void *, newObject,
+ int, pos)
+{
+ HTList * newNode;
+ HTList * temp = me;
+ HTList * prevNode;
+ int Pos = pos;
+
+ if (!temp) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTList: Trying to add object %p to a nonexisting list\n",
+ newObject);
+ }
+ return;
+ }
+ if (Pos < 0) {
+ Pos = 0;
+ if (TRACE) {
+ fprintf(stderr,
+ "HTList: Treating negative object position %d as %d.\n",
+ pos, Pos);
+ }
+ }
+
+ prevNode = temp;
+ while ((temp = temp->next)) {
+ if (Pos == 0) {
+ if ((newNode = (HTList *)calloc(1, sizeof(HTList))) == NULL)
+ outofmem(__FILE__, "HTList_addObjectAt");
+ newNode->object = newObject;
+ newNode->next = temp;
+ if (prevNode)
+ prevNode->next = newNode;
+ return;
+ }
+ prevNode = temp;
+ Pos--;
+ }
+ if (Pos >= 0)
+ HTList_addObject(prevNode, newObject);
+
+ return;
+}
+
+
+/* Remove specified object from list.
+*/
+PUBLIC BOOL HTList_removeObject ARGS2(
+ HTList *, me,
+ void *, oldObject)
+{
+ HTList *temp = me;
+ HTList *prevNode;
+
+ if (temp && oldObject) {
+ while (temp->next) {
+ prevNode = temp;
+ temp = temp->next;
+ if (temp->object == oldObject) {
+ prevNode->next = temp->next;
+ FREE (temp);
+ return YES; /* Success */
+ }
+ }
+ }
+ return NO; /* object not found or NULL list */
+}
+
+
+/* Remove object at a given position in the list, where 0 is the
+** object pointed to by the head (returns a pointer to the element
+** (->object) for the object, and NULL if the list is empty, or
+** if it doesn't exist - Yuk!).
+*/
+PUBLIC void * HTList_removeObjectAt ARGS2(
+ HTList *, me,
+ int, position)
+{
+ HTList * temp = me;
+ HTList * prevNode;
+ int pos = position;
+
+ if (!temp || pos < 0)
+ return NULL;
+
+ prevNode = temp;
+ while ((temp = temp->next)) {
+ if (pos == 0) {
+ prevNode->next = temp->next;
+ prevNode = temp;
+ FREE(temp);
+ return prevNode->object;
+ }
+ prevNode = temp;
+ pos--;
+ }
+
+ return NULL; /* Reached the end of the list */
+}
+
+
+/* Remove object from START of list (the Last one inserted
+** via HTList_addObject(), and pointed to by the head).
+*/
+PUBLIC void * HTList_removeLastObject ARGS1(
+ HTList *, me)
+{
+ HTList * lastNode;
+ void * lastObject;
+
+ if (me && me->next) {
+ lastNode = me->next;
+ lastObject = lastNode->object;
+ me->next = lastNode->next;
+ FREE (lastNode);
+ return lastObject;
+
+ } else { /* Empty list */
+ return NULL;
+ }
+}
+
+
+/* Remove object from END of list (the First one inserted
+** via HTList_addObject(), and furthest from the head).
+*/
+PUBLIC void * HTList_removeFirstObject ARGS1(
+ HTList *, me)
+{
+ HTList * temp = me;
+ HTList * prevNode;
+ void *firstObject;
+
+ if (!temp)
+ return NULL;
+
+ prevNode = temp;
+ if (temp->next) {
+ while (temp->next) {
+ prevNode = temp;
+ temp = temp->next;
+ }
+ firstObject = temp->object;
+ prevNode->next = NULL;
+ FREE (temp);
+ return firstObject;
+
+ } else { /* Empty list */
+ return NULL;
+ }
+}
+
+
+/* Determine total number of objects in the list,
+** not counting the head.
+*/
+PUBLIC int HTList_count ARGS1(
+ HTList *, me)
+{
+ HTList * temp = me;
+ int count = 0;
+
+ if (temp)
+ while ((temp = temp->next))
+ count++;
+
+ return count;
+}
+
+
+/* Determine position of an object in the list (a value of 0
+** means it is pointed to by the head; returns -1 if not found).
+*/
+PUBLIC int HTList_indexOf ARGS2(
+ HTList *, me,
+ void *, object)
+{
+ HTList * temp = me;
+ int position = 0;
+
+ if (temp) {
+ while ((temp = temp->next)) {
+ if (temp->object == object)
+ return position;
+ position++;
+ }
+ }
+
+ return -1; /* Object not in the list */
+}
+
+
+/* Return pointer to the object at a specified position in the list,
+** where 0 is the object pointed to by the head (returns NULL if
+** the list is empty, or if it doesn't exist - Yuk!).
+*/
+PUBLIC void * HTList_objectAt ARGS2(
+ HTList *, me,
+ int, position)
+{
+ HTList * temp = me;
+ int pos = position;
+
+ if (!temp || pos < 0)
+ return NULL;
+
+ while ((temp = temp->next)) {
+ if (pos == 0)
+ return temp->object;
+ pos--;
+ }
+
+ return NULL; /* Reached the end of the list */
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.h
new file mode 100644
index 00000000000..89c0e62bbc9
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTList.h
@@ -0,0 +1,146 @@
+
+/* List object
+**
+** The list object is a generic container for storing collections
+** of things in order.
+*/
+#ifndef HTLIST_H
+#define HTLIST_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h" /* for BOOL type and PARAMS and ARGS*/
+#endif /* HTUTILS_H */
+
+typedef struct _HTList HTList;
+
+struct _HTList {
+ void * object;
+ HTList * next;
+};
+
+#ifdef SHORT_NAMES
+#define HTList_new HTLiNew
+#define HTList_delete HTLiDele
+#define HTList_addObject HTLiAdOb
+#define HTList_removeObject HTLiReOb
+#define HTList_removeObjectAt HTLiReAt
+#define HTList_removeLastObject HTLiReLa
+#define HTList_removeFirstObject HTLiReFi
+#define HTList_count HTLiCoun
+#define HTList_indexOf HTLiInOf
+#define HTList_objectAt HTLiObAt
+#endif /* SHORT_NAMES */
+
+
+/* Fast macro to traverse a list. Call it first with copy of the list
+** header. It returns the first object and increments the passed list
+** pointer. Call it with the same variable until it returns NULL.
+*/
+#define HTList_nextObject(me) \
+ ((me) && ((me) = (me)->next) ? (me)->object : NULL)
+
+
+/* Macro to find object pointed to by the head (returns NULL
+** if list is empty, OR if it doesn't exist - Yuk!)
+*/
+#define HTList_lastObject(me) \
+ ((me) && (me)->next ? (me)->next->object : NULL)
+
+
+/* Macro to check if a list is empty (or doesn't exist - Yuk!)
+*/
+#define HTList_isEmpty(me) ((me) ? ((me)->next == NULL) : YES)
+
+
+/* Create list.
+*/
+extern HTList * HTList_new NOPARAMS;
+
+
+/* Delete list.
+*/
+extern void HTList_delete PARAMS((
+ HTList * me));
+
+
+/* Add object to START of list (so it is pointed to by the head).
+*/
+extern void HTList_addObject PARAMS((
+ HTList * me,
+ void * newObject));
+
+
+/* Append object to END of list (furthest from the head).
+*/
+extern void HTList_appendObject PARAMS((
+ HTList * me,
+ void * newObject));
+
+
+/* Insert an object into the list at a specified position.
+** If position is 0, this places the object at the head of the list
+** and is equivalent to HTList_addObject().
+*/
+extern void HTList_insertObjectAt PARAMS((
+ HTList * me,
+ void * newObject,
+ int pos));
+
+
+/* Remove specified object from list.
+*/
+extern BOOL HTList_removeObject PARAMS((
+ HTList * me,
+ void * oldObject));
+
+
+/* Remove object at a given position in the list, where 0 is the
+** object pointed to by the head (returns a pointer to the element
+** (->object) for the object, and NULL if the list is empty, or
+** if it doesn't exist - Yuk!).
+*/
+extern void * HTList_removeObjectAt PARAMS((
+ HTList * me,
+ int position));
+
+
+/* Remove object from START of list (the Last one inserted
+** via HTList_addObject(), and pointed to by the head).
+*/
+extern void * HTList_removeLastObject PARAMS((
+ HTList * me));
+
+
+/* Remove object from END of list (the First one inserted
+** via HTList_addObject(), and furthest from the head).
+*/
+extern void * HTList_removeFirstObject PARAMS((
+ HTList * me));
+
+
+/* Determine total number of objects in the list,
+** not counting the head.
+*/
+extern int HTList_count PARAMS((
+ HTList * me));
+
+
+/* Determine position of an object in the list (a value of 0
+** means it is pointed to by the head; returns -1 if not found).
+*/
+extern int HTList_indexOf PARAMS((
+ HTList * me,
+ void * object));
+
+
+/* Return pointer to the object at a specified position in the list,
+** where 0 is the object pointed to by the head (returns NULL if
+** the list is empty, or if it doesn't exist - Yuk!).
+*/
+extern void * HTList_objectAt PARAMS((
+ HTList * me,
+ int position));
+
+
+#endif /* HTLIST_H */
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.c
new file mode 100644
index 00000000000..1041bdff789
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.c
@@ -0,0 +1,2599 @@
+/* MIME Message Parse HTMIME.c
+** ==================
+**
+** This is RFC 1341-specific code.
+** The input stream pushed into this parser is assumed to be
+** stripped on CRs, ie lines end with LF, not CR LF.
+** (It is easy to change this except for the body part where
+** conversion can be slow.)
+**
+** History:
+** Feb 92 Written Tim Berners-Lee, CERN
+**
+*/
+#include "HTUtils.h"
+#include "HTMIME.h" /* Implemented here */
+#include "HTAlert.h"
+#include "HTCJK.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include "LYCharSets.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern CONST char *LYchar_set_names[];
+extern BOOLEAN LYRawMode;
+extern BOOL HTPassEightBitRaw;
+extern HTCJKlang HTCJK;
+
+extern void LYSetCookie PARAMS((
+ CONST char * SetCookie,
+ CONST char * SetCookie2,
+ CONST char * address));
+extern time_t LYmktime PARAMS((char *string, BOOL absolute));
+
+
+/* MIME Object
+** -----------
+*/
+
+typedef enum _MIME_state {
+ MIME_TRANSPARENT, /* put straight through to target ASAP! */
+ miBEGINNING_OF_LINE, /* first character and not a continuation */
+ miA,
+ miACCEPT_RANGES,
+ miAGE,
+ miAL,
+ miALLOW,
+ miALTERNATES,
+ miC,
+ miCACHE_CONTROL,
+ miCO,
+ miCOOKIE,
+ miCON,
+ miCONNECTION,
+ miCONTENT_,
+ miCONTENT_BASE,
+ miCONTENT_DISPOSITION,
+ miCONTENT_ENCODING,
+ miCONTENT_FEATURES,
+ miCONTENT_L,
+ miCONTENT_LANGUAGE,
+ miCONTENT_LENGTH,
+ miCONTENT_LOCATION,
+ miCONTENT_MD5,
+ miCONTENT_RANGE,
+ miCONTENT_T,
+ miCONTENT_TRANSFER_ENCODING,
+ miCONTENT_TYPE,
+ miDATE,
+ miE,
+ miETAG,
+ miEXPIRES,
+ miKEEP_ALIVE,
+ miL,
+ miLAST_MODIFIED,
+ miLINK,
+ miLOCATION,
+ miP,
+ miPR,
+ miPRAGMA,
+ miPROXY_AUTHENTICATE,
+ miPUBLIC,
+ miRETRY_AFTER,
+ miS,
+ miSAFE,
+ miSE,
+ miSERVER,
+ miSET_COOKIE,
+ miSET_COOKIE1,
+ miSET_COOKIE2,
+ miT,
+ miTITLE,
+ miTRANSFER_ENCODING,
+ miU,
+ miUPGRADE,
+ miURI,
+ miV,
+ miVARY,
+ miVIA,
+ miW,
+ miWARNING,
+ miWWW_AUTHENTICATE,
+ miSKIP_GET_VALUE, /* Skip space then get value */
+ miGET_VALUE, /* Get value till white space */
+ miJUNK_LINE, /* Ignore the rest of this folded line */
+ miNEWLINE, /* Just found a LF .. maybe continuation */
+ miCHECK, /* check against check_pointer */
+ MIME_NET_ASCII, /* Translate from net ascii */
+ MIME_IGNORE /* Ignore entire file */
+ /* TRANSPARENT and IGNORE are defined as stg else in _WINDOWS */
+} MIME_state;
+
+#define VALUE_SIZE 1024 /* @@@@@@@ Arbitrary? */
+struct _HTStream {
+ CONST HTStreamClass * isa;
+
+ BOOL net_ascii; /* Is input net ascii? */
+ MIME_state state; /* current state */
+ MIME_state if_ok; /* got this state if match */
+ MIME_state field; /* remember which field */
+ MIME_state fold_state; /* state on a fold */
+ CONST char * check_pointer; /* checking input */
+
+ char * value_pointer; /* storing values */
+ char value[VALUE_SIZE];
+
+ HTParentAnchor * anchor; /* Given on creation */
+ HTStream * sink; /* Given on creation */
+
+ char * boundary; /* For multipart */
+ char * set_cookie; /* Set-Cookie */
+ char * set_cookie2; /* Set-Cookie2 */
+
+ HTFormat encoding; /* Content-Transfer-Encoding */
+ char * compression_encoding;
+ HTFormat format; /* Content-Type */
+ HTStream * target; /* While writing out */
+ HTStreamClass targetClass;
+
+ HTAtom * targetRep; /* Converting into? */
+};
+
+/*
+** This function is for trimming off any paired
+** open- and close-double quotes from header values.
+** It does not parse the string for embedded quotes,
+** and will not modify the string unless both the
+** first and last characters are double-quotes. - FM
+*/
+PUBLIC void HTMIME_TrimDoubleQuotes ARGS1(
+ char *, value)
+{
+ int i;
+ char *cp = value;
+
+ if (!(cp && *cp) || *cp != '\"')
+ return;
+
+ i = strlen(cp);
+ if (cp[(i - 1)] != '\"')
+ return;
+ else
+ cp[(i - 1)] = '\0';
+
+ for (i = 0; value[i]; i++)
+ value[i] = cp[(i +1)];
+}
+
+/*_________________________________________________________________________
+**
+** A C T I O N R O U T I N E S
+*/
+
+/* Character handling
+** ------------------
+**
+** This is a FSM parser which is tolerant as it can be of all
+** syntax errors. It ignores field names it does not understand,
+** and resynchronises on line beginnings.
+*/
+PRIVATE void HTMIME_put_character ARGS2(
+ HTStream *, me,
+ char, c)
+{
+ int i, j;
+
+ if (me->state == MIME_TRANSPARENT) {
+ (*me->targetClass.put_character)(me->target, c);/* MUST BE FAST */
+ return;
+ }
+
+ /*
+ ** This slightly simple conversion just strips CR and turns LF to
+ ** newline. On unix LF is \n but on Mac \n is CR for example.
+ ** See NetToText for an implementation which preserves single CR or LF.
+ */
+ if (me->net_ascii) {
+ c = FROMASCII(c);
+ if (c == CR)
+ return;
+ else if (c == LF)
+ c = '\n';
+ }
+
+ switch(me->state) {
+
+ case MIME_IGNORE:
+ return;
+
+ case MIME_TRANSPARENT: /* Not reached see above */
+ (*me->targetClass.put_character)(me->target, c);
+ return;
+
+ case MIME_NET_ASCII:
+ (*me->targetClass.put_character)(me->target, c); /* MUST BE FAST */
+ return;
+
+ case miNEWLINE:
+ if (c != '\n' && WHITE(c)) { /* Folded line */
+ me->state = me->fold_state; /* pop state before newline */
+ break;
+ }
+
+ /* else Falls through */
+
+ case miBEGINNING_OF_LINE:
+ me->net_ascii = YES;
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->state = miA;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Got 'A' at beginning of line, state now A\n");
+ break;
+
+ case 'c':
+ case 'C':
+ me->state = miC;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'C' at beginning of line, state now C\n");
+ break;
+
+ case 'd':
+ case 'D':
+ me->check_pointer = "ate:";
+ me->if_ok = miDATE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'D' at beginning of line, checking for 'ate:'\n");
+ break;
+
+ case 'e':
+ case 'E':
+ me->state = miE;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'E' at beginning of line, state now E\n");
+ break;
+
+ case 'k':
+ case 'K':
+ me->check_pointer = "eep-alive:";
+ me->if_ok = miKEEP_ALIVE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Got 'K' at beginning of line, checking for 'eep-alive:'\n");
+ break;
+
+ case 'l':
+ case 'L':
+ me->state = miL;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'L' at beginning of line, state now L\n");
+ break;
+
+ case 'p':
+ case 'P':
+ me->state = miP;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'P' at beginning of line, state now P\n");
+ break;
+
+ case 'r':
+ case 'R':
+ me->check_pointer = "etry-after:";
+ me->if_ok = miRETRY_AFTER;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Got 'R' at beginning of line, checking for 'etry-after'\n");
+ break;
+
+ case 's':
+ case 'S':
+ me->state = miS;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'S' at beginning of line, state now S\n");
+ break;
+
+ case 't':
+ case 'T':
+ me->state = miT;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'T' at beginning of line, state now T\n");
+ break;
+
+ case 'u':
+ case 'U':
+ me->state = miU;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'U' at beginning of line, state now U\n");
+ break;
+
+ case 'v':
+ case 'V':
+ me->state = miV;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'V' at beginning of line, state now V\n");
+ break;
+
+ case 'w':
+ case 'W':
+ me->state = miW;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Got 'W' at beginning of line, state now W\n");
+ break;
+
+ case '\n': /* Blank line: End of Header! */
+ {
+ me->net_ascii = NO;
+ if (strchr(HTAtom_name(me->format), ';') != NULL) {
+ char *cp = NULL, *cp1, *cp2, *cp3 = NULL, *cp4;
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Extended MIME Content-Type is %s\n",
+ HTAtom_name(me->format));
+ StrAllocCopy(cp, HTAtom_name(me->format));
+ /*
+ ** Note that the Content-Type value was converted
+ ** to lower case when we loaded into me->format,
+ ** but there may have been a mixed or upper-case
+ ** atom, so we'll force lower-casing again. We
+ ** also stripped spaces and double-quotes, but
+ ** we'll make sure they're still gone from any
+ ** charset parameter we check. - FM
+ */
+ for (i = 0; cp[i]; i++)
+ cp[i] = TOLOWER(cp[i]);
+ if ((cp1 = strchr(cp, ';')) != NULL) {
+ BOOL chartrans_ok = NO;
+ if ((cp2 = strstr(cp1, "charset")) != NULL) {
+ int chndl;
+
+ cp2 += 7;
+ while (*cp2 == ' ' || *cp2 == '=' || *cp2 == '\"')
+ cp2++;
+ StrAllocCopy(cp3, cp2); /* copy to mutilate more */
+ for (cp4 = cp3; (*cp4 != '\0' && *cp4 != '\"' &&
+ *cp4 != ';' && *cp4 != ':' &&
+ !WHITE(*cp4)); cp4++)
+ ; /* do nothing */
+ *cp4 = '\0';
+ cp4 = cp3;
+ chndl = UCGetLYhndl_byMIME(cp3);
+ if (UCCanTranslateFromTo(chndl,
+ current_char_set)) {
+ chartrans_ok = YES;
+ *cp1 = '\0';
+ me->format = HTAtom_for(cp);
+ StrAllocCopy(me->anchor->charset, cp4);
+ HTAnchor_setUCInfoStage(me->anchor, chndl,
+ UCT_STAGE_MIME,
+ UCT_SETBY_MIME);
+ }
+ else if (chndl < 0) {/* got something but we don't
+ recognize it */
+ chndl = UCLYhndl_for_unrec;
+ if (UCCanTranslateFromTo(chndl,
+ current_char_set)) {
+ chartrans_ok = YES;
+ *cp1 = '\0';
+ me->format = HTAtom_for(cp);
+ HTAnchor_setUCInfoStage(me->anchor, chndl,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ }
+ }
+ FREE(cp3);
+ if (chartrans_ok) {
+ LYUCcharset * p_in =
+ HTAnchor_getUCInfoStage(me->anchor,
+ UCT_STAGE_MIME);
+ LYUCcharset * p_out =
+ HTAnchor_setUCInfoStage(me->anchor,
+ current_char_set,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ if (!p_out)
+ /*
+ ** Try again.
+ */
+ p_out =
+ HTAnchor_getUCInfoStage(me->anchor,
+ UCT_STAGE_HTEXT);
+
+ if (!strcmp(p_in->MIMEname,
+ "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(me->anchor,
+ HTAnchor_getUCLYhndl(me->anchor,
+ UCT_STAGE_HTEXT),
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ }
+ if (!strcmp(p_out->MIMEname,
+ "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(me->anchor,
+ HTAnchor_getUCLYhndl(me->anchor,
+ UCT_STAGE_MIME),
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ }
+ if (p_in->enc != UCT_ENC_CJK) {
+ HTCJK = NOCJK;
+ if (!(p_in->codepoints &
+ UCT_CP_SUBSETOF_LAT1) &&
+ chndl == current_char_set) {
+ HTPassEightBitRaw = TRUE;
+ }
+ } else if (p_out->enc == UCT_ENC_CJK) {
+ if (LYRawMode) {
+ if ((!strcmp(p_in->MIMEname,
+ "euc-jp") ||
+ !strcmp(p_in->MIMEname,
+ "shift_jis")) &&
+ (!strcmp(p_out->MIMEname,
+ "euc-jp") ||
+ !strcmp(p_out->MIMEname,
+ "shift_jis"))) {
+ HTCJK = JAPANESE;
+ } else if (!strcmp(p_in->MIMEname,
+ "euc-cn") &&
+ !strcmp(p_out->MIMEname,
+ "euc-cn")) {
+ HTCJK = CHINESE;
+ } else if (!strcmp(p_in->MIMEname,
+ "big-5") &&
+ !strcmp(p_out->MIMEname,
+ "big-5")) {
+ HTCJK = TAIPEI;
+ } else if (!strcmp(p_in->MIMEname,
+ "euc-kr") &&
+ !strcmp(p_out->MIMEname,
+ "euc-kr")) {
+ HTCJK = KOREAN;
+ } else {
+ HTCJK = NOCJK;
+ }
+ } else {
+ HTCJK = NOCJK;
+ }
+ }
+ /*
+ ** Check for an iso-8859-# we don't know. - FM
+ */
+ } else if
+ (!strncmp(cp4, "iso-8859-", 9) &&
+ isdigit((unsigned char)cp4[9]) &&
+ !strncmp(LYchar_set_names[current_char_set],
+ "Other ISO Latin", 15)) {
+ /*
+ ** Hope it's a match, for now. - FM
+ */
+ *cp1 = '\0';
+ me->format = HTAtom_for(cp);
+ cp1 = &cp4[10];
+ while (*cp1 &&
+ isdigit((unsigned char)(*cp1)))
+ cp1++;
+ *cp1 = '\0';
+ StrAllocCopy(me->anchor->charset, cp4);
+ HTPassEightBitRaw = TRUE;
+ HTAlert(me->anchor->charset);
+ }
+ FREE(cp3);
+ } else {
+ /*
+ ** No charset parameter is present.
+ ** Ignore all other parameters, as
+ ** we do when charset is present. - FM
+ */
+ *cp1 = '\0';
+ me->format = HTAtom_for(cp);
+ }
+ }
+ FREE(cp);
+ }
+ /*
+ ** If we have an Expires header and haven't
+ ** already set the no_cache element for the
+ ** anchor, check if we should set it based
+ ** on that header. - FM
+ */
+ if (me->anchor->no_cache == FALSE &&
+ me->anchor->expires != NULL) {
+ if (!strcmp(me->anchor->expires, "0")) {
+ /*
+ * The value is zero, which we treat as
+ * an absolute no-cache directive. - FM
+ */
+ me->anchor->no_cache = TRUE;
+ } else if (me->anchor->date != NULL) {
+ /*
+ ** We have a Date header, so check if
+ ** the value is less than or equal to
+ ** that. - FM
+ */
+ if (LYmktime(me->anchor->expires, TRUE) <=
+ LYmktime(me->anchor->date, TRUE)) {
+ me->anchor->no_cache = TRUE;
+ }
+ } else if (LYmktime(me->anchor->expires, FALSE) <= 0) {
+ /*
+ ** We don't have a Date header, and
+ ** the value is in past for us. - FM
+ */
+ me->anchor->no_cache = TRUE;
+ }
+ }
+ StrAllocCopy(me->anchor->content_type,
+ HTAtom_name(me->format));
+ if (!me->compression_encoding) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTMIME: MIME Content-Type is '%s', converting to '%s'\n",
+ HTAtom_name(me->format), HTAtom_name(me->targetRep));
+ }
+ } else {
+ /*
+ ** Change the format to that for "www/compressed"
+ ** and set up a stream to deal with it. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTMIME: MIME Content-Type is '%s',\n", HTAtom_name(me->format));
+ }
+ me->format = HTAtom_for("www/compressed");
+ if (TRACE) {
+ fprintf(stderr,
+ " Treating as '%s'. Converting to '%s'\n",
+ HTAtom_name(me->format), HTAtom_name(me->targetRep));
+ }
+ }
+ if (me->set_cookie != NULL || me->set_cookie2 != NULL) {
+ LYSetCookie(me->set_cookie,
+ me->set_cookie2,
+ me->anchor->address);
+ FREE(me->set_cookie);
+ FREE(me->set_cookie2);
+ }
+ me->target = HTStreamStack(me->format, me->targetRep,
+ me->sink , me->anchor);
+ if (!me->target) {
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Can't translate! ** \n");
+ me->target = me->sink; /* Cheat */
+ }
+ if (me->target) {
+ me->targetClass = *me->target->isa;
+ /*
+ ** Check for encoding and select state from there,
+ ** someday, but until we have the relevant code,
+ ** from now push straight through. - FM
+ */
+ me->state = MIME_TRANSPARENT;
+ } else {
+ me->state = MIME_IGNORE; /* What else to do? */
+ }
+ FREE(me->compression_encoding);
+ }
+ break;
+
+ default:
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miA: /* Check for 'c','g' or 'l' */
+ switch (c) {
+ case 'c':
+ case 'C':
+ me->check_pointer = "cept-ranges:";
+ me->if_ok = miACCEPT_RANGES;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was A, found C, checking for 'cept-ranges:'\n");
+ break;
+
+ case 'g':
+ case 'G':
+ me->check_pointer = "e:";
+ me->if_ok = miAGE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was A, found G, checking for 'e:'\n");
+ break;
+
+ case 'l':
+ case 'L':
+ me->state = miAL;
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Was A, found L, state now AL'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'g' or 'l'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miAL: /* Check for 'l' or 't' */
+ switch (c) {
+ case 'l':
+ case 'L':
+ me->check_pointer = "ow:";
+ me->if_ok = miALLOW;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was AL, found L, checking for 'ow:'\n");
+ break;
+
+ case 't':
+ case 'T':
+ me->check_pointer = "ernates:";
+ me->if_ok = miALTERNATES;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was AL, found T, checking for 'ernates:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'l' or 't'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miC: /* Check for 'a' or 'o' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "che-control:";
+ me->if_ok = miCACHE_CONTROL;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was C, found A, checking for 'che-control:'\n");
+ break;
+
+ case 'o':
+ case 'O':
+ me->state = miCO;
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Was C, found O, state now CO'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a' or 'o'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miCO: /* Check for 'n' or 'o' */
+ switch (c) {
+ case 'n':
+ case 'N':
+ me->state = miCON;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CO, found N, state now CON\n");
+ break;
+
+ case 'o':
+ case 'O':
+ me->check_pointer = "kie:";
+ me->if_ok = miCOOKIE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CO, found O, checking for 'kie:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'n' or 'o'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miCON: /* Check for 'n' or 't' */
+ switch (c) {
+ case 'n':
+ case 'N':
+ me->check_pointer = "ection:";
+ me->if_ok = miCONNECTION;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CON, found N, checking for 'ection:'\n");
+ break;
+
+ case 't':
+ case 'T':
+ me->check_pointer = "ent-";
+ me->if_ok = miCONTENT_;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CON, found T, checking for 'ent-'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'n' or 't'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miE: /* Check for 't' or 'x' */
+ switch (c) {
+ case 't':
+ case 'T':
+ me->check_pointer = "ag:";
+ me->if_ok = miETAG;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was E, found T, checking for 'ag:'\n");
+ break;
+
+ case 'x':
+ case 'X':
+ me->check_pointer = "pires:";
+ me->if_ok = miEXPIRES;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was E, found X, checking for 'pires:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'t' or 'x'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miL: /* Check for 'a', 'i' or 'o' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "st-modified:";
+ me->if_ok = miLAST_MODIFIED;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was L, found A, checking for 'st-modified:'\n");
+ break;
+
+ case 'i':
+ case 'I':
+ me->check_pointer = "nk:";
+ me->if_ok = miLINK;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was L, found I, checking for 'nk:'\n");
+ break;
+
+ case 'o':
+ case 'O':
+ me->check_pointer = "cation:";
+ me->if_ok = miLOCATION;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was L, found O, checking for 'cation:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a', 'i' or 'o'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miP: /* Check for 'r' or 'u' */
+ switch (c) {
+ case 'r':
+ case 'R':
+ me->state = miPR;
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Was P, found R, state now PR'\n");
+ break;
+
+ case 'u':
+ case 'U':
+ me->check_pointer = "blic:";
+ me->if_ok = miPUBLIC;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was P, found U, checking for 'blic:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'r' or 'u'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miPR: /* Check for 'a' or 'o' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "gma:";
+ me->if_ok = miPRAGMA;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was PR, found A, checking for 'gma'\n");
+ break;
+
+ case 'o':
+ case 'O':
+ me->check_pointer = "xy-authenticate:";
+ me->if_ok = miPROXY_AUTHENTICATE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was PR, found O, checking for 'xy-authenticate'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a' or 'o'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miS: /* Check for 'a' or 'e' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "fe:";
+ me->if_ok = miSAFE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Was S, found A, checking for 'fe:'\n");
+ break;
+
+ case 'e':
+ case 'E':
+ me->state = miSE;
+ if (TRACE)
+ fprintf(stderr, "HTMIME: Was S, found E, state now SE'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a' or 'e'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miSE: /* Check for 'r' or 't' */
+ switch (c) {
+ case 'r':
+ case 'R':
+ me->check_pointer = "ver:";
+ me->if_ok = miSERVER;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was SE, found R, checking for 'ver'\n");
+ break;
+
+ case 't':
+ case 'T':
+ me->check_pointer = "-cookie";
+ me->if_ok = miSET_COOKIE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was SE, found T, checking for '-cookie'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'r' or 't'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miSET_COOKIE: /* Check for ':' or '2' */
+ switch (c) {
+ case ':':
+ me->field = miSET_COOKIE1; /* remember it */
+ me->state = miSKIP_GET_VALUE;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was SET_COOKIE, found :, processing\n");
+ break;
+
+ case '2':
+ me->check_pointer = ":";
+ me->if_ok = miSET_COOKIE2;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was SET_COOKIE, found 2, checking for ':'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "':' or '2'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miT: /* Check for 'i' or 'r' */
+ switch (c) {
+ case 'i':
+ case 'I':
+ me->check_pointer = "tle:";
+ me->if_ok = miTITLE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was T, found I, checking for 'tle:'\n");
+ break;
+
+ case 'r':
+ case 'R':
+ me->check_pointer = "ansfer-encoding:";
+ me->if_ok = miTRANSFER_ENCODING;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was T, found R, checking for 'ansfer-encoding'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'i' or 'r'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miU: /* Check for 'p' or 'r' */
+ switch (c) {
+ case 'p':
+ case 'P':
+ me->check_pointer = "grade:";
+ me->if_ok = miUPGRADE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was U, found P, checking for 'grade:'\n");
+ break;
+
+ case 'r':
+ case 'R':
+ me->check_pointer = "i:";
+ me->if_ok = miURI;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was U, found R, checking for 'i:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'p' or 'r'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miV: /* Check for 'a' or 'i' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "ry:";
+ me->if_ok = miVARY;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was V, found A, checking for 'ry:'\n");
+ break;
+
+ case 'i':
+ case 'I':
+ me->check_pointer = "a:";
+ me->if_ok = miVIA;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was V, found I, checking for 'a:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a' or 'i'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miW: /* Check for 'a' or 'w' */
+ switch (c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "rning:";
+ me->if_ok = miWARNING;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was W, found A, checking for 'rning:'\n");
+ break;
+
+ case 'w':
+ case 'W':
+ me->check_pointer = "w-authenticate:";
+ me->if_ok = miWWW_AUTHENTICATE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was W, found W, checking for 'w-authenticate:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, "'a' or 'w'");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miCHECK: /* Check against string */
+ if (TOLOWER(c) == *(me->check_pointer)++) {
+ if (!*me->check_pointer)
+ me->state = me->if_ok;
+ } else { /* Error */
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Bad character `%c' found where `%s' expected\n",
+ c, me->check_pointer - 1);
+ goto bad_field_name;
+ }
+ break;
+
+ case miCONTENT_:
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: in case CONTENT_\n");
+ switch(c) {
+ case 'b':
+ case 'B':
+ me->check_pointer = "ase:";
+ me->if_ok = miCONTENT_BASE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found B, checking for 'ase:'\n");
+ break;
+
+ case 'd':
+ case 'D':
+ me->check_pointer = "isposition:";
+ me->if_ok = miCONTENT_DISPOSITION;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found D, checking for 'isposition:'\n");
+ break;
+
+ case 'e':
+ case 'E':
+ me->check_pointer = "ncoding:";
+ me->if_ok = miCONTENT_ENCODING;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found E, checking for 'ncoding:'\n");
+ break;
+
+ case 'f':
+ case 'F':
+ me->check_pointer = "eatures:";
+ me->if_ok = miCONTENT_FEATURES;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found F, checking for 'eatures:'\n");
+ break;
+
+ case 'l':
+ case 'L':
+ me->state = miCONTENT_L;
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Was CONTENT_, found L, state now CONTENT_L\n");
+ break;
+
+ case 'm':
+ case 'M':
+ me->check_pointer = "d5:";
+ me->if_ok = miCONTENT_MD5;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found M, checking for 'd5:'\n");
+ break;
+
+ case 'r':
+ case 'R':
+ me->check_pointer = "ange:";
+ me->if_ok = miCONTENT_RANGE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found R, checking for 'ange:'\n");
+ break;
+
+ case 't':
+ case 'T':
+ me->state = miCONTENT_T;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found T, state now CONTENT_T\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_, found nothing; bleah\n");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miCONTENT_L:
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: in case CONTENT_L\n");
+ switch(c) {
+ case 'a':
+ case 'A':
+ me->check_pointer = "nguage:";
+ me->if_ok = miCONTENT_LANGUAGE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_L, found A, checking for 'nguage:'\n");
+ break;
+
+ case 'e':
+ case 'E':
+ me->check_pointer = "ngth:";
+ me->if_ok = miCONTENT_LENGTH;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_L, found E, checking for 'ngth:'\n");
+ break;
+
+ case 'o':
+ case 'O':
+ me->check_pointer = "cation:";
+ me->if_ok = miCONTENT_LOCATION;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_L, found O, checking for 'cation:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Was CONTENT_L, found nothing; bleah\n");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miCONTENT_T:
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: in case CONTENT_T\n");
+ switch(c) {
+ case 'r':
+ case 'R':
+ me->check_pointer = "ansfer-encoding:";
+ me->if_ok = miCONTENT_TRANSFER_ENCODING;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_T, found R, checking for 'ansfer-encoding:'\n");
+ break;
+
+ case 'y':
+ case 'Y':
+ me->check_pointer = "pe:";
+ me->if_ok = miCONTENT_TYPE;
+ me->state = miCHECK;
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: Was CONTENT_T, found Y, checking for 'pe:'\n");
+ break;
+
+ default:
+ if (TRACE)
+ fprintf (stderr,
+ "HTMIME: Was CONTENT_T, found nothing; bleah\n");
+ goto bad_field_name;
+ break;
+
+ } /* switch on character */
+ break;
+
+ case miACCEPT_RANGES:
+ case miAGE:
+ case miALLOW:
+ case miALTERNATES:
+ case miCACHE_CONTROL:
+ case miCOOKIE:
+ case miCONNECTION:
+ case miCONTENT_BASE:
+ case miCONTENT_DISPOSITION:
+ case miCONTENT_ENCODING:
+ case miCONTENT_FEATURES:
+ case miCONTENT_LANGUAGE:
+ case miCONTENT_LENGTH:
+ case miCONTENT_LOCATION:
+ case miCONTENT_MD5:
+ case miCONTENT_RANGE:
+ case miCONTENT_TRANSFER_ENCODING:
+ case miCONTENT_TYPE:
+ case miDATE:
+ case miETAG:
+ case miEXPIRES:
+ case miKEEP_ALIVE:
+ case miLAST_MODIFIED:
+ case miLINK:
+ case miLOCATION:
+ case miPRAGMA:
+ case miPROXY_AUTHENTICATE:
+ case miPUBLIC:
+ case miRETRY_AFTER:
+ case miSAFE:
+ case miSERVER:
+ case miSET_COOKIE1:
+ case miSET_COOKIE2:
+ case miTITLE:
+ case miTRANSFER_ENCODING:
+ case miUPGRADE:
+ case miURI:
+ case miVARY:
+ case miVIA:
+ case miWARNING:
+ case miWWW_AUTHENTICATE:
+ me->field = me->state; /* remember it */
+ me->state = miSKIP_GET_VALUE;
+ /* Fall through! */
+
+ case miSKIP_GET_VALUE:
+ if (c == '\n') {
+ me->fold_state = me->state;
+ me->state = miNEWLINE;
+ break;
+ }
+ if (WHITE(c))
+ /*
+ ** Skip white space.
+ */
+ break;
+
+ me->value_pointer = me->value;
+ me->state = miGET_VALUE;
+ /* Fall through to store first character */
+
+ case miGET_VALUE:
+ if (WHITE(c) && c != 32) { /* End of field */
+ char *cp;
+ *me->value_pointer = '\0';
+ cp = (me->value_pointer - 1);
+ while ((cp >= me->value) && *cp == 32)
+ /*
+ ** Trim trailing spaces.
+ */
+ *cp = '\0';
+ switch (me->field) {
+ case miACCEPT_RANGES:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Accept-Ranges: '%s'\n",
+ me->value);
+ break;
+ case miAGE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Age: '%s'\n",
+ me->value);
+ break;
+ case miALLOW:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Allow: '%s'\n",
+ me->value);
+ break;
+ case miALTERNATES:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Alternates: '%s'\n",
+ me->value);
+ break;
+ case miCACHE_CONTROL:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Cache-Control: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Convert to lowercase and indicate in anchor. - FM
+ */
+ for (i = 0; me->value[i]; i++)
+ me->value[i] = TOLOWER(me->value[i]);
+ StrAllocCopy(me->anchor->cache_control, me->value);
+ /*
+ ** Check whether to set no_cache for the anchor. - FM
+ */
+ {
+ char *cp1, *cp0 = me->value;
+
+ while ((cp1 = strstr(cp0, "no-cache")) != NULL) {
+ cp1 += 8;
+ while (*cp1 != '\0' && WHITE(*cp1))
+ cp1++;
+ if (*cp1 == '\0' || *cp1 == ';') {
+ me->anchor->no_cache = TRUE;
+ break;
+ }
+ cp0 = cp1;
+ }
+ if (me->anchor->no_cache == TRUE)
+ break;
+ cp0 = me->value;
+ while ((cp1 = strstr(cp0, "max-age")) != NULL) {
+ cp1 += 7;
+ while (*cp1 != '\0' && WHITE(*cp1))
+ cp1++;
+ if (*cp1 == '=') {
+ cp1++;
+ while (*cp1 != '\0' && WHITE(*cp1))
+ cp1++;
+ if (isdigit((unsigned char)*cp1)) {
+ cp0 = cp1;
+ while (isdigit((unsigned char)*cp1))
+ cp1++;
+ if (*cp0 == '0' && cp1 == (cp0 + 1)) {
+ me->anchor->no_cache = TRUE;
+ break;
+ }
+ }
+ }
+ cp0 = cp1;
+ }
+ }
+ break;
+ case miCOOKIE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Cookie: '%s'\n",
+ me->value);
+ break;
+ case miCONNECTION:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Connection: '%s'\n",
+ me->value);
+ break;
+ case miCONTENT_BASE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Base: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->content_base, me->value);
+ break;
+ case miCONTENT_DISPOSITION:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Disposition: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->content_disposition, me->value);
+ /*
+ ** It's not clear yet from existing RFCs and IDs
+ ** whether we should be looking for file;, attachment;,
+ ** and/or inline; before the filename=value, so we'll
+ ** just search for "filename" followed by '=' and just
+ ** hope we get the intended value. It is purely a
+ ** suggested name, anyway. - FM
+ */
+ cp = me->anchor->content_disposition;
+ while (*cp != '\0' && strncasecomp(cp, "filename", 8))
+ cp++;
+ if (*cp == '\0')
+ break;
+ cp += 8;
+ while ((*cp != '\0') && (WHITE(*cp) || *cp == '='))
+ cp++;
+ if (*cp == '\0')
+ break;
+ while (*cp != '\0' && WHITE(*cp))
+ cp++;
+ if (*cp == '\0')
+ break;
+ StrAllocCopy(me->anchor->SugFname, cp);
+ if (*me->anchor->SugFname == '\"') {
+ if ((cp = strchr((me->anchor->SugFname + 1),
+ '\"')) != NULL) {
+ *(cp + 1) = '\0';
+ HTMIME_TrimDoubleQuotes(me->anchor->SugFname);
+ } else {
+ FREE(me->anchor->SugFname);
+ break;
+ }
+ }
+ cp = me->anchor->SugFname;
+ while (*cp != '\0' && !WHITE(*cp))
+ cp++;
+ *cp = '\0';
+ if (*me->anchor->SugFname == '\0')
+ FREE(me->anchor->SugFname);
+ break;
+ case miCONTENT_ENCODING:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Encoding: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value) ||
+ !strcasecomp(me->value, "identity"))
+ break;
+ /*
+ ** Convert to lowercase and indicate in anchor. - FM
+ */
+ for (i = 0; me->value[i]; i++)
+ me->value[i] = TOLOWER(me->value[i]);
+ StrAllocCopy(me->anchor->content_encoding, me->value);
+ FREE(me->compression_encoding);
+ if (!strcmp(me->value, "8bit") ||
+ !strcmp(me->value, "7bit") ||
+ !strcmp(me->value, "binary")) {
+ /*
+ ** Some server indicated "8bit", "7bit" or "binary"
+ ** inappropriately. We'll ignore it. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ " Ignoring it!\n");
+ } else {
+ /*
+ ** Save it to use as a flag for setting
+ ** up a "www/compressed" target. - FM
+ */
+ StrAllocCopy(me->compression_encoding, me->value);
+ }
+ break;
+ case miCONTENT_FEATURES:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Features: '%s'\n",
+ me->value);
+ break;
+ case miCONTENT_LANGUAGE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Language: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Convert to lowercase and indicate in anchor. - FM
+ */
+ for (i = 0; me->value[i]; i++)
+ me->value[i] = TOLOWER(me->value[i]);
+ StrAllocCopy(me->anchor->content_language, me->value);
+ break;
+ case miCONTENT_LENGTH:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Length: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Convert to integer and indicate in anchor. - FM
+ */
+ me->anchor->content_length = atoi(me->value);
+ if (me->anchor->content_length < 0)
+ me->anchor->content_length = 0;
+ if (TRACE)
+ fprintf(stderr,
+ " Converted to integer: '%d'\n",
+ me->anchor->content_length);
+ break;
+ case miCONTENT_LOCATION:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Location: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->content_location, me->value);
+ break;
+ case miCONTENT_MD5:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-MD5: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->content_md5, me->value);
+ break;
+ case miCONTENT_RANGE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Range: '%s'\n",
+ me->value);
+ break;
+ case miCONTENT_TRANSFER_ENCODING:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Transfer-Encoding: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Force the Content-Transfer-Encoding value
+ ** to all lower case. - FM
+ */
+ for (i = 0; me->value[i]; i++)
+ me->value[i] = TOLOWER(me->value[i]);
+ me->encoding = HTAtom_for(me->value);
+ break;
+ case miCONTENT_TYPE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Content-Type: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Force the Content-Type value to all lower case
+ ** and strip spaces and double-quotes. - FM
+ */
+ for (i = 0, j = 0; me->value[i]; i++) {
+ if (me->value[i] != ' ' && me->value[i] != '\"') {
+ me->value[j++] = TOLOWER(me->value[i]);
+ }
+ }
+ me->value[j] = '\0';
+ me->format = HTAtom_for(me->value);
+ break;
+ case miDATE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Date: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->date, me->value);
+ break;
+ case miETAG:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP ETag: '%s'\n",
+ me->value);
+ break;
+ case miEXPIRES:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Expires: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->expires, me->value);
+ break;
+ case miKEEP_ALIVE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Keep-Alive: '%s'\n",
+ me->value);
+ break;
+ case miLAST_MODIFIED:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Last-Modified: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->last_modified, me->value);
+ break;
+ case miLINK:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Link: '%s'\n",
+ me->value);
+ break;
+ case miLOCATION:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Location: '%s'\n",
+ me->value);
+ break;
+ case miPRAGMA:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Pragma: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Check whether to set no_cache for the anchor. - FM
+ */
+ if (!strcmp(me->value, "no-cache"))
+ me->anchor->no_cache = TRUE;
+ break;
+ case miPROXY_AUTHENTICATE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Proxy-Authenticate: '%s'\n",
+ me->value);
+ break;
+ case miPUBLIC:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Public: '%s'\n",
+ me->value);
+ break;
+ case miRETRY_AFTER:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Retry-After: '%s'\n",
+ me->value);
+ break;
+ case miSAFE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Safe: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor if "YES" or "TRUE". - FM
+ */
+ if (!strcasecomp(me->value, "YES") ||
+ !strcasecomp(me->value, "TRUE")) {
+ me->anchor->safe = TRUE;
+ }
+ break;
+ case miSERVER:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Server: '%s'\n",
+ me->value);
+ if (!(me->value && *me->value))
+ break;
+ /*
+ ** Indicate in anchor. - FM
+ */
+ StrAllocCopy(me->anchor->server, me->value);
+ break;
+ case miSET_COOKIE1:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Set-Cookie: '%s'\n",
+ me->value);
+ if (me->set_cookie == NULL) {
+ StrAllocCopy(me->set_cookie, me->value);
+ } else {
+ StrAllocCat(me->set_cookie, ", ");
+ StrAllocCat(me->set_cookie, me->value);
+ }
+ break;
+ case miSET_COOKIE2:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Set-Cookie2: '%s'\n",
+ me->value);
+ if (me->set_cookie2 == NULL) {
+ StrAllocCopy(me->set_cookie2, me->value);
+ } else {
+ StrAllocCat(me->set_cookie2, ", ");
+ StrAllocCat(me->set_cookie2, me->value);
+ }
+ break;
+ case miTITLE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Title: '%s'\n",
+ me->value);
+ break;
+ case miTRANSFER_ENCODING:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Transfer-Encoding: '%s'\n",
+ me->value);
+ break;
+ case miUPGRADE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Upgrade: '%s'\n",
+ me->value);
+ break;
+ case miURI:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP URI: '%s'\n",
+ me->value);
+ break;
+ case miVARY:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Vary: '%s'\n",
+ me->value);
+ break;
+ case miVIA:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Via: '%s'\n",
+ me->value);
+ break;
+ case miWARNING:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP Warning: '%s'\n",
+ me->value);
+ break;
+ case miWWW_AUTHENTICATE:
+ HTMIME_TrimDoubleQuotes(me->value);
+ if (TRACE)
+ fprintf(stderr,
+ "HTMIME: PICKED UP WWW-Authenticate: '%s'\n",
+ me->value);
+ break;
+ default: /* Should never get here */
+ break;
+ }
+ } else {
+ if (me->value_pointer < me->value + VALUE_SIZE - 1) {
+ *me->value_pointer++ = c;
+ break;
+ } else {
+ goto value_too_long;
+ }
+ }
+ /* Fall through */
+
+ case miJUNK_LINE:
+ if (c == '\n') {
+ me->state = miNEWLINE;
+ me->fold_state = me->state;
+ }
+ break;
+
+
+ } /* switch on state*/
+
+ return;
+
+value_too_long:
+ if (TRACE)
+ fprintf(stderr, "HTMIME: *** Syntax error. (string too long)\n");
+
+bad_field_name: /* Ignore it */
+ me->state = miJUNK_LINE;
+ return;
+
+}
+
+
+
+/* String handling
+** ---------------
+**
+** Strings must be smaller than this buffer size.
+*/
+PRIVATE void HTMIME_put_string ARGS2(
+ HTStream *, me,
+ CONST char *, s)
+{
+ CONST char * p;
+
+ if (me->state == MIME_TRANSPARENT) { /* Optimisation */
+ (*me->targetClass.put_string)(me->target,s);
+
+ } else if (me->state != MIME_IGNORE) {
+ if (TRACE)
+ fprintf(stderr, "HTMIME: %s\n", s);
+
+ for (p=s; *p; p++)
+ HTMIME_put_character(me, *p);
+ }
+}
+
+
+/* Buffer write. Buffers can (and should!) be big.
+** ------------
+*/
+PRIVATE void HTMIME_write ARGS3(
+ HTStream *, me,
+ CONST char *, s,
+ int, l)
+{
+ CONST char * p;
+
+ if (me->state == MIME_TRANSPARENT) { /* Optimisation */
+ (*me->targetClass.put_block)(me->target, s, l);
+
+ } else {
+ if (TRACE)
+ fprintf(stderr, "HTMIME: %.*s\n", l, s);
+
+ for (p = s; p < s+l; p++)
+ HTMIME_put_character(me, *p);
+ }
+}
+
+
+/* Free an HTML object
+** -------------------
+**
+*/
+PRIVATE void HTMIME_free ARGS1(
+ HTStream *, me)
+{
+ if (me->target)
+ (*me->targetClass._free)(me->target);
+ FREE(me);
+}
+
+/* End writing
+*/
+PRIVATE void HTMIME_abort ARGS2(
+ HTStream *, me,
+ HTError, e)
+{
+ if (me->target)
+ (*me->targetClass._abort)(me->target, e);
+ FREE(me);
+}
+
+
+/* Structured Object Class
+** -----------------------
+*/
+PRIVATE CONST HTStreamClass HTMIME =
+{
+ "MIMEParser",
+ HTMIME_free,
+ HTMIME_abort,
+ HTMIME_put_character,
+ HTMIME_put_string,
+ HTMIME_write
+};
+
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+PUBLIC HTStream* HTMIMEConvert ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream* me;
+
+ me = (HTStream *)calloc(1, sizeof(*me));
+ if (me == NULL)
+ outofmem(__FILE__, "HTMIMEConvert");
+ me->isa = &HTMIME;
+ me->sink = sink;
+ me->anchor = anchor;
+ me->anchor->safe = FALSE;
+ me->anchor->no_cache = FALSE;
+ FREE(me->anchor->cache_control);
+ FREE(me->anchor->SugFname);
+ FREE(me->anchor->charset);
+ FREE(me->anchor->content_language);
+ FREE(me->anchor->content_encoding);
+ FREE(me->anchor->content_base);
+ FREE(me->anchor->content_disposition);
+ FREE(me->anchor->content_location);
+ FREE(me->anchor->content_md5);
+ me->anchor->content_length = 0;
+ FREE(me->anchor->date);
+ FREE(me->anchor->expires);
+ FREE(me->anchor->last_modified);
+ FREE(me->anchor->server);
+ me->target = NULL;
+ me->state = miBEGINNING_OF_LINE;
+ /*
+ * Sadly enough, change this to always default to WWW_HTML
+ * to parse all text as HTML for the users.
+ * GAB 06-30-94
+ * Thanks to Robert Rowland robert@cyclops.pei.edu
+ *
+ * After discussion of the correct handline, should be application/octet-
+ * stream or unknown; causing servers to send a correct content
+ * type.
+ *
+ * The consequence of using WWW_UNKNOWN is that you end up downloading
+ * as a binary file what 99.9% of the time is an HTML file, which should
+ * have been rendered or displayed. So sadly enough, I'm changing it
+ * back to WWW_HTML, and it will handle the situation like Mosaic does,
+ * and as Robert Rowland suggested, because being functionally correct
+ * 99.9% of the time is better than being technically correct but
+ * functionally nonsensical. - FM
+ *//***
+ me->format = WWW_UNKNOWN;
+ ***/
+ me->format = WWW_HTML;
+ me->targetRep = pres->rep_out;
+ me->boundary = NULL; /* Not set yet */
+ me->set_cookie = NULL; /* Not set yet */
+ me->set_cookie2 = NULL; /* Not set yet */
+ me->encoding = 0; /* Not set yet */
+ me->compression_encoding = NULL; /* Not set yet */
+ me->net_ascii = NO; /* Local character set */
+ HTAnchor_setUCInfoStage(me->anchor, current_char_set,
+ UCT_STAGE_STRUCTURED,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_setUCInfoStage(me->anchor, current_char_set,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ return me;
+}
+
+PUBLIC HTStream* HTNetMIME ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream* me = HTMIMEConvert(pres,anchor, sink);
+ if (!me)
+ return NULL;
+
+ me->net_ascii = YES;
+ return me;
+}
+
+/* Japanese header handling functions
+** ==================================
+**
+** K&Rized and added 07-Jun-96 by FM, based on:
+**
+////////////////////////////////////////////////////////////////////////
+**
+** ISO-2022-JP handling routines
+** &
+** MIME decode routines (quick hack just for ISO-2022-JP)
+**
+** Thu Jan 25 10:11:42 JST 1996
+**
+** Copyright (C) 1994, 1995, 1996
+** Shuichi Ichikawa (ichikawa@nuee.nagoya-u.ac.jp)
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either versions 2, or (at your option)
+** any later version.
+**
+** This program is distributed in the hope that it will be useful
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with SKK, see the file COPYING. If not, write to the Free
+** Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* #include <stdio.h> */ /* Included via previous headers. - FM */
+/* #include <string.h> */ /* Included via previous headers. - FM */
+
+/*
+** MIME decoding routines
+**
+** Written by S. Ichikawa,
+** partially inspired by encdec.c of <jh@efd.lth.se>.
+*/
+#define BUFLEN 1024
+#ifdef ESC
+#undef ESC
+#endif /* ESC */
+#define ESC '\033'
+
+PRIVATE char HTmm64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
+PRIVATE char HTmmquote[] = "0123456789ABCDEF";
+PRIVATE int HTmmcont = 0;
+
+PUBLIC void HTmmdec_base64 ARGS2(
+ char *, t,
+ char *, s)
+{
+ int d, count, j, val;
+ char buf[BUFLEN], *bp, nw[4], *p;
+
+ for (bp = buf; *s; s += 4) {
+ val = 0;
+ if (s[2] == '=')
+ count = 1;
+ else if (s[3] == '=')
+ count = 2;
+ else
+ count = 3;
+
+ for (j = 0; j <= count; j++) {
+ if (!(p = strchr(HTmm64, s[j]))) {
+ return;
+ }
+ d = p - HTmm64;
+ d <<= (3-j)*6;
+ val += d;
+ }
+ for (j = 2; j >= 0; j--) {
+ nw[j] = val & 255;
+ val >>= 8;
+ }
+ if (count--)
+ *bp++ = nw[0];
+ if (count--)
+ *bp++ = nw[1];
+ if (count)
+ *bp++ = nw[2];
+ }
+ *bp = '\0';
+ strcpy(t, buf);
+}
+
+PUBLIC void HTmmdec_quote ARGS2(
+ char *, t,
+ char *, s)
+{
+ char buf[BUFLEN], cval, *bp, *p;
+
+ for (bp = buf; *s; ) {
+ if (*s == '=') {
+ cval = 0;
+ if (s[1] && (p = strchr(HTmmquote, s[1]))) {
+ cval += (p - HTmmquote);
+ } else {
+ *bp++ = *s++;
+ continue;
+ }
+ if (s[2] && (p = strchr(HTmmquote, s[2]))) {
+ cval <<= 4;
+ cval += (p - HTmmquote);
+ *bp++ = cval;
+ s += 3;
+ } else {
+ *bp++ = *s++;
+ }
+ } else if (*s == '_') {
+ *bp++ = 0x20;
+ s++;
+ } else {
+ *bp++ = *s++;
+ }
+ }
+ *bp = '\0';
+ strcpy(t, buf);
+}
+
+#ifdef NOTDEFINED
+/*
+** Generalized HTmmdecode for chartrans - K. Weide 1997-03-06
+*/
+PUBLIC void HTmmdecode ARGS2(
+ char *, trg,
+ char *, str)
+{
+ char buf[BUFLEN], mmbuf[BUFLEN];
+ char *s, *t, *u, *qm2;
+ int base64, quote;
+
+ buf[0] = '\0';
+
+ /*
+ ** Encoded-words look like
+ ** =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
+ */
+ for (s = str, u = buf; *s; ) {
+ base64 = quote = 0;
+ if (*s == '=' && s[1] == '?' &&
+ (s == str || *(s-1) == '(' || WHITE(*(s-1))))
+ { /* must be beginning of word */
+ qm2 = strchr(s+2, '?'); /* 2nd question mark */
+ if (qm2 &&
+ (qm2[1] == 'B' || qm2[1] == 'b' || qm2[1] == 'Q' ||
+ qm2[1] == 'q') &&
+ qm2[2] == '?') { /* 3rd question mark */
+ char * qm4 = strchr(qm2 + 3, '?'); /* 4th question mark */
+ if (qm4 && qm4 - s < 74 && /* RFC 2047 length restriction */
+ qm4[1] == '=') {
+ char *p;
+ BOOL invalid = NO;
+ for (p = s+2; p < qm4; p++)
+ if (WHITE(*p)) {
+ invalid = YES;
+ break;
+ }
+ if (!invalid) {
+ int LYhndl;
+
+ *qm2 = '\0';
+ for (p = s+2; *p; p++)
+ *p = TOLOWER(*p);
+ invalid = ((LYhndl = UCGetLYhndl_byMIME(s+2)) < 0 ||
+ UCCanTranslateFromTo(LYhndl,
+ current_char_set));
+ *qm2 = '?';
+ }
+ if (!invalid) {
+ if (qm2[1] == 'B' || qm2[1] == 'b')
+ base64 = 1;
+ else if (qm2[1] == 'Q' || qm2[1] == 'q')
+ quote = 1;
+ }
+ }
+ }
+ }
+ if (base64 || quote) {
+ if (HTmmcont) {
+ for (t = s - 1;
+ t >= str && (*t == ' ' || *t == '\t'); t--) {
+ u--;
+ }
+ }
+ for (s = qm2 + 3, t = mmbuf; *s; ) {
+ if (s[0] == '?' && s[1] == '=') {
+ break;
+ } else {
+ *t++ = *s++;
+ }
+ }
+ if (s[0] != '?' || s[1] != '=') {
+ goto end;
+ } else {
+ s += 2;
+ *t = '\0';
+ }
+ if (base64)
+ HTmmdec_base64(mmbuf, mmbuf);
+ if (quote)
+ HTmmdec_quote(mmbuf, mmbuf);
+ for (t = mmbuf; *t; )
+ *u++ = *t++;
+ HTmmcont = 1;
+ /* if (*s == ' ' || *s == '\t') *u++ = *s; */
+ /* for ( ; *s == ' ' || *s == '\t'; s++) ; */
+ } else {
+ if (*s != ' ' && *s != '\t')
+ HTmmcont = 0;
+ *u++ = *s++;
+ }
+ }
+ *u = '\0';
+end:
+ strcpy(trg, buf);
+}
+#else
+/*
+** HTmmdecode for ISO-2022-JP - FM
+*/
+PUBLIC void HTmmdecode ARGS2(
+ char *, trg,
+ char *, str)
+{
+ char buf[BUFLEN], mmbuf[BUFLEN];
+ char *s, *t, *u;
+ int base64, quote;
+
+ buf[0] = '\0';
+
+ for (s = str, u = buf; *s; ) {
+ if (!strncasecomp(s, "=?ISO-2022-JP?B?", 16)) {
+ base64 = 1;
+ } else {
+ base64 = 0;
+ }
+ if (!strncasecomp(s, "=?ISO-2022-JP?Q?", 16)) {
+ quote = 1;
+ } else {
+ quote = 0;
+ }
+ if (base64 || quote) {
+ if (HTmmcont) {
+ for (t = s - 1;
+ t >= str && (*t == ' ' || *t == '\t'); t--) {
+ u--;
+ }
+ }
+ for (s += 16, t = mmbuf; *s; ) {
+ if (s[0] == '?' && s[1] == '=') {
+ break;
+ } else {
+ *t++ = *s++;
+ }
+ }
+ if (s[0] != '?' || s[1] != '=') {
+ goto end;
+ } else {
+ s += 2;
+ *t = '\0';
+ }
+ if (base64)
+ HTmmdec_base64(mmbuf, mmbuf);
+ if (quote)
+ HTmmdec_quote(mmbuf, mmbuf);
+ for (t = mmbuf; *t; )
+ *u++ = *t++;
+ HTmmcont = 1;
+ /* if (*s == ' ' || *s == '\t') *u++ = *s; */
+ /* for ( ; *s == ' ' || *s == '\t'; s++) ; */
+ } else {
+ if (*s != ' ' && *s != '\t')
+ HTmmcont = 0;
+ *u++ = *s++;
+ }
+ }
+ *u = '\0';
+end:
+ strcpy(trg, buf);
+}
+#endif /* NOTDEFINED */
+
+/*
+** Modified for Lynx-jp by Takuya ASADA (and K&Rized by FM).
+*/
+#if NOTDEFINED
+PUBLIC int main ARGS2(
+ int, ac,
+ char **, av)
+{
+ FILE *fp;
+ char buf[BUFLEN];
+ char header = 1, body = 0, r_jis = 0;
+ int i, c;
+
+ for (i = 1; i < ac; i++) {
+ if (strcmp(av[i], "-B") == NULL)
+ body = 1;
+ else if (strcmp(av[i], "-r") == NULL)
+ r_jis = 1;
+ else
+ break;
+ }
+
+ if (i >= ac) {
+ fp = stdin;
+ } else {
+ if ((fp = fopen(av[i], "r")) == NULL) {
+ fprintf(stderr, "%s: cannot open %s\n", av[0], av[i]);
+ exit(1);
+ }
+ }
+
+ while (fgets(buf, BUFLEN, fp)) {
+ if (buf[0] == '\n' && buf[1] == '\0')
+ header = 0;
+ if (header) {
+ c = fgetc(fp);
+ if (c == ' ' || c == '\t') {
+ buf[strlen(buf)-1] = '\0';
+ ungetc(c, fp);
+ } else {
+ ungetc(c, fp);
+ }
+ }
+ if (header || body)
+ HTmmdecode(buf, buf);
+ if (r_jis)
+ HTrjis(buf, buf);
+ fprintf(stdout, "%s", buf);
+ }
+
+ close(fp);
+ exit(0);
+}
+#endif /* NOTDEFINED */
+
+/*
+** Insert ESC where it seems lost.
+** (The author of this function "rjis" is S. Ichikawa.)
+*/
+PUBLIC int HTrjis ARGS2(
+ char *, t,
+ char *, s)
+{
+ char *p, buf[BUFLEN];
+ int kanji = 0;
+
+ if (strchr(s, ESC) || !strchr(s, '$')) {
+ if (s != t)
+ strcpy(t, s);
+ return 1;
+ }
+ for (p = buf; *s; ) {
+ if (!kanji && s[0] == '$' && (s[1] == '@' || s[1] == 'B')) {
+ if (HTmaybekanji((int)s[2], (int)s[3])) {
+ kanji = 1;
+ *p++ = ESC;
+ *p++ = *s++;
+ *p++ = *s++;
+ *p++ = *s++;
+ *p++ = *s++;
+ continue;
+ }
+ *p++ = *s++;
+ continue;
+ }
+ if (kanji && s[0] == '(' && (s[1] == 'J' || s[1] == 'B')) {
+ kanji = 0;
+ *p++ = ESC;
+ *p++ = *s++;
+ *p++ = *s++;
+ continue;
+ }
+ *p++ = *s++;
+ }
+ *p = *s; /* terminate string */
+
+ strcpy(t, buf);
+ return 0;
+}
+
+/*
+** The following function "maybekanji" is derived from
+** RJIS-1.0 by Mr. Hironobu Takahashi.
+** Maybekanji() is included here under the courtesy of the author.
+** The original comment of rjis.c is also included here.
+*/
+/*
+ * RJIS ( Recover JIS code from broken file )
+ * $Header: /cvs/OpenBSD/src/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.c,v 1.1 1998/03/11 17:47:45 maja Exp $
+ * Copyright (C) 1992 1994
+ * Hironobu Takahashi (takahasi@tiny.or.jp)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either versions 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with SKK, see the file COPYING. If not, write to the Free
+ * Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+PUBLIC int HTmaybekanji ARGS2(
+ int, c1,
+ int, c2)
+{
+
+ if ((c2 < 33) || (c2 > 126))
+ return 0;
+ if ((c1 < 33) || ((40 < c1) && (c1 < 48)) || (116 < c1))
+ return 0;
+ c2 -= 32;
+ switch(c1-32) {
+ case 2:
+ if ((14 < c2) && ( c2 < 26))
+ return 0;
+ if ((33 < c2) && ( c2 < 42))
+ return 0;
+ if ((48 < c2) && ( c2 < 60))
+ return 0;
+ if ((74 < c2) && ( c2 < 82))
+ return 0;
+ if ((89 < c2) && ( c2 < 94))
+ return 0;
+ break;
+ case 3:
+ if (c2 < 16)
+ return 0;
+ if ((25 < c2) && ( c2 < 33))
+ return 0;
+ if ((58 < c2) && ( c2 < 65))
+ return 0;
+ if (90 < c2)
+ return 0;
+ break;
+ case 4:
+ if (83 < c2)
+ return 0;
+ break;
+ case 5:
+ if (86 < c2)
+ return 0;
+ break;
+ case 6:
+ if ((24 < c2) && ( c2 < 33))
+ return 0;
+ if (56 < c2)
+ return 0;
+ break;
+ case 7:
+ if ((33 < c2) && ( c2 < 49))
+ return 0;
+ if (81 < c2)
+ return 0;
+ break;
+ case 8:
+ if (32 < c2)
+ return 0;
+ break;
+ case 47:
+ if (51 < c2)
+ return 0;
+ break;
+ case 84:
+ if (6 < c2)
+ return 0;
+ break;
+ }
+ return 1;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.h
new file mode 100644
index 00000000000..823f6c76c0d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMIME.h
@@ -0,0 +1,87 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTMIME.html
+ MIME PARSER
+
+ The MIME parser stream presents a MIME document. It recursively invokes the format
+ manager to handle embedded formats.
+
+ As well as stripping off and parsing the headers, the MIME parser has to parse any
+ weirld MIME encodings it may meet within the body parts of messages, and must deal with
+ multipart messages.
+
+ This module is implemented to the level necessary for operation with WWW, but is not
+ currently complete for any arbitrary MIME message.
+
+ Check the source for latest additions to functionality.
+
+ The MIME parser is complicated by the fact that WWW allows real binary to be sent, not
+ ASCII encoded. Therefore the netascii decoding is included in this module. One cannot
+ layer it by converting first from Net to local text, then decoding it. Of course, for
+ local files, the net ascii decoding is not needed. There are therefore two creation
+ routines.
+
+ */
+#ifndef HTMIME_H
+#define HTMIME_H
+
+#include "HTStream.h"
+#include "HTAnchor.h"
+
+/*
+** This function is for trimming off any paired
+** open- and close-double quotes from header values.
+** It does not parse the string for embedded quotes,
+** and will not modify the string unless both the
+** first and last characters are double-quotes. - FM
+*/
+extern void HTMIME_TrimDoubleQuotes PARAMS((
+ char * value));
+
+/*
+
+ INPUT: LOCAL TEXT
+
+ */
+extern HTStream * HTMIMEConvert PARAMS((HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+/*
+
+ INPUT: NET ASCII
+
+ */
+extern HTStream * HTNetMIME PARAMS((HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+
+/*
+
+ For handling Japanese headers.
+
+*/
+extern void HTmmdec_base64 PARAMS((
+ char * t,
+ char * s));
+
+extern void HTmmdec_quote PARAMS((
+ char * t,
+ char * s));
+
+extern void HTmmdecode PARAMS((
+ char * trg,
+ char * str));
+
+extern int HTrjis PARAMS((
+ char * t,
+ char * s));
+
+PUBLIC int HTmaybekanji PARAMS((
+ int c1,
+ int c2));
+
+
+#endif /* !HTMIME_H */
+
+/*
+
+ end of HTMIME */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.c
new file mode 100644
index 00000000000..0d616bf1d2e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.c
@@ -0,0 +1,1674 @@
+/* Our Static DTD for HTML
+** -----------------------
+*/
+
+/* Implements:
+*/
+
+#include "HTUtils.h"
+#include "HTMLDTD.h"
+#include "LYLeaks.h"
+
+/* Entity Names
+** ------------
+**
+** This table must be matched exactly with ALL the translation tables
+** (this is an obsolete translation mechanism,
+** currently replaced with unicode chartrans in most cases...)
+*/
+static CONST char* entities[] = {
+ "AElig", /* capital AE diphthong (ligature) */
+ "Aacute", /* capital A, acute accent */
+ "Acirc", /* capital A, circumflex accent */
+ "Agrave", /* capital A, grave accent */
+ "Aring", /* capital A, ring */
+ "Atilde", /* capital A, tilde */
+ "Auml", /* capital A, dieresis or umlaut mark */
+ "Ccedil", /* capital C, cedilla */
+ "Dstrok", /* capital Eth, Icelandic */
+ "ETH", /* capital Eth, Icelandic */
+ "Eacute", /* capital E, acute accent */
+ "Ecirc", /* capital E, circumflex accent */
+ "Egrave", /* capital E, grave accent */
+ "Euml", /* capital E, dieresis or umlaut mark */
+ "Iacute", /* capital I, acute accent */
+ "Icirc", /* capital I, circumflex accent */
+ "Igrave", /* capital I, grave accent */
+ "Iuml", /* capital I, dieresis or umlaut mark */
+ "Ntilde", /* capital N, tilde */
+ "Oacute", /* capital O, acute accent */
+ "Ocirc", /* capital O, circumflex accent */
+ "Ograve", /* capital O, grave accent */
+ "Oslash", /* capital O, slash */
+ "Otilde", /* capital O, tilde */
+ "Ouml", /* capital O, dieresis or umlaut mark */
+ "THORN", /* capital THORN, Icelandic */
+ "Uacute", /* capital U, acute accent */
+ "Ucirc", /* capital U, circumflex accent */
+ "Ugrave", /* capital U, grave accent */
+ "Uuml", /* capital U, dieresis or umlaut mark */
+ "Yacute", /* capital Y, acute accent */
+ "aacute", /* small a, acute accent */
+ "acirc", /* small a, circumflex accent */
+ "acute", /* spacing acute */
+ "aelig", /* small ae diphthong (ligature) */
+ "agrave", /* small a, grave accent */
+ "amp", /* ampersand */
+ "aring", /* small a, ring */
+ "atilde", /* small a, tilde */
+ "auml", /* small a, dieresis or umlaut mark */
+ "brkbar", /* broken vertical bar */
+ "brvbar", /* broken vertical bar */
+ "ccedil", /* small c, cedilla */
+ "cedil", /* spacing cedilla */
+ "cent", /* cent sign */
+ "copy", /* copyright sign */
+ "curren", /* currency sign */
+ "deg", /* degree sign */
+ "die", /* spacing dieresis */
+ "divide", /* division sign */
+ "eacute", /* small e, acute accent */
+ "ecirc", /* small e, circumflex accent */
+ "egrave", /* small e, grave accent */
+ "emdash", /* dash the width of emsp */
+ "emsp", /* em space - not collapsed */
+ "endash", /* dash the width of ensp */
+ "ensp", /* en space - not collapsed */
+ "eth", /* small eth, Icelandic */
+ "euml", /* small e, dieresis or umlaut mark */
+ "frac12", /* fraction 1/2 */
+ "frac14", /* fraction 1/4 */
+ "frac34", /* fraction 3/4 */
+ "gt", /* greater than */
+ "hibar", /* spacing macron */
+ "iacute", /* small i, acute accent */
+ "icirc", /* small i, circumflex accent */
+ "iexcl", /* inverted exclamation mark */
+ "igrave", /* small i, grave accent */
+ "iquest", /* inverted question mark */
+ "iuml", /* small i, dieresis or umlaut mark */
+ "laquo", /* angle quotation mark, left */
+ "lt", /* less than */
+ "macr", /* spacing macron */
+ "mdash", /* dash the width of emsp */
+ "micro", /* micro sign */
+ "middot", /* middle dot */
+ "nbsp", /* non breaking space */
+ "ndash", /* dash the width of ensp */
+ "not", /* negation sign */
+ "ntilde", /* small n, tilde */
+ "oacute", /* small o, acute accent */
+ "ocirc", /* small o, circumflex accent */
+ "ograve", /* small o, grave accent */
+ "ordf", /* feminine ordinal indicator */
+ "ordm", /* masculine ordinal indicator */
+ "oslash", /* small o, slash */
+ "otilde", /* small o, tilde */
+ "ouml", /* small o, dieresis or umlaut mark */
+ "para", /* paragraph sign */
+ "plusmn", /* plus-or-minus sign */
+ "pound", /* pound sign */
+ "quot", /* quote '"' */
+ "raquo", /* angle quotation mark, right */
+ "reg", /* circled R registered sign */
+ "sect", /* section sign */
+ "shy", /* soft hyphen */
+ "sup1", /* superscript 1 */
+ "sup2", /* superscript 2 */
+ "sup3", /* superscript 3 */
+ "szlig", /* small sharp s, German (sz ligature) */
+ "thinsp", /* thin space (not collapsed) */
+ "thorn", /* small thorn, Icelandic */
+ "times", /* multiplication sign */
+ "trade", /* trade mark sign (U+2122) */
+ "uacute", /* small u, acute accent */
+ "ucirc", /* small u, circumflex accent */
+ "ugrave", /* small u, grave accent */
+ "uml", /* spacing dieresis */
+ "uuml", /* small u, dieresis or umlaut mark */
+ "yacute", /* small y, acute accent */
+ "yen", /* yen sign */
+ "yuml", /* small y, dieresis or umlaut mark */
+};
+
+#define HTML_ENTITIES 112
+
+#include <entities.h>
+
+/* Attribute Lists
+** ---------------
+**
+** Lists must be in alphabetical order by attribute name
+** The tag elements contain the number of attributes
+*/
+static attr a_attr[] = { /* Anchor attributes */
+ { "ACCESSKEY" },
+ { "CHARSET" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "COORDS" },
+ { "DIR" },
+ { "HREF" },
+ { "ID" },
+ { "ISMAP" },
+ { "LANG" },
+ { "MD" },
+ { "NAME" },
+ { "NOTAB" },
+ { "ONCLICK" },
+ { "ONMOUSEOUT" },
+ { "ONMOUSEOVER" },
+ { "REL" },
+ { "REV" },
+ { "SHAPE" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TARGET" },
+ { "TITLE" },
+ { "TYPE" },
+ { "URN" },
+ { 0 } /* Terminate list */
+};
+
+static attr address_attr[] = { /* ADDRESS attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NOWRAP" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr applet_attr[] = { /* APPLET attributes */
+ { "ALIGN" },
+ { "ALT" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "CODE" },
+ { "CODEBASE" },
+ { "DIR" },
+ { "DOWNLOAD" },
+ { "HEIGHT" },
+ { "HSPACE" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "STYLE" },
+ { "TITLE" },
+ { "VSPACE" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr area_attr[] = { /* AREA attributes */
+ { "ALT" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "COORDS" },
+ { "DIR" },
+ { "HREF" },
+ { "ID" },
+ { "LANG" },
+ { "NOHREF" },
+ { "NOTAB" },
+ { "ONCLICK" },
+ { "ONMOUSEOUT" },
+ { "ONMOUSEOVER" },
+ { "SHAPE" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TARGET" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr base_attr[] = { /* BASE attributes */
+ { "HREF" },
+ { "TARGET" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr bgsound_attr[] = { /* BGSOUND attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "LOOP" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr body_attr[] = { /* BODY attributes */
+ { "ALINK" },
+ { "BACKGROUND" },
+ { "BGCOLOR" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "LINK" },
+ { "ONLOAD" },
+ { "ONUNLOAD" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TEXT" },
+ { "VLINK" },
+ { 0 } /* Terminate list */
+};
+
+static attr bodytext_attr[] = { /* BODYTEXT attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DATA" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "OBJECT" },
+ { "REF" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { "VALUE" },
+ { "VALUETYPE" },
+ { 0 } /* Terminate list */
+};
+
+static attr bq_attr[] = { /* BQ (BLOCKQUOTE) attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NOWRAP" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr button_attr[] = { /* BUTTON attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DISABLED" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "ONFOCUS" },
+ { "ONBLUR" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TITLE" },
+ { "TYPE" },
+ { "VALUE" },
+ { 0 } /* Terminate list */
+};
+
+static attr caption_attr[] = { /* CAPTION attributes */
+ { "ACCESSKEY" },
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr col_attr[] = { /* COL and COLGROUP attributes */
+ { "ALIGN" },
+ { "CHAR" },
+ { "CHAROFF" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "SPAN" },
+ { "STYLE" },
+ { "TITLE" },
+ { "VALIGN" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr credit_attr[] = { /* CREDIT attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr div_attr[] = { /* DIV attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr embed_attr[] = { /* EMBED attributes */
+ { "ALIGN" }, /* (including, for now, those from FIG and IMG) */
+ { "ALT" },
+ { "BORDER" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "HEIGHT" },
+ { "ID" },
+ { "IMAGEMAP" },
+ { "ISMAP" },
+ { "LANG" },
+ { "MD" },
+ { "NAME" },
+ { "NOFLOW" },
+ { "PARAMS" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "UNITS" },
+ { "USEMAP" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr fig_attr[] = { /* FIG attributes */
+ { "ALIGN" },
+ { "BORDER" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "HEIGHT" },
+ { "ID" },
+ { "IMAGEMAP" },
+ { "ISOBJECT" },
+ { "LANG" },
+ { "MD" },
+ { "NOFLOW" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "UNITS" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr fieldset_attr[] = { /* FIELDSET attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr fn_attr[] = { /* FN attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr font_attr[] = { /* FONT attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "COLOR" },
+ { "DIR" },
+ { "END" },
+ { "FACE" },
+ { "ID" },
+ { "LANG" },
+ { "SIZE" },
+ { "STYLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr form_attr[] = { /* FORM attributes */
+ { "ACCEPT-CHARSET"}, /* HTML 4.0 draft - kw */
+ { "ACTION"},
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ENCTYPE" },
+ { "ID" },
+ { "LANG" },
+ { "METHOD" },
+ { "ONSUBMIT" },
+ { "SCRIPT" },
+ { "STYLE" },
+ { "SUBJECT" },
+ { "TARGET" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr frame_attr[] = { /* FRAME attributes */
+ { "ID" },
+ { "MARGINHEIGHT"},
+ { "MARGINWIDTH" },
+ { "NAME" },
+ { "NORESIZE" },
+ { "SCROLLING" },
+ { "SRC" },
+ { 0 } /* Terminate list */
+};
+
+static attr frameset_attr[] = { /* FRAMESET attributes */
+ { "COLS"},
+ { "ROWS" },
+ { 0 } /* Terminate list */
+};
+
+static attr gen_attr[] = { /* Minimum HTML 3.0 */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr glossary_attr[] = { /* DL (and DLC) attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "COMPACT" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr h_attr[] = { /* H1 - H6 attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DINGBAT" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "MD" },
+ { "NOWRAP" },
+ { "SEQNUM" },
+ { "SKIP" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr hr_attr[] = { /* HR attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "MD" },
+ { "NOSHADE" },
+ { "SIZE" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr iframe_attr[] = { /* IFRAME attributes */
+ { "ALIGN" },
+ { "FRAMEBORDER" },
+ { "HEIGHT" },
+ { "ID" },
+ { "MARGINHEIGHT"},
+ { "MARGINWIDTH" },
+ { "NAME" },
+ { "SCROLLING" },
+ { "SRC" },
+ { "STYLE" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr img_attr[] = { /* IMG attributes */
+ { "ALIGN" },
+ { "ALT" },
+ { "BORDER" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "HEIGHT" },
+ { "ID" },
+ { "ISMAP" },
+ { "ISOBJECT" },
+ { "LANG" },
+ { "MD" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "UNITS" },
+ { "USEMAP" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr input_attr[] = { /* INPUT attributes */
+ { "ACCEPT" },
+ { "ACCEPT-CHARSET" }, /* RFC 2070 HTML i18n - kw */
+ { "ALIGN" },
+ { "ALT" },
+ { "CHECKED" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DISABLED" },
+ { "ERROR" },
+ { "HEIGHT" },
+ { "ID" },
+ { "LANG" },
+ { "MAX" },
+ { "MAXLENGTH" },
+ { "MD" },
+ { "MIN" },
+ { "NAME" },
+ { "NOTAB" },
+ { "ONBLUR" },
+ { "ONCHANGE" },
+ { "ONCLICK" },
+ { "ONFOCUS" },
+ { "ONSELECT" },
+ { "SIZE" },
+ { "SRC" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TITLE" },
+ { "TYPE" },
+ { "VALUE" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr isindex_attr[] = { /* ISINDEX attributes */
+ { "ACTION" }, /* Not in spec. Lynx treats it as HREF. - FM */
+ { "DIR" },
+ { "HREF" }, /* HTML 3.0 attribute for search action. - FM */
+ { "ID" },
+ { "LANG" },
+ { "PROMPT" }, /* HTML 3.0 attribute for prompt string. - FM */
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr keygen_attr[] = { /* KEYGEN attributes */
+ { "CHALLENGE" },
+ { "CLASS" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr label_attr[] = { /* LABEL attributes */
+ { "ACCESSKEY" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "FOR" },
+ { "ID" },
+ { "LANG" },
+ { "ONCLICK" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr legend_attr[] = { /* LEGEND attributes */
+ { "ACCESSKEY" },
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr link_attr[] = { /* LINK attributes */
+ { "CHARSET" }, /* RFC 2070 HTML i18n -- hint for UA -- - kw */
+ { "CLASS" },
+ { "HREF" },
+ { "ID" },
+ { "MEDIA" },
+ { "REL" },
+ { "REV" },
+ { "STYLE" },
+ { "TARGET" },
+ { "TITLE" },
+ { "TYPE" },
+ { 0 } /* Terminate list */
+};
+
+static attr list_attr[] = { /* LI attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DINGBAT" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "MD" },
+ { "SKIP" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { "VALUE" },
+ { 0 } /* Terminate list */
+};
+
+static attr map_attr[] = { /* MAP attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr math_attr[] = { /* MATH attributes */
+ { "BOX" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr meta_attr[] = { /* META attributes */
+ { "CONTENT" },
+ { "HTTP-EQUIV" },
+ { "NAME" },
+ { 0 } /* Terminate list */
+};
+
+static attr nextid_attr[] = { /* NEXTID attributes */
+ { "N" }
+};
+
+static attr note_attr[] = { /* NOTE attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "MD" },
+ { "ROLE" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr object_attr[] = { /* OBJECT attributes */
+ { "ALIGN" },
+ { "BORDER" },
+ { "CLASS" },
+ { "CLASSID" },
+ { "CODEBASE" },
+ { "CODETYPE" },
+ { "DATA" },
+ { "DECLARE" },
+ { "DIR" },
+ { "HEIGHT" },
+ { "HSPACE" },
+ { "ID" },
+ { "ISMAP" },
+ { "LANG" },
+ { "NAME" },
+ { "NOTAB" },
+ { "SHAPES" },
+ { "STANDBY" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TITLE" },
+ { "TYPE" },
+ { "USEMAP" },
+ { "VSPACE" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr olist_attr[] = { /* OL attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "COMPACT" },
+ { "CONTINUE" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "SEQNUM" },
+ { "START" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { 0 } /* Terminate list */
+};
+
+static attr option_attr[] = { /* OPTION attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DISABLED" },
+ { "ERROR" },
+ { "ID" },
+ { "LANG" },
+ { "SELECTED" },
+ { "SHAPE" },
+ { "STYLE" },
+ { "TITLE" },
+ { "VALUE" },
+ { 0 } /* Terminate list */
+};
+
+static attr overlay_attr[] = { /* OVERLAY attributes */
+ { "CLASS" },
+ { "HEIGHT" },
+ { "ID" },
+ { "IMAGEMAP" },
+ { "MD" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "UNITS" },
+ { "WIDTH" },
+ { "X" },
+ { "Y" },
+ { 0 } /* Terminate list */
+};
+
+static attr p_attr[] = { /* P attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NOWRAP" },
+ { "STYLE" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr param_attr[] = { /* PARAM attributes */
+ { "ACCEPT" },
+ { "ACCEPT-CHARSET" },
+ { "ACCEPT-ENCODING" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DATA" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "OBJECT" },
+ { "REF" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { "VALUE" },
+ { "VALUEREF" },
+ { "VALUETYPE" },
+ { 0 } /* Terminate list */
+};
+
+static attr script_attr[] = { /* SCRIPT attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "EVENT" },
+ { "FOR" },
+ { "ID" },
+ { "LANG" },
+ { "LANGUAGE" },
+ { "NAME" },
+ { "SCRIPTENGINE" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { 0 } /* Terminate list */
+};
+
+static attr select_attr[] = { /* SELECT attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DISABLED" },
+ { "ERROR" },
+ { "HEIGHT" },
+ { "ID" },
+ { "LANG" },
+ { "MD" },
+ { "MULTIPLE" },
+ { "NAME" },
+ { "NOTAB" },
+ { "ONBLUR" },
+ { "ONCHANGE" },
+ { "ONFOCUS" },
+ { "SIZE" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TITLE" },
+ { "UNITS" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr style_attr[] = { /* STYLE attributes */
+ { "DIR" },
+ { "LANG" },
+ { "NOTATION" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr tab_attr[] = { /* TAB attributes */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DP" },
+ { "ID" },
+ { "INDENT" },
+ { "LANG" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TO" },
+ { 0 } /* Terminate list */
+};
+
+static attr table_attr[] = { /* TABLE attributes */
+ { "ALIGN" },
+ { "BORDER" },
+ { "CELLPADDING" },
+ { "CELLSPACING" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "COLS" },
+ { "COLSPEC" },
+ { "DIR" },
+ { "DP" },
+ { "FRAME" },
+ { "ID" },
+ { "LANG" },
+ { "NOFLOW" },
+ { "NOWRAP" },
+ { "RULES" },
+ { "STYLE" },
+ { "TITLE" },
+ { "UNITS" },
+ { "WIDTH" },
+ { 0 } /* Terminate list */
+};
+
+static attr td_attr[] = { /* TD and TH attributes */
+ { "ALIGN" },
+ { "AXES" },
+ { "AXIS" },
+ { "CHAR" },
+ { "CHAROFF" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "COLSPAN" },
+ { "DIR" },
+ { "DP" },
+ { "ID" },
+ { "LANG" },
+ { "NOWRAP" },
+ { "ROWSPAN" },
+ { "STYLE" },
+ { "TITLE" },
+ { "VALIGN" },
+ { 0 } /* Terminate list */
+};
+
+static attr textarea_attr[] = { /* TEXTAREA attributes */
+ { "ACCEPT-CHARSET" }, /* RFC 2070 HTML i18n - kw */
+ { "ALIGN" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "COLS" },
+ { "DIR" },
+ { "DISABLED" },
+ { "ERROR" },
+ { "ID" },
+ { "LANG" },
+ { "NAME" },
+ { "NOTAB" },
+ { "ONBLUR" },
+ { "ONCHANGE" },
+ { "ONFOCUS" },
+ { "ONSELECT" },
+ { "ROWS" },
+ { "STYLE" },
+ { "TABINDEX" },
+ { "TITLE" },
+ { 0 } /* Terminate list */
+};
+
+static attr tr_attr[] = { /* TR, THEAD, TFOOT, and TBODY attributes */
+ { "ALIGN" },
+ { "CHAR" },
+ { "CHAROFF" },
+ { "CLASS" },
+ { "CLEAR" },
+ { "DIR" },
+ { "DP" },
+ { "ID" },
+ { "LANG" },
+ { "NOWRAP" },
+ { "STYLE" },
+ { "TITLE" },
+ { "VALIGN" },
+ { 0 } /* Terminate list */
+};
+
+static attr ulist_attr[] = { /* UL attributes */
+ { "CLASS" },
+ { "CLEAR" },
+ { "COMPACT" },
+ { "DINGBAT" },
+ { "DIR" },
+ { "ID" },
+ { "LANG" },
+ { "MD" },
+ { "PLAIN" },
+ { "SRC" },
+ { "STYLE" },
+ { "TITLE" },
+ { "TYPE" },
+ { "WRAP" },
+ { 0 } /* Terminate list */
+};
+
+/* From Peter Flynn's intro to the HTML Pro DTD:
+
+ %structure;
+
+ DIV, CENTER, H1 to H6, P, UL, OL, DL, DIR, MENU, PRE, XMP, LISTING, BLOCKQUOTE, BQ,
+ 2 1 2 2 1 8 8 8 8 8 8 8 8 4 4
+ MULTICOL,?NOBR, FORM, TABLE, ADDRESS, FIG, BDO, NOTE, and FN; plus?WBR, LI, and LH
+ 8 n ?1 n 8 8 2 2 2 2 2 ?1 nE 4 4
+
+ %insertions;
+
+ Elements which usually contain special-purpose material, or no text material at all.
+
+ BASEFONT, APPLET, OBJECT, EMBED, SCRIPT, MAP, MARQUEE, HR, ISINDEX, BGSOUND, TAB,?IMG,
+ 1 e? 2 2 l 1 e 2 l 8 4 4 E 1? E 1 E ! E ?1 E
+ IMAGE, BR, plus NOEMBED, SERVER, SPACER, AUDIOSCOPE, and SIDEBAR; ?area
+ 1 n 1 E n n n n n 8 E
+
+ %text;
+
+ Elements within the %structure; which directly contain running text.
+
+ Descriptive or analytic markup: EM, STRONG, DFN, CODE, SAMP, KBD, VAR, CITE, Q, LANG, AU,
+ 2 2 2 2 2 2 2 2 2 2 n 2
+ AUTHOR, PERSON, ACRONYM, ABBREV, INS, DEL, and SPAN
+ 2 2 n 2 2 2 2 2
+ Visual markup:S, STRIKE, I, B, TT, U,?NOBR,?WBR, BR, BIG, SMALL, FONT, STYLE, BLINK, TAB,
+ 1 1 1 1 1 1 ?1 n ?1nE? 1 E 1 1 1 1 l 1 1 E?
+ BLACKFACE, LIMITTEXT, NOSMARTQUOTES, and SHADOW
+ 1 n 1 n 1 n 1 n
+ Hypertext and graphics: A and?IMG
+ 8 ?8 E
+ Mathematical: SUB, SUP, and MATH
+ 4 4 4 l
+ Documentary: COMMENT, ENTITY, ELEMENT, and ATTRIB
+ 4 4 n 4 n 4 n
+ %formula;
+ */
+
+/* Extra element info
+** ------------------
+**
+** Order and number of tags should match the tags_* tables
+** further below and definitions in HTMLDTD.html.
+**
+** The interspersed comments give the original Lynx tags[] entries
+** for orientation, so they do not necessarily reflect what will
+** be used with the T_* info (which is in tags_new[]).
+**
+** An important design goal was that info for each tag should fit on
+** one 80 character screen line :). The price to pay is that it's
+** a bit cryptic, to say the least... - kw
+*/
+/* 1 2 3 4 5 6 7 8 */
+/*345678901234567890123456789012345678901234567890123456789012345678901234567890 */
+
+/* self contain icont'n contn'd icont'd canclos omit */
+ /* { "A" , a_attr, HTML_A_ATTRIBUTES, SGML_MIXED }, */
+#define T_A 0x0008, 0x0B007,0x0FF17,0x37787,0x77BA7,0x8604F,0x00004
+ /* { "ABBREV" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_ABBREV 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "ACRONYM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_ACRONYM 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "ADDRESS" , address_attr, HTML_ADDRESS_ATTRIBUTES, SGML_MIXED }, */
+#define T_ADDRESS 0x0200, 0x0F14F,0x8FFFF,0x36680,0xB6FAF,0x80317,0x00000
+ /* { "APPLET" , applet_attr, HTML_APPLET_ATTRIBUTES, SGML_MIXED }, */
+#define T_APPLET 0x2000, 0x0B0CF,0x8FFFF,0x37F9F,0xB7FBF,0x8300F,0x00000
+ /* { "AREA" , area_attr, HTML_AREA_ATTRIBUTES, SGML_EMPTY }, */
+#define T_AREA 0x8000, 0x00000,0x00000,0x08000,0x3FFFF,0x00F1F,0x00001
+ /* { "AU" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_AU 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "AUTHOR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_AUTHOR 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "B" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_B 0x0001, 0x8B04F,0xAFFFF,0xA778F,0xF7FBF,0x00001,0x00004
+ /* { "BANNER" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_BANNER 0x0200, 0x0FB8F,0x0FFFF,0x30000,0x30000,0x8031F,0x00000
+ /* { "BASE" , base_attr, HTML_BASE_ATTRIBUTES, SGML_EMPTY }, */
+#define T_BASE 0x40000,0x00000,0x00000,0x50000,0x50000,0x8000F,0x00001
+ /* { "BASEFONT", font_attr, HTML_FONT_ATTRIBUTES, SGML_EMPTY }, */
+#define T_BASEFONT 0x1000, 0x00000,0x00000,0x377AF,0x37FAF,0x8F000,0x00001
+ /* { "BDO" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_BDO 0x0100, 0x0B04F,0x8FFFF,0x36680,0xB6FAF,0x0033F,0x00000
+ /* { "BGSOUND" , bgsound_attr, HTML_BGSOUND_ATTRIBUTES, SGML_EMPTY }, */
+#define T_BGSOUND 0x1000, 0x00000,0x00000,0x777AF,0x77FAF,0x8730F,0x00001
+ /* { "BIG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_BIG 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00004
+ /* { "BLINK" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_BLINK 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FAF,0x00001,0x00004
+ /* { "BLOCKQUOTE", bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED }, */
+#define T_BLOCKQUOTE 0x0200, 0xAFBCF,0xAFFFF,0xB6680,0xB6FAF,0x8031F,0x00000
+ /* { "BODY" , body_attr, HTML_BODY_ATTRIBUTES, SGML_MIXED }, */
+#define T_BODY 0x20000,0x2FB8F,0x2FFFF,0x30000,0x30000,0xDFF7F,0x00003
+ /* { "BODYTEXT", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED }, */
+#define T_BODYTEXT 0x20000,0x0FB8F,0xAFFFF,0x30200,0xB7FAF,0x8F17F,0x00003
+ /* { "BQ" , bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED }, */
+#define T_BQ 0x0200, 0xAFBCF,0xAFFFF,0xB6680,0xB6FAF,0x8031F,0x00000
+ /* { "BR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_BR 0x1000, 0x00000,0x00000,0x377BF,0x77FBF,0x8101F,0x00001
+#define T_BUTTON 0x0200, 0x0BB0B,0x0FF3B,0x0378F,0x37FAF,0x8035F,0x00000
+ /* { "CAPTION" , caption_attr, HTML_CAPTION_ATTRIBUTES, SGML_MIXED }, */
+#define T_CAPTION 0x0100, 0x0B04F,0x8FFFF,0x06A00,0xB6FA7,0x8035F,0x00000
+ /* { "CENTER" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED }, */
+#define T_CENTER 0x0200, 0x8FBCF,0x8FFFF,0xB6680,0xB6FA7,0x8071F,0x00000
+ /* { "CITE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_CITE 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00002,0x00000
+ /* { "CODE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_CODE 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00002,0x00000
+ /* { "COL" , col_attr, HTML_COL_ATTRIBUTES, SGML_EMPTY }, */
+#define T_COL 0x4000, 0x00000,0x00000,0x00820,0x36FA7,0x88F5F,0x00001
+ /* { "COLGROUP", col_attr, HTML_COL_ATTRIBUTES, SGML_EMPTY }, */
+#define T_COLGROUP 0x0020, 0x04000,0x04000,0x00800,0x36FA7,0x8875F,0x00001
+ /* { "COMMENT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_COMMENT 0x0004, 0x00000,0x00000,0xA77AF,0x7FFFF,0x00003,0x00000
+ /* { "CREDIT" , credit_attr, HTML_CREDIT_ATTRIBUTES, SGML_MIXED }, */
+#define T_CREDIT 0x0100, 0x0B04F,0x8FFFF,0x06A00,0xB7FBF,0x8030F,0x00000
+ /* { "DD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_DD 0x0400, 0x0FBCF,0x8FFFF,0x00800,0xB6FFF,0x8071F,0x00001
+ /* { "DEL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_DEL 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "DFN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_DFN 0x0002, 0x8B0CF,0x8FFFF,0x8778F,0xF7FBF,0x00003,0x00000
+ /* { "DIR" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED }, */
+#define T_DIR 0x0800, 0x0B400,0x0F75F,0x37680,0x36FB7,0x84F7F,0x00000
+ /* { "DIV" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED }, */
+#define T_DIV 0x0200, 0x8FB8F,0x8FFFF,0xB66A0,0xB7FFF,0x8031F,0x00004
+ /* { "DL" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED }, */
+#define T_DL 0x0800, 0x0C480,0x8FFFF,0x36680,0xB7FB7,0x0075F,0x00000
+ /* { "DLC" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED }, */
+#define T_DLC 0x0800, 0x0C480,0x8FFFF,0x36680,0xB7FB7,0x0075F,0x00000
+ /* { "DT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_DT 0x0400, 0x0B04F,0x0B1FF,0x00800,0x17FFF,0x8071F,0x00001
+ /* { "EM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_EM 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FAF,0x00003,0x00000
+ /* { "EMBED" , embed_attr, HTML_EMBED_ATTRIBUTES, SGML_EMPTY }, */
+#define T_EMBED 0x2000, 0x8F107,0x8FFF7,0xB6FBF,0xB7FBF,0x1FF7F,0x00001
+ /* { "FIELDSET", fieldset_attr,HTML_FIELDSET_ATTRIBUTES, SGML_MIXED }, */
+#define T_FIELDSET 0x0200, 0x0FB42,0x0FF5F,0x07787,0x37FF7,0x8805F,0x00000
+ /* { "FIG" , fig_attr, HTML_FIG_ATTRIBUTES, SGML_MIXED }, */
+#define T_FIG 0x0200, 0x0FB00,0x8FFFF,0x36680,0xB6FBF,0x8834F,0x00000
+ /* { "FN" , fn_attr, HTML_FN_ATTRIBUTES, SGML_MIXED }, */
+#define T_FN 0x0200, 0x8FBCF,0x8FFFF,0xB6680,0xB7EBF,0x8114F,0x00000
+ /* { "FONT" , font_attr, HTML_FONT_ATTRIBUTES, SGML_EMPTY }, */
+#define T_FONT 0x0001, 0x8B04F,0x8FFFF,0xB778F,0xF7FBF,0x00001,0x00004
+ /* { "FORM" , form_attr, HTML_FORM_ATTRIBUTES, SGML_EMPTY }, */
+#define T_FORM 0x0080, 0x0FF6F,0x0FF7F,0x36E07,0x33F07,0x88DFF,0x00000
+ /* { "FRAME" , frame_attr, HTML_FRAME_ATTRIBUTES, SGML_EMPTY }, */
+#define T_FRAME 0x10000,0x00000,0x00000,0x10000,0x10000,0x9FFFF,0x00001
+ /* { "FRAMESET", frameset_attr,HTML_FRAMESET_ATTRIBUTES, SGML_MIXED }, */
+#define T_FRAMESET 0x10000,0x90000,0x90000,0x90000,0x93000,0x9FFFF,0x00000
+ /* { "H1" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H1 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "H2" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H2 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "H3" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H3 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "H4" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H4 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "H5" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H5 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "H6" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED }, */
+#define T_H6 0x0100, 0x0B04F,0x0B05F,0x36680,0x37FAF,0x80317,0x00000
+ /* { "HEAD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_HEAD 0x40000,0x4F000,0x47000,0x10000,0x10000,0x9FF7F,0x00006
+ /* { "HR" , hr_attr, HTML_HR_ATTRIBUTES, SGML_EMPTY }, */
+#define T_HR 0x4000, 0x00000,0x00000,0x3FE80,0x3FFBF,0x87F37,0x00001
+ /* { "HTML" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_HTML 0x10000,0x7FB8F,0x7FFFF,0x00000,0x00000,0x1FFFF,0x00003
+#define T_HY 0x1000, 0x00000,0x00000,0x3779F,0x77FBF,0x8101F,0x00001
+ /* { "I" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_I 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00004
+#define T_IFRAME 0x2000, 0x8FBCF,0x8FFFF,0xB679F,0xB6FBF,0xD335F,0x00000
+ /* { "IMG" , img_attr, HTML_IMG_ATTRIBUTES, SGML_EMPTY }, */
+#define T_IMG 0x1000, 0x00000,0x00000,0x3779F,0x37FBF,0x80000,0x00001
+ /* { "INPUT" , input_attr, HTML_INPUT_ATTRIBUTES, SGML_EMPTY }, */
+#define T_INPUT 0x0040, 0x00000,0x00000,0x03F87,0x37F87,0x8904F,0x00001
+ /* { "INS" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_INS 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00003,0x00000
+ /* { "ISINDEX" , isindex_attr, HTML_ISINDEX_ATTRIBUTES,SGML_EMPTY }, */
+#define T_ISINDEX 0x8000, 0x00000,0x00000,0x7778F,0x7FFAF,0x80007,0x00001
+ /* { "KBD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_KBD 0x0002, 0x00000,0x00000,0x2778F,0x77FBF,0x00003,0x00000
+ /* { "KEYGEN" , keygen_attr, HTML_KEYGEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_KEYGEN 0x0040, 0x00000,0x00000,0x07FB7,0x37FB7,0x80070,0x00001
+ /* { "LABEL" , label_attr, HTML_LABEL_ATTRIBUTES, SGML_MIXED }, */
+#define T_LABEL 0x0020, 0x9FFFF,0x9FFFF,0x9FFFF,0x9FFFF,0x00007,0x00000
+#define T_LEGEND 0x0002, 0x0B04F,0x0FF7F,0x00200,0x37FA7,0x00003,0x00000
+ /* { "LH" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_LH 0x0400, 0x0BB7F,0x8FFFF,0x00800,0x97FFF,0x8071F,0x00001
+ /* { "LI" , list_attr, HTML_LI_ATTRIBUTES, SGML_EMPTY }, */
+#define T_LI 0x0400, 0x0BBFF,0x8FFFF,0x00800,0x97FFF,0x8071F,0x00001
+ /* { "LINK" , link_attr, HTML_LINK_ATTRIBUTES, SGML_EMPTY }, */
+#define T_LINK 0x8000, 0x00000,0x00000,0x50000,0x50000,0x0FF7F,0x00001
+ /* { "LISTING" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_LISTING 0x0800, 0x00000,0x00000,0x36600,0x36F00,0x80F1F,0x00000
+ /* { "MAP" , map_attr, HTML_MAP_ATTRIBUTES, SGML_MIXED }, */
+#define T_MAP 0x8000, 0x08000,0x08000,0x37FCF,0x37FBF,0x0071F,0x00000
+ /* { "MARQUEE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_MARQUEE 0x4000, 0x0000F,0x8F01F,0x37787,0xB7FA7,0x8301C,0x00000
+ /* { "MATH" , math_attr, HTML_MATH_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_MATH 0x0004, 0x0B05F,0x8FFFF,0x2778F,0xF7FBF,0x0001F,0x00000
+ /* { "MENU" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED }, */
+#define T_MENU 0x0800, 0x0B400,0x0F75F,0x17680,0x36FB7,0x88F7F,0x00000
+ /* { "META" , meta_attr, HTML_META_ATTRIBUTES, SGML_EMPTY }, */
+#define T_META 0x8000, 0x00000,0x00000,0x50000,0x50000,0x0FF7F,0x00001
+ /* { "NEXTID" , nextid_attr, 1, SGML_EMPTY }, */
+#define T_NEXTID 0x1000, 0x00000,0x00000,0x50000,0x1FFF7,0x00001,0x00001
+ /* { "NOFRAMES", gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_NOFRAMES 0x20000,0x2FB8F,0x0FFFF,0x17000,0x17000,0x0CF5F,0x00000
+ /* { "NOTE" , note_attr, HTML_NOTE_ATTRIBUTES, SGML_MIXED }, */
+#define T_NOTE 0x0200, 0x0BBAF,0x8FFFF,0x376B0,0xB7FFF,0x8031F,0x00000
+ /* { "OBJECT" , object_attr, HTML_OBJECT_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_OBJECT 0x2000, 0x8FBCF,0x8FFFF,0xB679F,0xB6FBF,0x83F5F,0x00000
+ /* { "OL" , olist_attr, HTML_OL_ATTRIBUTES, SGML_MIXED }, */
+#define T_OL 0x0800, 0x0C400,0x8FFFF,0x37680,0xB7FB7,0x88F7F,0x00000
+ /* { "OPTION" , option_attr, HTML_OPTION_ATTRIBUTES, SGML_EMPTY }, */
+#define T_OPTION 0x8000, 0x00000,0x00000,0x00040,0x37FFF,0x8031F,0x00001
+ /* { "OVERLAY" , overlay_attr, HTML_OVERLAY_ATTRIBUTES, SGML_EMPTY }, */
+#define T_OVERLAY 0x4000, 0x00000,0x00000,0x00200,0x37FBF,0x83F7F,0x00001
+ /* { "P" , p_attr, HTML_P_ATTRIBUTES, SGML_EMPTY }, */
+#define T_P 0x0100, 0x0B04F,0x8FFFF,0x36680,0xB6FA7,0x80117,0x00001
+ /* { "PARAM" , param_attr, HTML_PARAM_ATTRIBUTES, SGML_EMPTY }, */
+#define T_PARAM 0x1000, 0x00000,0x00000,0x03000,0x17FFF,0x81777,0x00001
+ /* { "PLAINTEXT", gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_PLAINTEXT 0x10000,0xFFFFF,0xFFFFF,0x90000,0x90000,0x3FFFF,0x00001
+ /* { "PRE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_PRE 0x0200, 0x0F04F,0x0F05E,0x36680,0x36FF0,0x8071E,0x00000
+ /* { "Q" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_Q 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FAF,0x00003,0x00000
+ /* { "S" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_S 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00000
+ /* { "SAMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_SAMP 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00002,0x00000
+ /* { "SCRIPT" , script_attr, HTML_SCRIPT_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_SCRIPT 0x2000, 0x00000,0x00000,0x77F9F,0x77FFF,0x87F5F,0x00000
+ /* { "SELECT" , select_attr, HTML_SELECT_ATTRIBUTES, SGML_MIXED }, */
+#define T_SELECT 0x0040, 0x08000,0x08000,0x03FAF,0x13FBF,0x80F5F,0x00008
+#define T_SHY 0x1000, 0x00000,0x00000,0x3779F,0x77FBF,0x8101F,0x00001
+ /* { "SMALL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_SMALL 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00004
+ /* { "SPAN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_SPAN 0x0002, 0x0B04F,0x0FFFF,0x2778F,0x77FBF,0x80003,0x00000
+ /* { "SPOT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY }, */
+#define T_SPOT 0x0008, 0x00000,0x00000,0x3FFF7,0x3FFF7,0x00008,0x00001
+ /* { "STRIKE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_STRIKE 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00000
+ /* { "STRONG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_STRONG 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FAF,0x00003,0x00000
+ /* { "STYLE" , style_attr, HTML_STYLE_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_STYLE 0x40000,0x00000,0x00000,0x7638F,0x76FAF,0x8001F,0x00000
+ /* { "SUB" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_SUB 0x0004, 0x8B05F,0x8FFFF,0x8779F,0xF7FBF,0x00007,0x00000
+ /* { "SUP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_SUP 0x0004, 0x8B05F,0x8FFFF,0x8779F,0xF7FBF,0x00007,0x00000
+ /* { "TAB" , tab_attr, HTML_TAB_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TAB 0x1000, 0x00000,0x00000,0x3778F,0x57FAF,0x00001,0x00001
+ /* { "TABLE" , table_attr, HTML_TABLE_ATTRIBUTES, SGML_MIXED }, */
+#define T_TABLE 0x0800, 0x0F1E0,0x8FFFF,0x36680,0xB6FA7,0x8C57F,0x00000
+ /* { "TBODY" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TBODY 0x0020, 0x00020,0x8FFFF,0x00880,0xB7FB7,0x8C75F,0x00003
+ /* { "TD" , td_attr, HTML_TD_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TD 0x0400, 0x0FBCF,0x8FFFF,0x00020,0xB7FB7,0x8C75F,0x00001
+ /* { "TEXTAREA", textarea_attr,HTML_TEXTAREA_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_TEXTAREA 0x0040, 0x00000,0x00000,0x07F8F,0x33FBF,0x80F5F,0x00000
+ /* { "TEXTFLOW", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED }, */
+#define T_TEXTFLOW 0x20000,0x8FBFF,0x9FFFF,0x977B0,0xB7FB7,0x9B00F,0x00003
+ /* { "TFOOT" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TFOOT 0x0020, 0x00020,0x8FFFF,0x00800,0xB7FB7,0x8CF5F,0x00001
+ /* { "TH" , td_attr, HTML_TD_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TH 0x0400, 0x0FBCF,0x0FFFF,0x00020,0xB7FB7,0x8CF5F,0x00001
+ /* { "THEAD" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY }, */
+#define T_THEAD 0x0020, 0x00020,0x8FFFF,0x00880,0xB7FB7,0x8CF5F,0x00001
+ /* { "TITLE", gen_attr, HTML_GEN_ATTRIBUTES, SGML_RCDATA }, */
+#define T_TITLE 0x40000,0x00000,0x00000,0x50000,0x50000,0x0031F,0x00004
+ /* { "TR" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY }, */
+#define T_TR 0x0020, 0x00400,0x8FFFF,0x00820,0xB7FB7,0x8C75F,0x00001
+ /* { "TT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_TT 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00000
+ /* { "U" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_U 0x0001, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00004
+ /* { "UL" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED }, */
+#define T_UL 0x0800, 0x0C480,0x8FFFF,0x36680,0xB7FFF,0x8075F,0x00000
+ /* { "VAR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED }, */
+#define T_VAR 0x0002, 0x8B04F,0x8FFFF,0xA778F,0xF7FBF,0x00001,0x00000
+#define T_WBR 0x0001, 0x00000,0x00000,0x3778F,0x77FBF,0x8101F,0x00001
+ /* { "XMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL }, */
+#define T_XMP 0x0800, 0x00000,0x00000,0x367E0,0x36FFF,0x0875F,0x00001
+
+#define T__UNREC_ 0x0000, 0x00000,0x00000,0x00000,0x00000,0x00000,0x00000
+
+/* Elements
+** --------
+**
+** Must match definitions in HTMLDTD.html!
+** Must be in alphabetical order.
+**
+** The T_* extra info is listed here, but it won't matter (is not used
+** in SGML.c if New_DTD is not set). This mainly simplifies comparison
+** of the tags_old[] table (otherwise unchanged from original Lynx treatment)
+** with the tags_new[] table below. - kw
+**
+** Name, Attributes, No. of attributes, content, extra info...
+*/
+static HTTag tags_old[HTML_ELEMENTS] = {
+ { "A" , a_attr, HTML_A_ATTRIBUTES, SGML_EMPTY,T_A},
+ { "ABBREV" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_ABBREV},
+ { "ACRONYM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_ACRONYM},
+ { "ADDRESS" , address_attr, HTML_ADDRESS_ATTRIBUTES, SGML_MIXED,T_ADDRESS},
+ { "APPLET" , applet_attr, HTML_APPLET_ATTRIBUTES, SGML_MIXED,T_APPLET},
+ { "AREA" , area_attr, HTML_AREA_ATTRIBUTES, SGML_EMPTY,T_AREA},
+ { "AU" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_AU},
+ { "AUTHOR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_AUTHOR},
+ { "B" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_B},
+ { "BANNER" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BANNER},
+ { "BASE" , base_attr, HTML_BASE_ATTRIBUTES, SGML_EMPTY,T_BASE},
+ { "BASEFONT", font_attr, HTML_FONT_ATTRIBUTES, SGML_EMPTY,T_BASEFONT},
+ { "BDO" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BDO},
+ { "BGSOUND" , bgsound_attr, HTML_BGSOUND_ATTRIBUTES, SGML_EMPTY,T_BGSOUND},
+ { "BIG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BIG},
+ { "BLINK" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_BLINK},
+ { "BLOCKQUOTE", bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED,T_BLOCKQUOTE},
+ { "BODY" , body_attr, HTML_BODY_ATTRIBUTES, SGML_MIXED,T_BODY},
+ { "BODYTEXT", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED,T_BODYTEXT},
+ { "BQ" , bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED,T_BQ},
+ { "BR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_BR},
+ { "BUTTON" , button_attr, HTML_BUTTON_ATTRIBUTES, SGML_MIXED,T_BUTTON},
+ { "CAPTION" , caption_attr, HTML_CAPTION_ATTRIBUTES, SGML_MIXED,T_CAPTION},
+ { "CENTER" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED,T_CENTER},
+ { "CITE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_CITE},
+ { "CODE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_CODE},
+ { "COL" , col_attr, HTML_COL_ATTRIBUTES, SGML_EMPTY,T_COL},
+ { "COLGROUP", col_attr, HTML_COL_ATTRIBUTES, SGML_EMPTY,T_COLGROUP},
+ { "COMMENT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_COMMENT},
+ { "CREDIT" , credit_attr, HTML_CREDIT_ATTRIBUTES, SGML_MIXED,T_CREDIT},
+ { "DD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_DD},
+ { "DEL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DEL},
+ { "DFN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DFN},
+ { "DIR" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_DIR},
+ { "DIV" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED,T_DIV},
+ { "DL" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED,T_DL},
+ { "DLC" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED,T_DLC},
+ { "DT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_DT},
+ { "EM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_EM},
+ { "EMBED" , embed_attr, HTML_EMBED_ATTRIBUTES, SGML_EMPTY,T_EMBED},
+ { "FIELDSET", fieldset_attr,HTML_FIELDSET_ATTRIBUTES, SGML_MIXED,T_FIELDSET},
+ { "FIG" , fig_attr, HTML_FIG_ATTRIBUTES, SGML_MIXED,T_FIG},
+ { "FN" , fn_attr, HTML_FN_ATTRIBUTES, SGML_MIXED,T_FN},
+ { "FONT" , font_attr, HTML_FONT_ATTRIBUTES, SGML_EMPTY,T_FONT},
+ { "FORM" , form_attr, HTML_FORM_ATTRIBUTES, SGML_EMPTY,T_FORM},
+ { "FRAME" , frame_attr, HTML_FRAME_ATTRIBUTES, SGML_EMPTY,T_FRAME},
+ { "FRAMESET", frameset_attr,HTML_FRAMESET_ATTRIBUTES, SGML_MIXED,T_FRAMESET},
+ { "H1" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H1},
+ { "H2" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H2},
+ { "H3" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H3},
+ { "H4" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H4},
+ { "H5" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H5},
+ { "H6" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H6},
+ { "HEAD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_HEAD},
+ { "HR" , hr_attr, HTML_HR_ATTRIBUTES, SGML_EMPTY,T_HR},
+ { "HTML" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_HTML},
+ { "HY" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_HY},
+ { "I" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_I},
+ { "IFRAME" , iframe_attr, HTML_IFRAME_ATTRIBUTES, SGML_MIXED,T_IFRAME},
+ { "IMG" , img_attr, HTML_IMG_ATTRIBUTES, SGML_EMPTY,T_IMG},
+ { "INPUT" , input_attr, HTML_INPUT_ATTRIBUTES, SGML_EMPTY,T_INPUT},
+ { "INS" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_INS},
+ { "ISINDEX" , isindex_attr, HTML_ISINDEX_ATTRIBUTES,SGML_EMPTY,T_ISINDEX},
+ { "KBD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_KBD},
+ { "KEYGEN" , keygen_attr, HTML_KEYGEN_ATTRIBUTES, SGML_EMPTY,T_KEYGEN},
+ { "LABEL" , label_attr, HTML_LABEL_ATTRIBUTES, SGML_MIXED,T_LABEL},
+ { "LEGEND" , legend_attr, HTML_LEGEND_ATTRIBUTES, SGML_MIXED,T_LEGEND},
+ { "LH" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_LH},
+ { "LI" , list_attr, HTML_LI_ATTRIBUTES, SGML_EMPTY,T_LI},
+ { "LINK" , link_attr, HTML_LINK_ATTRIBUTES, SGML_EMPTY,T_LINK},
+ { "LISTING" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_LISTING},
+ { "MAP" , map_attr, HTML_MAP_ATTRIBUTES, SGML_MIXED,T_MAP},
+ { "MARQUEE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_MARQUEE},
+ { "MATH" , math_attr, HTML_MATH_ATTRIBUTES, SGML_LITTERAL,T_MATH},
+ { "MENU" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_MENU},
+ { "META" , meta_attr, HTML_META_ATTRIBUTES, SGML_EMPTY,T_META},
+ { "NEXTID" , nextid_attr, 1, SGML_EMPTY,T_NEXTID},
+ { "NOFRAMES", gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_NOFRAMES},
+ { "NOTE" , note_attr, HTML_NOTE_ATTRIBUTES, SGML_MIXED,T_NOTE},
+ { "OBJECT" , object_attr, HTML_OBJECT_ATTRIBUTES, SGML_LITTERAL,T_OBJECT},
+ { "OL" , olist_attr, HTML_OL_ATTRIBUTES, SGML_MIXED,T_OL},
+ { "OPTION" , option_attr, HTML_OPTION_ATTRIBUTES, SGML_EMPTY,T_OPTION},
+ { "OVERLAY" , overlay_attr, HTML_OVERLAY_ATTRIBUTES, SGML_EMPTY,T_OVERLAY},
+ { "P" , p_attr, HTML_P_ATTRIBUTES, SGML_EMPTY,T_P},
+ { "PARAM" , param_attr, HTML_PARAM_ATTRIBUTES, SGML_EMPTY,T_PARAM},
+ { "PLAINTEXT", gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_PLAINTEXT},
+ { "PRE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_PRE},
+ { "Q" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_Q},
+ { "S" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_S},
+ { "SAMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SAMP},
+ { "SCRIPT" , script_attr, HTML_SCRIPT_ATTRIBUTES, SGML_LITTERAL,T_SCRIPT},
+ { "SELECT" , select_attr, HTML_SELECT_ATTRIBUTES, SGML_MIXED,T_SELECT},
+ { "SHY" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_SHY},
+ { "SMALL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SMALL},
+ { "SPAN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SPAN},
+ { "SPOT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_SPOT},
+ { "STRIKE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_STRIKE},
+ { "STRONG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_STRONG},
+ { "STYLE" , style_attr, HTML_STYLE_ATTRIBUTES, SGML_LITTERAL,T_STYLE},
+ { "SUB" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SUB},
+ { "SUP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SUP},
+ { "TAB" , tab_attr, HTML_TAB_ATTRIBUTES, SGML_EMPTY,T_TAB},
+ { "TABLE" , table_attr, HTML_TABLE_ATTRIBUTES, SGML_MIXED,T_TABLE},
+ { "TBODY" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY,T_TBODY},
+ { "TD" , td_attr, HTML_TD_ATTRIBUTES, SGML_EMPTY,T_TD},
+ { "TEXTAREA", textarea_attr,HTML_TEXTAREA_ATTRIBUTES, SGML_LITTERAL,T_TEXTAREA},
+ { "TEXTFLOW", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED,T_TEXTFLOW},
+ { "TFOOT" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY,T_TFOOT},
+ { "TH" , td_attr, HTML_TD_ATTRIBUTES, SGML_EMPTY,T_TH},
+ { "THEAD" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY,T_THEAD},
+ { "TITLE", gen_attr, HTML_GEN_ATTRIBUTES, SGML_RCDATA,T_TITLE},
+ { "TR" , tr_attr, HTML_TR_ATTRIBUTES, SGML_EMPTY,T_TR},
+ { "TT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_TT},
+ { "U" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_U},
+ { "UL" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_UL},
+ { "VAR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_VAR},
+ { "WBR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_WBR},
+ { "XMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_XMP},
+};
+
+static HTTag tags_new[HTML_ELEMENTS] = {
+ { "A" , a_attr, HTML_A_ATTRIBUTES, SGML_MIXED,T_A},
+ { "ABBREV" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_ABBREV},
+ { "ACRONYM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_ACRONYM},
+ { "ADDRESS" , address_attr, HTML_ADDRESS_ATTRIBUTES, SGML_MIXED,T_ADDRESS},
+ { "APPLET" , applet_attr, HTML_APPLET_ATTRIBUTES, SGML_MIXED,T_APPLET},
+ { "AREA" , area_attr, HTML_AREA_ATTRIBUTES, SGML_EMPTY,T_AREA},
+ { "AU" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_AU},
+ { "AUTHOR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_AUTHOR},
+ { "B" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_B},
+ { "BANNER" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BANNER},
+ { "BASE" , base_attr, HTML_BASE_ATTRIBUTES, SGML_EMPTY,T_BASE},
+ { "BASEFONT", font_attr, HTML_FONT_ATTRIBUTES, SGML_EMPTY,T_BASEFONT},
+ { "BDO" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BDO},
+ { "BGSOUND" , bgsound_attr, HTML_BGSOUND_ATTRIBUTES, SGML_EMPTY,T_BGSOUND},
+ { "BIG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BIG},
+ { "BLINK" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_BLINK},
+ { "BLOCKQUOTE", bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED,T_BLOCKQUOTE},
+ { "BODY" , body_attr, HTML_BODY_ATTRIBUTES, SGML_MIXED,T_BODY},
+ { "BODYTEXT", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED,T_BODYTEXT},
+ { "BQ" , bq_attr, HTML_BQ_ATTRIBUTES, SGML_MIXED,T_BQ},
+ { "BR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_BR},
+ { "BUTTON" , button_attr, HTML_BUTTON_ATTRIBUTES, SGML_MIXED,T_BUTTON},
+ { "CAPTION" , caption_attr, HTML_CAPTION_ATTRIBUTES, SGML_MIXED,T_CAPTION},
+ { "CENTER" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED,T_CENTER},
+ { "CITE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_CITE},
+ { "CODE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_CODE},
+ { "COL" , col_attr, HTML_COL_ATTRIBUTES, SGML_EMPTY,T_COL},
+ { "COLGROUP", col_attr, HTML_COL_ATTRIBUTES, SGML_ELEMENT,T_COLGROUP},
+ { "COMMENT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_PCDATA,T_COMMENT},
+ { "CREDIT" , credit_attr, HTML_CREDIT_ATTRIBUTES, SGML_MIXED,T_CREDIT},
+ { "DD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DD},
+ { "DEL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DEL},
+ { "DFN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DFN},
+ { "DIR" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_DIR},
+ { "DIV" , div_attr, HTML_DIV_ATTRIBUTES, SGML_MIXED,T_DIV},
+ { "DL" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED,T_DL},
+ { "DLC" , glossary_attr, HTML_DL_ATTRIBUTES, SGML_MIXED,T_DLC},
+ { "DT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_DT},
+ { "EM" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_EM},
+ { "EMBED" , embed_attr, HTML_EMBED_ATTRIBUTES, SGML_EMPTY,T_EMBED},
+ { "FIELDSET", fieldset_attr,HTML_FIELDSET_ATTRIBUTES, SGML_MIXED,T_FIELDSET},
+ { "FIG" , fig_attr, HTML_FIG_ATTRIBUTES, SGML_MIXED,T_FIG},
+ { "FN" , fn_attr, HTML_FN_ATTRIBUTES, SGML_MIXED,T_FN},
+ { "FONT" , font_attr, HTML_FONT_ATTRIBUTES, SGML_MIXED,T_FONT},
+ { "FORM" , form_attr, HTML_FORM_ATTRIBUTES, SGML_MIXED,T_FORM},
+ { "FRAME" , frame_attr, HTML_FRAME_ATTRIBUTES, SGML_EMPTY,T_FRAME},
+ { "FRAMESET", frameset_attr,HTML_FRAMESET_ATTRIBUTES, SGML_ELEMENT,T_FRAMESET},
+ { "H1" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H1},
+ { "H2" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H2},
+ { "H3" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H3},
+ { "H4" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H4},
+ { "H5" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H5},
+ { "H6" , h_attr, HTML_H_ATTRIBUTES, SGML_MIXED,T_H6},
+ { "HEAD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_ELEMENT,T_HEAD},
+ { "HR" , hr_attr, HTML_HR_ATTRIBUTES, SGML_EMPTY,T_HR},
+ { "HTML" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_HTML},
+ { "HY" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_HY},
+ { "I" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_I},
+ { "IFRAME" , iframe_attr, HTML_IFRAME_ATTRIBUTES, SGML_MIXED,T_IFRAME},
+ { "IMG" , img_attr, HTML_IMG_ATTRIBUTES, SGML_EMPTY,T_IMG},
+ { "INPUT" , input_attr, HTML_INPUT_ATTRIBUTES, SGML_EMPTY,T_INPUT},
+ { "INS" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_INS},
+ { "ISINDEX" , isindex_attr, HTML_ISINDEX_ATTRIBUTES,SGML_EMPTY,T_ISINDEX},
+ { "KBD" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_KBD},
+ { "KEYGEN" , keygen_attr, HTML_KEYGEN_ATTRIBUTES, SGML_EMPTY,T_KEYGEN},
+ { "LABEL" , label_attr, HTML_LABEL_ATTRIBUTES, SGML_MIXED,T_LABEL},
+ { "LEGEND" , legend_attr, HTML_LEGEND_ATTRIBUTES, SGML_MIXED,T_LEGEND},
+ { "LH" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_LH},
+ { "LI" , list_attr, HTML_LI_ATTRIBUTES, SGML_MIXED,T_LI},
+ { "LINK" , link_attr, HTML_LINK_ATTRIBUTES, SGML_EMPTY,T_LINK},
+ { "LISTING" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_LISTING},
+ { "MAP" , map_attr, HTML_MAP_ATTRIBUTES, SGML_ELEMENT,T_MAP},
+ { "MARQUEE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_MARQUEE},
+ { "MATH" , math_attr, HTML_MATH_ATTRIBUTES, SGML_LITTERAL,T_MATH},
+ { "MENU" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_MENU},
+ { "META" , meta_attr, HTML_META_ATTRIBUTES, SGML_EMPTY,T_META},
+ { "NEXTID" , nextid_attr, 1, SGML_EMPTY,T_NEXTID},
+ { "NOFRAMES", gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_NOFRAMES},
+ { "NOTE" , note_attr, HTML_NOTE_ATTRIBUTES, SGML_MIXED,T_NOTE},
+ { "OBJECT" , object_attr, HTML_OBJECT_ATTRIBUTES, SGML_LITTERAL,T_OBJECT},
+ { "OL" , olist_attr, HTML_OL_ATTRIBUTES, SGML_MIXED,T_OL},
+ { "OPTION" , option_attr, HTML_OPTION_ATTRIBUTES, SGML_PCDATA,T_OPTION},
+ { "OVERLAY" , overlay_attr, HTML_OVERLAY_ATTRIBUTES, SGML_PCDATA,T_OVERLAY},
+ { "P" , p_attr, HTML_P_ATTRIBUTES, SGML_MIXED,T_P},
+ { "PARAM" , param_attr, HTML_PARAM_ATTRIBUTES, SGML_EMPTY,T_PARAM},
+ { "PLAINTEXT", gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_PLAINTEXT},
+ { "PRE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_PRE},
+ { "Q" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_Q},
+ { "S" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_S},
+ { "SAMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SAMP},
+ { "SCRIPT" , script_attr, HTML_SCRIPT_ATTRIBUTES, SGML_LITTERAL,T_SCRIPT},
+ { "SELECT" , select_attr, HTML_SELECT_ATTRIBUTES, SGML_ELEMENT,T_SELECT},
+ { "SHY" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_SHY},
+ { "SMALL" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SMALL},
+ { "SPAN" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SPAN},
+ { "SPOT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_SPOT},
+ { "STRIKE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_STRIKE},
+ { "STRONG" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_STRONG},
+ { "STYLE" , style_attr, HTML_STYLE_ATTRIBUTES, SGML_LITTERAL,T_STYLE},
+ { "SUB" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SUB},
+ { "SUP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_SUP},
+ { "TAB" , tab_attr, HTML_TAB_ATTRIBUTES, SGML_EMPTY,T_TAB},
+ { "TABLE" , table_attr, HTML_TABLE_ATTRIBUTES, SGML_ELEMENT,T_TABLE},
+ { "TBODY" , tr_attr, HTML_TR_ATTRIBUTES, SGML_ELEMENT,T_TBODY},
+ { "TD" , td_attr, HTML_TD_ATTRIBUTES, SGML_MIXED,T_TD},
+ { "TEXTAREA", textarea_attr,HTML_TEXTAREA_ATTRIBUTES, SGML_LITTERAL,T_TEXTAREA},
+ { "TEXTFLOW", bodytext_attr,HTML_BODYTEXT_ATTRIBUTES, SGML_MIXED,T_TEXTFLOW},
+ { "TFOOT" , tr_attr, HTML_TR_ATTRIBUTES, SGML_ELEMENT,T_TFOOT},
+ { "TH" , td_attr, HTML_TD_ATTRIBUTES, SGML_MIXED,T_TH},
+ { "THEAD" , tr_attr, HTML_TR_ATTRIBUTES, SGML_ELEMENT,T_THEAD},
+ { "TITLE" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_PCDATA,T_TITLE},
+ { "TR" , tr_attr, HTML_TR_ATTRIBUTES, SGML_MIXED,T_TR},
+ { "TT" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_TT},
+ { "U" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_U},
+ { "UL" , ulist_attr, HTML_UL_ATTRIBUTES, SGML_MIXED,T_UL},
+ { "VAR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_MIXED,T_VAR},
+ { "WBR" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_EMPTY,T_WBR},
+ { "XMP" , gen_attr, HTML_GEN_ATTRIBUTES, SGML_LITTERAL,T_XMP},
+};
+
+/* Dummy space, will be filled with the contents of either tags_new
+ or tags_old on calling HTSwitchDTD - kw */
+
+static HTTag tags[HTML_ELEMENTS];
+
+PUBLIC CONST SGML_dtd HTML_dtd = {
+ tags,
+ HTML_ELEMENTS,
+ entities,
+ sizeof(entities)/sizeof(entities[0]),
+ unicode_entities,
+ sizeof(unicode_entities)/sizeof(unicode_entities[0])
+};
+
+/* This function fills the "tags" part of the HTML_dtd structure with
+ what we want to use, either tags_old or tags_new. Note that it
+ has to be called at least once before HTML_dtd is used, otherwise
+ the HTML_dtd contents will be invalid! This could be coded in a way
+ that would make an initialisation call unnecessary, but my C knowledge
+ is limited and I didn't want to list the whole tags_new table
+ twice... - kw */
+PUBLIC void HTSwitchDTD ARGS1(
+ BOOL, new)
+{
+ if (TRACE)
+ fprintf(stderr,"HTMLDTD: Copying DTD element info of size %d, %d * %d\n",
+ new ? sizeof(tags_new) : sizeof(tags_old),
+ HTML_ELEMENTS, sizeof(HTTag));
+ if (new)
+ memcpy(tags, tags_new, HTML_ELEMENTS * sizeof(HTTag));
+ else
+ memcpy(tags, tags_old, HTML_ELEMENTS * sizeof(HTTag));
+}
+
+PUBLIC CONST HTTag HTTag_unrecognized =
+ { NULL, NULL, 0, SGML_EMPTY,T__UNREC_};
+
+/*
+** Utility Routine: Useful for people building HTML objects.
+*/
+
+/* Start anchor element
+** --------------------
+**
+** It is kinda convenient to have a particulr routine for
+** starting an anchor element, as everything else for HTML is
+** simple anyway.
+*/
+struct _HTStructured {
+ HTStructuredClass * isa;
+ /* ... */
+};
+
+PUBLIC void HTStartAnchor ARGS3(
+ HTStructured *, obj,
+ CONST char *, name,
+ CONST char *, href)
+{
+ BOOL present[HTML_A_ATTRIBUTES];
+ CONST char * value[HTML_A_ATTRIBUTES];
+ int i;
+
+ for (i = 0; i < HTML_A_ATTRIBUTES; i++)
+ present[i] = NO;
+
+ if (name && *name) {
+ present[HTML_A_NAME] = YES;
+ value[HTML_A_NAME] = (CONST char *)name;
+ }
+ if (href) {
+ present[HTML_A_HREF] = YES;
+ value[HTML_A_HREF] = (CONST char *)href;
+ }
+
+ (*obj->isa->start_element)(obj, HTML_A, present, value, -1, 0);
+}
+
+PUBLIC void HTStartIsIndex ARGS3(
+ HTStructured *, obj,
+ CONST char *, prompt,
+ CONST char *, href)
+{
+ BOOL present[HTML_ISINDEX_ATTRIBUTES];
+ CONST char * value[HTML_ISINDEX_ATTRIBUTES];
+ int i;
+
+ for (i = 0; i < HTML_ISINDEX_ATTRIBUTES; i++)
+ present[i] = NO;
+
+ if (prompt && *prompt) {
+ present[HTML_ISINDEX_PROMPT] = YES;
+ value[HTML_ISINDEX_PROMPT] = (CONST char *)prompt;
+ }
+ if (href) {
+ present[HTML_ISINDEX_HREF] = YES;
+ value[HTML_ISINDEX_HREF] = (CONST char *)href;
+ }
+
+ (*obj->isa->start_element)(obj, HTML_ISINDEX , present, value, -1, 0);
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.h
new file mode 100644
index 00000000000..15004a1d7da
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLDTD.h
@@ -0,0 +1,1006 @@
+/* The HTML DTD -- software interface in libwww
+ HTML DTD - SOFTWARE INTERFACE
+
+ SGML purists should excuse the use of the term "DTD" in this file to
+ represent DTD-related information which is not exactly a DTD itself.
+
+ The C modular structure doesn't work very well here, as the dtd is
+ partly in the .h and partly in the .c which are not very independent.
+ Tant pis.
+
+ */
+#ifndef HTMLDTD_H
+#define HTMLDTD_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "SGML.h"
+
+/*
+** Lynx internal character representations.
+*/
+#ifndef HT_NON_BREAK_SPACE
+#define HT_NON_BREAK_SPACE ((char)1) /* For now */
+#endif /* !HT_NON_BREAK_SPACE */
+#ifndef HT_EM_SPACE
+#define HT_EM_SPACE ((char)2) /* For now */
+#endif /* !HT_EM_SPACE */
+#ifndef LY_SOFT_HYPHEN
+#define LY_SOFT_HYPHEN ((char)7)
+#endif /* !LY_SOFT_HYPHEN */
+
+/*
+
+Element Numbers
+
+ */
+
+/*
+
+ Must Match all tables by element!
+ These include tables in HTMLDTD.c and code in HTML.c.
+
+ */
+typedef enum _HTMLElement {
+ HTML_A,
+ HTML_ABBREV,
+ HTML_ACRONYM,
+ HTML_ADDRESS,
+ HTML_APPLET,
+ HTML_AREA,
+ HTML_AU,
+ HTML_AUTHOR,
+ HTML_B,
+ HTML_BANNER,
+ HTML_BASE,
+ HTML_BASEFONT,
+ HTML_BDO,
+ HTML_BGSOUND,
+ HTML_BIG,
+ HTML_BLINK,
+ HTML_BLOCKQUOTE,
+ HTML_BODY,
+ HTML_BODYTEXT,
+ HTML_BQ,
+ HTML_BR,
+ HTML_BUTTON,
+ HTML_CAPTION,
+ HTML_CENTER,
+ HTML_CITE,
+ HTML_CODE,
+ HTML_COL,
+ HTML_COLGROUP,
+ HTML_COMMENT,
+ HTML_CREDIT,
+ HTML_DD,
+ HTML_DEL,
+ HTML_DFN,
+ HTML_DIR,
+ HTML_DIV,
+ HTML_DL,
+ HTML_DLC,
+ HTML_DT,
+ HTML_EM,
+ HTML_EMBED,
+ HTML_FIELDSET,
+ HTML_FIG,
+ HTML_FN,
+ HTML_FONT,
+ HTML_FORM,
+ HTML_FRAME,
+ HTML_FRAMESET,
+ HTML_H1,
+ HTML_H2,
+ HTML_H3,
+ HTML_H4,
+ HTML_H5,
+ HTML_H6,
+ HTML_HEAD,
+ HTML_HR,
+ HTML_HTML,
+ HTML_HY,
+ HTML_I,
+ HTML_IFRAME,
+ HTML_IMG,
+ HTML_INPUT,
+ HTML_INS,
+ HTML_ISINDEX,
+ HTML_KBD,
+ HTML_KEYGEN,
+ HTML_LABEL,
+ HTML_LEGEND,
+ HTML_LH,
+ HTML_LI,
+ HTML_LINK,
+ HTML_LISTING,
+ HTML_MAP,
+ HTML_MARQUEE,
+ HTML_MATH,
+ HTML_MENU,
+ HTML_META,
+ HTML_NEXTID,
+ HTML_NOFRAMES,
+ HTML_NOTE,
+ HTML_OBJECT,
+ HTML_OL,
+ HTML_OPTION,
+ HTML_OVERLAY,
+ HTML_P,
+ HTML_PARAM,
+ HTML_PLAINTEXT,
+ HTML_PRE,
+ HTML_Q,
+ HTML_S,
+ HTML_SAMP,
+ HTML_SCRIPT,
+ HTML_SELECT,
+ HTML_SHY,
+ HTML_SMALL,
+ HTML_SPAN,
+ HTML_SPOT,
+ HTML_STRIKE,
+ HTML_STRONG,
+ HTML_STYLE,
+ HTML_SUB,
+ HTML_SUP,
+ HTML_TAB,
+ HTML_TABLE,
+ HTML_TBODY,
+ HTML_TD,
+ HTML_TEXTAREA,
+ HTML_TEXTFLOW,
+ HTML_TFOOT,
+ HTML_TH,
+ HTML_THEAD,
+ HTML_TITLE,
+ HTML_TR,
+ HTML_TT,
+ HTML_U,
+ HTML_UL,
+ HTML_VAR,
+ HTML_WBR,
+ HTML_XMP } HTMLElement;
+
+#define HTML_ELEMENTS 118
+
+/*
+
+Attribute numbers
+
+ */
+
+/*
+
+ Identifier is HTML_<element>_<attribute>.
+ These must match the tables in HTML.c!
+
+ */
+#define HTML_A_ACCESSKEY 0
+#define HTML_A_CHARSET 1 /* i18n draft, added tentatively - KW */
+#define HTML_A_CLASS 2
+#define HTML_A_CLEAR 3
+#define HTML_A_COORDS 4
+#define HTML_A_DIR 5
+#define HTML_A_HREF 6
+#define HTML_A_ID 7
+#define HTML_A_ISMAP 8
+#define HTML_A_LANG 9
+#define HTML_A_MD 10
+#define HTML_A_NAME 11
+#define HTML_A_NOTAB 12
+#define HTML_A_ONCLICK 13
+#define HTML_A_ONMOUSEOUT 14
+#define HTML_A_ONMOUSEOVER 15
+#define HTML_A_REL 16
+#define HTML_A_REV 17
+#define HTML_A_SHAPE 18
+#define HTML_A_STYLE 19
+#define HTML_A_TABINDEX 20
+#define HTML_A_TARGET 21
+#define HTML_A_TITLE 22
+#define HTML_A_TYPE 23
+#define HTML_A_URN 24
+#define HTML_A_ATTRIBUTES 25
+
+#define HTML_ADDRESS_CLASS 0
+#define HTML_ADDRESS_CLEAR 1
+#define HTML_ADDRESS_DIR 2
+#define HTML_ADDRESS_ID 3
+#define HTML_ADDRESS_LANG 4
+#define HTML_ADDRESS_NOWRAP 5
+#define HTML_ADDRESS_STYLE 6
+#define HTML_ADDRESS_TITLE 7
+#define HTML_ADDRESS_ATTRIBUTES 8
+
+#define HTML_APPLET_ALIGN 0
+#define HTML_APPLET_ALT 1
+#define HTML_APPLET_CLASS 2
+#define HTML_APPLET_CLEAR 3
+#define HTML_APPLET_CODE 4
+#define HTML_APPLET_CODEBASE 5
+#define HTML_APPLET_DIR 6
+#define HTML_APPLET_DOWNLOAD 7
+#define HTML_APPLET_HEIGHT 8
+#define HTML_APPLET_HSPACE 9
+#define HTML_APPLET_ID 10
+#define HTML_APPLET_LANG 11
+#define HTML_APPLET_NAME 12
+#define HTML_APPLET_STYLE 13
+#define HTML_APPLET_TITLE 14
+#define HTML_APPLET_VSPACE 15
+#define HTML_APPLET_WIDTH 16
+#define HTML_APPLET_ATTRIBUTES 17
+
+#define HTML_AREA_ALT 0
+#define HTML_AREA_CLASS 1
+#define HTML_AREA_CLEAR 2
+#define HTML_AREA_COORDS 3
+#define HTML_AREA_DIR 4
+#define HTML_AREA_HREF 5
+#define HTML_AREA_ID 6
+#define HTML_AREA_LANG 7
+#define HTML_AREA_NOHREF 8
+#define HTML_AREA_NONOTAB 9
+#define HTML_AREA_ONCLICK 10
+#define HTML_AREA_ONMOUSEOUT 11
+#define HTML_AREA_ONMOUSEOVER 12
+#define HTML_AREA_SHAPE 13
+#define HTML_AREA_STYLE 14
+#define HTML_AREA_TABINDEX 15
+#define HTML_AREA_TARGET 16
+#define HTML_AREA_TITLE 17
+#define HTML_AREA_ATTRIBUTES 18
+
+#define HTML_BASE_HREF 0
+#define HTML_BASE_TARGET 1
+#define HTML_BASE_TITLE 2
+#define HTML_BASE_ATTRIBUTES 3
+
+#define HTML_BGSOUND_CLASS 0
+#define HTML_BGSOUND_CLEAR 1
+#define HTML_BGSOUND_DIR 2
+#define HTML_BGSOUND_ID 3
+#define HTML_BGSOUND_LANG 4
+#define HTML_BGSOUND_LOOP 5
+#define HTML_BGSOUND_SRC 6
+#define HTML_BGSOUND_STYLE 7
+#define HTML_BGSOUND_TITLE 8
+#define HTML_BGSOUND_ATTRIBUTES 9
+
+#define HTML_BODY_ALINK 0
+#define HTML_BODY_BACKGROUND 1
+#define HTML_BODY_BGCOLOR 2
+#define HTML_BODY_CLASS 3
+#define HTML_BODY_CLEAR 4
+#define HTML_BODY_DIR 5
+#define HTML_BODY_ID 6
+#define HTML_BODY_LANG 7
+#define HTML_BODY_LINK 8
+#define HTML_BODY_ONLOAD 9
+#define HTML_BODY_ONUNLOAD 10
+#define HTML_BODY_STYLE 11
+#define HTML_BODY_TEXT 12
+#define HTML_BODY_TITLE 13
+#define HTML_BODY_VLINK 14
+#define HTML_BODY_ATTRIBUTES 15
+
+#define HTML_BODYTEXT_CLASS 0
+#define HTML_BODYTEXT_CLEAR 1
+#define HTML_BODYTEXT_DATA 2
+#define HTML_BODYTEXT_DIR 3
+#define HTML_BODYTEXT_ID 4
+#define HTML_BODYTEXT_LANG 5
+#define HTML_BODYTEXT_NAME 6
+#define HTML_BODYTEXT_OBJECT 7
+#define HTML_BODYTEXT_REF 8
+#define HTML_BODYTEXT_STYLE 9
+#define HTML_BODYTEXT_TITLE 10
+#define HTML_BODYTEXT_TYPE 11
+#define HTML_BODYTEXT_VALUE 12
+#define HTML_BODYTEXT_VALUETYPE 13
+#define HTML_BODYTEXT_ATTRIBUTES 14
+
+#define HTML_BQ_CLASS 0
+#define HTML_BQ_CLEAR 1
+#define HTML_BQ_DIR 2
+#define HTML_BQ_ID 3
+#define HTML_BQ_LANG 4
+#define HTML_BQ_NOWRAP 5
+#define HTML_BQ_STYLE 6
+#define HTML_BQ_TITLE 7
+#define HTML_BQ_ATTRIBUTES 8
+
+#define HTML_BUTTON_CLASS 0
+#define HTML_BUTTON_CLEAR 1
+#define HTML_BUTTON_DIR 2
+#define HTML_BUTTON_DISABLED 3
+#define HTML_BUTTON_ID 4
+#define HTML_BUTTON_LANG 5
+#define HTML_BUTTON_NAME 6
+#define HTML_BUTTON_ONFOCUS 7
+#define HTML_BUTTON_ONBLUR 8
+#define HTML_BUTTON_STYLE 9
+#define HTML_BUTTON_TABINDEX 10
+#define HTML_BUTTON_TITLE 11
+#define HTML_BUTTON_TYPE 12
+#define HTML_BUTTON_VALUE 13
+#define HTML_BUTTON_ATTRIBUTES 14
+
+#define HTML_CAPTION_ACCESSKEY 0
+#define HTML_CAPTION_ALIGN 1
+#define HTML_CAPTION_CLASS 2
+#define HTML_CAPTION_CLEAR 3
+#define HTML_CAPTION_DIR 4
+#define HTML_CAPTION_ID 5
+#define HTML_CAPTION_LANG 6
+#define HTML_CAPTION_STYLE 7
+#define HTML_CAPTION_TITLE 8
+#define HTML_CAPTION_ATTRIBUTES 9
+
+#define HTML_COL_ALIGN 0
+#define HTML_COL_CHAR 1
+#define HTML_COL_CHAROFF 2
+#define HTML_COL_CLASS 3
+#define HTML_COL_CLEAR 4
+#define HTML_COL_DIR 5
+#define HTML_COL_ID 6
+#define HTML_COL_LANG 7
+#define HTML_COL_SPAN 8
+#define HTML_COL_STYLE 9
+#define HTML_COL_TITLE 10
+#define HTML_COL_VALIGN 11
+#define HTML_COL_WIDTH 12
+#define HTML_COL_ATTRIBUTES 13
+
+#define HTML_CREDIT_CLASS 0
+#define HTML_CREDIT_CLEAR 1
+#define HTML_CREDIT_DIR 2
+#define HTML_CREDIT_ID 3
+#define HTML_CREDIT_LANG 4
+#define HTML_CREDIT_STYLE 5
+#define HTML_CREDIT_TITLE 6
+#define HTML_CREDIT_ATTRIBUTES 7
+
+#define HTML_DIV_ALIGN 0
+#define HTML_DIV_CLASS 1
+#define HTML_DIV_CLEAR 2
+#define HTML_DIV_DIR 3
+#define HTML_DIV_ID 4
+#define HTML_DIV_LANG 5
+#define HTML_DIV_STYLE 6
+#define HTML_DIV_TITLE 7
+#define HTML_DIV_ATTRIBUTES 8
+
+#define HTML_DL_CLASS 0
+#define HTML_DL_CLEAR 1
+#define HTML_DL_COMPACT 2
+#define HTML_DL_DIR 3
+#define HTML_DL_ID 4
+#define HTML_DL_LANG 5
+#define HTML_DL_STYLE 6
+#define HTML_DL_TITLE 7
+#define HTML_DL_ATTRIBUTES 8
+
+#define HTML_EMBED_ALIGN 0
+#define HTML_EMBED_ALT 1
+#define HTML_EMBED_BORDER 2
+#define HTML_EMBED_CLASS 3
+#define HTML_EMBED_CLEAR 4
+#define HTML_EMBED_DIR 5
+#define HTML_EMBED_HEIGHT 6
+#define HTML_EMBED_ID 7
+#define HTML_EMBED_IMAGEMAP 8
+#define HTML_EMBED_ISMAP 9
+#define HTML_EMBED_LANG 10
+#define HTML_EMBED_MD 11
+#define HTML_EMBED_NAME 12
+#define HTML_EMBED_NOFLOW 13
+#define HTML_EMBED_PARAMS 14
+#define HTML_EMBED_SRC 15
+#define HTML_EMBED_STYLE 16
+#define HTML_EMBED_TITLE 17
+#define HTML_EMBED_UNITS 18
+#define HTML_EMBED_USEMAP 19
+#define HTML_EMBED_WIDTH 20
+#define HTML_EMBED_ATTRIBUTES 21
+
+#define HTML_FIELDSET_CLASS 0
+#define HTML_FIELDSET_CLEAR 1
+#define HTML_FIELDSET_DIR 2
+#define HTML_FIELDSET_ID 3
+#define HTML_FIELDSET_LANG 4
+#define HTML_FIELDSET_STYLE 5
+#define HTML_FIELDSET_TITLE 6
+#define HTML_FIELDSET_ATTRIBUTES 7
+
+#define HTML_FIG_ALIGN 0
+#define HTML_FIG_BORDER 1
+#define HTML_FIG_CLASS 2
+#define HTML_FIG_CLEAR 3
+#define HTML_FIG_DIR 4
+#define HTML_FIG_HEIGHT 5
+#define HTML_FIG_ID 6
+#define HTML_FIG_IMAGEMAP 7
+#define HTML_FIG_ISOBJECT 8
+#define HTML_FIG_LANG 9
+#define HTML_FIG_MD 10
+#define HTML_FIG_NOFLOW 11
+#define HTML_FIG_SRC 12
+#define HTML_FIG_STYLE 13
+#define HTML_FIG_TITLE 14
+#define HTML_FIG_UNITS 15
+#define HTML_FIG_WIDTH 16
+#define HTML_FIG_ATTRIBUTES 17
+
+#define HTML_FN_CLASS 0
+#define HTML_FN_CLEAR 1
+#define HTML_FN_DIR 2
+#define HTML_FN_ID 3
+#define HTML_FN_LANG 4
+#define HTML_FN_STYLE 5
+#define HTML_FN_TITLE 6
+#define HTML_FN_ATTRIBUTES 7
+
+#define HTML_FONT_CLASS 0
+#define HTML_FONT_CLEAR 1
+#define HTML_FONT_COLOR 2
+#define HTML_FONT_DIR 3
+#define HTML_FONT_FACE 4
+#define HTML_FONT_ID 5
+#define HTML_FONT_LANG 6
+#define HTML_FONT_SIZE 7
+#define HTML_FONT_STYLE 8
+#define HTML_FONT_ATTRIBUTES 9
+
+#define HTML_FORM_ACCEPT_CHARSET 0 /* HTML 4.0 draft - kw */
+#define HTML_FORM_ACTION 1
+#define HTML_FORM_CLASS 2
+#define HTML_FORM_CLEAR 3
+#define HTML_FORM_DIR 4
+#define HTML_FORM_ENCTYPE 5
+#define HTML_FORM_ID 6
+#define HTML_FORM_LANG 7
+#define HTML_FORM_METHOD 8
+#define HTML_FORM_ONSUBMIT 9
+#define HTML_FORM_SCRIPT 10
+#define HTML_FORM_STYLE 11
+#define HTML_FORM_SUBJECT 12
+#define HTML_FORM_TARGET 13
+#define HTML_FORM_TITLE 14
+#define HTML_FORM_ATTRIBUTES 15
+
+#define HTML_FRAME_ID 0
+#define HTML_FRAME_MARGINHEIGHT 1
+#define HTML_FRAME_MARGINWIDTH 2
+#define HTML_FRAME_NAME 3
+#define HTML_FRAME_NORESIZE 4
+#define HTML_FRAME_SCROLLING 5
+#define HTML_FRAME_SRC 6
+#define HTML_FRAME_ATTRIBUTES 7
+
+#define HTML_FRAMESET_COLS 0
+#define HTML_FRAMESET_ROWS 1
+#define HTML_FRAMESET_ATTRIBUTES 2
+
+#define HTML_GEN_CLASS 0
+#define HTML_GEN_CLEAR 1
+#define HTML_GEN_DIR 2
+#define HTML_GEN_ID 3
+#define HTML_GEN_LANG 4
+#define HTML_GEN_STYLE 5
+#define HTML_GEN_TITLE 6
+#define HTML_GEN_ATTRIBUTES 7
+
+#define HTML_H_ALIGN 0
+#define HTML_H_CLASS 1
+#define HTML_H_CLEAR 2
+#define HTML_H_DINGBAT 3
+#define HTML_H_DIR 4
+#define HTML_H_ID 5
+#define HTML_H_LANG 6
+#define HTML_H_MD 7
+#define HTML_H_NOWRAP 8
+#define HTML_H_SEQNUM 9
+#define HTML_H_SKIP 10
+#define HTML_H_SRC 11
+#define HTML_H_STYLE 12
+#define HTML_H_TITLE 13
+#define HTML_H_ATTRIBUTES 14
+
+#define HTML_HR_ALIGN 0
+#define HTML_HR_CLASS 1
+#define HTML_HR_CLEAR 2
+#define HTML_HR_DIR 3
+#define HTML_HR_ID 4
+#define HTML_HR_MD 5
+#define HTML_HR_NOSHADE 6
+#define HTML_HR_SIZE 7
+#define HTML_HR_SRC 8
+#define HTML_HR_STYLE 9
+#define HTML_HR_TITLE 10
+#define HTML_HR_WIDTH 11
+#define HTML_HR_ATTRIBUTES 12
+
+#define HTML_IFRAME_ALIGN 0
+#define HTML_IFRAME_FRAMEBORDER 1
+#define HTML_IFRAME_HEIGHT 2
+#define HTML_IFRAME_ID 3
+#define HTML_IFRAME_MARGINHEIGHT 4
+#define HTML_IFRAME_MARGINWIDTH 5
+#define HTML_IFRAME_NAME 6
+#define HTML_IFRAME_SCROLLING 7
+#define HTML_IFRAME_SRC 8
+#define HTML_IFRAME_STYLE 9
+#define HTML_IFRAME_WIDTH 10
+#define HTML_IFRAME_ATTRIBUTES 11
+
+#define HTML_IMG_ALIGN 0
+#define HTML_IMG_ALT 1
+#define HTML_IMG_BORDER 2
+#define HTML_IMG_CLASS 3
+#define HTML_IMG_CLEAR 4
+#define HTML_IMG_DIR 5
+#define HTML_IMG_HEIGHT 6
+#define HTML_IMG_ID 7
+#define HTML_IMG_ISMAP 8
+#define HTML_IMG_ISOBJECT 9
+#define HTML_IMG_LANG 10
+#define HTML_IMG_MD 11
+#define HTML_IMG_SRC 12
+#define HTML_IMG_STYLE 13
+#define HTML_IMG_TITLE 14
+#define HTML_IMG_UNITS 15
+#define HTML_IMG_USEMAP 16
+#define HTML_IMG_WIDTH 17
+#define HTML_IMG_ATTRIBUTES 18
+
+#define HTML_INPUT_ACCEPT 0
+#define HTML_INPUT_ACCEPT_CHARSET 1 /* RFC 2070 HTML i18n - kw */
+#define HTML_INPUT_ALIGN 2
+#define HTML_INPUT_ALT 3
+#define HTML_INPUT_CHECKED 4
+#define HTML_INPUT_CLASS 5
+#define HTML_INPUT_CLEAR 6
+#define HTML_INPUT_DIR 7
+#define HTML_INPUT_DISABLED 8
+#define HTML_INPUT_ERROR 9
+#define HTML_INPUT_HEIGHT 10
+#define HTML_INPUT_ID 11
+#define HTML_INPUT_LANG 12
+#define HTML_INPUT_MAX 13
+#define HTML_INPUT_MAXLENGTH 14
+#define HTML_INPUT_MD 15
+#define HTML_INPUT_MIN 16
+#define HTML_INPUT_NAME 17
+#define HTML_INPUT_NOTAB 18
+#define HTML_INPUT_ONBLUR 19
+#define HTML_INPUT_ONCHANGE 20
+#define HTML_INPUT_ONCLICK 21
+#define HTML_INPUT_ONFOCUS 22
+#define HTML_INPUT_ONSELECT 23
+#define HTML_INPUT_SIZE 24
+#define HTML_INPUT_SRC 25
+#define HTML_INPUT_STYLE 26
+#define HTML_INPUT_TABINDEX 27
+#define HTML_INPUT_TITLE 28
+#define HTML_INPUT_TYPE 29
+#define HTML_INPUT_VALUE 30
+#define HTML_INPUT_WIDTH 31
+#define HTML_INPUT_ATTRIBUTES 32
+
+#define HTML_ISINDEX_ACTION 0 /* Treat as synonym for HREF. - FM */
+#define HTML_ISINDEX_DIR 1
+#define HTML_ISINDEX_HREF 2 /* HTML 3.0 "action". - FM */
+#define HTML_ISINDEX_ID 3
+#define HTML_ISINDEX_LANG 4
+#define HTML_ISINDEX_PROMPT 5 /* HTML 3.0 "prompt". - FM */
+#define HTML_ISINDEX_TITLE 6
+#define HTML_ISINDEX_ATTRIBUTES 7
+
+#define HTML_KEYGEN_CHALLENGE 0
+#define HTML_KEYGEN_CLASS 1
+#define HTML_KEYGEN_DIR 2
+#define HTML_KEYGEN_ID 3
+#define HTML_KEYGEN_LANG 4
+#define HTML_KEYGEN_NAME 5
+#define HTML_KEYGEN_STYLE 6
+#define HTML_KEYGEN_TITLE 7
+#define HTML_KEYGEN_ATTRIBUTES 8
+
+#define HTML_LABEL_ACCESSKEY 0
+#define HTML_LABEL_CLASS 1
+#define HTML_LABEL_CLEAR 2
+#define HTML_LABEL_DIR 3
+#define HTML_LABEL_FOR 4
+#define HTML_LABEL_ID 5
+#define HTML_LABEL_LANG 6
+#define HTML_LABEL_ONCLICK 7
+#define HTML_LABEL_STYLE 8
+#define HTML_LABEL_TITLE 9
+#define HTML_LABEL_ATTRIBUTES 10
+
+#define HTML_LEGEND_ACCESSKEY 0
+#define HTML_LEGEND_ALIGN 1
+#define HTML_LEGEND_CLASS 2
+#define HTML_LEGEND_CLEAR 3
+#define HTML_LEGEND_DIR 4
+#define HTML_LEGEND_ID 5
+#define HTML_LEGEND_LANG 6
+#define HTML_LEGEND_STYLE 7
+#define HTML_LEGEND_TITLE 8
+#define HTML_LEGEND_ATTRIBUTES 9
+
+#define HTML_LI_CLASS 0
+#define HTML_LI_CLEAR 1
+#define HTML_LI_DINGBAT 2
+#define HTML_LI_DIR 3
+#define HTML_LI_ID 4
+#define HTML_LI_LANG 5
+#define HTML_LI_MD 6
+#define HTML_LI_SKIP 7
+#define HTML_LI_SRC 8
+#define HTML_LI_STYLE 9
+#define HTML_LI_TITLE 10
+#define HTML_LI_TYPE 11
+#define HTML_LI_VALUE 12
+#define HTML_LI_ATTRIBUTES 13
+
+#define HTML_LINK_CHARSET 0 /* RFC 2070 HTML i18n - kw */
+#define HTML_LINK_CLASS 1
+#define HTML_LINK_HREF 2
+#define HTML_LINK_ID 3
+#define HTML_LINK_MEDIA 4
+#define HTML_LINK_REL 5
+#define HTML_LINK_REV 6
+#define HTML_LINK_STYLE 7
+#define HTML_LINK_TARGET 8
+#define HTML_LINK_TITLE 9
+#define HTML_LINK_TYPE 10
+#define HTML_LINK_ATTRIBUTES 11
+
+#define HTML_MAP_CLASS 0
+#define HTML_MAP_CLEAR 1
+#define HTML_MAP_DIR 2
+#define HTML_MAP_ID 3
+#define HTML_MAP_LANG 4
+#define HTML_MAP_NAME 5
+#define HTML_MAP_STYLE 6
+#define HTML_MAP_TITLE 7
+#define HTML_MAP_ATTRIBUTES 8
+
+#define HTML_MATH_BOX 0
+#define HTML_MATH_CLASS 1
+#define HTML_MATH_CLEAR 2
+#define HTML_MATH_DIR 3
+#define HTML_MATH_ID 4
+#define HTML_MATH_LANG 5
+#define HTML_MATH_STYLE 6
+#define HTML_MATH_TITLE 7
+#define HTML_MATH_ATTRIBUTES 8
+
+#define HTML_META_CONTENT 0
+#define HTML_META_HTTP_EQUIV 1 /* For parsing in HTML.c - FM */
+#define HTML_META_NAME 2
+#define HTML_META_ATTRIBUTES 3
+
+#define NEXTID_N 0
+
+#define HTML_NOTE_CLASS 0
+#define HTML_NOTE_CLEAR 1
+#define HTML_NOTE_DIR 2
+#define HTML_NOTE_ID 3
+#define HTML_NOTE_LANG 4
+#define HTML_NOTE_MD 5
+#define HTML_NOTE_ROLE 6 /* Old name for CLASS - FM */
+#define HTML_NOTE_SRC 7
+#define HTML_NOTE_STYLE 8
+#define HTML_NOTE_TITLE 9
+#define HTML_NOTE_ATTRIBUTES 10
+
+#define HTML_OBJECT_ALIGN 0
+#define HTML_OBJECT_BORDER 1
+#define HTML_OBJECT_CLASS 2
+#define HTML_OBJECT_CLASSID 3
+#define HTML_OBJECT_CODEBASE 4
+#define HTML_OBJECT_CODETYPE 5
+#define HTML_OBJECT_DATA 6
+#define HTML_OBJECT_DECLARE 7
+#define HTML_OBJECT_DIR 8
+#define HTML_OBJECT_HEIGHT 9
+#define HTML_OBJECT_HSPACE 10
+#define HTML_OBJECT_ID 11
+#define HTML_OBJECT_ISMAP 12
+#define HTML_OBJECT_LANG 13
+#define HTML_OBJECT_NAME 14
+#define HTML_OBJECT_NOTAB 15
+#define HTML_OBJECT_SHAPES 16
+#define HTML_OBJECT_STANDBY 17
+#define HTML_OBJECT_STYLE 18
+#define HTML_OBJECT_TABINDEX 19
+#define HTML_OBJECT_TITLE 20
+#define HTML_OBJECT_TYPE 21
+#define HTML_OBJECT_USEMAP 22
+#define HTML_OBJECT_VSPACE 23
+#define HTML_OBJECT_WIDTH 24
+#define HTML_OBJECT_ATTRIBUTES 25
+
+#define HTML_OL_CLASS 0
+#define HTML_OL_CLEAR 1
+#define HTML_OL_COMPACT 2
+#define HTML_OL_CONTINUE 3
+#define HTML_OL_DIR 4
+#define HTML_OL_ID 5
+#define HTML_OL_LANG 6
+#define HTML_OL_SEQNUM 7
+#define HTML_OL_START 8
+#define HTML_OL_STYLE 9
+#define HTML_OL_TITLE 10
+#define HTML_OL_TYPE 11
+#define HTML_OL_ATTRIBUTES 12
+
+#define HTML_OPTION_CLASS 0
+#define HTML_OPTION_CLEAR 1
+#define HTML_OPTION_DIR 2
+#define HTML_OPTION_DISABLED 3
+#define HTML_OPTION_ERROR 4
+#define HTML_OPTION_ID 5
+#define HTML_OPTION_LANG 6
+#define HTML_OPTION_SELECTED 7
+#define HTML_OPTION_SHAPE 8
+#define HTML_OPTION_STYLE 9
+#define HTML_OPTION_TITLE 10
+#define HTML_OPTION_VALUE 11
+#define HTML_OPTION_ATTRIBUTES 12
+
+#define HTML_OVERLAY_CLASS 0
+#define HTML_OVERLAY_HEIGHT 1
+#define HTML_OVERLAY_ID 2
+#define HTML_OVERLAY_IMAGEMAP 3
+#define HTML_OVERLAY_MD 4
+#define HTML_OVERLAY_SRC 5
+#define HTML_OVERLAY_STYLE 6
+#define HTML_OVERLAY_TITLE 7
+#define HTML_OVERLAY_UNITS 8
+#define HTML_OVERLAY_WIDTH 9
+#define HTML_OVERLAY_X 10
+#define HTML_OVERLAY_Y 11
+#define HTML_OVERLAY_ATTRIBUTES 12
+
+#define HTML_P_ALIGN 0
+#define HTML_P_CLASS 1
+#define HTML_P_CLEAR 2
+#define HTML_P_DIR 3
+#define HTML_P_ID 4
+#define HTML_P_LANG 5
+#define HTML_P_NOWRAP 6
+#define HTML_P_STYLE 7
+#define HTML_P_TITLE 8
+#define HTML_P_ATTRIBUTES 9
+
+#define HTML_PARAM_ACCEPT 0
+#define HTML_PARAM_ACCEPT_CHARSET 1
+#define HTML_PARAM_ACCEPT_ENCODING 2
+#define HTML_PARAM_CLASS 3
+#define HTML_PARAM_CLEAR 4
+#define HTML_PARAM_DATA 5
+#define HTML_PARAM_DIR 6
+#define HTML_PARAM_ID 7
+#define HTML_PARAM_LANG 8
+#define HTML_PARAM_NAME 9
+#define HTML_PARAM_OBJECT 10
+#define HTML_PARAM_REF 11
+#define HTML_PARAM_STYLE 12
+#define HTML_PARAM_TITLE 13
+#define HTML_PARAM_TYPE 14
+#define HTML_PARAM_VALUE 15
+#define HTML_PARAM_VALUEREF 16 /* Use VALUETYPE (DATA|REF|OBJECT). - FM */
+#define HTML_PARAM_VALUETYPE 17
+#define HTML_PARAM_ATTRIBUTES 18
+
+#define HTML_SCRIPT_CLASS 0
+#define HTML_SCRIPT_CLEAR 1
+#define HTML_SCRIPT_DIR 2
+#define HTML_SCRIPT_EVENT 3
+#define HTML_SCRIPT_FOR 4
+#define HTML_SCRIPT_ID 5
+#define HTML_SCRIPT_LANG 6
+#define HTML_SCRIPT_LANGUAGE 7
+#define HTML_SCRIPT_NAME 8
+#define HTML_SCRIPT_SCRIPTENGINE 9
+#define HTML_SCRIPT_SRC 10
+#define HTML_SCRIPT_STYLE 11
+#define HTML_SCRIPT_TITLE 12
+#define HTML_SCRIPT_TYPE 13
+#define HTML_SCRIPT_ATTRIBUTES 14
+
+#define HTML_SELECT_ALIGN 0
+#define HTML_SELECT_CLASS 1
+#define HTML_SELECT_CLEAR 2
+#define HTML_SELECT_DIR 3
+#define HTML_SELECT_DISABLED 4
+#define HTML_SELECT_ERROR 5
+#define HTML_SELECT_HEIGHT 6
+#define HTML_SELECT_ID 7
+#define HTML_SELECT_LANG 8
+#define HTML_SELECT_MD 9
+#define HTML_SELECT_MULTIPLE 10
+#define HTML_SELECT_NAME 11
+#define HTML_SELECT_NOTAB 12
+#define HTML_SELECT_ONBLUR 13
+#define HTML_SELECT_ONCHANGE 14
+#define HTML_SELECT_ONFOCUS 15
+#define HTML_SELECT_SIZE 16
+#define HTML_SELECT_STYLE 17
+#define HTML_SELECT_TABINDEX 18
+#define HTML_SELECT_TITLE 19
+#define HTML_SELECT_UNITS 20
+#define HTML_SELECT_WIDTH 21
+#define HTML_SELECT_ATTRIBUTES 22
+
+#define HTML_STYLE_DIR 0
+#define HTML_STYLE_LANG 1
+#define HTML_STYLE_NOTATION 2
+#define HTML_STYLE_TITLE 3
+#define HTML_STYLE_ATTRIBUTES 4
+
+#define HTML_TAB_ALIGN 0
+#define HTML_TAB_CLASS 1
+#define HTML_TAB_CLEAR 2
+#define HTML_TAB_DIR 3
+#define HTML_TAB_DP 4
+#define HTML_TAB_ID 5
+#define HTML_TAB_INDENT 6
+#define HTML_TAB_LANG 7
+#define HTML_TAB_STYLE 8
+#define HTML_TAB_TITLE 9
+#define HTML_TAB_TO 10
+#define HTML_TAB_ATTRIBUTES 11
+
+#define HTML_TABLE_ALIGN 0
+#define HTML_TABLE_BORDER 1
+#define HTML_TABLE_CELLPADDING 2
+#define HTML_TABLE_CELLSPACING 3
+#define HTML_TABLE_CLASS 4
+#define HTML_TABLE_CLEAR 5
+#define HTML_TABLE_COLS 6
+#define HTML_TABLE_COLSPEC 7
+#define HTML_TABLE_DIR 8
+#define HTML_TABLE_DP 9
+#define HTML_TABLE_FRAME 10
+#define HTML_TABLE_ID 11
+#define HTML_TABLE_LANG 12
+#define HTML_TABLE_NOFLOW 13
+#define HTML_TABLE_NOWRAP 14
+#define HTML_TABLE_RULES 15
+#define HTML_TABLE_STYLE 16
+#define HTML_TABLE_TITLE 17
+#define HTML_TABLE_UNITS 18
+#define HTML_TABLE_WIDTH 19
+#define HTML_TABLE_ATTRIBUTES 20
+
+#define HTML_TD_ALIGN 0
+#define HTML_TD_AXES 1
+#define HTML_TD_AXIS 2
+#define HTML_TD_CHAR 3
+#define HTML_TD_CHAROFF 4
+#define HTML_TD_CLASS 5
+#define HTML_TD_CLEAR 6
+#define HTML_TD_COLSPAN 7
+#define HTML_TD_DIR 8
+#define HTML_TD_DP 9
+#define HTML_TD_ID 10
+#define HTML_TD_LANG 11
+#define HTML_TD_NOWRAP 12
+#define HTML_TD_ROWSPAN 13
+#define HTML_TD_STYLE 14
+#define HTML_TD_TITLE 15
+#define HTML_TD_VALIGN 16
+#define HTML_TD_ATTRIBUTES 17
+
+#define HTML_TEXTAREA_ACCEPT_CHARSET 0 /* RFC 2070 HTML i18n - kw */
+#define HTML_TEXTAREA_ALIGN 1
+#define HTML_TEXTAREA_CLASS 2
+#define HTML_TEXTAREA_CLEAR 3
+#define HTML_TEXTAREA_COLS 4
+#define HTML_TEXTAREA_DIR 5
+#define HTML_TEXTAREA_DISABLED 6
+#define HTML_TEXTAREA_ERROR 7
+#define HTML_TEXTAREA_ID 8
+#define HTML_TEXTAREA_LANG 9
+#define HTML_TEXTAREA_NAME 10
+#define HTML_TEXTAREA_NOTAB 11
+#define HTML_TEXTAREA_ONBLUR 12
+#define HTML_TEXTAREA_ONCHANGE 13
+#define HTML_TEXTAREA_ONFOCUS 14
+#define HTML_TEXTAREA_ONSELECT 15
+#define HTML_TEXTAREA_ROWS 16
+#define HTML_TEXTAREA_STYLE 17
+#define HTML_TEXTAREA_TABINDEX 18
+#define HTML_TEXTAREA_TITLE 19
+#define HTML_TEXTAREA_ATTRIBUTES 20
+
+#define HTML_TR_ALIGN 0
+#define HTML_TR_CHAR 1
+#define HTML_TR_CHAROFF 2
+#define HTML_TR_CLASS 3
+#define HTML_TR_CLEAR 4
+#define HTML_TR_DIR 5
+#define HTML_TR_DP 6
+#define HTML_TR_ID 7
+#define HTML_TR_LANG 8
+#define HTML_TR_NOWRAP 9
+#define HTML_TR_STYLE 10
+#define HTML_TR_TITLE 11
+#define HTML_TR_VALIGN 12
+#define HTML_TR_ATTRIBUTES 13
+
+#define HTML_UL_CLASS 0
+#define HTML_UL_CLEAR 1
+#define HTML_UL_COMPACT 2
+#define HTML_UL_DINGBAT 3
+#define HTML_UL_DIR 4
+#define HTML_UL_ID 5
+#define HTML_UL_LANG 6
+#define HTML_UL_MD 7
+#define HTML_UL_PLAIN 8
+#define HTML_UL_SRC 9
+#define HTML_UL_STYLE 10
+#define HTML_UL_TITLE 11
+#define HTML_UL_TYPE 12
+#define HTML_UL_WRAP 13
+#define HTML_UL_ATTRIBUTES 14
+
+extern CONST SGML_dtd HTML_dtd;
+
+extern void HTSwitchDTD PARAMS((
+ BOOL new));
+
+extern CONST HTTag HTTag_unrecognized;
+
+/*
+
+Start anchor element
+
+ It is kinda convenient to have a particular routine for starting an anchor
+ element, as everything else for HTML is simple anyway.
+
+ ON ENTRY
+
+ targetstream points to a structured stream object.
+
+ name and href point to attribute strings or are NULL if the attribute is
+ to be omitted.
+
+ */
+extern void HTStartAnchor PARAMS((
+ HTStructured * targetstream,
+ CONST char * name,
+ CONST char * href));
+
+/*
+
+Start IsIndex element - FM
+
+ It is kinda convenient to have a particular routine for starting an IsIndex
+ element with the prompt and/or href (action) attributes specified.
+
+ ON ENTRY
+
+ targetstream points to a structured stream object.
+
+ prompt and href point to attribute strings or are NULL if the attribute is
+ to be omitted.
+
+ */
+extern void HTStartIsIndex PARAMS((
+ HTStructured * targetstream,
+ CONST char * prompt,
+ CONST char * href));
+
+
+#endif /* HTMLDTD_H */
+
+/*
+
+ End of module definition */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.c
new file mode 100644
index 00000000000..1839f3c41a1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.c
@@ -0,0 +1,544 @@
+/* HTML Generator
+** ==============
+**
+** This version of the HTML object sends HTML markup to the output stream.
+**
+** Bugs: Line wrapping is not done at all.
+** All data handled as PCDATA.
+** Should convert old XMP, LISTING and PLAINTEXT to PRE.
+**
+** It is not obvious to me right now whether the HEAD should be generated
+** from the incomming data or the anchor. Currently it is from the former
+** which is cleanest.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+#define BUFFER_SIZE 200 /* Line buffer attempts to make neat breaks */
+#define MAX_CLEANNESS 20
+
+/* Implements:
+*/
+#include "HTMLGen.h"
+
+#include <stdio.h>
+#include "HTMLDTD.h"
+#include "HTStream.h"
+#include "SGML.h"
+#include "HTFormat.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define PUTC(c) (*me->targetClass.put_character)(me->target, c)
+/* #define PUTS(s) (*me->targetClass.put_string)(me->target, s) */
+#define PUTB(s,l) (*me->targetClass.put_block)(me->target, s, l)
+
+/* HTML Object
+** -----------
+*/
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ HTStream * target;
+ HTStreamClass targetClass; /* COPY for speed */
+};
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ HTStream * target;
+ HTStreamClass targetClass; /* COPY for speed */
+
+ char buffer[BUFFER_SIZE+1]; /* 1for NL */
+ int buffer_maxchars;
+ char * write_pointer;
+ char * line_break [MAX_CLEANNESS+1];
+ int cleanness;
+ BOOL overflowed;
+ BOOL delete_line_break_char[MAX_CLEANNESS+1];
+ BOOL preformatted;
+ BOOL escape_specials;
+ BOOL in_attrval;
+};
+
+/* Flush Buffer
+** ------------
+*/
+
+PRIVATE void flush_breaks ARGS1(
+ HTStructured *, me)
+{
+ int i;
+ for (i=0; i<= MAX_CLEANNESS; i++) {
+ me->line_break[i] = NULL;
+ }
+}
+
+PRIVATE void HTMLGen_flush ARGS1(
+ HTStructured *, me)
+{
+ (*me->targetClass.put_block)(me->target,
+ me->buffer,
+ me->write_pointer - me->buffer);
+ me->write_pointer = me->buffer;
+ flush_breaks(me);
+ me->cleanness = 0;
+ me->delete_line_break_char[0] = NO;
+}
+
+/* Weighted optional line break
+**
+** We keep track of all the breaks for when we chop the line
+*/
+
+PRIVATE void allow_break ARGS3(
+ HTStructured *, me,
+ int, new_cleanness,
+ BOOL, dlbc)
+{
+ if (dlbc && me->write_pointer == me->buffer) dlbc = NO;
+ me->line_break[new_cleanness] =
+ dlbc ? me->write_pointer - 1 /* Point to space */
+ : me->write_pointer ; /* point to gap */
+ me->delete_line_break_char[new_cleanness] = dlbc;
+ if (new_cleanness >= me->cleanness &&
+ (me->overflowed || me->line_break[new_cleanness] > me->buffer))
+ me->cleanness = new_cleanness;
+}
+
+/* Character handling
+** ------------------
+**
+** The tricky bits are the line break handling. This attempts
+** to synchrononise line breaks on sentence or phrase ends. This
+** is important if one stores SGML files in a line-oriented code
+** repository, so that if a small change is made, line ends don't
+** shift in a ripple-through to apparently change a large part of the
+** file. We give extra "cleanness" to spaces appearing directly
+** after periods (full stops), [semi]colons and commas.
+** This should make the source files easier to read and modify
+** by hand, too, though this is not a primary design consideration. TBL
+*/
+PRIVATE void HTMLGen_put_character ARGS2(
+ HTStructured *, me,
+ char, c)
+{
+ if (me->escape_specials && (unsigned char)c < 32) {
+ if (c == HT_NON_BREAK_SPACE || c == HT_EM_SPACE ||
+ c == LY_SOFT_HYPHEN) { /* recursion... */
+ HTMLGen_put_character(me, '&');
+ HTMLGen_put_character(me, '#');
+ HTMLGen_put_character(me, 'x');
+ switch(c) {
+ case HT_NON_BREAK_SPACE: /* &#xA0; */
+ HTMLGen_put_character(me, 'A');
+ HTMLGen_put_character(me, '0');
+ break;
+ case HT_EM_SPACE: /* &#x2003; */
+ HTMLGen_put_character(me, '2');
+ HTMLGen_put_character(me, '0');
+ HTMLGen_put_character(me, '0');
+ HTMLGen_put_character(me, '3');
+ break;
+ case LY_SOFT_HYPHEN: /* &#xAD; */
+ HTMLGen_put_character(me, 'A');
+ HTMLGen_put_character(me, 'D');
+ break;
+ }
+ c = ';';
+ }
+ }
+
+ *me->write_pointer++ = c;
+
+ if (c == '\n') {
+ HTMLGen_flush(me);
+ return;
+ }
+
+ /* Figure our whether we can break at this point
+ */
+ if ((!me->preformatted && (c == ' ' || c == '\t'))) {
+ int new_cleanness = 3;
+ if (me->write_pointer > (me->buffer + 1)) {
+ char delims[5];
+ char * p;
+ strcpy(delims, ",;:."); /* @@ english bias */
+ p = strchr(delims, me->write_pointer[-2]);
+ if (p) new_cleanness = p - delims + 6;
+ if (!me->in_attrval) new_cleanness += 10;
+ }
+ allow_break(me, new_cleanness, YES);
+ }
+
+ /*
+ * Flush buffer out when full, or whenever the line is over
+ * the nominal maximum and we can break at all
+ */
+ if (me->write_pointer >= me->buffer + me->buffer_maxchars ||
+ (me->overflowed && me->cleanness)) {
+ if (me->cleanness) {
+ char line_break_char = me->line_break[me->cleanness][0];
+ char * saved = me->line_break[me->cleanness];
+
+ if (me->delete_line_break_char[me->cleanness]) saved++;
+ me->line_break[me->cleanness][0] = '\n';
+ (*me->targetClass.put_block)(me->target,
+ me->buffer,
+ me->line_break[me->cleanness] - me->buffer + 1);
+ me->line_break[me->cleanness][0] = line_break_char;
+ { /* move next line in */
+ char * p = saved;
+ char *q;
+ for (q = me->buffer; p < me->write_pointer; )
+ *q++ = *p++;
+ }
+ me->cleanness = 0;
+ /* Now we have to check whether ther are any perfectly good breaks
+ ** which weren't good enough for the last line but may be
+ ** good enough for the next
+ */
+ {
+ int i;
+ for(i=0; i <= MAX_CLEANNESS; i++) {
+ if (me->line_break[i] != NULL &&
+ me->line_break[i] > saved) {
+ me->line_break[i] = me->line_break[i] -
+ (saved-me->buffer);
+ me->cleanness = i;
+ } else {
+ me->line_break[i] = NULL;
+ }
+ }
+ }
+
+ me->delete_line_break_char[0] = 0;
+ me->write_pointer = me->write_pointer - (saved-me->buffer);
+ me->overflowed = NO;
+
+ } else {
+ (*me->targetClass.put_block)(me->target,
+ me->buffer,
+ me->buffer_maxchars);
+ me->write_pointer = me->buffer;
+ flush_breaks(me);
+ me->overflowed = YES;
+ }
+ }
+}
+
+/* String handling
+** ---------------
+*/
+PRIVATE void HTMLGen_put_string ARGS2(
+ HTStructured *, me,
+ CONST char *, s)
+{
+ CONST char * p;
+
+ for (p = s; *p; p++)
+ HTMLGen_put_character(me, *p);
+}
+
+PRIVATE void HTMLGen_write ARGS3(
+ HTStructured *, me,
+ CONST char *, s,
+ int, l)
+{
+ CONST char * p;
+
+ for (p = s; p < (s + l); p++)
+ HTMLGen_put_character(me, *p);
+}
+
+/* Start Element
+** -------------
+**
+** Within the opening tag, there may be spaces
+** and the line may be broken at these spaces.
+*/
+PRIVATE void HTMLGen_start_element ARGS6(
+ HTStructured *, me,
+ int, element_number,
+ CONST BOOL*, present,
+ CONST char **, value,
+ int, charset GCC_UNUSED,
+ char **, insert GCC_UNUSED)
+{
+ int i;
+ BOOL was_preformatted = me->preformatted;
+ HTTag * tag = &HTML_dtd.tags[element_number];
+
+ me->preformatted = YES; /* free text within tags */
+ HTMLGen_put_character(me, '<');
+ HTMLGen_put_string(me, tag->name);
+ if (present) {
+ BOOL had_attr = NO;
+ for (i = 0; i < tag->number_of_attributes; i++) {
+ if (present[i]) {
+ had_attr = YES;
+ HTMLGen_put_character(me, ' ');
+ allow_break(me, 11, YES);
+ HTMLGen_put_string(me, tag->attributes[i].name);
+ if (value[i]) {
+ me->preformatted = was_preformatted;
+ me->in_attrval = YES;
+ if (strchr(value[i], '"') == NULL) {
+ HTMLGen_put_string(me, "=\"");
+ HTMLGen_put_string(me, value[i]);
+ HTMLGen_put_character(me, '"');
+ } else if (strchr(value[i], '\'') == NULL) {
+ HTMLGen_put_string(me, "='");
+ HTMLGen_put_string(me, value[i]);
+ HTMLGen_put_character(me, '\'');
+ } else { /* attribute value has both kinds of quotes */
+ CONST char *p;
+ HTMLGen_put_string(me, "=\"");
+ for (p = value[i]; *p; p++) {
+ if (*p != '"') {
+ HTMLGen_put_character(me, *p);
+ } else {
+ HTMLGen_put_string(me, "&#34;");
+ }
+ }
+ HTMLGen_put_character(me, '"');
+ }
+ me->preformatted = YES;
+ me->in_attrval = NO;
+ }
+ }
+ }
+ if (had_attr)
+ allow_break(me, 12, NO);
+ }
+ HTMLGen_put_string(me, ">"); /* got rid of \n LJM */
+
+ /*
+ * Make very specific HTML assumption that PRE can't be nested!
+ */
+ me->preformatted = (element_number == HTML_PRE) ? YES : was_preformatted;
+
+ /*
+ * Can break after element start.
+ */
+ if (!me->preformatted && tag->contents != SGML_EMPTY) {
+ if (HTML_dtd.tags[element_number].contents == SGML_ELEMENT)
+ allow_break(me, 15, NO);
+ else
+ allow_break(me, 2, NO);
+ }
+}
+
+/* End Element
+** -----------
+**
+*/
+/* When we end an element, the style must be returned to that
+** in effect before that element. Note that anchors (etc?)
+** don't have an associated style, so that we must scan down the
+** stack for an element with a defined style. (In fact, the styles
+** should be linked to the whole stack not just the top one.)
+** TBL 921119
+*/
+PRIVATE void HTMLGen_end_element ARGS3(
+ HTStructured *, me,
+ int, element_number,
+ char **, insert GCC_UNUSED)
+{
+ if (!me->preformatted &&
+ HTML_dtd.tags[element_number].contents != SGML_EMPTY) {
+ /*
+ * Can break before element end.
+ */
+ if (HTML_dtd.tags[element_number].contents == SGML_ELEMENT)
+ allow_break(me, 14, NO);
+ else
+ allow_break(me, 1, NO);
+ }
+ HTMLGen_put_string(me, "</");
+ HTMLGen_put_string(me, HTML_dtd.tags[element_number].name);
+ HTMLGen_put_character(me, '>');
+ if (element_number == HTML_PRE) {
+ me->preformatted = NO;
+ }
+}
+
+/* Expanding entities
+** ------------------
+**
+*/
+PRIVATE int HTMLGen_put_entity ARGS2(
+ HTStructured *, me,
+ int, entity_number)
+{
+ int nent = HTML_dtd.number_of_entities;
+
+ HTMLGen_put_character(me, '&');
+ if (entity_number < nent) {
+ HTMLGen_put_string(me, HTML_dtd.entity_names[entity_number]);
+ }
+ HTMLGen_put_character(me, ';');
+ return HT_OK;
+}
+
+/* Free an HTML object
+** -------------------
+**
+*/
+PRIVATE void HTMLGen_free ARGS1(
+ HTStructured *, me)
+{
+ (*me->targetClass.put_character)(me->target, '\n');
+ HTMLGen_flush(me);
+ (*me->targetClass._free)(me->target); /* ripple through */
+ FREE(me);
+}
+
+PRIVATE void PlainToHTML_free ARGS1(
+ HTStructured *, me)
+{
+ HTMLGen_end_element(me, HTML_PRE, 0);
+ HTMLGen_free(me);
+}
+
+PRIVATE void HTMLGen_abort ARGS2(
+ HTStructured *, me,
+ HTError, e GCC_UNUSED)
+{
+ HTMLGen_free(me);
+}
+
+PRIVATE void PlainToHTML_abort ARGS2(
+ HTStructured *, me,
+ HTError, e GCC_UNUSED)
+{
+ PlainToHTML_free(me);
+}
+
+/* Structured Object Class
+** -----------------------
+*/
+PRIVATE CONST HTStructuredClass HTMLGeneration = /* As opposed to print etc */
+{
+ "HTMLGen",
+ HTMLGen_free,
+ HTMLGen_abort,
+ HTMLGen_put_character, HTMLGen_put_string, HTMLGen_write,
+ HTMLGen_start_element, HTMLGen_end_element,
+ HTMLGen_put_entity
+};
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+extern int LYcols; /* LYCurses.h, set in LYMain.c */
+extern BOOL dump_output_immediately; /* TRUE if no interactive user */
+extern int dump_output_width; /* -width instead of 80 */
+extern BOOLEAN LYPreparsedSource; /* Show source as preparsed? */
+
+PUBLIC HTStructured * HTMLGenerator ARGS1(
+ HTStream *, output)
+{
+ HTStructured* me = (HTStructured*)malloc(sizeof(*me));
+ if (me == NULL)
+ outofmem(__FILE__, "HTMLGenerator");
+ me->isa = &HTMLGeneration;
+
+ me->target = output;
+ me->targetClass = *me->target->isa; /* Copy pointers to routines for speed*/
+
+ me->write_pointer = me->buffer;
+ flush_breaks(me);
+ me->line_break[0] = me->buffer;
+ me->cleanness = 0;
+ me->overflowed = NO;
+ me->delete_line_break_char[0] = NO;
+ me->preformatted = NO;
+ me->in_attrval = NO;
+
+ /*
+ * For what line length should we attempt to wrap ? - kw
+ */
+ if (!LYPreparsedSource) {
+ me->buffer_maxchars = 80; /* work as before - kw */
+ } else if (dump_output_width > 1) {
+ me->buffer_maxchars = dump_output_width; /* try to honor -width - kw */
+ } else if (dump_output_immediately) {
+ me->buffer_maxchars = 80; /* try to honor -width - kw */
+ } else {
+ me->buffer_maxchars = LYcols - 2;
+ if (me->buffer_maxchars < 38) /* too narrow, let GridText deal */
+ me->buffer_maxchars = 40;
+ }
+ if (me->buffer_maxchars > 900) /* likely not true - kw */
+ me->buffer_maxchars = 78;
+ if (me->buffer_maxchars > BUFFER_SIZE) /* must not be larger! */
+ me->buffer_maxchars = BUFFER_SIZE - 2;
+
+ /*
+ * If dump_output_immediately is set, there likely isn't anything
+ * after this stream to interpret the Lynx special chars. Also
+ * if they get displayed via HTPlain, that will probably make
+ * non-breaking space chars etc. invisible. So let's translate
+ * them to numerical character references. For debugging
+ * purposes we'll use the new hex format.
+ */
+ me->escape_specials = LYPreparsedSource;
+
+ return me;
+}
+
+/* Stream Object Class
+** -------------------
+**
+** This object just converts a plain text stream into HTML
+** It is officially a structured strem but only the stream bits exist.
+** This is just the easiest way of typecasting all the routines.
+*/
+PRIVATE CONST HTStructuredClass PlainToHTMLConversion =
+{
+ "plaintexttoHTML",
+ HTMLGen_free,
+ PlainToHTML_abort,
+ HTMLGen_put_character,
+ HTMLGen_put_string,
+ HTMLGen_write,
+ NULL, /* Structured stuff */
+ NULL,
+ NULL
+};
+
+/* HTConverter from plain text to HTML Stream
+** ------------------------------------------
+*/
+PUBLIC HTStream* HTPlainToHTML ARGS3(
+ HTPresentation *, pres GCC_UNUSED,
+ HTParentAnchor *, anchor GCC_UNUSED,
+ HTStream *, sink)
+{
+ HTStructured *me = (HTStructured *)malloc(sizeof(*me));
+ if (me == NULL)
+ outofmem(__FILE__, "PlainToHTML");
+ me->isa = (CONST HTStructuredClass *)&PlainToHTMLConversion;
+
+ /*
+ * Copy pointers to routines for speed.
+ */
+ me->target = sink;
+ me->targetClass = *me->target->isa;
+ me->write_pointer = me->buffer;
+ flush_breaks(me);
+ me->cleanness = 0;
+ me->overflowed = NO;
+ me->delete_line_break_char[0] = NO;
+ /* try to honor -width - kw */
+ me->buffer_maxchars = (dump_output_width > 1 ?
+ dump_output_width : 80);
+
+ HTMLGen_put_string(me, "<HTML>\n<BODY>\n<PRE>\n");
+ me->preformatted = YES;
+ me->escape_specials = NO;
+ me->in_attrval = NO;
+ return (HTStream*) me;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.h
new file mode 100644
index 00000000000..ac814ad882a
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTMLGen.h
@@ -0,0 +1,32 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTMLGen.html
+ HTML GENERATOR
+
+ This module converts structed stream into stream. That is, given a stream to write to,
+ it will give you a structured stream to
+
+ */
+#ifndef HTMLGEN_H
+#define HTMLGEN_H
+
+#include "HTML.h"
+#include "HTStream.h"
+
+/* Subclass:
+*/
+/* extern CONST HTStructuredClass HTMLGeneration; */
+
+/* Special Creation:
+*/
+extern HTStructured * HTMLGenerator PARAMS((HTStream * output));
+
+extern HTStream * HTPlainToHTML PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+
+#endif
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.c
new file mode 100644
index 00000000000..2094df68eec
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.c
@@ -0,0 +1,2824 @@
+/* NEWS ACCESS HTNews.c
+** ===========
+**
+** History:
+** 26 Sep 90 Written TBL
+** 29 Nov 91 Downgraded to C, for portable implementation.
+*/
+
+#include "HTUtils.h" /* Coding convention macros */
+#include "tcp.h"
+
+/* Implements:
+*/
+#include "HTNews.h"
+
+#include "HTCJK.h"
+#include "HTMIME.h"
+#include "HTTCP.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* this define should be in HTFont.h :( */
+#define HT_NON_BREAK_SPACE ((char)1) /* For now */
+
+#define NEWS_PORT 119 /* See rfc977 */
+#define SNEWS_PORT 563 /* See Lou Montulli */
+#define APPEND /* Use append methods */
+PUBLIC int HTNewsChunkSize = 30;/* Number of articles for quick display */
+PUBLIC int HTNewsMaxChunk = 40; /* Largest number of articles in one window */
+
+#ifndef DEFAULT_NEWS_HOST
+#define DEFAULT_NEWS_HOST "news"
+#endif /* DEFAULT_NEWS_HOST */
+#ifndef SERVER_FILE
+#define SERVER_FILE "/usr/local/lib/rn/server"
+#endif /* SERVER_FILE */
+
+#define NEWS_NETWRITE NETWRITE
+#define NEWS_NETCLOSE NETCLOSE
+#define NEXT_CHAR HTGetCharacter()
+
+#include <ctype.h>
+
+#include "HTML.h"
+#include "HTParse.h"
+#include "HTFormat.h"
+#include "HTAlert.h"
+
+#include "LYNews.h"
+#include "LYGlobalDefs.h"
+#include "LYLeaks.h"
+
+#define BIG 1024 /* @@@ */
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+#define LINE_LENGTH 512 /* Maximum length of line of ARTICLE etc */
+#define GROUP_NAME_LENGTH 256 /* Maximum length of group name */
+extern BOOLEAN scan_for_buried_news_references;
+extern BOOLEAN LYListNewsNumbers;
+extern BOOLEAN LYListNewsDates;
+extern HTCJKlang HTCJK;
+extern int interrupted_in_htgetcharacter;
+extern BOOL keep_mime_headers; /* Include mime headers and force raw text */
+extern BOOL using_proxy; /* Are we using an NNTP proxy? */
+
+/*
+** Module-wide variables.
+*/
+PUBLIC char * HTNewsHost = NULL; /* Default host */
+PRIVATE char * NewsHost = NULL; /* Current host */
+PRIVATE char * NewsHREF = NULL; /* Current HREF prefix */
+PRIVATE int s; /* Socket for NewsHost */
+PRIVATE int HTCanPost = FALSE; /* Current POST permission */
+PRIVATE char response_text[LINE_LENGTH+1]; /* Last response */
+/* PRIVATE HText * HT; */ /* the new hypertext */
+PRIVATE HTStructured * target; /* The output sink */
+PRIVATE HTStructuredClass targetClass; /* Copy of fn addresses */
+PRIVATE HTStream * rawtarget = NULL; /* The output sink for rawtext */
+PRIVATE HTStreamClass rawtargetClass; /* Copy of fn addresses */
+PRIVATE HTParentAnchor *node_anchor; /* Its anchor */
+PRIVATE int diagnostic; /* level: 0=none 2=source */
+PRIVATE BOOL rawtext = NO; /* Flag: HEAD or -mime_headers */
+PRIVATE HTList *NNTP_AuthInfo = NULL; /* AUTHINFO database */
+
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define RAW_PUTS(s) (*rawtargetClass.put_string)(rawtarget, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
+ (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET if (rawtext) (*rawtargetClass._free)(rawtarget); \
+ else (*targetClass._free)(target)
+#define ABORT_TARGET if (rawtext) (*rawtargetClass._abort)(rawtarget, NULL); \
+ else (*targetClass._abort)(target, NULL)
+
+typedef struct _NNTPAuth {
+ char * host;
+ char * user;
+ char * pass;
+} NNTPAuth;
+
+PRIVATE void free_news_globals NOARGS
+{
+ if (s >= 0) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ FREE(HTNewsHost);
+ FREE(NewsHost);
+ FREE(NewsHREF);
+}
+
+PRIVATE void free_NNTP_AuthInfo NOARGS
+{
+ HTList *cur = NNTP_AuthInfo;
+ NNTPAuth *auth = NULL;
+
+ if (!cur)
+ return;
+
+ while (NULL != (auth = (NNTPAuth *)HTList_nextObject(cur))) {
+ FREE(auth->host);
+ FREE(auth->user);
+ FREE(auth->pass);
+ FREE(auth);
+ }
+ HTList_delete(NNTP_AuthInfo);
+ NNTP_AuthInfo = NULL;
+ return;
+}
+
+PUBLIC CONST char * HTGetNewsHost NOARGS
+{
+ return HTNewsHost;
+}
+
+PUBLIC void HTSetNewsHost ARGS1(CONST char *, value)
+{
+ StrAllocCopy(HTNewsHost, value);
+}
+
+/* Initialisation for this module
+** ------------------------------
+**
+** Except on the NeXT, we pick up the NewsHost name from
+**
+** 1. Environment variable NNTPSERVER
+** 2. File SERVER_FILE
+** 3. Compilation time macro DEFAULT_NEWS_HOST
+** 4. Default to "news"
+**
+** On the NeXT, we pick up the NewsHost name from, in order:
+**
+** 1. WorldWideWeb default "NewsHost"
+** 2. Global default "NewsHost"
+** 3. News default "NewsHost"
+** 4. Compilation time macro DEFAULT_NEWS_HOST
+** 5. Default to "news"
+*/
+PRIVATE BOOL initialized = NO;
+PRIVATE BOOL initialize NOARGS
+{
+#ifdef NeXTStep
+ char *cp = NULL;
+#endif
+
+ /*
+ ** Get name of Host.
+ */
+#ifdef NeXTStep
+ if ((cp = NXGetDefaultValue("WorldWideWeb","NewsHost"))==0) {
+ if ((cp = NXGetDefaultValue("News","NewsHost")) == 0) {
+ StrAllocCopy(HTNewsHost, DEFAULT_NEWS_HOST);
+ }
+ }
+ if (cp) {
+ StrAllocCopy(HTNewsHost, cp);
+ cp = NULL;
+ }
+#else
+ if (getenv("NNTPSERVER")) {
+ StrAllocCopy(HTNewsHost, (char *)getenv("NNTPSERVER"));
+ if (TRACE) fprintf(stderr, "HTNews: NNTPSERVER defined as `%s'\n",
+ HTNewsHost);
+ } else {
+ char server_name[256];
+ FILE* fp = fopen(SERVER_FILE, "r");
+ if (fp) {
+ if (fscanf(fp, "%s", server_name)==1) {
+ StrAllocCopy(HTNewsHost, server_name);
+ if (TRACE) fprintf(stderr,
+ "HTNews: File %s defines news host as `%s'\n",
+ SERVER_FILE, HTNewsHost);
+ }
+ fclose(fp);
+ }
+ }
+ if (!HTNewsHost)
+ StrAllocCopy(HTNewsHost, DEFAULT_NEWS_HOST);
+#endif /* NeXTStep */
+
+ s = -1; /* Disconnected */
+ atexit(free_news_globals);
+ return YES;
+}
+
+/* Send NNTP Command line to remote host & Check Response
+** ------------------------------------------------------
+**
+** On entry,
+** command points to the command to be sent, including CRLF, or is null
+** pointer if no command to be sent.
+** On exit,
+** Negative status indicates transmission error, socket closed.
+** Positive status is an NNTP status.
+*/
+PRIVATE int response ARGS1(CONST char *,command)
+{
+ int result;
+ char * p = response_text;
+ char ch;
+
+ if (command) {
+ int status;
+ int length = strlen(command);
+ if (TRACE) fprintf(stderr, "NNTP command to be sent: %s", command);
+#ifdef NOT_ASCII
+ {
+ CONST char * p;
+ char * q;
+ char ascii[LINE_LENGTH+1];
+ for(p = command, q=ascii; *p; p++, q++) {
+ *q = TOASCII(*p);
+ }
+ status = NEWS_NETWRITE(s, ascii, length);
+ }
+#else
+ status = NEWS_NETWRITE(s, (char *)command, length);
+#endif /* NOT_ASCII */
+ if (status < 0){
+ if (TRACE) fprintf(stderr,
+ "HTNews: Unable to send command. Disconnecting.\n");
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return status;
+ } /* if bad status */
+ } /* if command to be sent */
+
+ for (;;) {
+ if (((*p++ = NEXT_CHAR) == LF) ||
+ (p == &response_text[LINE_LENGTH])) {
+ *--p = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, "NNTP Response: %s\n", response_text);
+ sscanf(response_text, "%d", &result);
+ return result;
+ } /* if end of line */
+
+ if ((ch = *(p-1)) == (char)EOF) {
+ *(p-1) = '\0';
+ if (TRACE) {
+ if (interrupted_in_htgetcharacter) {
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ } else {
+ fprintf(stderr,
+ "HTNews: EOF on read, closing socket %d\n",
+ s);
+ }
+ }
+ NEWS_NETCLOSE(s); /* End of file, close socket */
+ s = -1;
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ return(HT_INTERRUPTED);
+ }
+ return((int)EOF); /* End of file on response */
+ }
+ } /* Loop over characters */
+}
+
+/* Case insensitive string comparisons
+** -----------------------------------
+**
+** On entry,
+** template must be already un upper case.
+** unknown may be in upper or lower or mixed case to match.
+*/
+PRIVATE BOOL match ARGS2 (CONST char *,unknown, CONST char *,template)
+{
+ CONST char * u = unknown;
+ CONST char * t = template;
+ for (; *u && *t && (TOUPPER(*u) == *t); u++, t++)
+ ; /* Find mismatch or end */
+ return (BOOL)(*t == 0); /* OK if end of template */
+}
+
+typedef enum {
+ NNTPAUTH_ERROR = 0, /* general failure */
+ NNTPAUTH_OK = 281, /* authenticated successfully */
+ NNTPAUTH_CLOSE = 502 /* server probably closed connection */
+} NNTPAuthResult;
+/*
+** This function handles nntp authentication. - FM
+*/
+PRIVATE NNTPAuthResult HTHandleAuthInfo ARGS1(
+ char *, host)
+{
+ HTList *cur = NULL;
+ NNTPAuth *auth = NULL;
+ char *UserName = NULL;
+ char *PassWord = NULL;
+ char *msg = NULL;
+ char buffer[512];
+ int status, tries;
+
+ /*
+ ** Make sure we have an interactive user and a host. - FM
+ */
+ if (dump_output_immediately || !(host && *host))
+ return NNTPAUTH_ERROR;
+
+ /*
+ ** Check for an existing authorization entry. - FM
+ */
+ if (NNTP_AuthInfo != NULL) {
+ cur = NNTP_AuthInfo;
+ while (NULL != (auth = (NNTPAuth *)HTList_nextObject(cur))) {
+ if (!strcmp(auth->host, host)) {
+ UserName = auth->user;
+ PassWord = auth->pass;
+ break;
+ }
+ }
+ } else {
+ NNTP_AuthInfo = HTList_new();
+ atexit(free_NNTP_AuthInfo);
+ }
+
+ /*
+ ** Handle the username. - FM
+ */
+ buffer[511] = '\0';
+ tries = 3;
+
+ while (tries) {
+ if (UserName == NULL) {
+ if ((msg = (char *)calloc(1, (strlen(host) + 30))) == NULL) {
+ outofmem(__FILE__, "HTHandleAuthInfo");
+ }
+ sprintf(msg, "Username for news host '%s':", host);
+ UserName = HTPrompt(msg, NULL);
+ FREE(msg);
+ if (!(UserName && *UserName)) {
+ FREE(UserName);
+ return NNTPAUTH_ERROR;
+ }
+ }
+ sprintf(buffer, "AUTHINFO USER %.*s%c%c", 495, UserName, CR, LF);
+ if ((status = response(buffer)) < 0) {
+ if (status == HT_INTERRUPTED)
+ _HTProgress("Connection interrupted.");
+ else
+ HTAlert("Connection closed ???");
+ if (auth) {
+ if (auth->user != UserName) {
+ FREE(auth->user);
+ auth->user = UserName;
+ }
+ } else {
+ FREE(UserName);
+ }
+ return NNTPAUTH_CLOSE;
+ }
+ if (status == 281) {
+ /*
+ ** Username is accepted and no password is required. - FM
+ */
+ if (auth) {
+ if (auth->user != UserName) {
+ FREE(auth->user);
+ auth->user = UserName;
+ }
+ } else {
+ /*
+ ** Store the accepted username and no password. - FM
+ */
+ if ((auth =
+ (NNTPAuth *)calloc(1, sizeof(NNTPAuth))) != NULL) {
+ StrAllocCopy(auth->host, host);
+ auth->user = UserName;
+ HTList_appendObject(NNTP_AuthInfo, auth);
+ }
+ }
+ return NNTPAUTH_OK;
+ }
+ if (status != 381) {
+ /*
+ ** Not success, nor a request for the password,
+ ** so it must be an error. - FM
+ */
+ HTAlert(response_text);
+ tries--;
+ if ((tries > 0) && HTConfirm("Change username?")) {
+ if (!auth || auth->user != UserName) {
+ FREE(UserName);
+ }
+ if ((UserName = HTPrompt("Username:", UserName)) != NULL &&
+ *UserName) {
+ continue;
+ }
+ }
+ if (auth) {
+ if (auth->user != UserName) {
+ FREE(auth->user);
+ }
+ FREE(auth->pass);
+ }
+ FREE(UserName);
+ return NNTPAUTH_ERROR;
+ }
+ break;
+ }
+
+ if (status == 381) {
+ /*
+ ** Handle the password. - FM
+ */
+ tries = 3;
+ while (tries) {
+ if (PassWord == NULL) {
+ if ((msg = (char *)calloc(1, (strlen(host) + 30))) == NULL) {
+ outofmem(__FILE__, "HTHandleAuthInfo");
+ }
+ sprintf(msg, "Password for news host '%s':", host);
+ PassWord = HTPromptPassword(msg);
+ FREE(msg);
+ if (!(PassWord && *PassWord)) {
+ FREE(PassWord);
+ return NNTPAUTH_ERROR;
+ }
+ }
+ sprintf(buffer, "AUTHINFO PASS %.*s%c%c", 495, PassWord, CR, LF);
+ if ((status = response(buffer)) < 0) {
+ if (status == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ } else {
+ HTAlert("Connection closed ???");
+ }
+ if (auth) {
+ if (auth->user != UserName) {
+ FREE(auth->user);
+ auth->user = UserName;
+ }
+ if (auth->pass != PassWord) {
+ FREE(auth->pass);
+ auth->pass = PassWord;
+ }
+ } else {
+ FREE(UserName);
+ FREE(PassWord);
+ }
+ return NNTPAUTH_CLOSE;
+ }
+ if (status == 502) {
+ /*
+ * That's what INN's nnrpd returns.
+ * It closes the connection after this. - kw
+ */
+ HTAlert(response_text);
+ if (auth) {
+ if (auth->user == UserName)
+ UserName = NULL;
+ FREE(auth->user);
+ if (auth->pass == PassWord)
+ PassWord = NULL;
+ FREE(auth->pass);
+ }
+ FREE(UserName);
+ FREE(PassWord);
+ return NNTPAUTH_CLOSE;
+ }
+ if (status == 281) {
+ /*
+ ** Password also is accepted, and everything
+ ** has been stored. - FM
+ */
+ if (auth) {
+ if (auth->user != UserName) {
+ FREE(auth->user);
+ auth->user = UserName;
+ }
+ if (auth->pass != PassWord) {
+ FREE(auth->pass);
+ auth->pass = PassWord;
+ }
+ } else {
+ if ((auth =
+ (NNTPAuth *)calloc(1, sizeof(NNTPAuth))) != NULL) {
+ StrAllocCopy(auth->host, host);
+ auth->user = UserName;
+ auth->pass = PassWord;
+ HTList_appendObject(NNTP_AuthInfo, auth);
+ }
+ }
+ return NNTPAUTH_OK;
+ }
+ /*
+ ** Not success, so it must be an error. - FM
+ */
+ HTAlert(response_text);
+ if (!auth || auth->pass != PassWord) {
+ FREE(PassWord);
+ } else {
+ PassWord = NULL;
+ }
+ tries--;
+ if ((tries > 0) && HTConfirm("Change password?")) {
+ continue;
+ }
+ if (auth) {
+ if (auth->user == UserName)
+ UserName = NULL;
+ FREE(auth->user);
+ FREE(auth->pass);
+ }
+ FREE(UserName);
+ break;
+ }
+ }
+
+ return NNTPAUTH_ERROR;
+}
+
+/* Find Author's name in mail address
+** ----------------------------------
+**
+** On exit,
+** Returns allocated string which cannot be freed by the
+** calling function, and is reallocated on subsequent calls
+** to this function.
+**
+** For example, returns "Tim Berners-Lee" if given any of
+** " Tim Berners-Lee <tim@online.cern.ch> "
+** or " tim@online.cern.ch ( Tim Berners-Lee ) "
+*/
+PRIVATE char * author_name ARGS1 (char *,email)
+{
+ static char *name = NULL;
+ char *p, *e;
+
+ StrAllocCopy(name, email);
+ if (TRACE)
+ fprintf(stderr,"Trying to find name in: %s\n",name);
+
+ if ((p = strchr(name, '(')) && (e = strchr(name, ')'))) {
+ if (e > p) {
+ *e = '\0'; /* Chop off everything after the ')' */
+ return HTStrip(p+1); /* Remove leading and trailing spaces */
+ }
+ }
+
+ if ((p = strchr(name, '<')) && (e = strchr(name, '>'))) {
+ if (e > p) {
+ strcpy(p, e+1); /* Remove <...> */
+ return HTStrip(name); /* Remove leading and trailing spaces */
+ }
+ }
+
+ return HTStrip(name); /* Default to the whole thing */
+}
+
+/* Find Author's mail address
+** --------------------------
+**
+** On exit,
+** Returns allocated string which cannot be freed by the
+** calling function, and is reallocated on subsequent calls
+** to this function.
+**
+** For example, returns "montulli@spaced.out.galaxy.net" if given any of
+** " Lou Montulli <montulli@spaced.out.galaxy.net> "
+** or " montulli@spaced.out.galaxy.net ( Lou "The Stud" Montulli ) "
+*/
+PRIVATE char * author_address ARGS1(char *,email)
+{
+ static char *address = NULL;
+ char *p, *at, *e;
+
+ StrAllocCopy(address, email);
+ if (TRACE)
+ fprintf(stderr,"Trying to find address in: %s\n",address);
+
+ if ((p = strchr(address, '<'))) {
+ if ((e = strchr(p, '>')) && (at = strchr(p, '@'))) {
+ if (at < e) {
+ *e = '\0'; /* Remove > */
+ return HTStrip(p+1); /* Remove leading and trailing spaces */
+ }
+ }
+ }
+
+ if ((p = strchr(address, '(')) &&
+ (e = strchr(address, ')')) && (at = strchr(address, '@'))) {
+ if (e > p && at < e) {
+ *p = '\0'; /* Chop off everything after the ')' */
+ return HTStrip(address); /* Remove leading and trailing spaces */
+ }
+ }
+
+ if ((at = strchr(address, '@')) && at > address) {
+ p = (at - 1);
+ e = (at + 1);
+ while (p > address && !isspace((unsigned char)*p))
+ p--;
+ while (*e && !isspace((unsigned char)*e))
+ e++;
+ *e = 0;
+ return HTStrip(p);
+ }
+
+ /*
+ ** Default to the first word.
+ */
+ p = address;
+ while (isspace((unsigned char)*p))
+ p++; /* find first non-space */
+ e = p;
+ while (!isspace((unsigned char)*e) && *e != '\0')
+ e++; /* find next space or end */
+ *e = '\0'; /* terminate space */
+
+ return(p);
+}
+
+/* Start anchor element
+** --------------------
+*/
+PRIVATE void start_anchor ARGS1(CONST char *, href)
+{
+ BOOL present[HTML_A_ATTRIBUTES];
+ CONST char* value[HTML_A_ATTRIBUTES];
+
+ {
+ int i;
+ for(i=0; i < HTML_A_ATTRIBUTES; i++)
+ present[i] = (i == HTML_A_HREF);
+ }
+ ((CONST char **)value)[HTML_A_HREF] = href;
+ (*targetClass.start_element)(target, HTML_A , present,
+ (CONST char **)value, -1, 0);
+}
+
+/* Start link element
+** ------------------
+*/
+PRIVATE void start_link ARGS2(CONST char *, href, CONST char *, rev)
+{
+ BOOL present[HTML_LINK_ATTRIBUTES];
+ CONST char* value[HTML_LINK_ATTRIBUTES];
+
+ {
+ int i;
+ for(i=0; i < HTML_LINK_ATTRIBUTES; i++)
+ present[i] = (i == HTML_LINK_HREF || i == HTML_LINK_REV);
+ }
+ ((CONST char **)value)[HTML_LINK_HREF] = href;
+ ((CONST char **)value)[HTML_LINK_REV] = rev;
+ (*targetClass.start_element)(target, HTML_LINK, present,
+ (CONST char **)value, -1, 0);
+}
+
+/* Start list element
+** ------------------
+*/
+PRIVATE void start_list ARGS1(int, seqnum)
+{
+ BOOL present[HTML_OL_ATTRIBUTES];
+ CONST char* value[HTML_OL_ATTRIBUTES];
+ char SeqNum[20];
+ int i;
+
+ for (i = 0; i < HTML_OL_ATTRIBUTES; i++)
+ present[i] = (i == HTML_OL_SEQNUM || i == HTML_OL_START);
+ sprintf(SeqNum, "%d", seqnum);
+ ((CONST char **)value)[HTML_OL_SEQNUM] = SeqNum;
+ ((CONST char **)value)[HTML_OL_START] = SeqNum;
+ (*targetClass.start_element)(target, HTML_OL , present,
+ (CONST char **)value, -1, 0);
+}
+
+/* Paste in an Anchor
+** ------------------
+**
+**
+** On entry,
+** HT has a selection of zero length at the end.
+** text points to the text to be put into the file, 0 terminated.
+** addr points to the hypertext reference address,
+** terminated by white space, comma, NULL or '>'
+*/
+PRIVATE void write_anchor ARGS2(CONST char *,text, CONST char *,addr)
+{
+ char href[LINE_LENGTH+1];
+
+ {
+ CONST char * p;
+ strcpy(href, NewsHREF);
+ for (p = addr; *p && (*p != '>') && !WHITE(*p) && (*p!=','); p++)
+ ;
+ strncat(href, addr, p-addr); /* Make complete hypertext reference */
+ }
+
+ start_anchor(href);
+ PUTS(text);
+ END(HTML_A);
+}
+
+/* Write list of anchors
+** ---------------------
+**
+** We take a pointer to a list of objects, and write out each,
+** generating an anchor for each.
+**
+** On entry,
+** HT has a selection of zero length at the end.
+** text points to a comma or space separated list of addresses.
+** On exit,
+** *text is NOT any more chopped up into substrings.
+*/
+PRIVATE void write_anchors ARGS1 (char *,text)
+{
+ char * start = text;
+ char * end;
+ char c;
+ for (;;) {
+ for (; *start && (WHITE(*start)); start++)
+ ; /* Find start */
+ if (!*start)
+ return; /* (Done) */
+ for (end = start;
+ *end && (*end != ' ') && (*end != ','); end++)
+ ;/* Find end */
+ if (*end)
+ end++; /* Include comma or space but not NULL */
+ c = *end;
+ *end = '\0';
+ if (*start == '<')
+ write_anchor(start, start+1);
+ else
+ write_anchor(start, start);
+ START(HTML_BR);
+ *end = c;
+ start = end; /* Point to next one */
+ }
+}
+
+/* Abort the connection abort_socket
+** --------------------
+*/
+PRIVATE void abort_socket NOARGS
+{
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: EOF on read, closing socket %d\n", s);
+ NEWS_NETCLOSE(s); /* End of file, close socket */
+ PUTS("Network Error: connection lost");
+ PUTC('\n');
+ s = -1; /* End of file on response */
+}
+
+/*
+** Determine if a line is a valid header line. valid_header
+** -------------------------------------------
+*/
+PRIVATE BOOLEAN valid_header ARGS1(
+ char *, line)
+{
+ char *colon, *space;
+
+ /*
+ ** Blank or tab in first position implies
+ ** this is a continuation header.
+ */
+ if (line[0] == ' ' || line[0] == '\t')
+ return(TRUE);
+
+ /*
+ ** Just check for initial letter, colon, and space to make
+ ** sure we discard only invalid headers.
+ */
+ colon = strchr(line, ':');
+ space = strchr(line, ' ');
+ if (isalpha(line[0]) && colon && space == colon + 1)
+ return(TRUE);
+
+ /*
+ ** Anything else is a bad header -- it should be ignored.
+ */
+ return(FALSE);
+}
+
+/* post in an Article post_article
+** ------------------
+** (added by FM, modeled on Lynx's previous mini inews)
+**
+** Note the termination condition of a single dot on a line by itself.
+**
+** On entry,
+** s Global socket number is OK
+** postfile file with header and article to post.
+*/
+PRIVATE void post_article ARGS1(
+ char *, postfile)
+{
+ char line[512];
+ char buf[512];
+ char crlf[3];
+ char *cp;
+ int status;
+ FILE *fd;
+ int in_header = 1, seen_header = 0, seen_fromline = 0;
+ int blen = 0, llen = 0;
+
+
+ /*
+ ** Open the temporary file with the
+ ** nntp headers and message body. - FM
+ */
+ if ((fd = fopen((postfile ? postfile : ""), "r")) == NULL) {
+ HTAlert("Cannot open temporary file for news POST.");
+ return;
+ }
+
+ /*
+ ** Read the temporary file and post
+ ** in maximum 512 byte chunks. - FM
+ */
+ buf[0] = '\0';
+ sprintf(crlf, "%c%c", CR, LF);
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ if ((cp = strchr(line, '\n')) != NULL)
+ *cp = '\0';
+ if (line[0] == '.') {
+ /*
+ ** A single '.' means end of transmission
+ ** for nntp. Lead dots on lines normally
+ ** are trimmed and the EOF is not registered
+ ** if the dot was not followed by CRLF.
+ ** We prepend an extra dot for any line
+ ** beginning with one, to retain the one
+ ** intended, as well as avoid a false EOF
+ ** signal. We know we have room for it in
+ ** the buffer, because we normally send when
+ ** it would exceed 510. - FM
+ */
+ strcat(buf, ".");
+ blen++;
+ }
+ llen = strlen(line);
+ if (in_header && !strncasecomp(line, "From:", 5)) {
+ seen_header = 1;
+ seen_fromline = 1;
+ }
+ if (in_header && line[0] == '\0') {
+ if (seen_header) {
+ in_header = 0;
+ if (!seen_fromline) {
+ if (blen < 475) {
+ strcat(buf, "From: anonymous@nowhere.you.know");
+ strcat(buf, crlf);
+ blen += 34;
+ } else {
+ NEWS_NETWRITE(s, buf, blen);
+ sprintf(buf,
+ "From: anonymous@nowhere.you.know%s", crlf);
+ blen = 34;
+ }
+ }
+ } else {
+ continue;
+ }
+ } else if (in_header) {
+ if (valid_header(line)) {
+ seen_header = 1;
+ } else {
+ continue;
+ }
+ }
+ strcat(line, crlf);
+ llen += 2;
+ if ((blen + llen) < 511) {
+ strcat(buf, line);
+ blen += llen;
+ } else {
+ NEWS_NETWRITE(s, buf, blen);
+ strcpy(buf, line);
+ blen = llen;
+ }
+ }
+ fclose(fd);
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+
+ /*
+ ** Send the nntp EOF and get the server's response. - FM
+ */
+ if (blen < 508) {
+ strcat(buf, ".");
+ strcat(buf, crlf);
+ blen += 3;
+ NEWS_NETWRITE(s, buf, blen);
+ } else {
+ NEWS_NETWRITE(s, buf, blen);
+ sprintf(buf, ".%s", crlf);
+ blen = 3;
+ NEWS_NETWRITE(s, buf, blen);
+ }
+ status = response(NULL);
+ if (status == 240) {
+ /*
+ ** Successful post. - FM
+ */
+ HTProgress(response_text);
+ } else {
+ /*
+ ** Shucks, something went wrong. - FM
+ */
+ HTAlert(response_text);
+ }
+}
+
+/* Read in an Article read_article
+** ------------------
+**
+** Note the termination condition of a single dot on a line by itself.
+** RFC 977 specifies that the line "folding" of RFC850 is not used, so we
+** do not handle it here.
+**
+** On entry,
+** s Global socket number is OK
+** HT Global hypertext object is ready for appending text
+*/
+PRIVATE int read_article NOARGS
+{
+ char line[LINE_LENGTH+1];
+ char *full_line = NULL;
+ char *subject = NULL; /* Subject string */
+ char *from = NULL; /* From string */
+ char *replyto = NULL; /* Reply-to string */
+ char *date = NULL; /* Date string */
+ char *organization = NULL; /* Organization string */
+ char *references = NULL; /* Hrefs for other articles */
+ char *newsgroups = NULL; /* Newsgroups list */
+ char *followupto = NULL; /* Followup list */
+ char *href = NULL;
+ char *p = line;
+ BOOL done = NO;
+
+ /*
+ ** Read in the HEADer of the article.
+ **
+ ** The header fields are either ignored,
+ ** or formatted and put into the text.
+ */
+ if (!diagnostic && !rawtext) {
+ while (!done) {
+ char ch = *p++ = NEXT_CHAR;
+ if (ch == (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ }
+ abort_socket(); /* End of file, close socket */
+ return(HT_LOADED); /* End of file on response */
+ }
+ if ((ch == LF) || (p == &line[LINE_LENGTH])) {
+ *--p = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, "H %s\n", line);
+
+ if (line[0] == '\t' || line[0] == ' ') {
+ int i = 0;
+ while (line[i]) {
+ if (line[i] == '\t')
+ line[i] = ' ';
+ i++;
+ }
+ if (full_line == NULL) {
+ StrAllocCopy(full_line, line);
+ } else {
+ StrAllocCat(full_line, line);
+ }
+ } else {
+ StrAllocCopy(full_line, line);
+ }
+
+ if (full_line[0] == '.') {
+ /*
+ ** End of article?
+ */
+ if ((unsigned char)full_line[1] < ' ') {
+ done = YES;
+ break;
+ }
+ } else if ((unsigned char)full_line[0] < ' ') {
+ break; /* End of Header? */
+
+ } else if (match(full_line, "SUBJECT:")) {
+ StrAllocCopy(subject, HTStrip(strchr(full_line,':')+1));
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(subject, subject);
+ HTrjis(subject, subject);
+ }
+
+ } else if (match(full_line, "DATE:")) {
+ StrAllocCopy(date, HTStrip(strchr(full_line,':')+1));
+
+ } else if (match(full_line, "ORGANIZATION:")) {
+ StrAllocCopy(organization,
+ HTStrip(strchr(full_line,':')+1));
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(organization, organization);
+ HTrjis(organization, organization);
+ }
+
+ } else if (match(full_line, "FROM:")) {
+ StrAllocCopy(from, HTStrip(strchr(full_line,':')+1));
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(from, from);
+ HTrjis(from, from);
+ }
+
+ } else if (match(full_line, "REPLY-TO:")) {
+ StrAllocCopy(replyto, HTStrip(strchr(full_line,':')+1));
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(replyto, replyto);
+ HTrjis(replyto, replyto);
+ }
+
+ } else if (match(full_line, "NEWSGROUPS:")) {
+ StrAllocCopy(newsgroups, HTStrip(strchr(full_line,':')+1));
+
+ } else if (match(full_line, "REFERENCES:")) {
+ StrAllocCopy(references, HTStrip(strchr(full_line,':')+1));
+
+ } else if (match(full_line, "FOLLOWUP-TO:")) {
+ StrAllocCopy(followupto, HTStrip(strchr(full_line,':')+1));
+
+ } /* end if match */
+ p = line; /* Restart at beginning */
+ } /* if end of line */
+ } /* Loop over characters */
+ FREE(full_line);
+
+ START(HTML_HEAD);
+ PUTC('\n');
+ START(HTML_TITLE);
+ if (subject && *subject != '\0')
+ PUTS(subject);
+ else
+ PUTS("No Subject");
+ END(HTML_TITLE);
+ PUTC('\n');
+ /*
+ ** Put in the owner as a link rel.
+ */
+ if (from || replyto) {
+ char *temp=NULL;
+ StrAllocCopy(temp, replyto ? replyto : from);
+ StrAllocCopy(href,"mailto:");
+ StrAllocCat(href, author_address(temp));
+ start_link(href, "made");
+ PUTC('\n');
+ FREE(temp);
+ }
+ END(HTML_HEAD);
+ PUTC('\n');
+
+ START(HTML_H1);
+ if (subject && *subject != '\0')
+ PUTS(subject);
+ else
+ PUTS("No Subject");
+ END(HTML_H1);
+ PUTC('\n');
+
+ if (subject)
+ FREE(subject);
+
+ START(HTML_DLC);
+ PUTC('\n');
+
+ if (from || replyto) {
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("From:");
+ END(HTML_B);
+ PUTC(' ');
+ if (from)
+ PUTS(from);
+ else
+ PUTS(from);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+
+ if (!replyto)
+ StrAllocCopy(replyto, from);
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("Reply to:");
+ END(HTML_B);
+ PUTC(' ');
+ start_anchor(href);
+ if (*replyto != '<')
+ PUTS(author_name(replyto));
+ else
+ PUTS(author_address(replyto));
+ END(HTML_A);
+ START(HTML_BR);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+
+ FREE(from);
+ FREE(replyto);
+ }
+
+ if (date) {
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("Date:");
+ END(HTML_B);
+ PUTC(' ');
+ PUTS(date);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+ FREE(date);
+ }
+
+ if (organization) {
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("Organization:");
+ END(HTML_B);
+ PUTC(' ');
+ PUTS(organization);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+ FREE(organization);
+ }
+
+ if (newsgroups && HTCanPost) {
+ /*
+ ** We have permission to POST to this host,
+ ** so add a link for posting followups for
+ ** this article. - FM
+ */
+ if (!strncasecomp(NewsHREF, "snews:", 6))
+ StrAllocCopy(href,"snewsreply://");
+ else
+ StrAllocCopy(href,"newsreply://");
+ StrAllocCat(href, NewsHost);
+ StrAllocCat(href, "/");
+ StrAllocCat(href, (followupto ? followupto : newsgroups));
+
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("Newsgroups:");
+ END(HTML_B);
+ PUTC('\n');
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ write_anchors(newsgroups);
+ MAYBE_END(HTML_DD);
+ PUTC('\n');
+
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("Followup to:");
+ END(HTML_B);
+ PUTC(' ');
+ start_anchor(href);
+ PUTS("newsgroup(s)");
+ END(HTML_A);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+ }
+ FREE(newsgroups);
+ FREE(followupto);
+
+ if (references) {
+ START(HTML_DT);
+ START(HTML_B);
+ PUTS("References:");
+ END(HTML_B);
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+ START(HTML_DD);
+ write_anchors(references);
+ MAYBE_END(HTML_DD);
+ PUTC('\n');
+ FREE(references);
+ }
+
+ END(HTML_DLC);
+ PUTC('\n');
+ FREE(href);
+ }
+
+ if (rawtext) {
+ /*
+ * No tags - kw
+ */
+ ;
+ } else if (diagnostic) {
+ /*
+ ** Read in the HEAD and BODY of the Article
+ ** as XMP formatted text. - FM
+ */
+ START(HTML_XMP);
+ } else {
+ /*
+ ** Read in the BODY of the Article
+ ** as PRE formatted text. - FM
+ */
+ START(HTML_PRE);
+ }
+ PUTC('\n');
+
+ p = line;
+ while (!done) {
+ char ch = *p++ = NEXT_CHAR;
+ if (ch == (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ }
+ abort_socket(); /* End of file, close socket */
+ return(HT_LOADED); /* End of file on response */
+ }
+ if ((ch == LF) || (p == &line[LINE_LENGTH])) {
+ *p++ = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, "B %s", line);
+ if (line[0] == '.') {
+ /*
+ ** End of article?
+ */
+ if ((unsigned char)line[1] < ' ') {
+ done = YES;
+ break;
+ } else { /* Line starts with dot */
+ if (rawtext)
+ RAW_PUTS(&line[1]);
+ else
+ PUTS(&line[1]); /* Ignore first dot */
+ }
+ } else {
+ if (rawtext) {
+ RAW_PUTS(line);
+ } else if (diagnostic || !scan_for_buried_news_references) {
+ /*
+ ** All lines are passed as unmodified source. - FM
+ */
+ PUTS(line);
+ } else {
+ /*
+ ** Normal lines are scanned for buried references
+ ** to other articles. Unfortunately, it could pick
+ ** up mail addresses as well! It also can corrupt
+ ** uuencoded messages! So we don't do this when
+ ** fetching articles as WWW_SOURCE or when downloading
+ ** (diagnostic is TRUE) or if the client has set
+ ** scan_for_buried_news_references to FALSE.
+ ** Otherwise, we convert all "<...@...>" strings
+ ** preceded by "rticle " to "news:...@..." links,
+ ** and any strings that look like URLs to links. - FM
+ */
+ char *l = line;
+ char *p2;
+
+ while ((p2 = strstr(l, "rticle <")) != NULL) {
+ char *q = strchr(p2,'>');
+ char *at = strchr(p2, '@');
+ if (q && at && at<q) {
+ char c = q[1];
+ q[1] = 0; /* chop up */
+ p2 += 7;
+ *p2 = 0;
+ while (*l) {
+ if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9))
+ PUTC (*l++);
+ else {
+ StrAllocCopy(href, l);
+ start_anchor(strtok(href, " \r\n\t,>)\""));
+ while (*l && !strchr(" \r\n\t,>)\"", *l))
+ PUTC(*l++);
+ END(HTML_A);
+ FREE(href);
+ }
+ }
+ *p2 = '<'; /* again */
+ *q = 0;
+ start_anchor(p2+1);
+ *q = '>'; /* again */
+ PUTS(p2);
+ END(HTML_A);
+ q[1] = c; /* again */
+ l=q+1;
+ } else {
+ break; /* line has unmatched <> */
+ }
+ }
+ while (*l) { /* Last bit of the line */
+ if (strncmp(l, "news:", 5) &&
+ strncmp(l, "snews://", 8) &&
+ strncmp(l, "nntp://", 7) &&
+ strncmp(l, "snewspost:", 10) &&
+ strncmp(l, "snewsreply:", 11) &&
+ strncmp(l, "newspost:", 9) &&
+ strncmp(l, "newsreply:", 10) &&
+ strncmp(l, "ftp://", 6) &&
+ strncmp(l, "file:/", 6) &&
+ strncmp(l, "finger://", 9) &&
+ strncmp(l, "http://", 7) &&
+ strncmp(l, "https://", 8) &&
+ strncmp(l, "wais://", 7) &&
+ strncmp(l, "mailto:", 7) &&
+ strncmp(l, "cso://", 6) &&
+ strncmp(l, "gopher://", 9))
+ PUTC (*l++);
+ else {
+ StrAllocCopy(href, l);
+ start_anchor(strtok(href, " \r\n\t,>)\""));
+ while (*l && !strchr(" \r\n\t,>)\"", *l))
+ PUTC(*l++);
+ END(HTML_A);
+ FREE(href);
+ }
+ }
+ } /* if diagnostic or not scan_for_buried_news_references */
+ } /* if not dot */
+ p = line; /* Restart at beginning */
+ } /* if end of line */
+ } /* Loop over characters */
+
+ if (rawtext)
+ return(HT_LOADED);
+
+ if (diagnostic)
+ END(HTML_XMP);
+ else
+ END(HTML_PRE);
+ PUTC('\n');
+ return(HT_LOADED);
+}
+
+/* Read in a List of Newsgroups
+** ----------------------------
+**
+** Note the termination condition of a single dot on a line by itself.
+** RFC 977 specifies that the line "folding" of RFC850 is not used,
+** so we do not handle it here.
+*/
+PRIVATE int read_list ARGS1(char *, arg)
+{
+ char line[LINE_LENGTH+1];
+ char *p;
+ BOOL done = NO;
+ BOOL head = NO;
+ BOOL tail = NO;
+ BOOL skip_this_line = NO;
+ BOOL skip_rest_of_line = NO;
+ int listing = 0;
+ char *pattern = NULL;
+ int len = 0;
+
+ /*
+ ** Support head or tail matches for groups to list. - FM
+ */
+ if (arg && strlen(arg) > 1) {
+ if (*arg == '*') {
+ tail = YES;
+ StrAllocCopy(pattern, (arg+1));
+ } else if (arg[strlen(arg)-1] == '*') {
+ head = YES;
+ StrAllocCopy(pattern, arg);
+ pattern[strlen(pattern)-1] = '\0';
+ }
+ if (tail || head) {
+ len = strlen(pattern);
+ }
+
+ }
+
+ /*
+ ** Read the server's reply.
+ **
+ ** The lines are scanned for newsgroup
+ ** names and descriptions.
+ */
+ START(HTML_HEAD);
+ PUTC('\n');
+ START(HTML_TITLE);
+ PUTS("Newsgroups");
+ END(HTML_TITLE);
+ PUTC('\n');
+ END(HTML_HEAD);
+ PUTC('\n');
+ START(HTML_H1);
+ PUTS( "Newsgroups");
+ END(HTML_H1);
+ PUTC('\n');
+ p = line;
+ START(HTML_DLC);
+ PUTC('\n');
+ while (!done) {
+ char ch = NEXT_CHAR;
+ if (ch == (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ }
+ abort_socket(); /* End of file, close socket */
+ FREE(pattern);
+ return(HT_LOADED); /* End of file on response */
+ } else if (skip_this_line) {
+ if (ch == LF) {
+ skip_this_line = skip_rest_of_line = NO;
+ p = line;
+ }
+ continue;
+ } else if (skip_rest_of_line) {
+ if (ch != LF) {
+ continue;
+ }
+ } else if (p == &line[LINE_LENGTH]) {
+ if (TRACE) {
+ fprintf(stderr, "b %.*s%c[...]\n", (LINE_LENGTH), line, ch);
+ }
+ *p = '\0';
+ if (ch == LF) {
+ ; /* Will be dealt with below */
+ } else if (WHITE(ch)) {
+ ch = LF; /* May treat as line without description */
+ skip_this_line = YES; /* ...and ignore until LF */
+ } else if (strchr(line, ' ') == NULL &&
+ strchr(line, '\t') == NULL) {
+ /* No separator found */
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews..... group name too long, discarding.\n");
+ skip_this_line = YES; /* ignore whole line */
+ continue;
+ } else {
+ skip_rest_of_line = YES; /* skip until ch == LF found */
+ }
+ } else {
+ *p++ = ch;
+ }
+ if (ch == LF) {
+ skip_rest_of_line = NO; /* done, reset flag */
+ *p = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, "B %s", line);
+ if (line[0] == '.') {
+ /*
+ ** End of article?
+ */
+ if ((unsigned char)line[1] < ' ') {
+ done = YES;
+ break;
+ } else { /* Line starts with dot */
+ START(HTML_DT);
+ PUTS(&line[1]);
+ MAYBE_END(HTML_DT);
+ }
+ } else if (line[0] == '#') { /* Comment? */
+ p = line; /* Restart at beginning */
+ continue;
+ } else {
+ /*
+ ** Normal lines are scanned for references to newsgroups.
+ */
+ int i = 0;
+
+ /* find whitespace if it exits */
+ for (; line[i] != '\0' && !WHITE(line[i]); i++)
+ ; /* null body */
+
+ if (line[i] != '\0') {
+ line[i] = '\0';
+ if ((head && strncasecomp(line, pattern, len)) ||
+ (tail && (i < len ||
+ strcasecomp((line + (i - len)), pattern)))) {
+ p = line; /* Restart at beginning */
+ continue;
+ }
+ START(HTML_DT);
+ write_anchor(line, line);
+ listing++;
+ MAYBE_END(HTML_DT);
+ PUTC('\n');
+ START(HTML_DD);
+ PUTS(&line[i+1]); /* put description */
+ MAYBE_END(HTML_DD);
+ } else {
+ if ((head && strncasecomp(line, pattern, len)) ||
+ (tail && (i < len ||
+ strcasecomp((line + (i - len)), pattern)))) {
+ p = line; /* Restart at beginning */
+ continue;
+ }
+ START(HTML_DT);
+ write_anchor(line, line);
+ MAYBE_END(HTML_DT);
+ listing++;
+ }
+ } /* if not dot */
+ p = line; /* Restart at beginning */
+ } /* if end of line */
+ } /* Loop over characters */
+ if (!listing) {
+ START(HTML_DT);
+ sprintf(line, "No matches for: %s", arg);
+ PUTS(line);
+ MAYBE_END(HTML_DT);
+ }
+ END(HTML_DLC);
+ PUTC('\n');
+ FREE(pattern);
+ return(HT_LOADED);
+}
+
+/* Read in a Newsgroup
+** -------------------
+**
+** Unfortunately, we have to ask for each article one by one if we
+** want more than one field.
+**
+*/
+PRIVATE int read_group ARGS3(
+ CONST char *,groupName,
+ int,first_required,
+ int,last_required)
+{
+ char line[LINE_LENGTH+1];
+ char author[LINE_LENGTH+1];
+ char subject[LINE_LENGTH+1];
+ char *date = NULL;
+ int i;
+ char *p;
+ BOOL done;
+
+ char buffer[LINE_LENGTH];
+ char *reference = NULL; /* Href for article */
+ int art; /* Article number WITHIN GROUP */
+ int status, count, first, last; /* Response fields */
+ /* count is only an upper limit */
+
+ author[0] = '\0';
+ START(HTML_HEAD);
+ PUTC('\n');
+ START(HTML_TITLE);
+ PUTS("Newsgroup ");
+ PUTS(groupName);
+ END(HTML_TITLE);
+ PUTC('\n');
+ END(HTML_HEAD);
+ PUTC('\n');
+
+ sscanf(response_text, " %d %d %d %d", &status, &count, &first, &last);
+ if (TRACE)
+ fprintf(stderr,
+ "Newsgroup status=%d, count=%d, (%d-%d) required:(%d-%d)\n",
+ status, count, first, last, first_required, last_required);
+ if (last == 0) {
+ PUTS("\nNo articles in this group.\n");
+ goto add_post;
+ }
+
+#define FAST_THRESHOLD 100 /* Above this, read IDs fast */
+#define CHOP_THRESHOLD 50 /* Above this, chop off the rest */
+
+ if (first_required < first)
+ first_required = first; /* clip */
+ if ((last_required == 0) || (last_required > last))
+ last_required = last;
+
+ if (last_required < first_required) {
+ PUTS("\nNo articles in this range.\n");
+ goto add_post;
+ }
+
+ if (last_required-first_required+1 > HTNewsMaxChunk) { /* Trim this block */
+ first_required = last_required-HTNewsChunkSize+1;
+ }
+ if (TRACE)
+ fprintf(stderr, " Chunk will be (%d-%d)\n",
+ first_required, last_required);
+
+ /*
+ ** Set window title.
+ */
+ sprintf(buffer, "%s, Articles %d-%d",
+ groupName, first_required, last_required);
+ START(HTML_H1);
+ PUTS(buffer);
+ END(HTML_H1);
+ PUTC('\n');
+
+ /*
+ ** Link to earlier articles.
+ */
+ if (first_required > first) {
+ int before; /* Start of one before */
+ if (first_required-HTNewsMaxChunk <= first)
+ before = first;
+ else
+ before = first_required-HTNewsChunkSize;
+ sprintf(buffer, "%s%s/%d-%d", NewsHREF, groupName,
+ before, first_required-1);
+ if (TRACE)
+ fprintf(stderr, " Block before is %s\n", buffer);
+ PUTC('(');
+ start_anchor(buffer);
+ PUTS("Earlier articles");
+ END(HTML_A);
+ PUTS("...)\n");
+ START(HTML_P);
+ PUTC('\n');
+ }
+
+ done = NO;
+
+/*#define USE_XHDR*/
+#ifdef USE_XHDR
+ if (count > FAST_THRESHOLD) {
+ sprintf(buffer,
+ "\nThere are about %d articles currently available in %s, IDs as follows:\n\n",
+ count, groupName);
+ PUTS(buffer);
+ sprintf(buffer, "XHDR Message-ID %d-%d%c%c", first, last, CR, LF);
+ status = response(buffer);
+ if (status == 221) {
+ p = line;
+ while (!done) {
+ char ch = *p++ = NEXT_CHAR;
+ if (ch == (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ }
+ abort_socket(); /* End of file, close socket */
+ return(HT_LOADED); /* End of file on response */
+ }
+ if ((ch == '\n') || (p == &line[LINE_LENGTH])) {
+ *p = '\0'; /* Terminate the string */
+ if (TRACE)
+ fprintf(stderr, "X %s", line);
+ if (line[0] == '.') {
+ /*
+ ** End of article?
+ */
+ if ((unsigned char)line[1] < ' ') {
+ done = YES;
+ break;
+ } else { /* Line starts with dot */
+ /* Ignore strange line */
+ }
+ } else {
+ /*
+ ** Normal lines are scanned for
+ ** references to articles.
+ */
+ char * space = strchr(line, ' ');
+ if (space++)
+ write_anchor(space, space);
+ } /* if not dot */
+ p = line; /* Restart at beginning */
+ } /* if end of line */
+ } /* Loop over characters */
+
+ /* leaving loop with "done" set */
+ } /* Good status */
+ }
+#endif /* USE_XHDR */
+
+ /*
+ ** Read newsgroup using individual fields.
+ */
+ if (!done) {
+ START(HTML_B);
+ if (first == first_required && last == last_required)
+ PUTS("All available articles in ");
+ else
+ PUTS("Articles in ");
+ PUTS(groupName);
+ END(HTML_B);
+ PUTC('\n');
+ if (LYListNewsNumbers)
+ start_list(first_required);
+ else
+ START(HTML_UL);
+ for (art = first_required; art <= last_required; art++) {
+/*#define OVERLAP*/
+#ifdef OVERLAP
+ /*
+ ** With this code we try to keep the server running flat out
+ ** by queuing just one extra command ahead of time.
+ ** We assume (1) that the server won't abort if it gets input
+ ** during output, and (2) that TCP buffering is enough for the
+ ** two commands. Both these assumptions seem very reasonable.
+ ** However, we HAVE had a hangup with a loaded server.
+ */
+ if (art == first_required) {
+ if (art == last_required) { /* Only one */
+ sprintf(buffer, "HEAD %d%c%c",
+ art, CR, LF);
+ status = response(buffer);
+ } else { /* First of many */
+ sprintf(buffer, "HEAD %d%c%cHEAD %d%c%c",
+ art, CR, LF, art+1, CR, LF);
+ status = response(buffer);
+ }
+ } else if (art == last_required) { /* Last of many */
+ status = response(NULL);
+ } else { /* Middle of many */
+ sprintf(buffer, "HEAD %d%c%c", art+1, CR, LF);
+ status = response(buffer);
+ }
+#else /* Not OVERLAP: */
+ sprintf(buffer, "HEAD %d%c%c", art, CR, LF);
+ status = response(buffer);
+#endif /* OVERLAP */
+ /*
+ ** Check for a good response (221) for the HEAD request,
+ ** and if so, parse it. Otherwise, indicate the error
+ ** so that the number of listings corresponds to what's
+ ** claimed for the range, and if we are listing numbers
+ ** via an ordered list, they stay in synchrony with the
+ ** article numbers. - FM
+ */
+ if (status == 221) { /* Head follows - parse it:*/
+ p = line; /* Write pointer */
+ done = NO;
+ while( !done ) {
+ char ch = *p++ = NEXT_CHAR;
+ if (ch == (char)EOF) {
+ if (interrupted_in_htgetcharacter) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ }
+ abort_socket(); /* End of file, close socket */
+ return(HT_LOADED); /* End of file on response */
+ }
+ if ((ch == LF) ||
+ (p == &line[LINE_LENGTH])) {
+
+ *--p = '\0'; /* Terminate & chop LF*/
+ p = line; /* Restart at beginning */
+ if (TRACE)
+ fprintf(stderr, "G %s\n", line);
+ switch(line[0]) {
+
+ case '.':
+ /*
+ ** End of article?
+ */
+ done = ((unsigned char)line[1] < ' ');
+ break;
+
+ case 'S':
+ case 's':
+ if (match(line, "SUBJECT:")) {
+ strcpy(subject, line+9);/* Save subject */
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(subject, subject);
+ HTrjis(subject, subject);
+ }
+ }
+ break;
+
+ case 'M':
+ case 'm':
+ if (match(line, "MESSAGE-ID:")) {
+ char * addr = HTStrip(line+11) +1; /* Chop < */
+ addr[strlen(addr)-1] = '\0'; /* Chop > */
+ StrAllocCopy(reference, addr);
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ if (match(line, "FROM:")) {
+ char * p2;
+ strcpy(author,
+ author_name(strchr(line,':')+1));
+ if (HTCJK == JAPANESE) {
+ HTmmdecode(author, author);
+ HTrjis(author, author);
+ }
+ p2 = author + strlen(author) - 1;
+ if (*p2==LF)
+ *p2 = '\0'; /* Chop off newline */
+ }
+ break;
+
+ case 'd':
+ case 'D':
+ if (LYListNewsDates && match(line, "DATE:")) {
+ StrAllocCopy(date,
+ HTStrip(strchr(line,':')+1));
+ }
+ break;
+
+ } /* end switch on first character */
+ } /* if end of line */
+ } /* Loop over characters */
+
+ PUTC('\n');
+ START(HTML_LI);
+ sprintf(buffer, "\"%s\"", subject);
+ if (reference) {
+ write_anchor(buffer, reference);
+ FREE(reference);
+ } else {
+ PUTS(buffer);
+ }
+ if (author[0] != '\0') {
+ PUTS(" - ");
+ if (LYListNewsDates)
+ START(HTML_I);
+ PUTS(author);
+ if (LYListNewsDates)
+ END(HTML_I);
+ author[0] = '\0';
+ }
+ if (date) {
+ if (!diagnostic) {
+ for (i = 0; date[i]; i++) {
+ if (date[i] == ' ') {
+ date[i] = HT_NON_BREAK_SPACE;
+ }
+ }
+ }
+ sprintf(buffer, " [%s]", date);
+ PUTS(buffer);
+ FREE(date);
+ }
+ MAYBE_END(HTML_LI);
+ /*
+ ** Indicate progress! @@@@@@
+ */
+ } else if (status == HT_INTERRUPTED) {
+ interrupted_in_htgetcharacter = 0;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on read, closing socket %d\n",
+ s);
+ NEWS_NETCLOSE(s);
+ s = -1;
+ return(HT_INTERRUPTED);
+ } else {
+ /*
+ ** Use the response text on error. - FM
+ */
+ PUTC('\n');
+ START(HTML_LI);
+ START(HTML_I);
+ if (LYListNewsNumbers)
+ strcpy(buffer, "Status:");
+ else
+ sprintf(buffer, "Status (ARTICLE %d):", art);
+ PUTS(buffer);
+ END(HTML_I);
+ PUTC(' ');
+ PUTS(response_text);
+ MAYBE_END(HTML_LI);
+ } /* Handle response to HEAD request */
+ } /* Loop over article */
+ } /* If read headers */
+ PUTC('\n');
+ if (LYListNewsNumbers)
+ END(HTML_OL);
+ else
+ END(HTML_UL);
+ PUTC('\n');
+
+ /*
+ ** Link to later articles.
+ */
+ if (last_required < last) {
+ int after; /* End of article after */
+ after = last_required+HTNewsChunkSize;
+ if (after == last)
+ sprintf(buffer, "%s%s", NewsHREF, groupName); /* original group */
+ else
+ sprintf(buffer, "%s%s/%d-%d", NewsHREF, groupName,
+ last_required+1, after);
+ if (TRACE)
+ fprintf(stderr, " Block after is %s\n", buffer);
+ PUTC('(');
+ start_anchor(buffer);
+ PUTS("Later articles");
+ END(HTML_A);
+ PUTS("...)\n");
+ }
+
+add_post:
+ if (HTCanPost) {
+ /*
+ ** We have permission to POST to this host,
+ ** so add a link for posting messages to
+ ** this newsgroup. - FM
+ */
+ char *href = NULL;
+
+ START(HTML_HR);
+ PUTC('\n');
+ if (!strncasecomp(NewsHREF, "snews:", 6))
+ StrAllocCopy(href,"snewspost://");
+ else
+ StrAllocCopy(href,"newspost://");
+ StrAllocCat(href, NewsHost);
+ StrAllocCat(href, "/");
+ StrAllocCat(href,groupName);
+ start_anchor(href);
+ PUTS("Post to ");
+ PUTS(groupName);
+ END(HTML_A);
+ FREE(href);
+ } else {
+ START(HTML_HR);
+ }
+ PUTC('\n');
+ return(HT_LOADED);
+}
+
+/* Load by name. HTLoadNews
+** =============
+*/
+PRIVATE int HTLoadNews ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, stream)
+{
+ char command[260]; /* The whole command */
+ char proxycmd[260]; /* The proxy command */
+ char groupName[GROUP_NAME_LENGTH]; /* Just the group name */
+ int status; /* tcp return */
+ int retries; /* A count of how hard we have tried */
+ BOOL group_wanted; /* Flag: group was asked for, not article */
+ BOOL list_wanted; /* Flag: list was asked for, not article */
+ BOOL post_wanted; /* Flag: new post to group was asked for */
+ BOOL reply_wanted; /* Flag: followup post was asked for */
+ BOOL spost_wanted; /* Flag: new SSL post to group was asked for */
+ BOOL sreply_wanted; /* Flag: followup SSL post was asked for */
+ BOOL head_wanted = NO; /* Flag: want HEAD of single article */
+ int first, last; /* First and last articles asked for */
+ char *cp = 0;
+ char *ListArg = NULL;
+ char *ProxyHost = NULL;
+ char *ProxyHREF = NULL;
+ char *postfile = NULL;
+
+ diagnostic = (format_out == WWW_SOURCE || /* set global flag */
+ format_out == HTAtom_for("www/download") ||
+ format_out == HTAtom_for("www/dump"));
+ rawtext = NO;
+
+ if (TRACE) fprintf(stderr, "HTNews: Looking for %s\n", arg);
+
+ if (!initialized)
+ initialized = initialize();
+ if (!initialized)
+ return -1; /* FAIL */
+
+ FREE(NewsHREF);
+ command[0] = '\0';
+ command[259] = '\0';
+ proxycmd[0] = '\0';
+ proxycmd[259] = '\0';
+
+ {
+ CONST char * p1 = arg;
+
+ /*
+ ** We will ask for the document, omitting the host name & anchor.
+ **
+ ** Syntax of address is
+ ** xxx@yyy Article
+ ** <xxx@yyy> Same article
+ ** xxxxx News group (no "@")
+ ** group/n1-n2 Articles n1 to n2 in group
+ */
+ spost_wanted = (strstr(arg, "snewspost:") != NULL);
+ sreply_wanted = (!(spost_wanted) &&
+ strstr(arg, "snewsreply:") != NULL);
+ post_wanted = (!(spost_wanted || sreply_wanted) &&
+ strstr(arg, "newspost:") != NULL);
+ reply_wanted = (!(spost_wanted || sreply_wanted ||
+ post_wanted) &&
+ strstr(arg, "newsreply:") != NULL);
+ group_wanted = (!(spost_wanted || sreply_wanted ||
+ post_wanted || reply_wanted) &&
+ strchr(arg, '@') == NULL) && (strchr(arg, '*') == NULL);
+ list_wanted = (!(spost_wanted || sreply_wanted ||
+ post_wanted || reply_wanted ||
+ group_wanted) &&
+ strchr(arg, '@') == NULL) && (strchr(arg, '*') != NULL);
+
+ if (!strncasecomp(arg, "snewspost:", 10) ||
+ !strncasecomp(arg, "snewsreply:", 11)) {
+ HTAlert(
+ "This client does not contain support for posting to news with SSL.");
+ return HT_NOT_LOADED;
+ }
+ if (post_wanted || reply_wanted || spost_wanted || sreply_wanted) {
+ /*
+ ** Make sure we have a non-zero path for the newsgroup(s). - FM
+ */
+ if ((p1 = strrchr(arg, '/')) != NULL) {
+ p1++;
+ } else if ((p1 = strrchr(arg, ':')) != NULL) {
+ p1++;
+ }
+ if (!(p1 && *p1)) {
+ HTAlert("Invalid URL!");
+ return(HT_NO_DATA);
+ }
+ if (!(cp = HTParse(arg, "", PARSE_HOST)) || *cp == '\0') {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, HTNewsHost)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, HTNewsHost);
+ } else {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, cp)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, cp);
+ }
+ FREE(cp);
+ sprintf(command, "%s://%.245s/",
+ (post_wanted ?
+ "newspost" :
+ (reply_wanted ?
+ "newreply" :
+ (spost_wanted ?
+ "snewspost" : "snewsreply"))), NewsHost);
+ StrAllocCopy(NewsHREF, command);
+
+ /*
+ ** If the SSL daemon is being used as a proxy,
+ ** reset p1 to the start of the proxied URL
+ ** rather than to the start of the newsgroup(s). - FM
+ */
+ if (spost_wanted && strncasecomp(arg, "snewspost:", 10))
+ p1 = strstr(arg, "snewspost:");
+ if (sreply_wanted && strncasecomp(arg, "snewsreply:", 11))
+ p1 = strstr(arg, "snewsreply:");
+
+ /* p1 = HTParse(arg, "", PARSE_PATH | PARSE_PUNCTUATION); */
+ /*
+ ** Don't use HTParse because news: access doesn't follow traditional
+ ** rules. For instance, if the article reference contains a '#',
+ ** the rest of it is lost -- JFG 10/7/92, from a bug report
+ */
+ } else if (!strncasecomp (arg, "nntp:", 5)) {
+ if (((*(arg + 5) == '\0') ||
+ (!strcmp((arg + 5), "/") ||
+ !strcmp((arg + 5), "//") ||
+ !strcmp((arg + 5), "///"))) ||
+ ((!strncmp((arg + 5), "//", 2)) &&
+ (!(cp = strchr((arg + 7), '/')) || *(cp + 1) == '\0'))) {
+ p1 = "*";
+ group_wanted = FALSE;
+ list_wanted = TRUE;
+ } else if (*(arg + 5) != '/') {
+ p1 = (arg + 5);
+ } else if (*(arg + 5) == '/' && *(arg + 6) != '/') {
+ p1 = (arg + 6);
+ } else {
+ p1 = (cp + 1);
+ }
+ if (!(cp = HTParse(arg, "", PARSE_HOST)) || *cp == '\0') {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, HTNewsHost)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, HTNewsHost);
+ } else {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, cp)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, cp);
+ }
+ FREE(cp);
+ sprintf(command, "nntp://%.251s/", NewsHost);
+ StrAllocCopy(NewsHREF, command);
+ }
+ else if (!strncasecomp(arg, "snews:", 6)) {
+ HTAlert("This client does not contain support for SNEWS URLs.");
+ return HT_NOT_LOADED;
+ }
+ else if (!strncasecomp (arg, "news:/", 6)) {
+ if (((*(arg + 6) == '\0') ||
+ !strcmp((arg + 6), "/") ||
+ !strcmp((arg + 6), "//")) ||
+ ((*(arg + 6) == '/') &&
+ (!(cp = strchr((arg + 7), '/')) || *(cp + 1) == '\0'))) {
+ p1 = "*";
+ group_wanted = FALSE;
+ list_wanted = TRUE;
+ } else if (*(arg + 6) != '/') {
+ p1 = (arg + 6);
+ } else {
+ p1 = (cp + 1);
+ }
+ if (!(cp = HTParse(arg, "", PARSE_HOST)) || *cp == '\0') {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, HTNewsHost)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, HTNewsHost);
+ } else {
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, cp)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, cp);
+ }
+ FREE(cp);
+ sprintf(command, "news://%.251s/", NewsHost);
+ StrAllocCopy(NewsHREF, command);
+ } else {
+ p1 = (arg + 5); /* Skip "news:" prefix */
+ if (*p1 == '\0') {
+ p1 = "*";
+ group_wanted = FALSE;
+ list_wanted = TRUE;
+ }
+ if (s >= 0 && NewsHost && strcasecomp(NewsHost, HTNewsHost)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ StrAllocCopy(NewsHost, HTNewsHost);
+ StrAllocCopy(NewsHREF, "news:");
+ }
+
+ /*
+ ** Set up any proxy for snews URLs that returns NNTP
+ ** responses for Lynx to convert to HTML, instead of
+ ** doing the conversion itself, and for handling posts
+ ** or followups. - TZ & FM
+ */
+ if (!strncasecomp(p1, "snews:", 6) ||
+ !strncasecomp(p1, "snewspost:", 10) ||
+ !strncasecomp(p1, "snewsreply:", 11)) {
+ StrAllocCopy(ProxyHost, NewsHost);
+ if ((cp = HTParse(p1, "", PARSE_HOST)) != NULL && *cp != '\0') {
+ sprintf(command, "snews://%.250s", cp);
+ StrAllocCopy(NewsHost, cp);
+ } else {
+ sprintf(command, "snews://%.250s", NewsHost);
+ }
+ command[258] = '\0';
+ FREE(cp);
+ sprintf(proxycmd, "GET %.251s%c%c%c%c", command, CR, LF, CR, LF);
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Proxy command is '%.*s'\n",
+ (int)(strlen(proxycmd) - 4), proxycmd);
+ strcat(command, "/");
+ StrAllocCopy(ProxyHREF, NewsHREF);
+ StrAllocCopy(NewsHREF, command);
+ if (spost_wanted || sreply_wanted) {
+ /*
+ ** Reset p1 so that it points to the newsgroup(s).
+ */
+ if ((p1 = strrchr(arg, '/')) != NULL) {
+ p1++;
+ } else {
+ p1 = (strrchr(arg, ':') + 1);
+ }
+ } else {
+ /*
+ ** Reset p1 so that it points to the newgroup
+ ** (or a wildcard), or the article.
+ */
+ if (!(cp = strrchr((p1 + 6), '/')) || *(cp + 1) == '\0') {
+ p1 = "*";
+ group_wanted = FALSE;
+ list_wanted = TRUE;
+ } else {
+ p1 = (cp + 1);
+ }
+ }
+ }
+
+ /*
+ ** Set up command for a post, listing, or article request. - FM
+ */
+ if (post_wanted || reply_wanted || spost_wanted || sreply_wanted) {
+ strcpy(command, "POST");
+ } else if (list_wanted) {
+ sprintf(command, "XGTITLE %.*s", 249, p1);
+ } else if (group_wanted) {
+ char * slash = strchr(p1, '/');
+ strcpy(command, "GROUP ");
+ first = 0;
+ last = 0;
+ if (slash) {
+ *slash = '\0';
+ strcpy(groupName, p1);
+ *slash = '/';
+ (void)sscanf(slash+1, "%d-%d", &first, &last);
+ if ((first > 0) && (isdigit(*(slash+1))) &&
+ (strchr(slash+1, '-') == NULL || first == last)) {
+ /*
+ ** We got a number greater than 0, which will be
+ ** loaded as first, and either no range or the
+ ** range computes to zero, so make last negative,
+ ** as a flag to select the group and then fetch
+ ** an article by number (first) instead of by
+ ** messageID. - FM
+ */
+ last = -1;
+ }
+ } else {
+ strcpy(groupName, p1);
+ }
+ strcat(command, groupName);
+ } else {
+ strcpy(command, "ARTICLE ");
+ if (strchr(p1, '<') == 0)
+ strcat(command,"<");
+ strcat(command, p1);
+ if (strchr(p1, '>') == 0)
+ strcat(command,">");
+ }
+
+ {
+ char * p = command + strlen(command);
+ /*
+ ** Terminate command with CRLF, as in RFC 977.
+ */
+ *p++ = CR; /* Macros to be correct on Mac */
+ *p++ = LF;
+ *p++ = 0;
+ }
+ StrAllocCopy(ListArg, p1);
+ } /* scope of p1 */
+
+ if (!*arg) {
+ FREE(NewsHREF);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ FREE(ListArg);
+ return NO; /* Ignore if no name */
+ }
+
+ if (!(post_wanted || reply_wanted || spost_wanted || sreply_wanted ||
+ (group_wanted && last != -1) || list_wanted)) {
+ head_wanted = anAnchor->isHEAD;
+ if (head_wanted && !strncmp(command, "ARTICLE_", 8)) {
+ /* overwrite "ARTICLE" - hack... */
+ strcpy(command, "HEAD ");
+ for (cp = command + 5; ; cp++)
+ if ((*cp = *(cp + 3)) == '\0')
+ break;
+ }
+ rawtext = (head_wanted || keep_mime_headers);
+ }
+ if (rawtext) {
+ node_anchor = anAnchor;
+ rawtarget = HTStreamStack(WWW_PLAINTEXT,
+ format_out,
+ stream, anAnchor);
+ if (!rawtarget) {
+ FREE(NewsHost);
+ FREE(NewsHREF);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ FREE(ListArg);
+ HTAlert("No target for raw text!");
+ return(HT_NOT_LOADED);
+ } /* Copy routine entry points */
+ rawtargetClass = *rawtarget->isa;
+ } else
+ /*
+ ** Make a hypertext object with an anchor list.
+ */
+ if (!(post_wanted || reply_wanted || spost_wanted || sreply_wanted)) {
+ node_anchor = anAnchor;
+ target = HTML_new(anAnchor, format_out, stream);
+ targetClass = *target->isa; /* Copy routine entry points */
+ }
+
+ /*
+ ** Now, let's get a stream setup up from the NewsHost.
+ */
+ for (retries = 0; retries < 2; retries++) {
+ if (s < 0) {
+ /* CONNECTING to news host */
+ char url[260];
+ if (!strcmp(NewsHREF, "news:")) {
+ sprintf (url, "lose://%.251s/", NewsHost);
+ } else if (ProxyHREF) {
+ sprintf (url, "%.259s", ProxyHREF);
+ } else {
+ sprintf (url, "%.259s", NewsHREF);
+ }
+ if (TRACE)
+ fprintf (stderr, "News: doing HTDoConnect on '%s'\n", url);
+
+ _HTProgress("Connecting to NewsHost ...");
+
+ status = HTDoConnect (url, "NNTP", NEWS_PORT, &s);
+ if (status == HT_INTERRUPTED) {
+ /*
+ ** Interrupt cleanly.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Interrupted on connect; recovering cleanly.\n");
+ _HTProgress("Connection interrupted.");
+ if (!(post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted)) {
+ ABORT_TARGET;
+ }
+ FREE(NewsHost);
+ FREE(NewsHREF);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return HT_NOT_LOADED;
+ }
+ if (status < 0) {
+ char message[256];
+ NEWS_NETCLOSE(s);
+ s = -1;
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Unable to connect to news host.\n");
+ if (retries < 1)
+ continue;
+ sprintf(message, "Could not access %s.", NewsHost);
+ FREE(NewsHost);
+ FREE(NewsHREF);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return HTLoadError(stream, 500, message);
+ } else {
+ if (TRACE)
+ fprintf(stderr, "HTNews: Connected to news host %s.\n",
+ NewsHost);
+ HTInitInput(s); /* set up buffering */
+ if (proxycmd[0]) {
+ status = NEWS_NETWRITE(s, proxycmd, strlen(proxycmd));
+ if (TRACE)
+ fprintf(stderr,
+ "HTNews: Proxy command returned status '%d'.\n",
+ status);
+ }
+ if (((status = response(NULL)) / 100) != 2) {
+ char message[BIG];
+ NEWS_NETCLOSE(s);
+ s = -1;
+ if (status == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ if (!(post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted)) {
+ ABORT_TARGET;
+ }
+ FREE(NewsHost);
+ FREE(NewsHREF);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return(HT_NOT_LOADED);
+ }
+ if (retries < 1)
+ continue;
+ sprintf(message,
+ "Can't read news info. News host %.20s responded: %.200s",
+ NewsHost, response_text);
+ return HTLoadError(stream, 500, message);
+ }
+ if (status == 200) {
+ HTCanPost = TRUE;
+ } else {
+ HTCanPost = FALSE;
+ if (post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted) {
+ HTAlert("Cannot POST to this host.");
+ FREE(NewsHREF);
+ if (ProxyHREF) {
+ StrAllocCopy(NewsHost, ProxyHost);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ }
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return(HT_NOT_LOADED);
+ }
+ }
+ }
+ } /* If needed opening */
+
+ if (post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted) {
+ if (!HTCanPost) {
+ HTAlert("Cannot POST to this host.");
+ FREE(NewsHREF);
+ if (ProxyHREF) {
+ StrAllocCopy(NewsHost, ProxyHost);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ }
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return(HT_NOT_LOADED);
+ }
+ if (postfile == NULL) {
+ postfile = LYNewsPost(ListArg, (reply_wanted || sreply_wanted));
+ }
+ if (postfile == NULL) {
+ HTProgress("Cancelled!");
+ FREE(NewsHREF);
+ if (ProxyHREF) {
+ StrAllocCopy(NewsHost, ProxyHost);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ }
+ FREE(ListArg);
+ return(HT_NOT_LOADED);
+ }
+ } else {
+ /*
+ ** Ensure reader mode, but don't bother checking the
+ ** status for anything but HT_INTERRUPTED or a 480
+ ** Authorization request, because if the reader mode
+ ** command is not needed, the server probably returned
+ ** a 500, which is irrelevant at this point. - FM
+ */
+ char buffer[20];
+
+ sprintf(buffer, "mode reader%c%c", CR, LF);
+ if ((status = response(buffer)) == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ break;
+ }
+ if (status == 480) {
+ NNTPAuthResult auth_result = HTHandleAuthInfo(NewsHost);
+ if (auth_result == NNTPAUTH_CLOSE) {
+ if (s != -1 && !(ProxyHost || ProxyHREF)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ }
+ if (auth_result != NNTPAUTH_OK) {
+ break;
+ }
+ if ((status = response(buffer)) == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ break;
+ }
+ }
+ }
+
+Send_NNTP_command:
+ if ((status = response(command)) == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ break;
+ }
+ if (status < 0) {
+ if (retries < 1) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ /*
+ * For some well known error responses which are expected
+ * to occur in normal use, break from the loop without retrying
+ * and without closing the connection. It is unlikely that
+ * these are leftovers from a timed-out connection (but we do
+ * some checks to see whether the response rorresponds to the
+ * last command), or that they will give anything else when
+ * automatically retried. - kw
+ */
+ if (status == 411 && group_wanted &&
+ !strncmp(command, "GROUP ", 6) &&
+ !strncasecomp(response_text + 3, " No such group ", 15) &&
+ !strcmp(response_text + 18, groupName)) {
+
+ HTAlert(response_text);
+ break;
+ } else if (status == 430 && !group_wanted && !list_wanted &&
+ !strncmp(command, "ARTICLE <", 9) &&
+ !strcasecomp(response_text + 3, " No such article")) {
+
+ HTAlert(response_text);
+ break;
+ }
+ if ((status/100) != 2 &&
+ status != 340 &&
+ status != 480) {
+ if (retries) {
+ if (list_wanted && !strncmp(command, "XGTITLE", 7)) {
+ sprintf(command, "LIST NEWSGROUPS%c%c", CR, LF);
+ goto Send_NNTP_command;
+ }
+ HTAlert(response_text);
+ } else {
+ _HTProgress(response_text);
+ }
+ NEWS_NETCLOSE(s);
+ s = -1;
+ /*
+ ** Message might be a leftover "Timeout-disconnected",
+ ** so try again if the retries maximum has not been
+ ** reached.
+ */
+ continue;
+ }
+
+ /*
+ ** Post or load a group, article, etc
+ */
+ if (status == 480) {
+ NNTPAuthResult auth_result;
+ /*
+ * Some servers return 480 for a failed XGTITLE. - FM
+ */
+ if (list_wanted && !strncmp(command, "XGTITLE", 7) &&
+ strstr(response_text, "uthenticat") == NULL &&
+ strstr(response_text, "uthor") == NULL) {
+ sprintf(command, "LIST NEWSGROUPS%c%c", CR, LF);
+ goto Send_NNTP_command;
+ }
+ /*
+ ** Handle Authorization. - FM
+ */
+ if ((auth_result = HTHandleAuthInfo(NewsHost)) == NNTPAUTH_OK) {
+ goto Send_NNTP_command;
+ } else if (auth_result == NNTPAUTH_CLOSE) {
+ if (s != -1 && !(ProxyHost || ProxyHREF)) {
+ NEWS_NETCLOSE(s);
+ s = -1;
+ }
+ if (retries < 1)
+ continue;
+ }
+ status = HT_NOT_LOADED;
+ } else if (post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted) {
+ /*
+ ** Handle posting of an article. - FM
+ */
+ if (status != 340) {
+ HTAlert("Cannot POST to this host.");
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ }
+ } else {
+ post_article(postfile);
+ }
+ FREE(postfile);
+ status = HT_NOT_LOADED;
+ } else if (list_wanted) {
+ /*
+ ** List available newsgroups. - FM
+ */
+ _HTProgress("Reading list of available newsgroups.");
+ status = read_list(ListArg);
+ } else if (group_wanted) {
+ /*
+ ** List articles in a news group. - FM
+ */
+ if (last < 0) {
+ /*
+ ** We got one article number rather than a range
+ ** following the slash which followed the group
+ ** name, or the range was zero, so now that we
+ ** have selected that group, load ARTICLE and the
+ ** the number (first) as the command and go back
+ ** to send it and check the response. - FM
+ */
+ sprintf(command, "%s %d%c%c",
+ head_wanted ? "HEAD" : "ARTICLE",
+ first, CR, LF);
+ group_wanted = FALSE;
+ retries = 2;
+ goto Send_NNTP_command;
+ }
+ _HTProgress("Reading list of articles in newsgroup.");
+ status = read_group(groupName, first, last);
+ } else {
+ /*
+ ** Get an article from a news group. - FM
+ */
+ _HTProgress("Reading news article.");
+ status = read_article();
+ }
+ if (status == HT_INTERRUPTED) {
+ _HTProgress("Connection interrupted.");
+ status = HT_LOADED;
+ }
+ if (!(post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted)) {
+ if (status == HT_NOT_LOADED) {
+ ABORT_TARGET;
+ } else {
+ FREE_TARGET;
+ }
+ }
+ FREE(NewsHREF);
+ if (ProxyHREF) {
+ StrAllocCopy(NewsHost, ProxyHost);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ }
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return status;
+ } /* Retry loop */
+
+ /* HTAlert("Sorry, could not load requested news."); */
+
+/* NXRunAlertPanel(NULL, "Sorry, could not load `%s'.",
+ NULL,NULL,NULL, arg);No -- message earlier wil have covered it */
+
+ if (!(post_wanted || reply_wanted ||
+ spost_wanted || sreply_wanted)) {
+ ABORT_TARGET;
+ }
+ FREE(NewsHREF);
+ if (ProxyHREF) {
+ StrAllocCopy(NewsHost, ProxyHost);
+ FREE(ProxyHost);
+ FREE(ProxyHREF);
+ }
+ FREE(ListArg);
+ if (postfile) {
+#ifdef VMS
+ while (remove(postfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(postfile);
+#endif /* VMS */
+ FREE(postfile);
+ }
+ return HT_NOT_LOADED;
+}
+
+/*
+** This function clears all authorization information by
+** invoking the free_HTAAGlobals() function, which normally
+** is invoked at exit. It allows a browser command to do
+** this at any time, for example, if the user is leaving
+** the terminal for a period of time, but does not want
+** to end the current session. - FM
+*/
+PUBLIC void HTClearNNTPAuthInfo NOARGS
+{
+ /*
+ ** Need code to check cached documents and do
+ ** something to ensure that any protected
+ ** documents no longer can be accessed without
+ ** a new retrieval. - FM
+ */
+
+ /*
+ ** Now free all of the authorization info. - FM
+ */
+ free_NNTP_AuthInfo();
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTNEWS_C_1_INIT { "news", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTNews,_HTNEWS_C_1_INIT);
+#define _HTNEWS_C_2_INIT { "nntp", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTNNTP,_HTNEWS_C_2_INIT);
+#define _HTNEWS_C_3_INIT { "newspost", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTNewsPost,_HTNEWS_C_3_INIT);
+#define _HTNEWS_C_4_INIT { "newsreply", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTNewsReply,_HTNEWS_C_4_INIT);
+#define _HTNEWS_C_5_INIT { "snews", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTSNews,_HTNEWS_C_5_INIT);
+#define _HTNEWS_C_6_INIT { "snewspost", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTSNewsPost,_HTNEWS_C_6_INIT);
+#define _HTNEWS_C_7_INIT { "snewsreply", HTLoadNews, NULL }
+GLOBALDEF (HTProtocol,HTSNewsReply,_HTNEWS_C_7_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTNews = { "news", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTNNTP = { "nntp", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTNewsPost = { "newspost", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTNewsReply = { "newsreply", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTSNews = { "snews", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTSNewsPost = { "snewspost", HTLoadNews, NULL };
+GLOBALDEF PUBLIC HTProtocol HTSNewsReply = { "snewsreply", HTLoadNews, NULL };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.h
new file mode 100644
index 00000000000..bc25fc87a1b
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTNews.h
@@ -0,0 +1,46 @@
+/* Network News Transfer protocol module for the WWW library
+ HTNEWS
+
+ */
+/* History:
+** 26 Sep 90 Written TBL in Objective-C
+** 29 Nov 91 Downgraded to C, for portable implementation.
+*/
+
+#ifndef HTNEWS_H
+#define HTNEWS_H
+
+#include "HTAccess.h"
+#include "HTAnchor.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF(HTProtocol, HTNews);
+extern GLOBALREF(HTProtocol, HTNNTP);
+extern GLOBALREF(HTProtocol, HTNewsPost);
+extern GLOBALREF(HTProtocol, HTNewsReply);
+extern GLOBALREF(HTProtocol, HTSNews);
+extern GLOBALREF(HTProtocol, HTSNewsPost);
+extern GLOBALREF(HTProtocol, HTSNewsReply);
+#else
+GLOBALREF HTProtocol HTNews;
+GLOBALREF HTProtocol HTNNTP;
+GLOBALREF HTProtocol HTNewsPost;
+GLOBALREF HTProtocol HTNewsReply;
+GLOBALREF HTProtocol HTSNews;
+GLOBALREF HTProtocol HTSNewsPost;
+GLOBALREF HTProtocol HTSNewsReply;
+#endif /* GLOBALREF_IS_MACRO */
+
+extern void HTSetNewsHost PARAMS((
+ CONST char * value));
+extern CONST char * HTGetNewsHost NOPARAMS;
+extern char * HTNewsHost;
+
+extern void HTClearNNTPAuthInfo NOPARAMS;
+
+#endif /* HTNEWS_H */
+
+
+/*
+
+ tbl */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.c
new file mode 100644
index 00000000000..655801fa9e3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.c
@@ -0,0 +1,901 @@
+/* Parse HyperText Document Address HTParse.c
+** ================================
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define HEX_ESCAPE '%'
+
+struct struct_parts {
+ char * access;
+ char * host;
+ char * absolute;
+ char * relative;
+/* char * search; no - treated as part of path */
+ char * anchor;
+};
+
+
+/* Strip white space off a string. HTStrip()
+** -------------------------------
+**
+** On exit,
+** Return value points to first non-white character, or to 0 if none.
+** All trailing white space is OVERWRITTEN with zero.
+*/
+PUBLIC char * HTStrip ARGS1(
+ char *, s)
+{
+#define SPACE(c) ((c == ' ') || (c == '\t') || (c == '\n'))
+ char * p = s;
+ for (p = s; *p; p++)
+ ; /* Find end of string */
+ for (p--; p >= s; p--) {
+ if (SPACE(*p))
+ *p = '\0'; /* Zap trailing blanks */
+ else
+ break;
+ }
+ while (SPACE(*s))
+ s++; /* Strip leading blanks */
+ return s;
+}
+
+/* Scan a filename for its consituents. scan()
+** ------------------------------------
+**
+** On entry,
+** name points to a document name which may be incomplete.
+** On exit,
+** absolute or relative may be nonzero (but not both).
+** host, anchor and access may be nonzero if they were specified.
+** Any which are nonzero point to zero terminated strings.
+*/
+PRIVATE void scan ARGS2(
+ char *, name,
+ struct struct_parts *, parts)
+{
+ char * after_access;
+ char * p;
+#ifdef NOTDEFINED
+ int length = strlen(name);
+#endif /* NOTDEFINED */
+
+ parts->access = NULL;
+ parts->host = NULL;
+ parts->absolute = NULL;
+ parts->relative = NULL;
+ parts->anchor = NULL;
+
+ /*
+ ** Scan left-to-right for a scheme (access).
+ */
+ after_access = name;
+ for (p = name; *p; p++) {
+ if (*p==':') {
+ *p = '\0';
+ parts->access = name; /* Access name has been specified */
+ after_access = (p + 1);
+ break;
+ }
+ if (*p == '/' || *p == '#' || *p == ';' || *p == '?')
+ break;
+ }
+
+#ifdef NOTDEFINED
+ for (p = (name + length-1); p >= name; p--) {}
+#endif /* NOTDEFINED */
+ /*
+ ** Scan left-to-right for a fragment (anchor).
+ */
+ for (p = after_access; *p; p++) {
+ if (*p =='#') {
+ parts->anchor = (p + 1);
+ *p = '\0'; /* terminate the rest */
+ break; /* leave things after first # alone - kw */
+ }
+ }
+
+ /*
+ ** Scan left-to-right for a host or absolute path.
+ */
+ p = after_access;
+ if (*p == '/') {
+ if (p[1] == '/') {
+ parts->host = (p + 2); /* host has been specified */
+ *p = '\0'; /* Terminate access */
+ p = strchr(parts->host, '/'); /* look for end of host name if any */
+ if (p != NULL) {
+ *p = '\0'; /* Terminate host */
+ parts->absolute = (p + 1); /* Root has been found */
+ }
+ } else {
+ parts->absolute = (p + 1); /* Root found but no host */
+ }
+ } else {
+ parts->relative = (*after_access) ?
+ after_access : NULL; /* NULL for "" */
+ }
+
+ /*
+ ** Check schemes that commonly have unescaped hashes.
+ */
+ if (parts->access && parts->anchor) {
+ if ((!parts->host && strcasecomp(parts->access, "lynxcgi")) ||
+ !strcasecomp(parts->access, "nntp") ||
+ !strcasecomp(parts->access, "snews") ||
+ !strcasecomp(parts->access, "news") ||
+ !strcasecomp(parts->access, "data")) {
+ /*
+ * Access specified but no host and not a lynxcgi URL, so the
+ * anchor may not really be one, e.g., news:j462#36487@foo.bar,
+ * or it's an nntp or snews URL, or news URL with a host.
+ * Restore the '#' in the address.
+ */
+ /* but only if we have found a path component of which this will
+ * become part. - kw */
+ if (parts->relative || parts->absolute) {
+ *(parts->anchor - 1) = '#';
+ parts->anchor = NULL;
+ }
+ }
+ }
+
+#ifdef NOT_DEFINED /* search is just treated as part of path */
+ {
+ char *p = (relative ? relative : absolute);
+ if (p != NULL) {
+ char *q = strchr(p, '?'); /* Any search string? */
+ if (q != NULL) {
+ *q = '\0'; /* If so, chop that off. */
+ parts->search = (q + 1);
+ }
+ }
+ }
+#endif /* NOT_DEFINED */
+} /*scan */
+
+
+/* Parse a Name relative to another name. HTParse()
+** --------------------------------------
+**
+** This returns those parts of a name which are given (and requested)
+** substituting bits from the related name where necessary.
+**
+** On entry,
+** aName A filename given
+** relatedName A name relative to which aName is to be parsed
+** wanted A mask for the bits which are wanted.
+**
+** On exit,
+** returns A pointer to a calloc'd string which MUST BE FREED
+*/
+PUBLIC char * HTParse ARGS3(
+ CONST char *, aName,
+ CONST char *, relatedName,
+ int, wanted)
+{
+ char * result = NULL;
+ char * return_value = NULL;
+ int len;
+ char * name = NULL;
+ char * rel = NULL;
+ char * p;
+ char * acc_method;
+ struct struct_parts given, related;
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTParse: aName:%s relatedName:%s\n", aName, relatedName);
+
+ /*
+ ** Allocate the output string.
+ */
+ len = strlen(aName) + strlen(relatedName) + 10;
+ result = (char *)calloc(1, len); /* Lots of space: more than enough */
+ if (result == NULL) {
+ outofmem(__FILE__, "HTParse");
+ }
+
+ /*
+ ** Make working copies of the input strings to cut up.
+ */
+ StrAllocCopy(name, aName);
+ StrAllocCopy(rel, relatedName);
+
+ /*
+ ** Cut up the strings into URL fields.
+ */
+ scan(name, &given);
+ scan(rel, &related);
+
+ /*
+ ** Handle the scheme (access) field.
+ */
+ if (given.access && given.host && !given.relative && !given.absolute) {
+ if (!strcmp(given.access, "http") ||
+ !strcmp(given.access, "https") ||
+ !strcmp(given.access, "ftp"))
+ /*
+ ** Assume root.
+ */
+ given.absolute = "";
+ }
+ acc_method = given.access ? given.access : related.access;
+ if (wanted & PARSE_ACCESS) {
+ if (acc_method) {
+ strcat(result, acc_method);
+ if (wanted & PARSE_PUNCTUATION)
+ strcat(result, ":");
+ }
+ }
+
+ /*
+ ** If different schemes, inherit nothing.
+ **
+ ** We'll try complying with RFC 1808 and
+ ** the Fielding draft, and inherit nothing
+ ** if both schemes are given, rather than
+ ** only when they differ, except for
+ ** file URLs - FM
+ **
+ ** After trying it for a while, it's still
+ ** premature, IHMO, to go along with it, so
+ ** this is back to inheriting for identical
+ ** schemes whether or not they are "file".
+ ** If you want to try it again yourself,
+ ** uncomment the strncasecomp() below. - FM
+ */
+ if ((given.access && related.access) &&
+ (/* strcasecomp(given.access, "file") || */
+ strcmp(given.access, related.access))) {
+ related.host = NULL;
+ related.absolute = NULL;
+ related.relative = NULL;
+ related.anchor = NULL;
+ }
+
+ /*
+ ** Handle the host field.
+ */
+ if (wanted & PARSE_HOST)
+ if (given.host || related.host) {
+ char *tail = result + strlen(result);
+ if (wanted & PARSE_PUNCTUATION)
+ strcat(result, "//");
+ strcat(result, given.host ? given.host : related.host);
+#define CLEAN_URLS
+#ifdef CLEAN_URLS
+ /*
+ ** Ignore default port numbers, and trailing dots on FQDNs,
+ ** which will only cause identical addresses to look different.
+ */
+ {
+ char *p2, *h;
+ if ((p2 = strchr(result, '@')) != NULL)
+ tail = (p2 + 1);
+ p2 = strchr(tail, ':');
+ if (p2 != NULL && !isdigit((unsigned char)p2[1]))
+ /*
+ ** Colon not followed by a port number.
+ */
+ *p2 = '\0';
+ if (p2 != NULL && *p2 != '\0' && acc_method != NULL) {
+ /*
+ ** Port specified.
+ */
+ if ((!strcmp(acc_method, "http" ) && !strcmp(p2, ":80" )) ||
+ (!strcmp(acc_method, "https" ) && !strcmp(p2, ":443")) ||
+ (!strcmp(acc_method, "gopher" ) && !strcmp(p2, ":70" )) ||
+ (!strcmp(acc_method, "ftp" ) && !strcmp(p2, ":21" )) ||
+ (!strcmp(acc_method, "wais" ) && !strcmp(p2, ":210")) ||
+ (!strcmp(acc_method, "nntp" ) && !strcmp(p2, ":119")) ||
+ (!strcmp(acc_method, "news" ) && !strcmp(p2, ":119")) ||
+ (!strcmp(acc_method, "newspost" ) && !strcmp(p2, ":119")) ||
+ (!strcmp(acc_method, "newsreply" ) && !strcmp(p2, ":119")) ||
+ (!strcmp(acc_method, "snews" ) && !strcmp(p2, ":563")) ||
+ (!strcmp(acc_method, "snewspost" ) && !strcmp(p2, ":563")) ||
+ (!strcmp(acc_method, "snewsreply") && !strcmp(p2, ":563")) ||
+ (!strcmp(acc_method, "finger" ) && !strcmp(p2, ":79" )) ||
+ (!strcmp(acc_method, "telnet" ) && !strcmp(p2, ":23" )) ||
+ (!strcmp(acc_method, "tn3270" ) && !strcmp(p2, ":23" )) ||
+ (!strcmp(acc_method, "rlogin" ) && !strcmp(p2, ":513")) ||
+ (!strcmp(acc_method, "cso" ) && !strcmp(p2, ":105")))
+ *p2 = '\0'; /* It is the default: ignore it */
+ }
+ if (p2 == NULL) {
+ int len2 = strlen(tail);
+
+ if (len2 > 0) {
+ h = tail + len2 - 1; /* last char of hostname */
+ if (*h == '.')
+ *h = '\0'; /* chop final . */
+ }
+ } else {
+ h = p2;
+ h--; /* End of hostname */
+ if (*h == '.') {
+ /*
+ ** Slide p2 over h.
+ */
+ while (*p2 != '\0')
+ *h++ = *p2++;
+ *h = '\0'; /* terminate */
+ }
+ }
+ }
+#endif /* CLEAN_URLS */
+ }
+
+ /*
+ ** If different hosts, inherit no path.
+ */
+ if (given.host && related.host)
+ if (strcmp(given.host, related.host) != 0) {
+ related.absolute = NULL;
+ related.relative = NULL;
+ related.anchor = NULL;
+ }
+
+ /*
+ ** Handle the path.
+ */
+ if (wanted & PARSE_PATH) {
+ if (acc_method && !given.absolute && given.relative) {
+ if (!strcasecomp(acc_method, "nntp") ||
+ !strcasecomp(acc_method, "snews") ||
+ (!strcasecomp(acc_method, "news") &&
+ !strncasecomp(result, "news://", 7))) {
+ /*
+ * Treat all given nntp or snews paths,
+ * or given paths for news URLs with a host,
+ * as absolute.
+ */
+ given.absolute = given.relative;
+ given.relative = NULL;
+ }
+ }
+ if (given.absolute) { /* All is given */
+ if (wanted & PARSE_PUNCTUATION)
+ strcat(result, "/");
+ strcat(result, given.absolute);
+ if (TRACE)
+ fprintf(stderr, "1\n");
+ } else if (related.absolute) { /* Adopt path not name */
+ strcat(result, "/");
+ strcat(result, related.absolute);
+ if (given.relative) {
+ p = strchr(result, '?'); /* Search part? */
+ if (p == NULL)
+ p = (result + strlen(result) - 1);
+ for (; *p != '/'; p--)
+ ; /* last / */
+ p[1] = '\0'; /* Remove filename */
+ strcat(result, given.relative); /* Add given one */
+ HTSimplify (result);
+ }
+ if (TRACE)
+ fprintf(stderr, "2\n");
+ } else if (given.relative) {
+ strcat(result, given.relative); /* what we've got */
+ if (TRACE)
+ fprintf(stderr, "3\n");
+ } else if (related.relative) {
+ strcat(result, related.relative);
+ if (TRACE)
+ fprintf(stderr, "4\n");
+ } else { /* No inheritance */
+ if (strncasecomp(aName, "lynxcgi:", 8) &&
+ strncasecomp(aName, "lynxexec:", 9) &&
+ strncasecomp(aName, "lynxprog:", 9)) {
+ strcat(result, "/");
+ }
+ if (!strcmp(result, "news:/"))
+ result[5] = '*';
+ if (TRACE)
+ fprintf(stderr, "5\n");
+ }
+ }
+
+ /*
+ ** Handle the fragment (anchor).
+ */
+ if (wanted & PARSE_ANCHOR)
+ if ((given.anchor && *given.anchor) ||
+ (!given.anchor && related.anchor)) {
+ if (wanted & PARSE_PUNCTUATION)
+ strcat(result, "#");
+ strcat(result, (given.anchor) ?
+ given.anchor : related.anchor);
+ }
+ if (TRACE)
+ fprintf(stderr, "HTParse: result:%s\n", result);
+ FREE(rel);
+ FREE(name);
+
+ StrAllocCopy(return_value, result);
+ FREE(result);
+
+ return return_value; /* exactly the right length */
+}
+
+/* Simplify a filename. HTSimplify()
+** --------------------
+**
+** A unix-style file is allowed to contain the seqeunce xxx/../ which may
+** be replaced by "" , and the seqeunce "/./" which may be replaced by "/".
+** Simplification helps us recognize duplicate filenames.
+**
+** Thus, /etc/junk/../fred becomes /etc/fred
+** /etc/junk/./fred becomes /etc/junk/fred
+**
+** but we should NOT change
+** http://fred.xxx.edu/../..
+**
+** or ../../albert.html
+*/
+PUBLIC void HTSimplify ARGS1(
+ char *, filename)
+{
+ char *p;
+ char *q, *q1;
+
+ if (filename == NULL)
+ return;
+
+ if (!(filename[0] && filename[1]) ||
+ filename[0] == '?' || filename[1] == '?' || filename[2] == '?')
+ return;
+
+ if (strchr(filename, '/') != NULL) {
+ for (p = (filename + 2); *p; p++) {
+ if (*p == '?') {
+ /*
+ ** We're still treating a ?searchpart as part of
+ ** the path in HTParse() and scan(), but if we
+ ** encounter a '?' here, assume it's the delimiter
+ ** and break. We also could check for a parameter
+ ** delimiter (';') here, but the current Fielding
+ ** draft (wisely or ill-advisedly :) says that it
+ ** should be ignored and collapsing be allowed in
+ ** it's value). The only defined parameter at
+ ** present is ;type=[A, I, or D] for ftp URLs, so
+ ** if there's a "/..", "/../", "/./", or terminal
+ ** '.' following the ';', it must be due to the
+ ** ';' being an unescaped path character and not
+ ** actually a parameter delimiter. - FM
+ */
+ break;
+ }
+ if (*p == '/') {
+ if ((p[1] == '.') && (p[2] == '.') &&
+ (p[3] == '/' || p[3] == '?' || p[3] == '\0')) {
+ /*
+ ** Handle "../", "..?" or "..".
+ */
+ for (q = (p - 1); (q >= filename) && (*q != '/'); q--)
+ /*
+ ** Back up to previous slash or beginning of string.
+ */
+ ;
+ if ((q[0] == '/') &&
+ (strncmp(q, "/../", 4) &&
+ strncmp(q, "/..?", 4)) &&
+ !((q - 1) > filename && q[-1] == '/')) {
+ /*
+ ** Not at beginning of string or in a
+ ** host field, so remove the "/xxx/..".
+ */
+ q1 = (p + 3);
+ p = q;
+ while (*q1 != '\0')
+ *p++ = *q1++;
+ *p = '\0'; /* terminate */
+#ifdef NOTDEFINED
+ /*
+ ** Make sure filename has at least one slash.
+ */
+ if (*filename == '\0') {
+ *filename = '/';
+ *(filename + 1) = '\0';
+ }
+#endif /* NOTDEFINED */
+ /*
+ ** Start again with previous slash.
+ */
+ p = (q - 1);
+ }
+ } else if (p[1] == '.' && p[2] == '/') {
+ /*
+ ** Handle "./" by removing both characters.
+ */
+ q = p;
+ q1 = (p + 2);
+ while (*q1 != '\0')
+ *q++ = *q1++;
+ *q = '\0'; /* terminate */
+ p--;
+ } else if (p[1] == '.' && p[2] == '?') {
+ /*
+ ** Handle ".?" by removing the dot.
+ */
+ q = (p + 1);
+ q1 = (p + 2);
+ while (*q1 != '\0')
+ *q++ = *q1++;
+ *q = '\0'; /* terminate */
+ p--;
+ } else if (p[1] == '.' && p[2] == '\0') {
+ /*
+ ** Handle terminal "." by removing the character.
+ */
+ p[1] = '\0';
+ }
+ }
+ }
+ if (p >= filename + 2 && *p == '?' && *(p-1) == '.') {
+ if (*(p-2) == '/') {
+ /*
+ ** Handle "/.?" by removing the dot.
+ */
+ q = p - 1;
+ q1 = p;
+ while (*q1 != '\0')
+ *q++ = *q1++;
+ *q = '\0';
+ } else if (*(p-2) == '.' &&
+ p >= filename + 4 && *(p-3) == '/' &&
+ (*(p-4) != '/' ||
+ (p > filename + 4 && *(p-5) != ':'))) {
+ /*
+ ** Handle "xxx/..?"
+ */
+ for (q = (p - 4); (q > filename) && (*q != '/'); q--)
+ /*
+ ** Back up to previous slash or beginning of string.
+ */
+ ;
+ if (*q == '/') {
+ if (q > filename && *(q-1) == '/' &&
+ !(q > filename + 1 && *(q-1) != ':'))
+ return;
+ q++;
+ }
+ if (strncmp(q, "../", 3) && strncmp(q, "./", 2)) {
+ /*
+ ** Not after "//" at beginning of string or
+ ** after "://", and xxx is not ".." or ".",
+ ** so remove the "xxx/..".
+ */
+ q1 = p;
+ p = q;
+ while (*q1 != '\0')
+ *p++ = *q1++;
+ *p = '\0'; /* terminate */
+ }
+ }
+ }
+ }
+}
+
+/* Make Relative Name. HTRelative()
+** -------------------
+**
+** This function creates and returns a string which gives an expression of
+** one address as related to another. Where there is no relation, an absolute
+** address is retured.
+**
+** On entry,
+** Both names must be absolute, fully qualified names of nodes
+** (no anchor bits)
+**
+** On exit,
+** The return result points to a newly allocated name which, if
+** parsed by HTParse relative to relatedName, will yield aName.
+** The caller is responsible for freeing the resulting name later.
+**
+*/
+PUBLIC char * HTRelative ARGS2(
+ CONST char *, aName,
+ CONST char *, relatedName)
+{
+ char * result = NULL;
+ CONST char *p = aName;
+ CONST char *q = relatedName;
+ CONST char * after_access = NULL;
+ CONST char * path = NULL;
+ CONST char * last_slash = NULL;
+ int slashes = 0;
+
+ for (; *p; p++, q++) { /* Find extent of match */
+ if (*p != *q)
+ break;
+ if (*p == ':')
+ after_access = p+1;
+ if (*p == '/') {
+ last_slash = p;
+ slashes++;
+ if (slashes == 3)
+ path=p;
+ }
+ }
+
+ /* q, p point to the first non-matching character or zero */
+
+ if (!after_access) { /* Different access */
+ StrAllocCopy(result, aName);
+ } else if (slashes < 3){ /* Different nodes */
+ StrAllocCopy(result, after_access);
+ } else if (slashes == 3){ /* Same node, different path */
+ StrAllocCopy(result, path);
+ } else { /* Some path in common */
+ int levels = 0;
+ for (; *q && (*q != '#'); q++)
+ if (*q == '/')
+ levels++;
+ result = (char *)calloc(1, (3*levels + strlen(last_slash) + 1));
+ if (result == NULL)
+ outofmem(__FILE__, "HTRelative");
+ result[0] = '\0';
+ for (; levels; levels--)
+ strcat(result, "../");
+ strcat(result, last_slash+1);
+ }
+ if (TRACE)
+ fprintf(stderr, "HT: `%s' expressed relative to\n `%s' is\n `%s'.",
+ aName, relatedName, result);
+ return result;
+}
+
+/* Escape undesirable characters using % HTEscape()
+** -------------------------------------
+**
+** This function takes a pointer to a string in which
+** some characters may be unacceptable unescaped.
+** It returns a string which has these characters
+** represented by a '%' character followed by two hex digits.
+**
+** Unlike HTUnEscape(), this routine returns a calloced string.
+*/
+PRIVATE CONST unsigned char isAcceptable[96] =
+
+/* Bit 0 xalpha -- see HTFile.h
+** Bit 1 xpalpha -- as xalpha but with plus.
+** Bit 3 ... path -- as xpalphas but with /
+*/
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 0,0,0,0,0,0,0,0,0,0,7,6,0,7,7,4, /* 2x !"#$%&'()*+,-./ */
+ 7,7,7,7,7,7,7,7,7,7,0,0,0,0,0,0, /* 3x 0123456789:;<=>? */
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 4x @ABCDEFGHIJKLMNO */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,7, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, /* 6x `abcdefghijklmno */
+ 7,7,7,7,7,7,7,7,7,7,7,0,0,0,0,0 }; /* 7X pqrstuvwxyz{|}~ DEL */
+
+PRIVATE char *hex = "0123456789ABCDEF";
+#define ACCEPTABLE(a) ( a>=32 && a<128 && ((isAcceptable[a-32]) & mask))
+
+PUBLIC char * HTEscape ARGS2(
+ CONST char *, str,
+ unsigned char, mask)
+{
+ CONST char * p;
+ char * q;
+ char * result;
+ int unacceptable = 0;
+ for (p = str; *p; p++)
+ if (!ACCEPTABLE((unsigned char)TOASCII(*p)))
+ unacceptable++;
+ result = (char *)calloc(1, (p-str + unacceptable + unacceptable + 1));
+ if (result == NULL)
+ outofmem(__FILE__, "HTEscape");
+ for (q = result, p = str; *p; p++) {
+ unsigned char a = TOASCII(*p);
+ if (!ACCEPTABLE(a)) {
+ *q++ = HEX_ESCAPE; /* Means hex commming */
+ *q++ = hex[a >> 4];
+ *q++ = hex[a & 15];
+ }
+ else *q++ = *p;
+ }
+ *q++ = '\0'; /* Terminate */
+ return result;
+}
+
+/* Escape undesirable characters using % but space to +. HTEscapeSP()
+** -----------------------------------------------------
+**
+** This function takes a pointer to a string in which
+** some characters may be unacceptable unescaped.
+** It returns a string which has these characters
+** represented by a '%' character followed by two hex digits,
+** except that spaces are converted to '+' instead of %2B.
+**
+** Unlike HTUnEscape(), this routine returns a calloced string.
+*/
+PUBLIC char * HTEscapeSP ARGS2(
+ CONST char *, str,
+ unsigned char, mask)
+{
+ CONST char * p;
+ char * q;
+ char * result;
+ int unacceptable = 0;
+ for (p = str; *p; p++)
+ if (!(*p == ' ' || ACCEPTABLE((unsigned char)TOASCII(*p))))
+ unacceptable++;
+ result = (char *)calloc(1, (p-str + unacceptable + unacceptable + 1));
+ if (result == NULL)
+ outofmem(__FILE__, "HTEscape");
+ for (q = result, p = str; *p; p++) {
+ unsigned char a = TOASCII(*p);
+ if (a == 32) {
+ *q++ = '+';
+ } else if (!ACCEPTABLE(a)) {
+ *q++ = HEX_ESCAPE; /* Means hex commming */
+ *q++ = hex[a >> 4];
+ *q++ = hex[a & 15];
+ } else {
+ *q++ = *p;
+ }
+ }
+ *q++ = '\0'; /* Terminate */
+ return result;
+}
+
+/* Decode %xx escaped characters. HTUnEscape()
+** ------------------------------
+**
+** This function takes a pointer to a string in which some
+** characters may have been encoded in %xy form, where xy is
+** the acsii hex code for character 16x+y.
+** The string is converted in place, as it will never grow.
+*/
+PRIVATE char from_hex ARGS1(
+ char, c)
+{
+ return c >= '0' && c <= '9' ? c - '0'
+ : c >= 'A' && c <= 'F'? c - 'A' + 10
+ : c - 'a' + 10; /* accept small letters just in case */
+}
+
+PUBLIC char * HTUnEscape ARGS1(
+ char *, str)
+{
+ char * p = str;
+ char * q = str;
+
+ if (!(p && *p))
+ return str;
+
+ while (*p != '\0') {
+ if (*p == HEX_ESCAPE &&
+ /*
+ * Tests shouldn't be needed, but better safe than sorry.
+ */
+ p[1] && p[2] &&
+ isxdigit((unsigned char)p[1]) &&
+ isxdigit((unsigned char)p[2])) {
+ p++;
+ if (*p)
+ *q = from_hex(*p++) * 16;
+ if (*p)
+ *q = FROMASCII(*q + from_hex(*p++));
+ q++;
+ } else {
+ *q++ = *p++;
+ }
+ }
+
+ *q++ = '\0';
+ return str;
+
+} /* HTUnEscape */
+
+/* Decode some %xx escaped characters. HTUnEscapeSome()
+** ----------------------------------- Klaus Weide
+** (kweide@tezcat.com)
+** This function takes a pointer to a string in which some
+** characters may have been encoded in %xy form, where xy is
+** the acsii hex code for character 16x+y, and a pointer to
+** a second string containing one or more characters which
+** should be unescaped if escaped in the first string.
+** The first string is converted in place, as it will never grow.
+*/
+PUBLIC char * HTUnEscapeSome ARGS2(
+ char *, str,
+ CONST char *, do_trans)
+{
+ char * p = str;
+ char * q = str;
+ char testcode;
+
+ if (p == NULL || *p == '\0' || do_trans == NULL || *do_trans == '\0')
+ return str;
+
+ while (*p != '\0') {
+ if (*p == HEX_ESCAPE &&
+ p[1] && p[2] && /* tests shouldn't be needed, but.. */
+ isxdigit((unsigned char)p[1]) &&
+ isxdigit((unsigned char)p[2]) &&
+ (testcode = from_hex(p[1])*16 + from_hex(p[2])) && /* %00 no good*/
+ strchr(do_trans, testcode)) { /* it's one of the ones we want */
+ *q++ = FROMASCII(testcode);
+ p += 3;
+ } else {
+ *q++ = *p++;
+ }
+ }
+
+ *q++ = '\0';
+ return str;
+
+} /* HTUnEscapeSome */
+
+PRIVATE CONST unsigned char crfc[96] =
+
+/* Bit 0 xalpha -- need "quoting"
+** Bit 1 xpalpha -- need \escape if quoted
+*/
+ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
+ { 1,0,3,0,0,0,0,0,1,1,0,0,1,0,1,0, /* 2x !"#$%&'()*+,-./ */
+ 0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0, /* 3x 0123456789:;<=>? */
+ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4x @ABCDEFGHIJKLMNO */
+ 0,0,0,0,0,0,0,0,0,0,0,1,2,1,0,0, /* 5X PQRSTUVWXYZ[\]^_ */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6x `abcdefghijklmno */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 }; /* 7X pqrstuvwxyz{|}~ DEL */
+
+/*
+** Turn a string which is not a RFC 822 token into a quoted-string. - KW
+*/
+PUBLIC void HTMake822Word ARGS1(
+ char **, str)
+{
+ CONST char * p;
+ char * q;
+ char * result;
+ unsigned char a;
+ int added = 0;
+ if (!(*str) || !(**str)) {
+ StrAllocCopy(*str, "\"\"");
+ return;
+ }
+ for (p = *str; *p; p++) {
+ a = *p;
+ if (a < 32 || a >= 128 ||
+ ((crfc[a-32]) & 1)) {
+ if (!added)
+ added = 2;
+ if (a >= 160 || a == '\t')
+ continue;
+ if (a == '\r' || a == '\n')
+ added += 2;
+ else if ((a & 127) < 32 || ((crfc[a-32]) & 2))
+ added++;
+ }
+ }
+ if (!added)
+ return;
+ result = (char *)calloc(1, (p-(*str) + added + 1));
+ if (result == NULL)
+ outofmem(__FILE__, "HTMake822Word");
+ result[0] = '"';
+ for (q = result + 1, p = *str; *p; p++) {
+ a = TOASCII(*p);
+ if ((a != '\t') && ((a & 127) < 32 ||
+ ( a < 128 && ((crfc[a-32]) & 2))))
+ *q++ = '\\';
+ *q++ = *p;
+ if (a == '\n' || (a == '\r' && (TOASCII(*(p+1)) != '\n')))
+ *q++ = ' ';
+ }
+ *q++ = '"';
+ *q++ = '\0'; /* Terminate */
+ FREE(*str);
+ *str = result;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.h
new file mode 100644
index 00000000000..2f77f0796cf
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTParse.h
@@ -0,0 +1,167 @@
+/* HTParse: URL parsing in the WWW Library
+** HTPARSE
+**
+** This module of the WWW library contains code to parse URLs and various
+** related things.
+** Implemented by HTParse.c .
+*/
+#ifndef HTPARSE_H
+#define HTPARSE_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+/*
+** The following are flag bits which may be ORed together to form
+** a number to give the 'wanted' argument to HTParse.
+*/
+#define PARSE_ACCESS 16
+#define PARSE_HOST 8
+#define PARSE_PATH 4
+#define PARSE_ANCHOR 2
+#define PARSE_PUNCTUATION 1
+#define PARSE_ALL 31
+
+/*
+** The following are valid mask values. The terms are the BNF names
+** in the URL document.
+*/
+#define URL_XALPHAS (unsigned char) 1
+#define URL_XPALPHAS (unsigned char) 2
+#define URL_PATH (unsigned char) 4
+
+
+/* Strip white space off a string. HTStrip()
+** -------------------------------
+**
+** On exit,
+** Return value points to first non-white character, or to 0 if none.
+** All trailing white space is OVERWRITTEN with zero.
+*/
+extern char * HTStrip PARAMS((
+ char * s));
+
+/* Parse a Name relative to another name. HTParse()
+** --------------------------------------
+**
+** This returns those parts of a name which are given (and requested)
+** substituting bits from the related name where necessary.
+**
+** On entry,
+** aName A filename given
+** relatedName A name relative to which aName is to be parsed
+** wanted A mask for the bits which are wanted.
+**
+** On exit,
+** returns A pointer to a malloc'd string which MUST BE FREED
+*/
+extern char * HTParse PARAMS((
+ CONST char * aName,
+ CONST char * relatedName,
+ int wanted));
+
+/* Simplify a filename. HTSimplify()
+** --------------------
+**
+** A unix-style file is allowed to contain the seqeunce xxx/../ which may
+** be replaced by "" , and the seqeunce "/./" which may be replaced by "/".
+** Simplification helps us recognize duplicate filenames.
+**
+** Thus, /etc/junk/../fred becomes /etc/fred
+** /etc/junk/./fred becomes /etc/junk/fred
+**
+** but we should NOT change
+** http://fred.xxx.edu/../..
+**
+** or ../../albert.html
+*/
+extern void HTSimplify PARAMS((
+ char * filename));
+
+/* Make Relative Name. HTRelative()
+** -------------------
+**
+** This function creates and returns a string which gives an expression of
+** one address as related to another. Where there is no relation, an absolute
+** address is retured.
+**
+** On entry,
+** Both names must be absolute, fully qualified names of nodes
+** (no anchor bits)
+**
+** On exit,
+** The return result points to a newly allocated name which, if
+** parsed by HTParse relative to relatedName, will yield aName.
+** The caller is responsible for freeing the resulting name later.
+**
+*/
+extern char * HTRelative PARAMS((
+ CONST char * aName,
+ CONST char * relatedName));
+
+/* Escape undesirable characters using % HTEscape()
+** -------------------------------------
+**
+** This function takes a pointer to a string in which
+** some characters may be unacceptable unescaped.
+** It returns a string which has these characters
+** represented by a '%' character followed by two hex digits.
+**
+** Unlike HTUnEscape(), this routine returns a malloced string.
+*/
+extern char * HTEscape PARAMS((
+ CONST char * str,
+ unsigned char mask));
+
+/* Escape undesirable characters using % but space to +. HTEscapeSP()
+** -----------------------------------------------------
+**
+** This function takes a pointer to a string in which
+** some characters may be unacceptable unescaped.
+** It returns a string which has these characters
+** represented by a '%' character followed by two hex digits,
+** except that spaces are converted to '+' instead of %2B.
+**
+** Unlike HTUnEscape(), this routine returns a malloced string.
+*/
+extern char * HTEscapeSP PARAMS((
+ CONST char * str,
+ unsigned char mask));
+
+/* Decode %xx escaped characters. HTUnEscape()
+** ------------------------------
+**
+** This function takes a pointer to a string in which some
+** characters may have been encoded in %xy form, where xy is
+** the acsii hex code for character 16x+y.
+** The string is converted in place, as it will never grow.
+*/
+extern char * HTUnEscape PARAMS((
+ char * str));
+
+/* Decode some %xx escaped characters. HTUnEscapeSome()
+** ----------------------------------- Klaus Weide
+** (kweide@tezcat.com)
+** This function takes a pointer to a string in which some
+** characters may have been encoded in %xy form, where xy is
+** the acsii hex code for character 16x+y, and a pointer to
+** a second string containing one or more characters which
+** should be unescaped if escaped in the first string.
+** The first string is converted in place, as it will never grow.
+*/
+extern char * HTUnEscapeSome PARAMS((
+ char * str,
+ CONST char * do_trans));
+
+/*
+** Turn a string which is not a RFC 822 token into a quoted-string. - KW
+*/
+extern void HTMake822Word PARAMS((
+ char ** str));
+
+#endif /* HTPARSE_H */
+
+/*
+ end of HTParse
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.c
new file mode 100644
index 00000000000..ada39ee5005
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.c
@@ -0,0 +1,301 @@
+
+/* MODULE HTPasswd.c
+** PASSWORD FILE ROUTINES
+**
+** AUTHORS:
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+** MD Mark Donszelmann duns@vxdeop.cern.ch
+**
+** HISTORY:
+** 7 Nov 93 MD free for crypt taken out (static data returned)
+**
+**
+** BUGS:
+**
+**
+*/
+
+
+#include "HTUtils.h"
+#include "tcp.h" /* FROMASCII() */
+#include <string.h>
+#include "HTAAUtil.h" /* Common parts of AA */
+#include "HTAAFile.h" /* File routines */
+#include "HTAAServ.h" /* Server routines */
+#include "HTPasswd.h" /* Implemented here */
+
+#include "LYLeaks.h"
+
+extern char *crypt();
+
+
+PRIVATE char salt_chars [65] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+
+
+/* PRIVATE next_rec()
+** GO TO THE BEGINNING OF THE NEXT RECORD
+** Otherwise like HTAAFile_nextRec() but
+** does not handle continuation lines
+** (because password file has none).
+** ON ENTRY:
+** fp is the password file from which records are read from.
+**
+** ON EXIT:
+** returns nothing. File read pointer is located at the beginning
+** of the next record.
+*/
+PRIVATE void next_rec ARGS1(FILE *, fp)
+{
+ int ch = getc(fp);
+
+ while (ch != EOF && ch != CR && ch != LF)
+ ch = getc(fp); /* Skip until end-of-line */
+
+ while (ch != EOF &&
+ (ch == CR || ch == LF)) /*Skip carriage returns and linefeeds*/
+ ch = getc(fp);
+
+ if (ch != EOF)
+ ungetc(ch, fp);
+}
+
+
+/* PUBLIC HTAA_encryptPasswd()
+** ENCRYPT PASSWORD TO THE FORM THAT IT IS SAVED
+** IN THE PASSWORD FILE.
+** ON ENTRY:
+** password is a string of arbitrary lenght.
+**
+** ON EXIT:
+** returns password in one-way encrypted form.
+**
+** NOTE:
+** Uses currently the C library function crypt(), which
+** only accepts at most 8 characters long strings and produces
+** always 13 characters long strings. This function is
+** called repeatedly so that longer strings can be encrypted.
+** This is of course not as safe as encrypting the entire
+** string at once, but then again, we are not that paranoid
+** about the security inside the machine.
+**
+*/
+PUBLIC char *HTAA_encryptPasswd ARGS1(CONST char *, password)
+{
+ char salt[3];
+ char chunk[9];
+ char *result;
+ char *tmp;
+ CONST char *cur = password;
+ int len = strlen(password);
+ int randum = (int)theTime; /* This is random enough */
+
+ if (!(result = (char*)malloc(13*((strlen(password)+7)/8) + 1)))
+ outofmem(__FILE__, "HTAA_encryptPasswd");
+
+ *result = (char)0;
+ while (len > 0) {
+ salt[0] = salt_chars[randum%64];
+ salt[1] = salt_chars[(randum/64)%64];
+ salt[2] = (char)0;
+
+ strncpy(chunk, cur, 8);
+ chunk[8] = (char)0;
+
+ tmp = crypt((char*)password, salt); /*crypt() doesn't change its args*/
+ strcat(result, tmp);
+
+ cur += 8;
+ len -= 8;
+ } /* while */
+
+ return result;
+}
+
+
+
+/* PUBLIC HTAA_passwdMatch()
+** VERIFY THE CORRECTNESS OF A GIVEN PASSWORD
+** AGAINST A ONE-WAY ENCRYPTED FORM OF PASSWORD.
+** ON ENTRY:
+** password is cleartext password.
+** encrypted is one-way encrypted password, as returned
+** by function HTAA_encryptPasswd().
+** This is typically read from the password
+** file.
+**
+** ON EXIT:
+** returns YES, if password matches the encrypted one.
+** NO, if not, or if either parameter is NULL.
+** FIX:
+** Only the length of original encrypted password is
+** checked -- longer given passwords are accepted if
+** common length is correct (but not shorter).
+** This is to allow interoperation of servers and clients
+** who have a hard-coded limit of 8 to password.
+*/
+PUBLIC BOOL HTAA_passwdMatch ARGS2(CONST char *, password,
+ CONST char *, encrypted)
+{
+ char *result;
+ int len;
+ int status;
+
+ if (!password || !encrypted)
+ return NO;
+
+ len = 13*((strlen(password)+7)/8);
+ if (len < strlen(encrypted))
+ return NO;
+
+ if (!(result = (char*)malloc(len + 1)))
+ outofmem(__FILE__, "HTAA_encryptPasswd");
+
+ *result = (char)0;
+ while (len > 0) {
+ char salt[3];
+ char chunk[9];
+ CONST char *cur1 = password;
+ CONST char *cur2 = encrypted;
+ char *tmp;
+
+ salt[0] = *cur2;
+ salt[1] = *(cur2+1);
+ salt[2] = (char)0;
+
+ strncpy(chunk, cur1, 8);
+ chunk[8] = (char)0;
+
+ tmp = crypt((char*)password, salt);
+ strcat(result, tmp);
+
+ cur1 += 8;
+ cur2 += 13;
+ len -= 13;
+ } /* while */
+
+ status = strncmp(result, encrypted, strlen(encrypted));
+
+ if (TRACE)
+ fprintf(stderr,
+ "%s `%s' (encrypted: `%s') with: `%s' => %s\n",
+ "HTAA_passwdMatch: Matching password:",
+ password, result, encrypted,
+ (status==0 ? "OK" : "INCORRECT"));
+
+ FREE(result);
+
+ if (status==0)
+ return YES;
+ else
+ return NO;
+}
+
+
+/* PUBLIC HTAAFile_readPasswdRec()
+** READ A RECORD FROM THE PASSWORD FILE
+** ON ENTRY:
+** fp open password file
+** out_username buffer to put the read username, must be at
+** least MAX_USERNAME_LEN+1 characters long.
+** out_passwd buffer to put the read password, must be at
+** least MAX_PASSWORD_LEN+1 characters long.
+** ON EXIT:
+** returns EOF on end of file,
+** otherwise the number of read fields
+** (i.e. in a correct case returns 2).
+** out_username contains the null-terminated read username.
+** out_password contains the null-terminated read password.
+**
+** FORMAT OF PASSWORD FILE:
+** username:password:maybe real name or other stuff
+** (may include even colons)
+**
+** There may be whitespace (blanks or tabs) in the beginning and
+** the end of each field. They are ignored.
+*/
+PUBLIC int HTAAFile_readPasswdRec ARGS3(FILE *, fp,
+ char *, out_username,
+ char *, out_password)
+{
+ int terminator;
+
+ terminator = HTAAFile_readField(fp, out_username, MAX_USERNAME_LEN);
+
+ if (terminator == EOF) { /* End of file */
+ return EOF;
+ }
+ else if (terminator == CR || terminator == LF) { /* End of line */
+ next_rec(fp);
+ return 1;
+ }
+ else {
+ HTAAFile_readField(fp, out_password, MAX_PASSWORD_LEN);
+ next_rec(fp);
+ return 2;
+ }
+}
+
+
+
+/* PUBLIC HTAA_checkPassword()
+** CHECK A USERNAME-PASSWORD PAIR
+** ON ENTRY:
+** username is a null-terminated string containing
+** the client's username.
+** password is a null-terminated string containing
+** the client's corresponding password.
+** filename is a null-terminated absolute filename
+** for password file.
+** If NULL or empty, the value of
+** PASSWD_FILE is used.
+** ON EXIT:
+** returns YES, if the username-password pair was correct.
+** NO, otherwise; also, if open fails.
+*/
+PUBLIC BOOL HTAA_checkPassword ARGS3(CONST char *, username,
+ CONST char *, password,
+ CONST char *, filename)
+{
+ FILE *fp = NULL;
+ char user[MAX_USERNAME_LEN+1];
+ char pw[MAX_PASSWORD_LEN+1];
+ int status;
+
+ if (filename && *filename) fp = fopen(filename,"r");
+ else fp = fopen(PASSWD_FILE,"r");
+
+ if (!fp) {
+ if (TRACE) fprintf(stderr, "%s `%s'\n",
+ "HTAA_checkPassword: Unable to open password file",
+ (filename && *filename ? filename : PASSWD_FILE));
+ return NO;
+ }
+ do {
+ if (2 == (status = HTAAFile_readPasswdRec(fp,user,pw))) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTAAFile_validateUser: %s \"%s\" %s \"%s:%s\"\n",
+ "Matching username:", username,
+ "against passwd record:", user, pw);
+ if (username && user && !strcmp(username,user)) {
+ /* User's record found */
+ if (*pw != '\0') { /* So password is required for this user */
+ if (!password ||
+ !HTAA_passwdMatch(password,pw)) /* Check the password */
+ status = EOF; /* If wrong, indicate it with EOF */
+ }
+ break; /* exit loop */
+ } /* if username found */
+ } /* if record is ok */
+ } while (status != EOF);
+
+ fclose(fp);
+
+ if (TRACE) fprintf(stderr, "HTAAFile_checkPassword: (%s,%s) %scorrect\n",
+ username, password, ((status != EOF) ? "" : "in"));
+
+ if (status == EOF) return NO; /* We traversed to the end without luck */
+ else return YES; /* The user was found */
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.h
new file mode 100644
index 00000000000..0c3b3eb680f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPasswd.h
@@ -0,0 +1,129 @@
+/* PASSWORD FILE ROUTINES
+
+ */
+
+#ifndef HTPASSWD_H
+#define HTPASSWD_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTList.h"
+
+#ifdef SHORT_NAMES
+#define HTAAenPw HTAA_encryptPasswd
+#define HTAApwMa HTAA_passwdMatch
+#define HTAAFrPR HTAAFile_readPasswdRec
+#define HTAAchPw HTAA_checkPasswd
+#endif /* SHORT_NAMES */
+
+/*
+
+User Authentication
+
+ HTAA_checkPassword(username,password,passwdfile)opens the password file, and checks if
+ the username-password pair is correct. Return value is YES, if and only if they are
+ correct. Otherwise, and also if the open fails, returns NO.
+
+ If the given password file name is NULL or an empty string, the default password file
+ name is used (macro PASSWD_FILE).
+
+ */
+
+/* PUBLIC HTAA_checkPassword()
+** VALIDATE A USERNAME-PASSWORD PAIR
+** ON ENTRY:
+** username is a null-terminated string containing
+** the client's username.
+** password is a null-terminated string containing
+** the client's corresponding password.
+** filename is a null-terminated absolute filename
+** for password file.
+** If NULL or empty, the value of
+** PASSWD_FILE is used.
+** ON EXIT:
+** returns YES, if the username-password pair was correct.
+** NO, otherwise; also, if open fails.
+*/
+PUBLIC BOOL HTAA_checkPassword PARAMS((CONST char * username,
+ CONST char * password,
+ CONST char * filename));
+/*
+
+Password File Maintenance Routines
+
+ */
+
+/* PUBLIC HTAA_encryptPasswd()
+** ENCRYPT PASSWORD TO THE FORM THAT IT IS SAVED
+** IN THE PASSWORD FILE.
+** ON ENTRY:
+** password is a string of arbitrary lenght.
+**
+** ON EXIT:
+** returns password in one-way encrypted form.
+**
+** NOTE:
+** Uses currently the C library function crypt(), which
+** only accepts at most 8 characters long strings and produces
+** always 13 characters long strings. This function is
+** called repeatedly so that longer strings can be encrypted.
+** This is of course not as safe as encrypting the entire
+** string at once, but then again, we are not that paranoid
+** about the security inside the machine.
+**
+*/
+PUBLIC char *HTAA_encryptPasswd PARAMS((CONST char * password));
+
+
+/* PUBLIC HTAA_passwdMatch()
+** VERIFY THE CORRECTNESS OF A GIVEN PASSWORD
+** AGAINST A ONE-WAY ENCRYPTED FORM OF PASSWORD.
+** ON ENTRY:
+** password is cleartext password.
+** encrypted is one-way encrypted password, as returned
+** by function HTAA_encryptPasswd().
+** This is typically read from the password
+** file.
+**
+** ON EXIT:
+** returns YES, if password matches the encrypted one.
+** NO, if not, or if either parameter is NULL.
+*/
+PUBLIC BOOL HTAA_passwdMatch PARAMS((CONST char * password,
+ CONST char * encrypted));
+
+
+/* PUBLIC HTAAFile_readPasswdRec()
+** READ A RECORD FROM THE PASSWORD FILE
+** ON ENTRY:
+** fp open password file
+** out_username buffer to put the read username, must be at
+** least MAX_USERNAME_LEN+1 characters long.
+** out_passwd buffer to put the read password, must be at
+** least MAX_PASSWORD_LEN+1 characters long.
+** ON EXIT:
+** returns EOF on end of file,
+** otherwise the number of read fields
+** (i.e. in a correct case returns 2).
+** out_username contains the null-terminated read username.
+** out_password contains the null-terminated read password.
+**
+** FORMAT OF PASSWORD FILE:
+** username:password:maybe real name or other stuff
+** (may include even colons)
+**
+** There may be whitespace (blanks or tabs) in the beginning and
+** the end of each field. They are ignored.
+*/
+PUBLIC int HTAAFile_readPasswdRec PARAMS((FILE * fp,
+ char * out_username,
+ char * out_password));
+/*
+
+ */
+
+#endif /* not HTPASSWD_H */
+/*
+
+ End of file HTPasswd.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.c
new file mode 100644
index 00000000000..dda98d5fe82
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.c
@@ -0,0 +1,665 @@
+/* Plain text object HTWrite.c
+** =================
+**
+** This version of the stream object just writes to a socket.
+** The socket is assumed open and left open.
+**
+** Bugs:
+** strings written must be less than buffer size.
+*/
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTPlain.h"
+
+#include "HTChunk.h"
+#include "HText.h"
+#include "HTStyle.h"
+#define Lynx_HTML_Handler
+#include "HTML.h" /* styles[] */
+
+#define BUFFER_SIZE 4096; /* Tradeoff */
+
+#include "HText.h"
+#include "HTStyle.h"
+#include "HTMLDTD.h"
+#include "HTCJK.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include "LYCharSets.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern BOOLEAN LYRawMode;
+extern BOOL HTPassEightBitRaw;
+extern BOOL HTPassHighCtrlRaw;
+extern HTCJKlang HTCJK;
+
+PUBLIC int HTPlain_lastraw = -1;
+
+/* HTML Object
+** -----------
+*/
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ HText * text;
+ /*
+ ** The node_anchor UCInfo and handle for the input (PARSER) stage. - FM
+ */
+ LYUCcharset * inUCI;
+ int inUCLYhndl;
+ /*
+ ** The node_anchor UCInfo and handle for the output (HTEXT) stage. - FM
+ */
+ int outUCLYhndl;
+ /*
+ ** Counter, value, buffer and pointer for UTF-8 handling. - FM
+ */
+ char utf_count;
+ UCode_t utf_char;
+ char utf_buf[8];
+ char * utf_buf_p;
+ /*
+ ** The charset transformation structure. - FM
+ */
+ UCTransParams T;
+};
+
+PRIVATE char replace_buf [64]; /* buffer for replacement strings */
+
+PRIVATE void HTPlain_getChartransInfo ARGS2(
+ HTStream *, me,
+ HTParentAnchor *, anchor)
+{
+ if (me->inUCLYhndl < 0) {
+ HTAnchor_copyUCInfoStage(anchor, UCT_STAGE_PARSER, UCT_STAGE_MIME,
+ UCT_SETBY_PARSER);
+ me->inUCLYhndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_PARSER);
+ }
+ if (me->outUCLYhndl < 0) {
+ int chndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_HTEXT);
+ if (chndl < 0) {
+ chndl = current_char_set;
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_HTEXT, UCT_SETBY_DEFAULT);
+ }
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_HTEXT, UCT_SETBY_DEFAULT);
+ me->outUCLYhndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_HTEXT);
+ }
+ me->inUCI = HTAnchor_getUCInfoStage(anchor, UCT_STAGE_PARSER);
+}
+
+/* Write the buffer out to the socket
+** ----------------------------------
+*/
+
+/*_________________________________________________________________________
+**
+** A C T I O N R O U T I N E S
+*/
+
+PRIVATE void HTPlain_write PARAMS((
+ HTStream * me,
+ CONST char * s,
+ int l));
+
+/* Character handling
+** ------------------
+*/
+PRIVATE void HTPlain_put_character ARGS2(
+ HTStream *, me,
+ char, c)
+{
+#ifdef REMOVE_CR_ONLY
+ /*
+ ** Throw away \r's.
+ */
+ if (c != '\r') {
+ HText_appendCharacter(me->text, c);
+ }
+#else
+ /*
+ ** See HTPlain_write() for explanations of the following code
+ ** (we've been called via HTPlain_put_string() to do for each
+ ** character of a terminated string what HTPlain_write() does
+ ** via a while loop for each character in a stream of given
+ ** length). - FM
+ */
+ if ((HTPlain_lastraw == '\r') && c == '\n') {
+ HTPlain_lastraw = -1;
+ return;
+ }
+ HTPlain_lastraw = c;
+ if (c == '\r') {
+ HText_appendCharacter(me->text, '\n');
+ } else if (HTCJK != NOCJK) {
+ HText_appendCharacter(me->text, c);
+ } else if ((unsigned char)c >= 127) {
+ /*
+ ** For now, don't repeat everything here
+ ** that has been done below - KW
+ */
+ HTPlain_write(me, &c, 1);
+ } else if ((unsigned char)c >= 127 && (unsigned char)c < 161 &&
+ HTPassHighCtrlRaw) {
+ HText_appendCharacter(me->text, c);
+ } else if ((unsigned char)c == 160) {
+ HText_appendCharacter(me->text, ' ');
+ } else if ((unsigned char)c == 173) {
+ return;
+ } else if (((unsigned char)c >= 32 && (unsigned char)c < 127) ||
+ c == '\n' || c == '\t') {
+ HText_appendCharacter(me->text, c);
+ } else if ((unsigned char)c > 160) {
+ if (!HTPassEightBitRaw &&
+ current_char_set != 0) {
+ size_t len, high, low, i;
+ int diff = 1;
+ CONST char * name;
+ UCode_t value = (UCode_t)((unsigned char)c - 160);
+
+ name = HTMLGetEntityName(value);
+ len = strlen(name);
+ for (low = 0, high = HTML_dtd.number_of_entities;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) {
+ /* Binary search */
+ i = (low + (high-low)/2);
+ diff = strncmp(HTML_dtd.entity_names[i], name, len);
+ if (diff == 0) {
+ HText_appendText(me->text,
+ LYCharSets[current_char_set][i]);
+ break;
+ }
+ }
+ if (diff) {
+ HText_appendCharacter(me->text, c);
+ }
+ } else {
+ HText_appendCharacter(me->text, c);
+ }
+ }
+#endif /* REMOVE_CR_ONLY */
+}
+
+
+/* String handling
+** ---------------
+**
+*/
+PRIVATE void HTPlain_put_string ARGS2(HTStream *, me, CONST char*, s)
+{
+#ifdef REMOVE_CR_ONLY
+ HText_appendText(me->text, s);
+#else
+ CONST char * p;
+
+ if (s == NULL)
+ return;
+ for (p = s; *p; p++) {
+ HTPlain_put_character(me, *p);
+ }
+#endif /* REMOVE_CR_ONLY */
+}
+
+
+/*
+** Entry function for displayed text/plain and WWW_SOURCE strings. - FM
+** ---------------------------------------------------------------
+*/
+PRIVATE void HTPlain_write ARGS3(HTStream *, me, CONST char*, s, int, l)
+{
+ CONST char * p;
+ CONST char * e = s+l;
+ char c;
+ unsigned char c_unsign;
+ BOOL chk;
+ UCode_t code;
+ long uck = 0;
+
+ for (p = s; p < e; p++) {
+#ifdef REMOVE_CR_ONLY
+ /*
+ ** Append the whole string, but remove any \r's. - FM
+ */
+ if (*p != '\r') {
+ HText_appendCharacter(me->text, *p);
+ }
+#else
+ /*
+ ** Try to handle lone LFs, CRLFs and lone CRs
+ ** as newline, and to deal with control, ASCII,
+ ** and 8-bit characters based on best guesses
+ ** of what's appropriate. - FM
+ */
+ if ((HTPlain_lastraw == '\r') && *p == '\n') {
+ HTPlain_lastraw = -1;
+ continue;
+ }
+ HTPlain_lastraw = *p;
+ if (*p == '\r') {
+ HText_appendCharacter(me->text, '\n');
+ continue;
+ }
+ /*
+ ** Make sure the character is handled as Unicode
+ ** whenever that's appropriate. - FM
+ */
+ c = *p;
+ c_unsign = (unsigned char)c;
+ code = (UCode_t)c_unsign;
+ /*
+ ** Combine any UTF-8 multibytes into Unicode
+ ** to check for special characters. - FM
+ */
+ if (me->T.decode_utf8) {
+ /*
+ ** Combine UTF-8 into Unicode.
+ ** Incomplete characters silently ignored.
+ ** from Linux kernel's console.c - KW
+ */
+ if (c_unsign > 127) {
+ /*
+ ** We have an octet from a multibyte character. - FM
+ */
+ if (me->utf_count > 0 && (c & 0xc0) == 0x80) {
+ /*
+ ** Adjust the UCode_t value, add the octet
+ ** to the buffer, and decrement the byte
+ ** count. - FM
+ */
+ me->utf_char = (me->utf_char << 6) | (c & 0x3f);
+ me->utf_count--;
+ *(me->utf_buf_p) = c;
+ (me->utf_buf_p)++;
+ if (me->utf_count == 0) {
+ /*
+ ** Got a complete multibyte character.
+ */
+ *(me->utf_buf_p) = '\0';
+ code = me->utf_char;
+ if (code < 256) {
+ c = FROMASCII((char)code);
+ }
+ } else {
+ /*
+ ** Get the next byte. - FM
+ */
+ continue;
+ }
+ } else {
+ /*
+ ** Start handling a new multibyte character. - FM
+ */
+ me->utf_buf_p = me->utf_buf;
+ me->utf_buf_p[0] = c;
+ (me->utf_buf_p)++;
+ if ((*p & 0xe0) == 0xc0) {
+ me->utf_count = 1;
+ me->utf_char = (c & 0x1f);
+ } else if ((*p & 0xf0) == 0xe0) {
+ me->utf_count = 2;
+ me->utf_char = (c & 0x0f);
+ } else if ((*p & 0xf8) == 0xf0) {
+ me->utf_count = 3;
+ me->utf_char = (c & 0x07);
+ } else if ((*p & 0xfc) == 0xf8) {
+ me->utf_count = 4;
+ me->utf_char = (c & 0x03);
+ } else if ((*p & 0xfe) == 0xfc) {
+ me->utf_count = 5;
+ me->utf_char = (c & 0x01);
+ } else {
+ /*
+ * We got garbage, so ignore it. - FM
+ */
+ me->utf_count = 0;
+ me->utf_buf_p = me->utf_buf;
+ me->utf_buf_p[0] = '\0';
+ }
+ /*
+ ** Get the next byte. - FM
+ */
+ continue;
+ }
+ } else {
+ /*
+ ** Got an ASCII character.
+ */
+ me->utf_count = 0;
+ me->utf_buf[0] = '\0';
+ me->utf_buf_p = me->utf_buf;
+ }
+ }
+
+ if (me->T.trans_to_uni &&
+ (code >= 127 ||
+ (code < 32 && code != 0 &&
+ me->T.trans_C0_to_uni))) {
+ /*
+ ** Convert the octet to Unicode. - FM
+ */
+ code = (UCode_t)UCTransToUni(c, me->inUCLYhndl);
+ if (code > 0) {
+ if (code < 256) {
+ c = FROMASCII((char)code);
+ }
+ }
+ }
+ /*
+ ** At this point we have either code in Unicode
+ ** (and c in latin1 if code is in the latin1 range),
+ ** or code and c will have to be passed raw.
+ */
+
+ /*
+ ** If CJK mode is on, we'll assume the document matches
+ ** the user's selected character set, and if not, the
+ ** user should toggle off raw/CJK mode to reload. - FM
+ */
+ if (HTCJK != NOCJK) {
+ HText_appendCharacter(me->text, c);
+
+#define PASSHICTRL (me->T.transp || \
+ code >= LYlowest_eightbit[me->inUCLYhndl])
+#define PASS8859SPECL me->T.pass_160_173_raw
+#define PASSHI8BIT (HTPassEightBitRaw || \
+ (me->T.do_8bitraw && !me->T.trans_from_uni))
+ /*
+ ** If HTPassHighCtrlRaw is set (e.g., for KOI8-R) assume the
+ ** document matches and pass 127-160 8-bit characters. If it
+ ** doesn't match, the user should toggle raw/CJK mode off. - FM
+ */
+ } else if (code >= 127 && code < 161 &&
+ PASSHICTRL && PASS8859SPECL) {
+ HText_appendCharacter(me->text, c);
+ } else if (code == 173 && PASS8859SPECL) {
+ HText_appendCharacter(me->text, c);
+ /*
+ ** If neither HTPassHighCtrlRaw nor CJK is set, play it safe
+ ** and treat 160 (nbsp) as an ASCII space (32). - FM
+ */
+ } else if (code == 160) {
+ HText_appendCharacter(me->text, ' ');
+ /*
+ ** If neither HTPassHighCtrlRaw nor CJK is set, play it safe
+ ** and ignore 173 (shy). - FM
+ */
+ } else if (code == 173) {
+ continue;
+ /*
+ ** If we get to here, pass the displayable ASCII characters. - FM
+ */
+ } else if ((code >= 32 && code < 127) ||
+ (PASSHI8BIT &&
+ c >= LYlowest_eightbit[me->outUCLYhndl]) ||
+ *p == '\n' || *p == '\t') {
+ HText_appendCharacter(me->text, c);
+
+ } else if (me->T.use_raw_char_in) {
+ HText_appendCharacter(me->text, *p);
+#ifdef NOTDEFINED
+ /*
+ ** Use an ASCII space (32) for ensp, emsp or thinsp. - FM
+ */
+ } else if (code == 8194 || code == 8195 || code == 8201) {
+ HText_appendCharacter(me->text, ' ');
+#endif /* NOTDEFINED */
+
+/******************************************************************
+ * I. LATIN-1 OR UCS2 TO DISPLAY CHARSET
+ ******************************************************************/
+ } else if ((chk = (me->T.trans_from_uni && code >= 160)) &&
+ (uck = UCTransUniChar(code,
+ me->outUCLYhndl)) >= 32 &&
+ uck < 256) {
+ if (TRACE) {
+ fprintf(stderr,
+ "UCTransUniChar returned 0x%.2lX:'%c'.\n",
+ uck, FROMASCII((char)uck));
+ }
+ HText_appendCharacter(me->text, ((char)(uck & 0xff)));
+ } else if (chk &&
+ (uck == -4 ||
+ (me->T.repl_translated_C0 && uck > 0 && uck < 32)) &&
+ /*
+ ** Not found; look for replacement string.
+ */
+ (uck = UCTransUniCharStr(replace_buf, 60, code,
+ me->outUCLYhndl, 0) >= 0)) {
+ /*
+ ** No further tests for valididy - assume that whoever
+ ** defined replacement strings knew what she was doing.
+ */
+ HText_appendText(me->text, replace_buf);
+ /*
+ ** If we get to here, and should have translated,
+ ** translation has failed so far.
+ */
+ } else if (chk && code > 127 && me->T.output_utf8) {
+ /*
+ ** We want UTF-8 output, so do it now. - FM
+ */
+ if (*me->utf_buf) {
+ HText_appendText(me->text, me->utf_buf);
+ me->utf_buf[0] = '\0';
+ me->utf_buf_p = me->utf_buf;
+ } else if (UCConvertUniToUtf8(code, replace_buf)) {
+ HText_appendText(me->text, replace_buf);
+ } else {
+ sprintf(replace_buf, "U%.2lX", code);
+ HText_appendText(me->text, replace_buf);
+ }
+#ifdef NOTDEFINED
+ } else if (me->T.strip_raw_char_in &&
+ (unsigned char)*p >= 192 &&
+ (unsigned char)*p < 255) {
+ /*
+ ** KOI special: strip high bit, gives
+ ** (somewhat) readable ASCII.
+ */
+ HText_appendCharacter(me->text, (char)(*p & 0x7f));
+ /*
+ ** If we do not have the "7-bit approximations" as our
+ ** output character set (in which case we did it already)
+ ** seek a translation for that. Otherwise, or if the
+ ** translation fails, use UHHH notation. - FM
+ */
+ } else if (chk &&
+ (chk = (!HTPassEightBitRaw &&
+ (me->outUCLYhndl !=
+ UCGetLYhndl_byMIME("us-ascii")))) &&
+ (uck = UCTransUniChar(code,
+ UCGetLYhndl_byMIME("us-ascii")))
+ >= 32 && uck < 127) {
+ /*
+ ** Got an ASCII character (yippey). - FM
+ */
+ c = ((char)(uck & 0xff));
+ HText_appendCharacter(me->text, c);
+ } else if ((chk && uck == -4) &&
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ UCGetLYhndl_byMIME("us-ascii"),
+ 0) >= 0)) {
+ /*
+ ** Got a repacement string (yippey). - FM
+ */
+ HText_appendText(me->text, replace_buf);
+ } else if (code == 8204 || code == 8205) {
+ /*
+ ** Ignore 8204 (zwnj) or 8205 (zwj), if we get to here. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTPlain_write: Ignoring '%ld'.\n", code);
+ }
+ } else if (code == 8206 || code == 8207) {
+ /*
+ ** Ignore 8206 (lrm) or 8207 (rlm), if we get to here. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTPlain_write: Ignoring '%ld'.\n", code);
+ }
+#endif /* NOTDEFINED */
+ } else if (me->T.trans_from_uni && code > 255) {
+ if (PASSHI8BIT && PASSHICTRL && LYRawMode &&
+ (unsigned char)*p >= LYlowest_eightbit[me->outUCLYhndl]) {
+ HText_appendCharacter(me->text, *p);
+ } else {
+ sprintf(replace_buf, "U%.2lX", code);
+ HText_appendText(me->text, replace_buf);
+ }
+ /*
+ ** If we get to here and HTPassEightBitRaw or the
+ ** selected character set is not "ISO Latin 1",
+ ** use the translation tables for 161-255 8-bit
+ ** characters (173 was handled above). - FM
+ */
+ } else if (code > 160) {
+ if (!HTPassEightBitRaw && code <= 255 &&
+ me->outUCLYhndl != 0) {
+ /*
+ ** Out of luck, so use the UHHH notation (ugh). - FM
+ */
+ size_t len, high, low, i;
+ int diff = 1;
+ CONST char * name;
+ int value = (int)(code - 160);
+
+ name = HTMLGetEntityName(value);
+ len = strlen(name);
+ for(low = 0, high = HTML_dtd.number_of_entities;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) {
+ /* Binary search */
+ i = (low + (high-low)/2);
+ diff = strncmp(HTML_dtd.entity_names[i], name, len);
+ if (diff == 0) {
+ HText_appendText(me->text,
+ LYCharSets[me->outUCLYhndl][i]);
+ break;
+ }
+ }
+ if (diff) {
+ /*
+ ** Something went wrong in the translation, so
+ ** either output as UTF8 or a hex representation or
+ ** pass the raw character and hope it's OK.
+ */
+ if (!PASSHI8BIT)
+ c = FROMASCII((char)code);
+ if (me->T.output_utf8 &&
+ *me->utf_buf) {
+ HText_appendText(me->text, me->utf_buf);
+ me->utf_buf_p = me->utf_buf;
+ *(me->utf_buf_p) = '\0';
+
+ } else if (me->T.trans_from_uni) {
+ sprintf(replace_buf, "U%.2lX", code);
+ HText_appendText(me->text, replace_buf);
+ } else
+ HText_appendCharacter(me->text, c);
+ }
+ } else {
+ /*
+ ** Didn't attempt a translation. - FM
+ */
+ /* Either output as UTF8 or a hex representation or
+ ** pass the raw character and hope it's OK.
+ */
+ if (code <= 255 && !PASSHI8BIT)
+ c = FROMASCII((char)code);
+ if (code > 127 && me->T.output_utf8 && *me->utf_buf) {
+ HText_appendText(me->text, me->utf_buf);
+ me->utf_buf_p = me->utf_buf;
+ *(me->utf_buf_p) = '\0';
+
+ } else if (LYRawMode &&
+ me->inUCLYhndl != me->outUCLYhndl &&
+ (PASSHI8BIT || PASSHICTRL) &&
+ (unsigned char)c >=
+ LYlowest_eightbit[me->outUCLYhndl]) {
+ HText_appendCharacter(me->text, c);
+ } else if (me->T.trans_from_uni && code >= 127) {
+ sprintf(replace_buf, "U%.2lX", code);
+ HText_appendText(me->text, replace_buf);
+ } else
+ HText_appendCharacter(me->text, c);
+ }
+ }
+#endif /* REMOVE_CR_ONLY */
+ }
+}
+
+/* Free an HTML object
+** -------------------
+**
+** Note that the SGML parsing context is freed, but the created object is
+** not, as it takes on an existence of its own unless explicitly freed.
+*/
+PRIVATE void HTPlain_free ARGS1(
+ HTStream *, me)
+{
+ FREE(me);
+}
+
+/* End writing
+*/
+PRIVATE void HTPlain_abort ARGS2(
+ HTStream *, me,
+ HTError, e GCC_UNUSED)
+{
+ HTPlain_free(me);
+}
+
+/* Structured Object Class
+** -----------------------
+*/
+PUBLIC CONST HTStreamClass HTPlain =
+{
+ "PlainPresenter",
+ HTPlain_free,
+ HTPlain_abort,
+ HTPlain_put_character, HTPlain_put_string, HTPlain_write,
+};
+
+/* New object
+** ----------
+*/
+PUBLIC HTStream* HTPlainPresent ARGS3(
+ HTPresentation *, pres GCC_UNUSED,
+ HTParentAnchor *, anchor,
+ HTStream *, sink GCC_UNUSED)
+{
+
+ HTStream* me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL)
+ outofmem(__FILE__, "HTPlain_new");
+ me->isa = &HTPlain;
+
+ HTPlain_lastraw = -1;
+
+ me->utf_count = 0;
+ me->utf_char = 0;
+ me->utf_buf[0] = me->utf_buf[6] =me->utf_buf[7] = '\0';
+ me->utf_buf_p = me->utf_buf;
+ me->outUCLYhndl = HTAnchor_getUCLYhndl(anchor,UCT_STAGE_HTEXT);
+ me->inUCLYhndl = HTAnchor_getUCLYhndl(anchor,UCT_STAGE_PARSER);
+ HTPlain_getChartransInfo(me, anchor);
+ UCSetTransParams(&me->T,
+ me->inUCLYhndl, me->inUCI,
+ me->outUCLYhndl,
+ HTAnchor_getUCInfoStage(anchor,UCT_STAGE_HTEXT));
+
+ me->text = HText_new(anchor);
+ HText_setStyle(me->text, styles[HTML_XMP] );
+ HText_beginAppend(me->text);
+
+ return (HTStream*) me;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.h
new file mode 100644
index 00000000000..f4ce3e14696
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTPlain.h
@@ -0,0 +1,21 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTPlain.html
+ PLAIN TEXT OBJECT
+
+ */
+#ifndef HTPLAIN_H
+#define HTPLAIN_H
+
+#include "HTStream.h"
+#include "HTAnchor.h"
+
+extern HTStream* HTPlainPresent PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+
+#endif
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.c
new file mode 100644
index 00000000000..93a9eb255ee
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.c
@@ -0,0 +1,418 @@
+/* Configuration manager for Hypertext Daemon HTRules.c
+** ==========================================
+**
+**
+** History:
+** 3 Jun 91 Written TBL
+** 10 Aug 91 Authorisation added after Daniel Martin (pass, fail)
+** Rule order in file changed
+** Comments allowed with # on 1st char of rule line
+** 17 Jun 92 Bug fix: pass and fail failed if didn't contain '*' TBL
+** 1 Sep 93 Bug fix: no memory check - Nathan Torkington
+** BYTE_ADDRESSING removed - Arthur Secret
+** 11 Sep 93 MD Changed %i into %d in debug printf.
+** VMS does not recognize %i.
+** Bug Fix: in case of PASS, only one parameter to printf.
+** 19 Sep 93 AL Added Access Authorization stuff.
+** 1 Nov 93 AL Added htbin.
+**
+*/
+
+/* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
+#include "HTRules.h"
+
+#include "HTUtils.h"
+#include "tcp.h"
+/*#include <stdio.h> included by HTUtils.h -- FM */
+#include "HTFile.h"
+#include "HTAAServ.h" /* Access Authorization */
+
+#include "LYLeaks.h"
+
+#define LINE_LENGTH 256
+
+
+typedef struct _rule {
+ struct _rule * next;
+ HTRuleOp op;
+ char * pattern;
+ char * equiv;
+} rule;
+
+/* Global variables
+** ----------------
+*/
+PUBLIC char *HTBinDir = NULL; /* Physical /htbin directory path. */
+ /* In future this should not be global. */
+PUBLIC char *HTSearchScript = NULL; /* Search script name. */
+
+
+/* Module-wide variables
+** ---------------------
+*/
+
+PRIVATE rule * rules = 0; /* Pointer to first on list */
+#ifndef PUT_ON_HEAD
+PRIVATE rule * rule_tail = 0; /* Pointer to last on list */
+#endif
+
+
+/* Add rule to the list HTAddRule()
+** --------------------
+**
+** On entry,
+** pattern points to 0-terminated string containing a single "*"
+** equiv points to the equivalent string with * for the
+** place where the text matched by * goes.
+** On exit,
+** returns 0 if success, -1 if error.
+*/
+
+#ifdef __STDC__
+PUBLIC int HTAddRule (HTRuleOp op, const char * pattern, const char * equiv)
+#else
+int HTAddRule(op, pattern, equiv)
+ HTRuleOp op;
+ char * pattern;
+ char * equiv;
+#endif
+{ /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
+ rule * temp;
+ char * pPattern;
+
+ temp = (rule *)malloc(sizeof(*temp));
+ if (temp==NULL)
+ outofmem(__FILE__, "HTAddRule");
+ pPattern = (char *)malloc(strlen(pattern)+1);
+ if (pPattern==NULL)
+ outofmem(__FILE__, "HTAddRule");
+ if (equiv) { /* Two operands */
+ char * pEquiv = (char *)malloc(strlen(equiv)+1);
+ if (pEquiv==NULL)
+ outofmem(__FILE__, "HTAddRule");
+ temp->equiv = pEquiv;
+ strcpy(pEquiv, equiv);
+ } else {
+ temp->equiv = 0;
+ }
+ temp->pattern = pPattern;
+ temp->op = op;
+
+ strcpy(pPattern, pattern);
+ if (TRACE) {
+ if (equiv)
+ fprintf(stderr, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
+ else
+ fprintf(stderr, "Rule: For `%s' op %d\n", pattern, op);
+ }
+
+#ifdef PUT_ON_HEAD
+ temp->next = rules;
+ rules = temp;
+#else
+ temp->next = 0;
+ if (rule_tail) rule_tail->next = temp;
+ else rules = temp;
+ rule_tail = temp;
+#endif
+
+
+ return 0;
+}
+
+
+/* Clear all rules HTClearRules()
+** ---------------
+**
+** On exit,
+** There are no rules
+** returns 0 if success, -1 if error.
+**
+** See also
+** HTAddRule()
+*/
+#ifdef __STDC__
+int HTClearRules(void)
+#else
+int HTClearRules()
+#endif
+{
+ while (rules) {
+ rule * temp = rules;
+ rules = temp->next;
+ FREE(temp->pattern);
+ FREE(temp->equiv);
+ FREE(temp);
+ }
+#ifndef PUT_ON_HEAD
+ rule_tail = 0;
+#endif
+
+ return 0;
+}
+
+
+/* Translate by rules HTTranslate()
+** ------------------
+**
+** The most recently defined rules are applied first.
+**
+** On entry,
+** required points to a string whose equivalent value is neeed
+** On exit,
+** returns the address of the equivalent string allocated from
+** the heap which the CALLER MUST FREE. If no translation
+** occured, then it is a copy of te original.
+** NEW FEATURES:
+** When a "protect" or "defprot" rule is mathed,
+** a call to HTAA_setCurrentProtection() or
+** HTAA_setDefaultProtection() is made to notify
+** the Access Authorization module that the file is
+** protected, and so it knows how to handle it.
+** -- AL
+*/
+#ifdef __STDC__
+char * HTTranslate(const char * required)
+#else
+char * HTTranslate(required)
+ char * required;
+#endif
+{
+ rule * r;
+ char *current = NULL;
+ StrAllocCopy(current, required);
+
+ HTAA_clearProtections(); /* Reset from previous call -- AL */
+
+ for(r = rules; r; r = r->next) {
+ char * p = r->pattern;
+ int m=0; /* Number of characters matched against wildcard */
+ CONST char * q = current;
+ for(;*p && *q; p++, q++) { /* Find first mismatch */
+ if (*p!=*q) break;
+ }
+
+ if (*p == '*') { /* Match up to wildcard */
+ m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
+ if(m<0) continue; /* tail is too short to match */
+ if (0!=strcmp(q+m, p+1)) continue; /* Tail mismatch */
+ } else /* Not wildcard */
+ if (*p != *q) continue; /* plain mismatch: go to next rule */
+
+ switch (r->op) { /* Perform operation */
+
+#ifdef ACCESS_AUTH
+ case HT_DefProt:
+ case HT_Protect:
+ {
+ char *local_copy = NULL;
+ char *p2;
+ char *eff_ids = NULL;
+ char *prot_file = NULL;
+
+ if (TRACE) fprintf(stderr,
+ "HTRule: `%s' matched %s %s: `%s'\n",
+ current,
+ (r->op==HT_Protect ? "Protect" : "DefProt"),
+ "rule, setup",
+ (r->equiv ? r->equiv :
+ (r->op==HT_Protect ?"DEFAULT" :"NULL!!")));
+
+ if (r->equiv) {
+ StrAllocCopy(local_copy, r->equiv);
+ p2 = local_copy;
+ prot_file = HTNextField(&p2);
+ eff_ids = HTNextField(&p2);
+ }
+
+ if (r->op == HT_Protect)
+ HTAA_setCurrentProtection(current, prot_file, eff_ids);
+ else
+ HTAA_setDefaultProtection(current, prot_file, eff_ids);
+
+ FREE(local_copy);
+
+ /* continue translating rules */
+ }
+ break;
+#endif /* ACCESS_AUTH */
+
+ case HT_Pass: /* Authorised */
+ if (!r->equiv) {
+ if (TRACE) fprintf(stderr, "HTRule: Pass `%s'\n", current);
+ return current;
+ }
+ /* Else fall through ...to map and pass */
+
+ case HT_Map:
+ if (*p == *q) { /* End of both strings, no wildcard */
+ if (TRACE) fprintf(stderr,
+ "For `%s' using `%s'\n", current, r->equiv);
+ StrAllocCopy(current, r->equiv); /* use entire translation */
+ } else {
+ char * ins = strchr(r->equiv, '*'); /* Insertion point */
+ if (ins) { /* Consistent rule!!! */
+ char * temp = (char *)malloc(
+ strlen(r->equiv)-1 + m + 1);
+ if (temp==NULL)
+ outofmem(__FILE__, "HTTranslate"); /* NT & AS */
+ strncpy(temp, r->equiv, ins-r->equiv);
+ /* Note: temp may be unterminated now! */
+ strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
+ strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
+ if (TRACE) fprintf(stderr, "For `%s' using `%s'\n",
+ current, temp);
+ FREE(current);
+ current = temp; /* Use this */
+
+ } else { /* No insertion point */
+ char * temp = (char *)malloc(strlen(r->equiv)+1);
+ if (temp==NULL)
+ outofmem(__FILE__, "HTTranslate"); /* NT & AS */
+ strcpy(temp, r->equiv);
+ if (TRACE) fprintf(stderr, "For `%s' using `%s'\n",
+ current, temp);
+ FREE(current);
+ current = temp; /* Use this */
+ } /* If no insertion point exists */
+ }
+ if (r->op == HT_Pass) {
+ if (TRACE) fprintf(stderr, "HTRule: ...and pass `%s'\n",
+ current);
+ return current;
+ }
+ break;
+
+ case HT_Invalid:
+ case HT_Fail: /* Unauthorised */
+ if (TRACE) fprintf(stderr, "HTRule: *** FAIL `%s'\n",
+ current);
+ return (char *)0;
+
+ } /* if tail matches ... switch operation */
+
+ } /* loop over rules */
+
+
+ return current;
+}
+
+/* Load one line of configuration
+** ------------------------------
+**
+** Call this, for example, to load a X resource with config info.
+**
+** returns 0 OK, < 0 syntax error.
+*/
+PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
+{
+ HTRuleOp op;
+ char * line = NULL;
+ char * pointer = line;
+ char *word1, *word2, *word3;
+ float quality, secs, secs_per_byte;
+ int maxbytes;
+ int status;
+
+ StrAllocCopy(line, config);
+ {
+ char * p = strchr(line, '#'); /* Chop off comments */
+ if (p) *p = 0;
+ }
+ pointer = line;
+ word1 = HTNextField(&pointer);
+ if (!word1) {
+ FREE(line);
+ return 0;
+ } ; /* Comment only or blank */
+
+ word2 = HTNextField(&pointer);
+
+ if (0==strcasecomp(word1, "defprot") ||
+ 0==strcasecomp(word1, "protect"))
+ word3 = pointer; /* The rest of the line to be parsed by AA module */
+ else
+ word3 = HTNextField(&pointer); /* Just the next word */
+
+ if (!word2) {
+ fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
+ FREE(line);
+ return -2; /*syntax error */
+ }
+
+ if (0==strcasecomp(word1, "suffix")) {
+ char * encoding = HTNextField(&pointer);
+ if (pointer) status = sscanf(pointer, "%f", &quality);
+ else status = 0;
+ HTSetSuffix(word2, word3,
+ encoding ? encoding : "binary",
+ status >= 1? quality : 1.0);
+
+ } else if (0==strcasecomp(word1, "presentation")) {
+ if (pointer) status = sscanf(pointer, "%f%f%f%d",
+ &quality, &secs, &secs_per_byte, &maxbytes);
+ else status = 0;
+ HTSetPresentation(word2, word3,
+ status >= 1? quality : 1.0,
+ status >= 2 ? secs : 0.0,
+ status >= 3 ? secs_per_byte : 0.0,
+ status >= 4 ? maxbytes : 0 );
+
+ } else if (0==strncasecomp(word1, "htbin", 5) ||
+ 0==strncasecomp(word1, "bindir", 6)) {
+ StrAllocCopy(HTBinDir, word2); /* Physical /htbin location */
+
+ } else if (0==strncasecomp(word1, "search", 6)) {
+ StrAllocCopy(HTSearchScript, word2); /* Search script name */
+
+ } else {
+ op = 0==strcasecomp(word1, "map") ? HT_Map
+ : 0==strcasecomp(word1, "pass") ? HT_Pass
+ : 0==strcasecomp(word1, "fail") ? HT_Fail
+ : 0==strcasecomp(word1, "defprot") ? HT_DefProt
+ : 0==strcasecomp(word1, "protect") ? HT_Protect
+ : HT_Invalid;
+ if (op==HT_Invalid) {
+ fprintf(stderr, "HTRule: Bad rule `%s'\n", config);
+ } else {
+ HTAddRule(op, word2, word3);
+ }
+ }
+ FREE(line);
+ return 0;
+}
+
+
+/* Load the rules from a file HTLoadRules()
+** --------------------------
+**
+** On entry,
+** Rules can be in any state
+** On exit,
+** Any existing rules will have been kept.
+** Any new rules will have been loaded.
+** Returns 0 if no error, 0 if error!
+**
+** Bugs:
+** The strings may not contain spaces.
+*/
+
+int HTLoadRules ARGS1(CONST char *, filename)
+{
+ FILE * fp = fopen(filename, "r");
+ char line[LINE_LENGTH+1];
+
+ if (!fp) {
+ if (TRACE) fprintf(stderr,
+ "HTRules: Can't open rules file %s\n", filename);
+ return -1; /* File open error */
+ }
+ for(;;) {
+ if (!fgets(line, LINE_LENGTH+1, fp)) break; /* EOF or error */
+ (void) HTSetConfiguration(line);
+ }
+ fclose(fp);
+ return 0; /* No error or syntax errors ignored */
+}
+
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.h
new file mode 100644
index 00000000000..8407524467f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTRules.h
@@ -0,0 +1,165 @@
+/* Configuration Manager for libwww
+ CONFIGURATION MANAGER
+
+ Author Tim Berners-Lee/CERN. Public domain. Please mail changes to timbl@info.cern.ch.
+
+ The configuration information loaded includes tables (file suffixes, presentation
+ methods) in other modules. The most likely routines needed by developers will be:
+
+ HTSetConfiguration to load configuration information.
+
+ HTLoadRules to load a whole file of configuration information
+
+ HTTranslate to translate a URL using the rule table.
+
+ */
+#ifndef HTRULE_H
+#define HTRULE_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+typedef enum _HTRuleOp {
+ HT_Invalid,
+ HT_Map,
+ HT_Pass,
+ HT_Fail,
+ HT_DefProt,
+ HT_Protect
+} HTRuleOp;
+
+#ifdef SHORT_NAMES
+#define HTSearSc HTSearchScript
+#endif /*SHORT_NAMES*/
+
+/*
+
+Server Side Script Execution
+
+ If a URL starts with /htbin/ it is understood to mean a script execution request on
+ server. This feature needs to be turned on by setting HTBinDir by the htbin rule.
+ Index searching is enabled by setting HTSearchScript into the name of script in BinDir
+ doing the actual search by search rule (BinDir must also be set in this case, of
+ course).
+
+ */
+
+extern char * HTBinDir; /* Physical /htbin location */
+extern char * HTSearchScript; /* Search script name */
+
+/*
+
+HTAddRule: Add rule to the list
+
+ ON ENTRY,
+
+ pattern points to 0-terminated string containing a single "*"
+
+ equiv points to the equivalent string with * for the place where the
+ text matched by * goes.
+
+ ON EXIT,
+
+ returns 0 if success, -1 if error.
+
+ Note that if BYTE_ADDRESSING is set, the three blocks required are allocated and
+ deallocated as one. This will save time and storage, when malloc's allocation units are
+ large.
+
+ */
+extern int HTAddRule PARAMS((HTRuleOp op, const char * pattern, const char * equiv));
+
+
+/*
+
+HTClearRules: Clear all rules
+
+ ON EXIT,
+
+ Rule file There are no rules
+
+ returns
+ 0 if success, -1 if error.
+
+ */
+
+#ifdef __STDC__
+extern int HTClearRules(void);
+#else
+extern int HTClearRules();
+#endif
+
+
+/*
+
+HTTranslate: Translate by rules
+
+ */
+
+/*
+
+ ON ENTRY,
+
+ required points to a string whose equivalent value is neeed
+
+ ON EXIT,
+
+ returns the address of the equivalent string allocated from the heap
+ which the CALLER MUST FREE. If no translation occured, then it is
+ a copy of the original.
+
+ */
+#ifdef __STDC__
+extern char * HTTranslate(const char * required);
+#else
+extern char * HTTranslate();
+#endif
+
+
+/*
+
+HTSetConfiguration: Load one line of configuration information
+
+ ON ENTRY,
+
+ config is a string in the syntax of a rule file line.
+
+ This routine may be used for loading configuration information from sources other than
+ the rule file, for example INI files for X resources.
+
+ */
+extern int HTSetConfiguration PARAMS((CONST char * config));
+
+
+/*
+
+HtLoadRules: Load the rules from a file
+
+ ON ENTRY,
+
+ Rule table Rules can be in any state
+
+ ON EXIT,
+
+ Rule table Any existing rules will have been kept. Any new rules will have
+ been loaded on top, so as to be tried first.
+
+ Returns 0 if no error.
+
+ */
+
+#ifdef __STDC__
+extern int HTLoadRules(const char * filename);
+#else
+extern int HTLoadRules();
+#endif
+/*
+
+ */
+
+
+#endif /* HTUtils.h */
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStream.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStream.h
new file mode 100644
index 00000000000..72344cd367e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStream.h
@@ -0,0 +1,61 @@
+/* The Stream class definition -- libwww
+ STREAM OBJECT DEFINITION
+
+ A Stream object is something which accepts a stream of text.
+
+ The creation methods will vary on the type of Stream Object. All creation methods
+ return a pointer to the stream type below.
+
+ As you can see, but the methods used to write to the stream and close it are pointed to
+ be the object itself.
+
+ */
+#ifndef HTSTREAM_H
+#define HTSTREAM_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+typedef struct _HTStream HTStream;
+
+/*
+
+ These are the common methods of all streams. They should be self-explanatory, except
+ for end_document which must be called before free. It should be merged with free in
+ fact: it should be dummy for new streams.
+
+ The put_block method was write, but this upset systems whiuch had macros for write().
+
+ */
+typedef struct _HTStreamClass {
+
+ char* name; /* Just for diagnostics */
+
+ void (*_free) PARAMS((
+ HTStream* me));
+
+ void (*_abort) PARAMS((
+ HTStream* me,
+ HTError e));
+
+ void (*put_character) PARAMS((
+ HTStream* me,
+ char ch));
+
+ void (*put_string) PARAMS((
+ HTStream* me,
+ CONST char * str));
+
+ void (*put_block) PARAMS((
+ HTStream* me,
+ CONST char * str,
+ int len));
+
+}HTStreamClass;
+
+#endif /* HTSTREAM_H */
+
+/*
+
+ end of HTStream.h */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c
new file mode 100644
index 00000000000..5f358b9775f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.c
@@ -0,0 +1,344 @@
+/* Case-independent string comparison HTString.c
+**
+** Original version came with listserv implementation.
+** Version TBL Oct 91 replaces one which modified the strings.
+** 02-Dec-91 (JFG) Added stralloccopy and stralloccat
+** 23 Jan 92 (TBL) Changed strallocc* to 8 char HTSAC* for VM and suchlike
+** 6 Oct 92 (TBL) Moved WWW_TraceFlag in here to be in library
+*/
+#include <ctype.h>
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "LYLeaks.h"
+#include "LYStrings.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC int WWW_TraceFlag = 0; /* Global trace flag for ALL W3 code */
+
+#ifndef VC
+#define VC "unknown"
+#endif /* !VC */
+
+PUBLIC CONST char * HTLibraryVersion = VC; /* String for help screen etc */
+
+/*
+** strcasecomp8 is a variant of strcasecomp (below)
+** ------------ -----------
+** but uses 8bit upper/lower case information
+** from the current display charset.
+** It returns 0 if exact match.
+*/
+PUBLIC int strcasecomp8 ARGS2(
+ CONST char*, a,
+ CONST char *, b)
+{
+ CONST char *p = a;
+ CONST char *q = b;
+
+ for ( ; *p && *q; p++, q++) {
+ int diff = UPPER8(*p, *q);
+ if (diff) return diff;
+ }
+ if (*p)
+ return 1; /* p was longer than q */
+ if (*q)
+ return -1; /* p was shorter than q */
+ return 0; /* Exact match */
+}
+
+/*
+** strncasecomp8 is a variant of strncasecomp (below)
+** ------------- ------------
+** but uses 8bit upper/lower case information
+** from the current display charset.
+** It returns 0 if exact match.
+*/
+PUBLIC int strncasecomp8 ARGS3(
+ CONST char*, a,
+ CONST char *, b,
+ int, n)
+{
+ CONST char *p = a;
+ CONST char *q = b;
+
+ for ( ; ; p++, q++) {
+ int diff;
+ if (p == (a+n))
+ return 0; /* Match up to n characters */
+ if (!(*p && *q))
+ return (*p - *q);
+ diff = UPPER8(*p, *q);
+ if (diff)
+ return diff;
+ }
+ /*NOTREACHED*/
+}
+#ifndef VM /* VM has these already it seems */
+
+/* Strings of any length
+** ---------------------
+*/
+PUBLIC int strcasecomp ARGS2(
+ CONST char*, a,
+ CONST char *, b)
+{
+ CONST char *p = a;
+ CONST char *q = b;
+
+ for ( ; *p && *q; p++, q++) {
+ int diff = TOLOWER(*p) - TOLOWER(*q);
+ if (diff) return diff;
+ }
+ if (*p)
+ return 1; /* p was longer than q */
+ if (*q)
+ return -1; /* p was shorter than q */
+ return 0; /* Exact match */
+}
+
+
+/* With count limit
+** ----------------
+*/
+PUBLIC int strncasecomp ARGS3(
+ CONST char*, a,
+ CONST char *, b,
+ int, n)
+{
+ CONST char *p = a;
+ CONST char *q = b;
+
+ for ( ; ; p++, q++) {
+ int diff;
+ if (p == (a+n))
+ return 0; /* Match up to n characters */
+ if (!(*p && *q))
+ return (*p - *q);
+ diff = TOLOWER(*p) - TOLOWER(*q);
+ if (diff)
+ return diff;
+ }
+ /*NOTREACHED*/
+}
+#endif /* VM */
+
+/* Allocate a new copy of a string, and returns it
+*/
+PUBLIC char * HTSACopy ARGS2(
+ char **, dest,
+ CONST char *, src)
+{
+ FREE(*dest);
+ if (src) {
+ *dest = (char *) malloc (strlen(src) + 1);
+ if (*dest == NULL)
+ outofmem(__FILE__, "HTSACopy");
+ strcpy (*dest, src);
+ }
+ return *dest;
+}
+
+/* String Allocate and Concatenate
+*/
+PUBLIC char * HTSACat ARGS2(
+ char **, dest,
+ CONST char *, src)
+{
+ if (src && *src) {
+ if (*dest) {
+ int length = strlen(*dest);
+ *dest = (char *)realloc(*dest, length + strlen(src) + 1);
+ if (*dest == NULL)
+ outofmem(__FILE__, "HTSACat");
+ strcpy (*dest + length, src);
+ } else {
+ *dest = (char *)malloc(strlen(src) + 1);
+ if (*dest == NULL)
+ outofmem(__FILE__, "HTSACat");
+ strcpy (*dest, src);
+ }
+ }
+ return *dest;
+}
+
+
+/* Find next Field
+** ---------------
+**
+** On entry,
+** *pstr points to a string containig white space separated
+** field, optionlly quoted.
+**
+** On exit,
+** *pstr has been moved to the first delimiter past the
+** field
+** THE STRING HAS BEEN MUTILATED by a 0 terminator
+**
+** returns a pointer to the first field
+*/
+PUBLIC char * HTNextField ARGS1(
+ char **, pstr)
+{
+ char * p = *pstr;
+ char * start; /* start of field */
+
+ while (*p && WHITE(*p))
+ p++; /* Strip white space */
+ if (!*p) {
+ *pstr = p;
+ return NULL; /* No first field */
+ }
+ if (*p == '"') { /* quoted field */
+ p++;
+ start = p;
+ for (; *p && *p!='"'; p++) {
+ if (*p == '\\' && p[1])
+ p++; /* Skip escaped chars */
+ }
+ } else {
+ start = p;
+ while (*p && !WHITE(*p))
+ p++; /* Skip first field */
+ }
+ if (*p)
+ *p++ = '\0';
+ *pstr = p;
+ return start;
+}
+
+/* Find next Token
+** ---------------
+** Finds the next token in a string
+** On entry,
+** *pstr points to a string to be parsed.
+** delims lists characters to be recognized as delimiters.
+** If NULL default is white white space "," ";" or "=".
+** The word can optionally be quoted or enclosed with
+** chars from bracks.
+** Comments surrrounded by '(' ')' are filtered out
+** unless they are specifically reqested by including
+** ' ' or '(' in delims or bracks.
+** bracks lists bracketing chars. Some are recognized as
+** special, for those give the opening char.
+** If NULL defaults to <"> and "<" ">".
+** found points to location to fill with the ending delimiter
+** found, or is NULL.
+**
+** On exit,
+** *pstr has been moved to the first delimiter past the
+** field
+** THE STRING HAS BEEN MUTILATED by a 0 terminator
+** found points to the delimiter found unless it was NULL.
+** Returns a pointer to the first word or NULL on error
+*/
+PUBLIC char * HTNextTok ARGS4(
+ char **, pstr,
+ const char *, delims,
+ const char *, bracks,
+ char *, found)
+{
+ char * p = *pstr;
+ char * start = NULL;
+ BOOL get_blanks, skip_comments;
+ BOOL get_comments;
+ BOOL get_closing_char_too = FALSE;
+ char closer;
+ if (!pstr || !*pstr) return NULL;
+ if (!delims) delims = " ;,=" ;
+ if (!bracks) bracks = "<\"" ;
+
+ get_blanks = (!strchr(delims,' ') && !strchr(bracks,' '));
+ get_comments = (strchr(bracks,'(') != NULL);
+ skip_comments = (!get_comments && !strchr(delims,'(') && !get_blanks);
+#define skipWHITE(c) (!get_blanks && WHITE(c))
+
+ while (*p && skipWHITE(*p))
+ p++; /* Strip white space */
+ if (!*p) {
+ *pstr = p;
+ if (found) *found = '\0';
+ return NULL; /* No first field */
+ }
+ while (1) {
+ /* Strip white space and other delimiters */
+ while (*p && (skipWHITE(*p) || strchr(delims,*p))) p++;
+ if (!*p) {
+ *pstr = p;
+ if (found) *found = *(p-1);
+ return NULL; /* No field */
+ }
+
+ if (*p == '(' && (skip_comments || get_comments)) { /* Comment */
+ int comment_level = 0;
+ if (get_comments && !start) start = p+1;
+ for(;*p && (*p!=')' || --comment_level>0); p++) {
+ if (*p == '(') comment_level++;
+ else if (*p == '"') { /* quoted field within Comment */
+ for(p++; *p && *p!='"'; p++)
+ if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
+ if (!*p) break; /* (invalid) end of string found, leave */
+ }
+ if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
+ }
+ if (get_comments)
+ break;
+ if (*p) p++;
+ if (get_closing_char_too) {
+ if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) {
+ break;
+ } else
+ get_closing_char_too = (strchr(bracks,*p) != NULL);
+ }
+ } else if (strchr(bracks,*p)) { /* quoted or bracketted field */
+ switch (*p) {
+ case '<': closer = '>'; break;
+ case '[': closer = ']'; break;
+ case '{': closer = '}'; break;
+ case ':': closer = ';'; break;
+ default: closer = *p;
+ }
+ if (!start) start = ++p;
+ for(;*p && *p!=closer; p++)
+ if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
+ if (get_closing_char_too) {
+ p++;
+ if (!*p || (!strchr(bracks,*p) && strchr(delims,*p))) {
+ break;
+ } else
+ get_closing_char_too = (strchr(bracks,*p) != NULL);
+ } else
+ break; /* kr95-10-9: needs to stop here */
+#if 0
+ } else if (*p == '<') { /* quoted field */
+ if (!start) start = ++p;
+ for(;*p && *p!='>'; p++)
+ if (*p == '\\' && *(p+1)) p++; /* Skip escaped chars */
+ break; /* kr95-10-9: needs to stop here */
+#endif
+ } else { /* Spool field */
+ if (!start) start = p;
+ while(*p && !skipWHITE(*p) && !strchr(bracks,*p) &&
+ !strchr(delims,*p))
+ p++;
+ if (*p && strchr(bracks,*p)) {
+ get_closing_char_too = TRUE;
+ } else {
+ if (*p=='(' && skip_comments) {
+ *pstr = p;
+ HTNextTok(pstr, NULL, "(", found); /* Advance pstr */
+ *p = '\0';
+ if (*pstr && **pstr) (*pstr)++;
+ return start;
+ }
+ break; /* Got it */
+ }
+ }
+ }
+ if (found) *found = *p;
+
+ if (*p) *p++ = '\0';
+ *pstr = p;
+ return start;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.h
new file mode 100644
index 00000000000..0b2c23dcca6
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTString.h
@@ -0,0 +1,63 @@
+/* String handling for libwww
+ STRINGS
+
+ Case-independent string comparison and allocations with copies etc
+
+ */
+#ifndef HTSTRING_H
+#define HTSTRING_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+extern int WWW_TraceFlag; /* Global flag for all W3 trace */
+
+extern CONST char * HTLibraryVersion; /* String for help screen etc */
+
+/*
+
+Case-insensitive string comparison
+
+ The usual routines (comp instead of cmp) had some problem.
+
+ */
+extern int strcasecomp PARAMS((CONST char *a, CONST char *b));
+extern int strncasecomp PARAMS((CONST char *a, CONST char *b, int n));
+
+extern int strcasecomp8 PARAMS((CONST char *a, CONST char *b));
+extern int strncasecomp8 PARAMS((CONST char *a, CONST char *b, int n));
+ /*
+ ** strcasecomp8 and strncasecomp8 are variants of strcasecomp
+ ** and strncasecomp, but use 8bit upper/lower case information
+ ** from the current display charset
+ */
+
+
+/*
+
+Malloced string manipulation
+
+ */
+#define StrAllocCopy(dest, src) HTSACopy (&(dest), src)
+#define StrAllocCat(dest, src) HTSACat (&(dest), src)
+extern char * HTSACopy PARAMS ((char **dest, CONST char *src));
+extern char * HTSACat PARAMS ((char **dest, CONST char *src));
+
+/*
+
+Next word or quoted string
+
+ */
+extern char * HTNextField PARAMS ((char** pstr));
+
+/* A more general parser - kw */
+extern char * HTNextTok PARAMS((char ** pstr,
+ const char * delims, const char * bracks, char * found));
+
+#endif
+/*
+
+ end
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.c
new file mode 100644
index 00000000000..a5e242056b6
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.c
@@ -0,0 +1,363 @@
+/* Style Implementation for Hypertext HTStyle.c
+** ==================================
+**
+** Styles allow the translation between a logical property
+** of a piece of text and its physical representation.
+**
+** A StyleSheet is a collection of styles, defining the
+** translation necessary to
+** represent a document. It is a linked list of styles.
+*/
+#include "HTUtils.h"
+#include "HTStyle.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* Create a new style
+*/
+PUBLIC HTStyle* HTStyleNew NOARGS
+{
+ HTStyle * self = (HTStyle *)malloc(sizeof(*self));
+ memset((void *)self, 0, sizeof(*self));
+ self->font = (HTFont) 0;
+ self->color = 0;
+ return self;
+}
+
+/* Create a new style with a name
+*/
+PUBLIC HTStyle* HTStyleNewNamed ARGS1 (CONST char *,name)
+{
+ HTStyle * self = HTStyleNew();
+ StrAllocCopy(self->name, name);
+ return self;
+}
+
+
+/* Free a style
+*/
+PUBLIC HTStyle * HTStyleFree ARGS1 (HTStyle *,self)
+{
+ FREE(self->name);
+ FREE(self->SGMLTag);
+ FREE(self);
+ return NULL;
+}
+
+
+#ifdef SUPPRESS /* Only on the NeXT */
+/* Read a style from a stream (without its name)
+** --------------------------
+**
+** Reads a style with paragraph information from a stream.
+** The style name is not read or written by these routines.
+*/
+#define NONE_STRING "(None)"
+#define HTStream NXStream
+
+HTStyle * HTStyleRead (HTStyle * style, HTStream * stream)
+{
+ char myTag[STYLE_NAME_LENGTH];
+ char fontName[STYLE_NAME_LENGTH];
+ NXTextStyle *p;
+ int tab;
+ int gotpara; /* flag: have we got a paragraph definition? */
+
+ NXScanf(stream, "%s%s%f%d",
+ myTag,
+ fontName,
+ &style->fontSize,
+ &gotpara);
+ if (gotpara) {
+ if (!style->paragraph) {
+ style->paragraph = malloc(sizeof(*(style->paragraph)));
+ style->paragraph->tabs = 0;
+ }
+ p = style->paragraph;
+ NXScanf(stream, "%f%f%f%f%hd%f%f%hd",
+ &p->indent1st,
+ &p->indent2nd,
+ &p->lineHt,
+ &p->descentLine,
+ &p->alignment,
+ &style->spaceBefore,
+ &style->spaceAfter,
+ &p->numTabs);
+ FREE(p->tabs);
+ p->tabs = malloc(p->numTabs * sizeof(p->tabs[0]));
+ for (tab=0; tab < p->numTabs; tab++) {
+ NXScanf(stream, "%hd%f",
+ &p->tabs[tab].kind,
+ &p->tabs[tab].x);
+ }
+ } else { /* No paragraph */
+ FREE(style->paragraph);
+ } /* if no paragraph */
+ StrAllocCopy(style->SGMLTag, myTag);
+ if (strcmp(fontName, NONE_STRING)==0)
+ style->font = 0;
+ else
+ style->font = [Font newFont:fontName size:style->fontSize];
+ return NULL;
+}
+
+
+/* Write a style to a stream in a compatible way
+*/
+HTStyle * HTStyleWrite (HTStyle * style, NXStream * stream)
+{
+ int tab;
+ NXTextStyle *p = style->paragraph;
+ NXPrintf(stream, "%s %s %f %d\n",
+ style->SGMLTag,
+ style->font ? [style->font name] : NONE_STRING,
+ style->fontSize,
+ p!=0);
+
+ if (p) {
+ NXPrintf(stream, "\t%f %f %f %f %d %f %f\t%d\n",
+ p->indent1st,
+ p->indent2nd,
+ p->lineHt,
+ p->descentLine,
+ p->alignment,
+ style->spaceBefore,
+ style->spaceAfter,
+ p->numTabs);
+
+ for (tab=0; tab < p->numTabs; tab++)
+ NXPrintf(stream, "\t%d %f\n",
+ p->tabs[tab].kind,
+ p->tabs[tab].x);
+ }
+ return style;
+}
+
+
+/* Write a style to stdout for diagnostics
+*/
+HTStyle * HTStyleDump (HTStyle * style)
+{
+ int tab;
+ NXTextStyle *p = style->paragraph;
+ printf("Style %d `%s' SGML:%s. Font %s %.1f point.\n",
+ style,
+ style->name,
+ style->SGMLTag,
+ [style->font name],
+ style->fontSize);
+ if (p) {
+ printf(
+ "\tIndents: first=%.0f others=%.0f, Height=%.1f Desc=%.1f\n"
+ "\tAlign=%d, %d tabs. (%.0f before, %.0f after)\n",
+ p->indent1st,
+ p->indent2nd,
+ p->lineHt,
+ p->descentLine,
+ p->alignment,
+ p->numTabs,
+ style->spaceBefore,
+ style->spaceAfter);
+
+ for (tab=0; tab < p->numTabs; tab++) {
+ printf("\t\tTab kind=%d at %.0f\n",
+ p->tabs[tab].kind,
+ p->tabs[tab].x);
+ }
+ printf("\n");
+ } /* if paragraph */
+ return style;
+}
+#endif /* SUPPRESS */
+
+
+/* StyleSheet Functions
+** ====================
+*/
+
+/* Searching for styles:
+*/
+HTStyle * HTStyleNamed ARGS2 (HTStyleSheet *,self, CONST char *,name)
+{
+ HTStyle * scan;
+ for (scan=self->styles; scan; scan=scan->next)
+ if (0==strcmp(scan->name, name)) return scan;
+ if (TRACE) fprintf(stderr, "StyleSheet: No style named `%s'\n", name);
+ return NULL;
+}
+
+#ifdef NEXT_SUPRESS /* Not in general common code */
+
+HTStyle * HTStyleMatching (HTStyleSheet * self, HTStyle *style)
+{
+ HTStyle * scan;
+ for (scan=self->styles; scan; scan=scan->next)
+ if (scan->paragraph == para) return scan;
+ return NULL;
+}
+
+/* Find the style which best fits a given run
+** ------------------------------------------
+**
+** This heuristic is used for guessing the style for a run of
+** text which has been pasted in. In order, we try:
+**
+** A style whose paragraph structure is actually used by the run.
+** A style matching in font
+** A style matching in paragraph style exactly
+** A style matching in paragraph to a degree
+*/
+
+HTStyle * HTStyleForRun (HTStyleSheet *self, NXRun *run)
+{
+ HTStyle * scan;
+ HTStyle * best = 0;
+ int bestMatch = 0;
+ NXTextStyle * rp = run->paraStyle;
+ for (scan=self->styles; scan; scan=scan->next)
+ if (scan->paragraph == run->paraStyle) return scan; /* Exact */
+
+ for (scan=self->styles; scan; scan=scan->next){
+ NXTextStyle * sp = scan->paragraph;
+ if (sp) {
+ int match = 0;
+ if (sp->indent1st == rp->indent1st) match = match+1;
+ if (sp->indent2nd == rp->indent2nd) match = match+2;
+ if (sp->lineHt == rp->lineHt) match = match+1;
+ if (sp->numTabs == rp->numTabs) match = match+1;
+ if (sp->alignment == rp->alignment) match = match+3;
+ if (scan->font == run->font) match = match+10;
+ if (match>bestMatch) {
+ best=scan;
+ bestMatch=match;
+ }
+ }
+ }
+ if (TRACE) fprintf(stderr, "HTStyleForRun: Best match for style is %d out of 18\n",
+ bestMatch);
+ return best;
+}
+#endif /* NEXT_SUPRESS */
+
+
+/* Add a style to a sheet
+** ----------------------
+*/
+HTStyleSheet * HTStyleSheetAddStyle ARGS2
+ (HTStyleSheet *,self, HTStyle *,style)
+{
+ style->next = 0; /* The style will go on the end */
+ if (!self->styles) {
+ self->styles = style;
+ } else {
+ HTStyle * scan;
+ for(scan=self->styles; scan->next; scan=scan->next); /* Find end */
+ scan->next=style;
+ }
+ return self;
+}
+
+
+/* Remove the given object from a style sheet if it exists
+*/
+HTStyleSheet * HTStyleSheetRemoveStyle ARGS2
+ (HTStyleSheet *,self, HTStyle *,style)
+{
+ if (self->styles == style) {
+ self->styles = style->next;
+ return self;
+ } else {
+ HTStyle * scan;
+ for(scan = self->styles; scan; scan = scan->next) {
+ if (scan->next == style) {
+ scan->next = style->next;
+ return self;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Create new style sheet
+*/
+
+HTStyleSheet * HTStyleSheetNew NOARGS
+{
+ HTStyleSheet * self = (HTStyleSheet *)malloc(sizeof(*self));
+
+ memset((void*)self, 0, sizeof(*self)); /* ANSI */
+/* Harbison c ref man says (char*)self
+ but k&r ansii and abc books and Think_C say (void*) */
+
+/* bzero(self, sizeof(*self)); */ /* BSD */
+ return self;
+}
+
+
+/* Free off a style sheet pointer
+*/
+HTStyleSheet * HTStyleSheetFree ARGS1 (HTStyleSheet *,self)
+{
+ HTStyle * style;
+ while((style=self->styles)!=0) {
+ self->styles = style->next;
+ HTStyleFree(style);
+ }
+ FREE(self);
+ return NULL;
+}
+
+
+/* Read a stylesheet from a typed stream
+** -------------------------------------
+**
+** Reads a style sheet from a stream. If new styles have the same names
+** as existing styles, they replace the old ones without changing the ids.
+*/
+
+#ifdef NEXT_SUPRESS /* Only on the NeXT */
+HTStyleSheet * HTStyleSheetRead(HTStyleSheet * self, NXStream * stream)
+{
+ int numStyles;
+ int i;
+ HTStyle * style;
+ char styleName[80];
+ NXScanf(stream, " %d ", &numStyles);
+ if (TRACE) fprintf(stderr, "Stylesheet: Reading %d styles\n", numStyles);
+ for (i=0; i<numStyles; i++) {
+ NXScanf(stream, "%s", styleName);
+ style = HTStyleNamed(self, styleName);
+ if (!style) {
+ style = HTStyleNewNamed(styleName);
+ (void) HTStyleSheetAddStyle(self, style);
+ }
+ (void) HTStyleRead(style, stream);
+ if (TRACE) HTStyleDump(style);
+ }
+ return self;
+}
+
+/* Write a stylesheet to a typed stream
+** ------------------------------------
+**
+** Writes a style sheet to a stream.
+*/
+
+HTStyleSheet * HTStyleSheetWrite(HTStyleSheet * self, NXStream * stream)
+{
+ int numStyles = 0;
+ HTStyle * style;
+
+ for(style=self->styles; style; style=style->next) numStyles++;
+ NXPrintf(stream, "%d\n", numStyles);
+
+ if (TRACE) fprintf(stderr, "StyleSheet: Writing %d styles\n", numStyles);
+ for (style=self->styles; style; style=style->next) {
+ NXPrintf(stream, "%s ", style->name);
+ (void) HTStyleWrite(style, stream);
+ }
+ return self;
+}
+#endif /* NEXT_SUPRESS */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.h
new file mode 100644
index 00000000000..bbab0ea662c
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTStyle.h
@@ -0,0 +1,182 @@
+/* HTStyle: Style management for libwww
+ STYLE DEFINITION FOR HYPERTEXT
+
+ Styles allow the translation between a logical property of a piece of text and its
+ physical representation.
+
+ A StyleSheet is a collection of styles, defining the translation necessary to represent
+ a document. It is a linked list of styles.
+
+Overriding this module
+
+ Why is the style structure declared in the HTStyle.h module, instead of having the user
+ browser define the structure, and the HTStyle routines just use sizeof() for copying?
+
+ It's not obvious whether HTStyle.c should be common code. It's useful to have common
+ code for loading style sheets, especially if the movement toward standard style sheets
+ gets going.
+
+ If it IS common code, then both the hypertext object and HTStyle.c must know the
+ structure of a style, so HTStyle.h is a suitable place to put that. HTStyle.c has to
+ be compiled with a knowledge of the
+
+ It we take it out of the library, then of course HTStyle could be declared as an
+ undefined structure. The only references to it are in the structure-flattening code
+ HTML.c and HTPlain.c, which only use HTStypeNamed().
+
+ You can in any case override this function in your own code, which will prevent the
+ HTStyle from being loaded. You will be able to redefine your style structure in this
+ case without problems, as no other moule needs to know it.
+
+ */
+#ifndef HTStyle_H
+#define HTStyle_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTAnchor.h"
+
+typedef long int HTFont; /* Dummy definition instead */
+
+#ifdef SHORT_NAMES
+#define HTStyleNew HTStNew
+#define HTStyleFree HTStFree
+#define HTStyleRead HTStRead
+#define HTStyleWrite HTStWrite
+#define HTStyleSheetNew HTStShNe
+#define HTStyleSheetFree HTStShFr
+#define HTStyleNamed HTStName
+#define HTStyleForParagraph HTStFoPa
+#define HTStyleMatching HTStMatc
+#define HTStyleForRun HTStFoRu
+#define HTStyleSheetAddStyle HTStShAd
+#define HTStyleSheetRemoveStyle HTStShRm
+#define HTStyleSheetRead HTStShRe
+#define HTStyleSheetWrite HTStShWr
+#endif
+
+#ifdef NeXT_suppressed
+#include <appkit/appkit.h>
+typedef NXCoord HTCoord;
+#define HTParagraphStyle NXTextStyle
+#define HTCoord NXCoord
+typedef struct _color {
+ float grey;
+ int RGBColor;
+} HTColor;
+#else
+
+typedef int HTCoord; /* changed from float to int - kw */
+
+typedef struct _HTParagraphStyle {
+ HTCoord left_indent; /* @@@@ junk! etc etc*/
+} HTParagraphStyle;
+
+typedef int HTColor; /* Sorry about the US spelling! */
+
+#endif
+
+
+
+#define STYLE_NAME_LENGTH 80 /* @@@@@@@@@@@ */
+
+typedef struct {
+ short kind; /* only NX_LEFTTAB implemented*/
+ HTCoord position; /* x coordinate for stop */
+} HTTabStop;
+
+
+/* The Style Structure
+** -------------------
+*/
+
+typedef struct _HTStyle {
+
+/* Style management information
+*/
+ struct _HTStyle *next; /* Link for putting into stylesheet */
+ char * name; /* Style name */
+ char * SGMLTag; /* Tag name to start */
+
+
+/* Character attributes (a la NXRun)
+*/
+ HTFont font; /* Font id */
+ HTCoord fontSize; /* The size of font, not independent */
+ HTColor color; /* text gray of current run */
+ int superscript; /* superscript (-sub) in points */
+
+ HTAnchor *anchor; /* Anchor id if any, else zero */
+
+/* Paragraph Attribtes (a la NXTextStyle)
+*/
+ HTCoord indent1st; /* how far first line in paragraph is
+ * indented */
+ HTCoord leftIndent; /* how far second line is indented */
+ HTCoord rightIndent; /* (Missing from NeXT version */
+ short alignment; /* quad justification */
+ HTCoord lineHt; /* line height */
+ HTCoord descentLine; /* descender bottom from baseline */
+ CONST HTTabStop *tabs; /* array of tab stops, 0 terminated */
+
+ BOOL wordWrap; /* Yes means wrap at space not char */
+ BOOL freeFormat; /* Yes means \n is just white space */
+ HTCoord spaceBefore; /* Omissions from NXTextStyle */
+ HTCoord spaceAfter;
+ int paraFlags; /* Paragraph flags, bits as follows: */
+
+#define PARA_KEEP 1 /* Do not break page within this paragraph */
+#define PARA_WITH_NEXT 2 /* Do not break page after this paragraph */
+
+#define HT_JUSTIFY 0 /* For alignment */
+#define HT_LEFT 1
+#define HT_RIGHT 2
+#define HT_CENTER 3
+
+} HTStyle;
+
+
+/* Style functions:
+*/
+extern HTStyle * HTStyleNew NOPARAMS;
+extern HTStyle * HTStyleNewNamed PARAMS ((CONST char * name));
+extern HTStyle * HTStyleFree PARAMS((HTStyle * self));
+#ifdef SUPRESS
+extern HTStyle * HTStyleRead PARAMS((HTStyle * self, HTStream * stream));
+extern HTStyle * HTStyleWrite PARAMS((HTStyle * self, HTStream * stream));
+#endif
+/* Style Sheet
+** -----------
+*/
+typedef struct _HTStyleSheet {
+ char * name;
+ HTStyle * styles;
+} HTStyleSheet;
+
+
+/* Stylesheet functions:
+*/
+extern HTStyleSheet * HTStyleSheetNew NOPARAMS;
+extern HTStyleSheet * HTStyleSheetFree PARAMS((HTStyleSheet * self));
+extern HTStyle * HTStyleNamed PARAMS((HTStyleSheet * self, CONST char * name));
+extern HTStyle * HTStyleForParagraph PARAMS((HTStyleSheet * self,
+ HTParagraphStyle * paraStyle));
+extern HTStyle * HTStyleMatching PARAMS((HTStyleSheet *self, HTStyle * style));
+/* extern HTStyle * HTStyleForRun PARAMS((HTStyleSheet *self, NXRun * run)); */
+extern HTStyleSheet * HTStyleSheetAddStyle PARAMS((HTStyleSheet * self,
+ HTStyle * style));
+extern HTStyleSheet * HTStyleSheetRemoveStyle PARAMS((HTStyleSheet * self,
+ HTStyle * style));
+#ifdef SUPPRESS
+extern HTStyleSheet * HTStyleSheetRead PARAMS((HTStyleSheet * self,
+ HTStream * stream));
+extern HTStyleSheet * HTStyleSheetWrite PARAMS((HTStyleSheet * self,
+ HTStream * stream));
+#endif
+#define CLEAR_POINTER ((void *)-1) /* Pointer value means "clear me" */
+
+/* DefaultStyle.c */
+extern HTStyleSheet * DefaultStyle NOPARAMS;
+
+#endif /* HTStyle_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.c
new file mode 100644
index 00000000000..dab7ab7373e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.c
@@ -0,0 +1,1142 @@
+/* Generic Communication Code HTTCP.c
+** ==========================
+**
+** This code is in common between client and server sides.
+**
+** 16 Jan 92 TBL Fix strtol() undefined on CMU Mach.
+** 25 Jun 92 JFG Added DECNET option through TCP socket emulation.
+** 13 Sep 93 MD Added correct return of vmserrorno for HTInetStatus.
+** Added decoding of vms error message for MULTINET.
+** 7-DEC-1993 Bjorn S. Nilsson, ALEPH, CERN, VMS UCX ioctl() changes
+** (done of Mosaic)
+** 19 Feb 94 Danny Mayer Added Bjorn Fixes to Lynx version
+** 7 Mar 94 Danny Mayer Added Fix UCX version for full domain name
+** 20 May 94 Andy Harper Added support for CMU TCP/IP transport
+** 17 Nov 94 Andy Harper Added support for SOCKETSHR transport
+** 16 Jul 95 S. Bjorndahl added kluge to deal with LIBCMU bug
+*/
+
+#include "HTUtils.h"
+#include "tcp.h" /* Defines SHORT_NAMES if necessary */
+#include "HTAccess.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "HTTCP.h"
+
+#ifdef NSL_FORK
+#include <signal.h>
+#include <sys/wait.h>
+#endif /* NSL_FORK */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern int HTCheckForInterrupt NOPARAMS;
+
+#ifdef SVR4_BSDSELECT
+PUBLIC int BSDselect PARAMS((
+ int nfds,
+ fd_set * readfds,
+ fd_set * writefds,
+ fd_set * exceptfds,
+ struct timeval * timeout));
+#ifdef select
+#undef select
+#endif /* select */
+#define select BSDselect
+#ifdef SOCKS
+#ifdef Rselect
+#undef Rselect
+#endif /* Rselect */
+#define Rselect BSDselect
+#endif /* SOCKS */
+#endif /* SVR4_BSDSELECT */
+
+#include "LYLeaks.h"
+
+#ifdef SHORT_NAMES
+#define HTInetStatus HTInStat
+#define HTInetString HTInStri
+#define HTParseInet HTPaInet
+#endif /* SHORT_NAMES */
+
+#ifndef FD_SETSIZE
+#if defined(UCX) || defined(SOCKETSHR_TCP) || defined(CMU_TCP)
+#define FD_SETSIZE 32
+#else
+#define FD_SETSIZE 256
+#endif /* Limit # sockets to 32 for UCX, BSN - also SOCKETSHR and CMU, AH */
+#endif /* FD_SETSIZE */
+
+/*
+** Module-Wide variables
+*/
+PRIVATE char *hostname = NULL; /* The name of this host */
+
+/*
+** PUBLIC VARIABLES
+*/
+#ifdef SOCKS
+extern BOOLEAN socks_flag;
+PUBLIC unsigned long socks_bind_remoteAddr; /* for long Rbind */
+#endif /* SOCKS */
+
+/* PUBLIC SockA HTHostAddress; */ /* The internet address of the host */
+ /* Valid after call to HTHostName() */
+
+/* Encode INET status (as in sys/errno.h) inet_status()
+** ------------------
+**
+** On entry,
+** where gives a description of what caused the error
+** global errno gives the error number in the Unix way.
+**
+** On return,
+** returns a negative status in the Unix way.
+*/
+#ifndef PCNFS
+
+#ifdef VMS
+#include <perror.h>
+#ifndef errno
+extern int errno;
+#endif /* !errno */
+#endif /* VMS */
+
+#ifndef VM
+#ifndef VMS
+#ifndef THINK_C
+
+#ifdef DECL_SYS_ERRLIST
+extern char *sys_errlist[]; /* see man perror on cernvax */
+extern int sys_nerr;
+#endif /* DECL_SYS_ERRLIST */
+
+#endif /* !THINK_C */
+#endif /* !VMS */
+#endif /* !VM */
+
+#endif /* !PCNFS */
+
+#if defined(VMS) && defined(UCX)
+/*
+** A routine to mimic the ioctl function for UCX.
+** Bjorn S. Nilsson, 25-Nov-1993. Based on an example in the UCX manual.
+*/
+#include <iodef.h>
+#define IOC_OUT (int)0x40000000
+extern int vaxc$get_sdc(), sys$qiow();
+
+PUBLIC int HTioctl ARGS3(
+ int, d,
+ int, request,
+ int *, argp)
+{
+ int sdc, status;
+ unsigned short fun, iosb[4];
+ char *p5, *p6;
+ struct comm {
+ int command;
+ char *addr;
+ } ioctl_comm;
+ struct it2 {
+ unsigned short len;
+ unsigned short opt;
+ struct comm *addr;
+ } ioctl_desc;
+
+ if ((sdc = vaxc$get_sdc (d)) == 0) {
+ errno = EBADF;
+ return -1;
+ }
+ ioctl_desc.opt = UCX$C_IOCTL;
+ ioctl_desc.len = sizeof(struct comm);
+ ioctl_desc.addr = &ioctl_comm;
+ if (request & IOC_OUT) {
+ fun = IO$_SENSEMODE;
+ p5 = 0;
+ p6 = (char *)&ioctl_desc;
+ } else {
+ fun = IO$_SETMODE;
+ p5 = (char *)&ioctl_desc;
+ p6 = 0;
+ }
+ ioctl_comm.command = request;
+ ioctl_comm.addr = (char *)argp;
+ status = sys$qiow (0, sdc, fun, iosb, 0, 0, 0, 0, 0, 0, p5, p6);
+ if (!(status & 01)) {
+ errno = status;
+ return -1;
+ }
+ if (!(iosb[0] & 01)) {
+ errno = iosb[0];
+ return -1;
+ }
+ return 0;
+}
+#endif /* VMS && UCX */
+
+/* Report Internet Error
+** ---------------------
+*/
+PUBLIC int HTInetStatus ARGS1(
+ char *, where)
+{
+#ifdef VMS
+#ifdef MULTINET
+ SOCKET_ERRNO = vmserrno;
+#endif /* MULTINET */
+#endif /* VMS */
+
+ CTRACE(tfp,
+ "TCP: Error %d in `SOCKET_ERRNO' after call to %s() failed.\n\t%s\n",
+ SOCKET_ERRNO, where,
+ /* third arg is transport/platform specific */
+#ifdef VM
+ "(Error number not translated)"); /* What Is the VM equiv? */
+#define ER_NO_TRANS_DONE
+#endif /* VM */
+
+#ifdef VMS
+#ifdef MULTINET
+ vms_errno_string());
+#else
+ ((SOCKET_ERRNO > 0 && SOCKET_ERRNO <= 65) ?
+ strerror(SOCKET_ERRNO) : "(Error number not translated)"));
+#endif /* MULTINET */
+#define ER_NO_TRANS_DONE
+#endif /* VMS */
+
+#ifdef HAVE_STRERROR
+ strerror(SOCKET_ERRNO));
+#define ER_NO_TRANS_DONE
+#endif /* HAVE_STRERROR */
+
+#ifndef ER_NO_TRANS_DONE
+ (SOCKET_ERRNO < sys_nerr ?
+ sys_errlist[SOCKET_ERRNO] : "Unknown error" ));
+#endif /* !ER_NO_TRANS_DONE */
+
+#ifdef VMS
+#ifndef MULTINET
+ CTRACE(tfp,
+ " Unix error number (SOCKET_ERRNO) = %ld dec\n",
+ SOCKET_ERRNO);
+ CTRACE(tfp,
+ " VMS error (vaxc$errno) = %lx hex\n",
+ vaxc$errno);
+#endif /* MULTINET */
+#endif /* VMS */
+
+#ifdef VMS
+ /*
+ ** uerrno and errno happen to be zero if vmserrno <> 0
+ */
+#ifdef MULTINET
+ return -vmserrno;
+#else
+ return -vaxc$errno;
+#endif /* MULTINET */
+#else
+ return -SOCKET_ERRNO;
+#endif /* VMS */
+}
+
+/* Parse a cardinal value parse_cardinal()
+** ----------------------
+**
+** On entry,
+** *pp points to first character to be interpreted, terminated by
+** non 0:9 character.
+** *pstatus points to status already valid
+** maxvalue gives the largest allowable value.
+**
+** On exit,
+** *pp points to first unread character
+** *pstatus points to status updated iff bad
+*/
+PUBLIC unsigned int HTCardinal ARGS3(
+ int *, pstatus,
+ char **, pp,
+ unsigned int, max_value)
+{
+ unsigned int n;
+ if ((**pp<'0') || (**pp>'9')) { /* Null string is error */
+ *pstatus = -3; /* No number where one expected */
+ return 0;
+ }
+
+ n = 0;
+ while ((**pp >= '0') && (**pp <= '9'))
+ n = n*10 + *((*pp)++) - '0';
+
+ if (n > max_value) {
+ *pstatus = -4; /* Cardinal outside range */
+ return 0;
+ }
+
+ return n;
+}
+
+#ifndef DECNET /* Function only used below for a trace message */
+/* Produce a string for an Internet address
+** ----------------------------------------
+**
+** On exit,
+** returns a pointer to a static string which must be copied if
+** it is to be kept.
+*/
+PUBLIC CONST char * HTInetString ARGS1(
+ SockA*, soc_in)
+{
+ static char string[16];
+ sprintf(string, "%d.%d.%d.%d",
+ (int)*((unsigned char *)(&soc_in->sin_addr)+0),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+1),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+2),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+3));
+ return string;
+}
+#endif /* !DECNET */
+
+/* Parse a network node address and port
+** -------------------------------------
+**
+** On entry,
+** str points to a string with a node name or number,
+** with optional trailing colon and port number.
+** soc_in points to the binary internet or decnet address field.
+**
+** On exit,
+** *soc_in is filled in. If no port is specified in str, that
+** field is left unchanged in *soc_in.
+*/
+PUBLIC int HTParseInet ARGS2(
+ SockA *, soc_in,
+ CONST char *, str)
+{
+ char *port;
+ char *host = NULL;
+ int dotcount_ip = 0; /* for dotted decimal IP addr */
+ struct hostent *phost; /* Pointer to host - See netdb.h */
+
+ if (!str) {
+ if (TRACE) {
+ fprintf(stderr, "HTParseInet: Can't parse `NULL'.\n");
+ }
+ return -1;
+ }
+ if (HTCheckForInterrupt()) {
+ if (TRACE) {
+ fprintf (stderr, "HTParseInet: INTERRUPTED for '%s'.\n", str);
+ }
+ return -1;
+ }
+ StrAllocCopy(host, str); /* Make a copy we can mutilate */
+
+ /*
+ ** Parse port number if present.
+ */
+ if ((port = strchr(host, ':')) != NULL) {
+ *port++ = 0; /* Chop off port */
+ if (port[0] >= '0' && port[0] <= '9') {
+#ifdef unix
+ soc_in->sin_port = htons(atol(port));
+#else /* VMS: */
+#ifdef DECNET
+ soc_in->sdn_objnum = (unsigned char)(strtol(port, (char**)0, 10));
+#else
+ soc_in->sin_port = htons((unsigned short)strtol(port,(char**)0,10));
+#endif /* Decnet */
+#endif /* Unix vs. VMS */
+#ifdef SUPPRESS /* 1. crashes!?!. 2. Not recommended */
+ } else {
+ struct servent * serv = getservbyname(port, (char*)0);
+ if (serv) {
+ soc_in->sin_port = serv->s_port;
+ } else if (TRACE) {
+ fprintf(stderr, "TCP: Unknown service %s\n", port);
+ }
+#endif /* SUPPRESS */
+ }
+ }
+
+#ifdef DECNET
+ /*
+ ** Read Decnet node name. @@ Should know about DECnet addresses, but
+ ** it's probably worth waiting until the Phase transition from IV to V.
+ */
+ soc_in->sdn_nam.n_len = min(DN_MAXNAML, strlen(host)); /* <=6 in phase 4 */
+ strncpy(soc_in->sdn_nam.n_name, host, soc_in->sdn_nam.n_len + 1);
+ if (TRACE) {
+ fprintf(stderr,
+ "DECnet: Parsed address as object number %d on host %.6s...\n",
+ soc_in->sdn_objnum, host);
+ }
+#else /* parse Internet host: */
+
+ if (*host >= '0' && *host <= '9') { /* Test for numeric node address: */
+ char *strptr = host;
+ while (*strptr) {
+ if (*strptr == '.') {
+ dotcount_ip++;
+ } else if (!isdigit(*strptr)) {
+ break;
+ }
+ strptr++;
+ }
+ if (*strptr) { /* found non-numeric, assume domain name */
+ dotcount_ip = 0;
+ }
+ }
+
+ /*
+ ** Parse host number if present.
+ */
+ if (dotcount_ip == 3) { /* Numeric node address: */
+
+#ifdef DJGPP
+ soc_in->sin_addr.s_addr = htonl(aton(host));
+#else
+#ifdef DGUX_OLD
+ soc_in->sin_addr.s_addr = inet_addr(host).s_addr; /* See arpa/inet.h */
+#else
+#ifdef GUSI
+ soc_in->sin_addr = inet_addr(host); /* See netinet/in.h */
+#else
+ soc_in->sin_addr.s_addr = inet_addr(host); /* See arpa/inet.h */
+#endif /* GUSI */
+#endif /* DGUX_OLD */
+#endif /* DJGPP */
+ FREE(host);
+ } else { /* Alphanumeric node name: */
+#ifdef MVS /* Outstanding problem with crash in MVS gethostbyname */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: Calling gethostbyname(%s)\n", host);
+ }
+#endif /* MVS */
+
+#ifdef NSL_FORK
+ /*
+ ** Start block for fork-based gethostbyname() with
+ ** checks for interrupts. - Tom Zerucha (tz@execpc.com) & FM
+ */
+ {
+ /*
+ ** Pipe, child pid, and status buffers.
+ */
+ pid_t fpid, waitret = (pid_t)0;
+ int pfd[2], cstat, cst1 = 0;
+
+ pipe(pfd);
+
+ if ((fpid = fork()) == 0 ) {
+ /*
+ ** Child - for the long call.
+ */
+ phost = gethostbyname(host);
+ cst1 = 0;
+ /*
+ ** Return value (or nulls).
+ */
+ if (phost != NULL)
+ write(pfd[1], phost->h_addr, phost->h_length);
+ else
+ write(pfd[1], &cst1, 4);
+ /*
+ ** Return an error code.
+ */
+ _exit(phost == NULL);
+ }
+
+ /*
+ ** (parent) Wait until lookup finishes, or interrupt.
+ */
+ cstat = 0;
+ while (cstat <= 0) {
+ /*
+ ** Exit when data sent.
+ */
+ IOCTL(pfd[0], FIONREAD, &cstat);
+ if (cstat > 0)
+ break;
+ /*
+ ** Exit if child exited.
+ */
+ if ((waitret = waitpid(fpid, &cst1, WNOHANG)) > 0) {
+ break;
+ }
+ /*
+ ** Abort if interrupt key pressed.
+ */
+ if (HTCheckForInterrupt()) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: INTERRUPTED gethostbyname.\n");
+ }
+ kill(fpid , SIGKILL);
+ waitpid(fpid, NULL, 0);
+ FREE(host);
+ close(pfd[0]);
+ close(pfd[1]);
+ return HT_INTERRUPTED;
+ }
+ /*
+ ** Be nice to the system.
+ */
+ sleep(1);
+ }
+ if (waitret <= 0) {
+ waitret = waitpid(fpid, &cst1, WNOHANG);
+ }
+ if (TRACE) {
+ if (WIFEXITED(cst1)) {
+ fprintf(stderr,
+ "HTParseInet: NSL_FORK child %d exited, status 0x%x.\n",
+ (int)waitret, cst1);
+ } else if (WIFSIGNALED(cst1)) {
+ fprintf(stderr,
+ "HTParseInet: NSL_FORK child %d got signal, status 0x%x!\n",
+ (int)waitret, cst1);
+#ifdef WCOREDUMP
+ if (WCOREDUMP(cst1)) {
+ fprintf(stderr,
+ "HTParseInet: NSL_FORK child %d dumped core!\n",
+ (int)waitret);
+ }
+#endif /* WCOREDUMP */
+ } else if (WIFSTOPPED(cst1)) {
+ fprintf(stderr,
+ "HTParseInet: NSL_FORK child %d is stopped, status 0x%x!\n",
+ (int)waitret, cst1);
+ }
+ }
+ /*
+ ** Read as much as we can - should be the address.
+ */
+ IOCTL(pfd[0], FIONREAD, &cstat);
+ if (cstat < 4) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: NSL_FORK child returns only %d bytes.\n",
+ cstat);
+ fprintf(stderr,
+ " Trying again without forking.\n");
+ }
+ phost = gethostbyname(host); /* See netdb.h */
+ if (!phost) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: Can't find internet node name `%s'.\n",
+ host);
+ }
+ memset((void *)&soc_in->sin_addr, 0, sizeof(soc_in->sin_addr));
+ } else {
+ memcpy((void *)&soc_in->sin_addr,
+ phost->h_addr, phost->h_length);
+ }
+#ifdef NOTDEFINED
+ cstat = read(pfd[0], (void *)&soc_in->sin_addr , 4);
+#endif /* NOTDEFINED */
+ } else {
+ cstat = read(pfd[0], (void *)&soc_in->sin_addr , cstat);
+ }
+ close(pfd[0]);
+ close(pfd[1]);
+ }
+ if (soc_in->sin_addr.s_addr == 0) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: Can't find internet node name `%s'.\n",
+ host);
+ }
+ FREE(host);
+ return -1;
+ }
+ FREE(host);
+#ifdef MVS
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: gethostbyname() returned %d\n", phost);
+ }
+#endif /* MVS */
+
+#else /* Not NSL_FORK: */
+#ifdef DJGPP
+ soc_in->sin_addr.s_addr = htonl(resolve(host));
+ FREE(host);
+ if (soc_in->sin_addr.s_addr == 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTTPAccess: Can't find internet node name `%s'.\n",host);
+ return -1; /* Fail? */
+ }
+#else
+ phost = gethostbyname(host); /* See netdb.h */
+#ifdef MVS
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: gethostbyname() returned %d\n", phost);
+ }
+#endif /* MVS */
+ if (!phost) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: Can't find internet node name `%s'.\n",
+ host);
+ }
+ FREE(host);
+ return -1; /* Fail? */
+ }
+ FREE(host);
+#if defined(VMS) && defined(CMU_TCP)
+ /*
+ ** In LIBCMU, phost->h_length contains not the length of one address
+ ** (four bytes) but the number of bytes in *h_addr, i.e. some multiple
+ ** of four. Thus we need to hard code the value here, and remember to
+ ** change it if/when IP addresses change in size. :-( LIBCMU is no
+ ** longer supported, and CMU users are encouraged to obtain and use
+ ** SOCKETSHR/NETLIB instead. - S. Bjorndahl
+ */
+ memcpy((void *)&soc_in->sin_addr, phost->h_addr, 4);
+#else
+ memcpy((void *)&soc_in->sin_addr, phost->h_addr, phost->h_length);
+#endif /* VMS && CMU_TCP */
+#endif /* DJGPP */
+#endif /* NSL_FORK */
+ }
+
+ if (TRACE) {
+ fprintf(stderr,
+ "HTParseInet: Parsed address as port %d, IP address %d.%d.%d.%d\n",
+ (int)ntohs(soc_in->sin_port),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+0),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+1),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+2),
+ (int)*((unsigned char *)(&soc_in->sin_addr)+3));
+ }
+#endif /* Internet vs. Decnet */
+
+ return 0; /* OK */
+}
+
+/* Free our name for the host on which we are - FM
+** -------------------------------------------
+**
+*/
+PRIVATE void free_HTTCP_hostname NOARGS
+{
+ FREE(hostname);
+}
+
+/* Derive the name of the host on which we are
+** -------------------------------------------
+**
+*/
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64 /* Arbitrary limit */
+#endif /* MAXHOSTNAMELEN */
+
+PRIVATE void get_host_details NOARGS
+{
+ char name[MAXHOSTNAMELEN+1]; /* The name of this host */
+#ifdef UCX
+ char *domain_name; /* The name of this host domain */
+#endif /* UCX */
+#ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
+ struct hostent * phost; /* Pointer to host -- See netdb.h */
+#endif /* NEED_HOST_ADDRESS */
+ int namelength = sizeof(name);
+
+ if (hostname)
+ return; /* Already done */
+ gethostname(name, namelength); /* Without domain */
+ StrAllocCopy(hostname, name);
+ atexit(free_HTTCP_hostname);
+#ifdef UCX
+ /*
+ ** UCX doesn't give the complete domain name.
+ ** Get rest from UCX$BIND_DOM logical.
+ */
+ if (strchr(hostname,'.') == NULL) { /* Not full address */
+ domain_name = getenv("UCX$BIND_DOMAIN");
+ if (domain_name != NULL) {
+ StrAllocCat(hostname, ".");
+ StrAllocCat(hostname, domain_name);
+ }
+ }
+#endif /* UCX */
+ CTRACE(tfp, "TCP: Local host name is %s\n", hostname);
+
+#ifndef DECNET /* Decnet ain't got no damn name server 8#OO */
+#ifdef NEED_HOST_ADDRESS /* no -- needs name server! */
+ phost = gethostbyname(name); /* See netdb.h */
+ if (!phost) {
+ if (TRACE) fprintf(stderr,
+ "TCP: Can't find my own internet node address for `%s'!!\n",
+ name);
+ return; /* Fail! */
+ }
+ StrAllocCopy(hostname, phost->h_name);
+ memcpy(&HTHostAddress, &phost->h_addr, phost->h_length);
+ if (TRACE) fprintf(stderr, " Name server says that I am `%s' = %s\n",
+ hostname, HTInetString(&HTHostAddress));
+#endif /* NEED_HOST_ADDRESS */
+
+#endif /* !DECNET */
+}
+
+PUBLIC CONST char * HTHostName NOARGS
+{
+ get_host_details();
+ return hostname;
+}
+
+/*
+** Interruptable connect as implemented for Mosaic by Marc Andreesen
+** and hacked in for Lynx years ago by Lou Montulli, and further
+** modified over the years by numerous Lynx lovers. - FM
+*/
+PUBLIC int HTDoConnect ARGS4(
+ CONST char *, url,
+ char *, protocol,
+ int, default_port,
+ int *, s)
+{
+ struct sockaddr_in soc_address;
+ struct sockaddr_in *soc_in = &soc_address;
+ int status;
+ char *line = NULL;
+ char *p1 = NULL;
+ char *at_sign = NULL;
+ char *host = NULL;
+
+ /*
+ ** Set up defaults.
+ */
+ soc_in->sin_family = AF_INET;
+ soc_in->sin_port = htons(default_port);
+
+ /*
+ ** Get node name and optional port number.
+ */
+ p1 = HTParse(url, "", PARSE_HOST);
+ if ((at_sign = strchr(p1, '@')) != NULL) {
+ /*
+ ** If there's an @ then use the stuff after it as a hostname.
+ */
+ StrAllocCopy(host, (at_sign + 1));
+ } else {
+ StrAllocCopy(host, p1);
+ }
+ FREE(p1);
+
+ line = (char *)calloc(1, (strlen(host) + strlen(protocol) + 128));
+ if (line == NULL)
+ outofmem(__FILE__, "HTDoConnect");
+ sprintf (line, "Looking up %s.", host);
+ _HTProgress (line);
+ status = HTParseInet(soc_in, host);
+ if (status) {
+ if (status != HT_INTERRUPTED) {
+ sprintf (line, "Unable to locate remote host %s.", host);
+ _HTProgress(line);
+ status = HT_NO_DATA;
+ }
+ FREE(host);
+ FREE(line);
+ return status;
+ }
+
+ sprintf (line, "Making %s connection to %s.", protocol, host);
+ _HTProgress (line);
+ FREE(host);
+
+ /*
+ ** Now, let's get a socket set up from the server for the data.
+ */
+ *s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (*s == -1) {
+ HTAlert("socket failed.");
+ FREE(line);
+ return HT_NO_DATA;
+ }
+
+#ifndef DOSPATH
+#if !defined(NO_IOCTL) || defined(USE_FCNTL)
+ /*
+ ** Make the socket non-blocking, so the connect can be canceled.
+ ** This means that when we issue the connect we should NOT
+ ** have to wait for the accept on the other end.
+ */
+ {
+#ifdef USE_FCNTL
+ int ret = fcntl(*s, F_SETFL, O_NONBLOCK);
+#else
+ int val = 1;
+ int ret = IOCTL(*s, FIONBIO, &val);
+#endif /* USE_FCNTL */
+ if (ret == -1)
+ _HTProgress("Could not make connection non-blocking.");
+ }
+#endif /* !NO_IOCTL || USE_FCNTL */
+#endif /* !DOSPATH */
+
+ /*
+ ** Issue the connect. Since the server can't do an instantaneous
+ ** accept and we are non-blocking, this will almost certainly return
+ ** a negative status.
+ */
+#ifdef SOCKS
+ if (socks_flag) {
+ status = Rconnect(*s, (struct sockaddr*)&soc_address,
+ sizeof(soc_address));
+ /*
+ ** For long Rbind.
+ */
+ socks_bind_remoteAddr = soc_address.sin_addr.s_addr;
+ } else
+#endif /* SOCKS */
+ status = connect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
+#ifndef DJGPP
+ /*
+ ** According to the Sun man page for connect:
+ ** EINPROGRESS The socket is non-blocking and the con-
+ ** nection cannot be completed immediately.
+ ** It is possible to select(2) for comple-
+ ** tion by selecting the socket for writ-
+ ** ing.
+ ** According to the Motorola SVR4 man page for connect:
+ ** EAGAIN The socket is non-blocking and the con-
+ ** nection cannot be completed immediately.
+ ** It is possible to select for completion
+ ** by selecting the socket for writing.
+ ** However, this is only possible if the
+ ** socket STREAMS module is the topmost
+ ** module on the protocol stack with a
+ ** write service procedure. This will be
+ ** the normal case.
+ */
+ if ((status < 0) &&
+ (SOCKET_ERRNO == EINPROGRESS || SOCKET_ERRNO == EAGAIN)) {
+ struct timeval timeout;
+ int ret;
+ int tries=0;
+
+ ret = 0;
+ while (ret <= 0) {
+ fd_set writefds;
+
+ /*
+ ** Protect against an infinite loop.
+ */
+ if (tries++ >= 180000) {
+ HTAlert("Connection failed for 180,000 tries.");
+ FREE(line);
+ return HT_NO_DATA;
+ }
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 100000;
+ FD_ZERO(&writefds);
+ FD_SET(*s, &writefds);
+#ifdef SOCKS
+ if (socks_flag)
+ ret = Rselect(FD_SETSIZE, NULL,
+ (void *)&writefds, NULL, &timeout);
+ else
+#endif /* SOCKS */
+ ret = select(FD_SETSIZE, NULL, (void *)&writefds, NULL, &timeout);
+
+ /*
+ ** If we suspend, then it is possible that select will be
+ ** interrupted. Allow for this possibility. - JED
+ */
+ if ((ret == -1) && (errno == EINTR))
+ continue;
+
+ /*
+ ** Again according to the Sun and Motorola man pages for connect:
+ ** EALREADY The socket is non-blocking and a previ-
+ ** ous connection attempt has not yet been
+ ** completed.
+ ** Thus if the SOCKET_ERRNO is NOT EALREADY we have a real error,
+ ** and should break out here and return that error.
+ ** Otherwise if it is EALREADY keep on trying to complete the
+ ** connection.
+ */
+ if ((ret < 0) && (SOCKET_ERRNO != EALREADY)) {
+ status = ret;
+ break;
+ } else if (ret > 0) {
+ /*
+ ** Extra check here for connection success, if we try to
+ ** connect again, and get EISCONN, it means we have a
+ ** successful connection. But don't check with SOCKS.
+ */
+#ifdef SOCKS
+ if (socks_flag) {
+ status = 0;
+ } else {
+#endif /* SOCKS */
+ status = connect(*s, (struct sockaddr*)&soc_address,
+ sizeof(soc_address));
+#ifdef UCX
+ /*
+ ** A UCX feature: Instead of returning EISCONN
+ ** UCX returns EADDRINUSE.
+ ** Test for this status also.
+ */
+ if ((status < 0) && ((SOCKET_ERRNO == EISCONN) ||
+ (SOCKET_ERRNO == EADDRINUSE)))
+#else
+ if ((status < 0) && (SOCKET_ERRNO == EISCONN))
+#endif /* UCX */
+ {
+ status = 0;
+ }
+
+ if (status && (SOCKET_ERRNO == EALREADY)) /* new stuff LJM */
+ ret = 0; /* keep going */
+ else
+ break;
+#ifdef SOCKS
+ }
+#endif /* SOCKS */
+ }
+#ifdef SOCKS
+ else if (!socks_flag)
+#else
+ else
+#endif /* SOCKS */
+ {
+ /*
+ ** The select says we aren't ready yet. Try to connect
+ ** again to make sure. If we don't get EALREADY or EISCONN,
+ ** something has gone wrong. Break out and report it.
+ **
+ ** For some reason, SVR4 returns EAGAIN here instead of
+ ** EALREADY, even though the man page says it should be
+ ** EALREADY.
+ **
+ ** For some reason, UCX pre 3 apparently returns
+ ** errno = 18242 instead the EALREADY or EISCONN.
+ */
+ status = connect(*s, (struct sockaddr*)&soc_address,
+ sizeof(soc_address));
+ if ((status < 0) &&
+ (SOCKET_ERRNO != EALREADY && SOCKET_ERRNO != EAGAIN) &&
+#ifdef UCX
+ (SOCKET_ERRNO != 18242) &&
+#endif /* UCX */
+ (SOCKET_ERRNO != EISCONN)) {
+ break;
+ }
+ }
+ if (HTCheckForInterrupt()) {
+ if (TRACE)
+ fprintf(stderr, "*** INTERRUPTED in middle of connect.\n");
+ status = HT_INTERRUPTED;
+ SOCKET_ERRNO = EINTR;
+ break;
+ }
+ }
+ }
+#endif /* !DJGPP */
+ if (status < 0) {
+ /*
+ ** The connect attempt failed or was interrupted,
+ ** so close up the socket.
+ */
+ NETCLOSE(*s);
+ }
+#ifndef DOSPATH
+#if !defined(NO_IOCTL) || defined(USE_FCNTL)
+ else {
+ /*
+ ** Make the socket blocking again on good connect.
+ */
+#ifdef USE_FCNTL
+ int ret = fcntl(*s, F_SETFL, 0);
+#else
+ int val = 0;
+ int ret = IOCTL(*s, FIONBIO, &val);
+#endif /* USE_FCNTL */
+ if (ret == -1)
+ _HTProgress("Could not restore socket to blocking.");
+ }
+#endif /* !NO_IOCTL || USE_FCNTL */
+#endif /* !DOSPATH */
+
+ FREE(line);
+ return status;
+}
+
+/*
+** This is so interruptible reads can be implemented cleanly.
+*/
+PUBLIC int HTDoRead ARGS3(
+ int, fildes,
+ void *, buf,
+ unsigned, nbyte)
+{
+ int ready, ret;
+ fd_set readfds;
+ struct timeval timeout;
+ int tries=0;
+#ifdef UCX
+ int nb;
+#endif /* UCX, BSN */
+
+ if (fildes <= 0)
+ return -1;
+
+ if (HTCheckForInterrupt()) {
+ SOCKET_ERRNO = EINTR;
+ return (HT_INTERRUPTED);
+ }
+
+#if !defined(NO_IOCTL)
+ ready = 0;
+#else
+ ready = 1;
+#endif /* bypass for NO_IOCTL */
+ while (!ready) {
+ /*
+ ** Protect against an infinite loop.
+ */
+ if (tries++ >= 180000) {
+ HTAlert("Socket read failed for 180,000 tries.");
+ SOCKET_ERRNO = EINTR;
+ return HT_INTERRUPTED;
+ }
+
+ /*
+ ** If we suspend, then it is possible that select will be
+ ** interrupted. Allow for this possibility. - JED
+ */
+ do {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 100000;
+ FD_ZERO(&readfds);
+ FD_SET(fildes, &readfds);
+#ifdef SOCKS
+ if (socks_flag)
+ ret = Rselect(FD_SETSIZE,
+ (void *)&readfds, NULL, NULL, &timeout);
+ else
+#endif /* SOCKS */
+ ret = select(FD_SETSIZE,
+ (void *)&readfds, NULL, NULL, &timeout);
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret < 0) {
+ return -1;
+ } else if (ret > 0) {
+ ready = 1;
+ } else if (HTCheckForInterrupt()) {
+ SOCKET_ERRNO = EINTR;
+ return HT_INTERRUPTED;
+ }
+ }
+
+#if !defined(UCX) || !defined(VAXC)
+ return SOCKET_READ (fildes, buf, nbyte);
+#else
+ /*
+ ** VAXC and UCX problem only.
+ */
+ errno = vaxc$errno = 0;
+ nb = SOCKET_READ (fildes, buf, nbyte);
+ CTRACE(tfp,
+ "Read - nb,errno,vaxc$errno: %d %d %d\n", nb,errno,vaxc$errno);
+ if ((nb <= 0) && TRACE)
+ perror ("HTTCP.C:HTDoRead:read"); /* RJF */
+ /*
+ ** An errno value of EPIPE and nb < 0 indicates end-of-file on VAXC.
+ */
+ if ((nb <= 0) && (errno == EPIPE)) {
+ nb = 0;
+ errno = 0;
+ }
+ return nb;
+#endif /* UCX, BSN */
+}
+
+#ifdef SVR4_BSDSELECT
+/*
+** This is a fix for the difference between BSD's select() and
+** SVR4's select(). SVR4's select() can never return a value larger
+** than the total number of file descriptors being checked. So, if
+** you select for read and write on one file descriptor, and both
+** are true, SVR4 select() will only return 1. BSD select in the
+** same situation will return 2.
+**
+** Additionally, BSD select() on timing out, will zero the masks,
+** while SVR4 does not. This is fixed here as well.
+**
+** Set your tabstops to 4 characters to have this code nicely formatted.
+**
+** Jerry Whelan, guru@bradley.edu, June 12th, 1993
+*/
+#ifdef select
+#undef select
+#endif /* select */
+
+#ifdef SOCKS
+#ifdef Rselect
+#undef Rselect
+#endif /* Rselect */
+#endif /* SOCKS */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/select.h>
+
+PUBLIC int BSDselect ARGS5(
+ int, nfds,
+ fd_set *, readfds,
+ fd_set *, writefds,
+ fd_set *, exceptfds,
+ struct timeval *, timeout)
+{
+ int rval,
+ i;
+
+#ifdef SOCKS
+ if (socks_flag)
+ rval = Rselect(nfds, readfds, writefds, exceptfds, timeout);
+ else
+#endif /* SOCKS */
+ rval = select(nfds, readfds, writefds, exceptfds, timeout);
+
+ switch (rval) {
+ case -1:
+ return(rval);
+ break;
+
+ case 0:
+ if (readfds != NULL)
+ FD_ZERO(readfds);
+ if (writefds != NULL)
+ FD_ZERO(writefds);
+ if (exceptfds != NULL)
+ FD_ZERO(exceptfds);
+ return(rval);
+ break;
+
+ default:
+ for (i = 0, rval = 0; i < nfds; i++) {
+ if ((readfds != NULL) && FD_ISSET(i, readfds))
+ rval++;
+ if ((writefds != NULL) && FD_ISSET(i, writefds))
+ rval++;
+ if ((exceptfds != NULL) && FD_ISSET(i, exceptfds))
+ rval++;
+
+ }
+ return(rval);
+ }
+/* Should never get here */
+}
+#endif /* SVR4_BSDSELECT */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.h
new file mode 100644
index 00000000000..b4dab1d6d88
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTCP.h
@@ -0,0 +1,120 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/src/HTTCP.html
+ GENERIC TCP/IP COMMUNICATION
+
+ This module has the common code for handling TCP/IP connections etc.
+
+ */
+#ifndef HTTCP_H
+#define HTTCP_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "tcp.h"
+
+#ifdef SHORT_NAMES
+#define HTInetStatus HTInStat
+#define HTInetString HTInStri
+#define HTParseInet HTPaInet
+#endif
+
+
+/* Produce a string for an internet address
+** ---------------------------------------
+**
+** On exit:
+** returns a pointer to a static string which must be copied if
+** it is to be kept.
+*/
+#ifndef _WINDOWS
+#ifdef __STDC__
+ extern const char * HTInetString(struct sockaddr_in* mysin);
+#else
+ extern char * HTInetString();
+#endif
+#endif
+
+
+/* Encode INET status (as in sys/errno.h) inet_status()
+** ------------------
+**
+** On entry:
+** where gives a description of what caused the error
+** global errno gives the error number in the unix way.
+**
+** On return:
+** returns a negative status in the unix way.
+*/
+#ifdef __STDC__
+ extern int HTInetStatus(char *where);
+#else
+ extern int HTInetStatus();
+#endif
+
+/* Publicly accessible variables
+*/
+/* extern struct sockaddr_in HTHostAddress; */
+ /* The internet address of the host */
+ /* Valid after call to HTHostName() */
+
+
+/* Parse a cardinal value parse_cardinal()
+** ----------------------
+**
+** On entry:
+** *pp points to first character to be interpreted, terminated by
+** non 0..9 character.
+** *pstatus points to status already valid,
+** maxvalue gives the largest allowable value.
+**
+** On exit:
+** *pp points to first unread character,
+** *pstatus points to status updated iff bad
+*/
+
+extern unsigned int HTCardinal PARAMS((int *pstatus,
+ char **pp,
+ unsigned int max_value));
+
+
+/* Parse an internet node address and port
+** ---------------------------------------
+**
+** On entry:
+** str points to a string with a node name or number,
+** with optional trailing colon and port number.
+** sin points to the binary internet or decnet address field.
+**
+** On exit:
+** *sin is filled in. If no port is specified in str, that
+** field is left unchanged in *sin.
+*/
+#ifdef __STDC__
+ extern int HTParseInet(struct sockaddr_in * mysin, CONST char * str);
+ /*!! had to change this to get it to compile. CTB */
+#else
+ extern int HTParseInet();
+#endif
+
+/* Get Name of This Machine
+** ------------------------
+**
+*/
+
+extern CONST char * HTHostName NOPARAMS;
+
+extern int HTDoConnect PARAMS((
+ CONST char * url,
+ char * protocol,
+ int default_port,
+ int * s));
+
+extern int HTDoRead PARAMS((
+ int fildes,
+ void * buf,
+ unsigned nbyte));
+
+#endif /* HTTCP_H */
+/*
+
+ End. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.c
new file mode 100644
index 00000000000..d13549110d0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.c
@@ -0,0 +1,1854 @@
+/* HyperText Tranfer Protocol - Client implementation HTTP.c
+** ==========================
+** Modified:
+** 27 Jan 1994 PDM Added Ari Luotonen's Fix for Reload when using proxy
+** servers.
+** 28 Apr 1997 AJL,FM Do Proxy Authorisation.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTTP.h"
+
+#define HTTP_VERSION "HTTP/1.0"
+
+#define HTTP_PORT 80
+#define HTTPS_PORT 443
+#define SNEWS_PORT 563
+
+#define INIT_LINE_SIZE 1024 /* Start with line buffer this big */
+#define LINE_EXTEND_THRESH 256 /* Minimum read size */
+#define VERSION_LENGTH 20 /* for returned protocol version */
+
+#include "HTParse.h"
+#include "HTTCP.h"
+#include "HTFormat.h"
+#include "HTFile.h"
+#include <ctype.h>
+#include "HTAlert.h"
+#include "HTMIME.h"
+#include "HTML.h"
+#include "HTInit.h"
+#include "HTAABrow.h"
+
+#include "LYGlobalDefs.h"
+#include "LYLeaks.h"
+
+/* #define TRACE 1 */
+
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+extern char * HTAppName; /* Application name: please supply */
+extern char * HTAppVersion; /* Application version: please supply */
+extern char * personal_mail_address; /* User's name/email address */
+extern char * LYUserAgent; /* Lynx User-Agent string */
+extern BOOL LYNoRefererHeader; /* Never send Referer header? */
+extern BOOL LYNoRefererForThis; /* No Referer header for this URL? */
+extern BOOL LYNoFromHeader; /* Never send From header? */
+extern BOOL LYSetCookies; /* Act on Set-Cookie headers? */
+
+extern BOOL using_proxy; /* Are we using an HTTP gateway? */
+PUBLIC BOOL reloading = FALSE; /* Reloading => send no-cache pragma to proxy */
+PUBLIC char * redirecting_url = NULL; /* Location: value. */
+PUBLIC BOOL permanent_redirection = FALSE; /* Got 301 status? */
+PUBLIC BOOL redirect_post_content = FALSE; /* Don't convert to GET? */
+
+extern char LYUserSpecifiedURL; /* Is the URL a goto? */
+
+extern BOOL keep_mime_headers; /* Include mime headers and force source dump */
+extern BOOL no_url_redirection; /* Don't follow Location: URL for */
+extern char *http_error_file; /* Store HTTP status code in this file */
+extern BOOL traversal; /* TRUE if we are doing a traversal */
+extern BOOL dump_output_immediately; /* TRUE if no interactive user */
+
+extern char * HTLoadedDocumentURL NOPARAMS;
+extern int HTCheckForInterrupt NOPARAMS;
+extern void LYSetCookie PARAMS((
+ CONST char * SetCookie,
+ CONST char * SetCookie2,
+ CONST char * address));
+extern char * LYCookie PARAMS((
+ CONST char * hostname,
+ CONST char * path,
+ int port,
+ BOOL secure));
+
+#define HTTP_NETREAD(a, b, c, d) NETREAD(a, b, c)
+#define HTTP_NETWRITE(a, b, c, d) NETWRITE(a, b, c)
+#define HTTP_NETCLOSE(a, b) (void)NETCLOSE(a)
+
+
+/* Load Document from HTTP Server HTLoadHTTP()
+** ==============================
+**
+** Given a hypertext address, this routine loads a document.
+**
+**
+** On entry,
+** arg is the hypertext reference of the article to be loaded.
+**
+** On exit,
+** returns >=0 If no error, a good socket number
+** <0 Error.
+**
+** The socket must be closed by the caller after the document has been
+** read.
+**
+*/
+PRIVATE int HTLoadHTTP ARGS4 (
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ int s; /* Socket number for returned data */
+ CONST char *url = arg; /* The URL which get_physical() returned */
+ char *command = NULL; /* The whole command */
+ char *eol; /* End of line if found */
+ char *start_of_data; /* Start of body of reply */
+ int status; /* tcp return */
+ int bytes_already_read;
+ char crlf[3]; /* A CR LF equivalent string */
+ HTStream *target; /* Unconverted data */
+ HTFormat format_in; /* Format arriving in the message */
+ BOOL do_head = FALSE; /* Whether or not we should do a head */
+ BOOL do_post = FALSE; /* ARE WE posting ? */
+ char *METHOD;
+
+ BOOL had_header; /* Have we had at least one header? */
+ char *line_buffer;
+ char *line_kept_clean;
+ BOOL extensions; /* Assume good HTTP server */
+ char line[INIT_LINE_SIZE];
+ char temp[80];
+ BOOL first_Accept = TRUE;
+ BOOL show_401 = FALSE;
+ BOOL show_407 = FALSE;
+ BOOL auth_proxy = NO; /* Generate a proxy authorization. - AJL */
+
+ int length, rv;
+ BOOL doing_redirect, already_retrying = FALSE, bad_location = FALSE;
+ int len = 0;
+
+ void * handle = NULL;
+
+ if (anAnchor->isHEAD)
+ do_head = TRUE;
+ else if (anAnchor->post_data)
+ do_post = TRUE;
+
+ if (!url) {
+ status = -3;
+ _HTProgress ("Bad request.");
+ goto done;
+ }
+ if (!*url) {
+ status = -2;
+ _HTProgress ("Bad request.");
+ goto done;
+ }
+
+ sprintf(crlf, "%c%c", CR, LF);
+
+ /*
+ ** At this point, we're talking HTTP/1.0.
+ */
+ extensions = YES;
+
+try_again:
+ /*
+ ** All initializations are moved down here from up above,
+ ** so we can start over here...
+ */
+ eol = 0;
+ bytes_already_read = 0;
+ had_header = NO;
+ length = 0;
+ doing_redirect = FALSE;
+ permanent_redirection = FALSE;
+ redirect_post_content = FALSE;
+ target = NULL;
+ line_buffer = NULL;
+ line_kept_clean = NULL;
+
+ if (!strncmp(url, "https", 5))
+ {
+ HTAlert("This client does not contain support for HTTPS URLs.");
+ status = HT_NOT_LOADED;
+ goto done;
+ }
+ status = HTDoConnect (arg, "HTTP", HTTP_PORT, &s);
+ if (status == HT_INTERRUPTED) {
+ /*
+ ** Interrupt cleanly.
+ */
+ if (TRACE)
+ fprintf (stderr,
+ "HTTP: Interrupted on connect; recovering cleanly.\n");
+ _HTProgress ("Connection interrupted.");
+ status = HT_NOT_LOADED;
+ goto done;
+ }
+ if (status < 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Unable to connect to remote host for `%s' (errno = %d).\n",
+ url, SOCKET_ERRNO);
+ HTAlert("Unable to connect to remote host.");
+ status = HT_NOT_LOADED;
+ goto done;
+ }
+
+ /* Ask that node for the document,
+ ** omitting the host name & anchor
+ */
+ {
+ char * p1 = (HTParse(url, "", PARSE_PATH|PARSE_PUNCTUATION));
+
+ if (do_post) {
+ METHOD = "POST";
+ StrAllocCopy(command, "POST ");
+ } else if (do_head) {
+ METHOD = "HEAD";
+ StrAllocCopy(command, "HEAD ");
+ } else {
+ METHOD = "GET";
+ StrAllocCopy(command, "GET ");
+ }
+
+ /*
+ ** If we are using a proxy gateway don't copy in the first slash
+ ** of say: /gopher://a;lkdjfl;ajdf;lkj/;aldk/adflj
+ ** so that just gopher://.... is sent.
+ */
+ if (using_proxy)
+ StrAllocCat(command, p1+1);
+ else
+ StrAllocCat(command, p1);
+ FREE(p1);
+ }
+ if (extensions) {
+ StrAllocCat(command, " ");
+ StrAllocCat(command, HTTP_VERSION);
+ }
+
+ StrAllocCat(command, crlf); /* CR LF, as in rfc 977 */
+
+ if (extensions) {
+ int n, i;
+ char * host = NULL;
+
+ if ((host = HTParse(anAnchor->address, "", PARSE_HOST)) != NULL) {
+ sprintf(line, "Host: %s%c%c", host, CR,LF);
+ StrAllocCat(command, line);
+ FREE(host);
+ }
+
+ if (!HTPresentations)
+ HTFormatInit();
+ n = HTList_count(HTPresentations);
+
+ first_Accept = TRUE;
+ len = 0;
+ for (i = 0; i < n; i++) {
+ HTPresentation *pres =
+ (HTPresentation *)HTList_objectAt(HTPresentations, i);
+ if (pres->rep_out == WWW_PRESENT) {
+ if (pres->rep != WWW_SOURCE &&
+ strcasecomp(HTAtom_name(pres->rep), "www/mime") &&
+ strcasecomp(HTAtom_name(pres->rep), "www/compressed") &&
+ pres->quality <= 1.0 && pres->quality >= 0.0) {
+ if (pres->quality < 1.0) {
+ if (pres->maxbytes > 0) {
+ sprintf(temp, ";q=%4.3f;mxb=%ld",
+ pres->quality, pres->maxbytes);
+ } else {
+ sprintf(temp, ";q=%4.3f", pres->quality);
+ }
+ } else if (pres->maxbytes > 0) {
+ sprintf(temp, ";mxb=%ld", pres->maxbytes);
+ } else {
+ temp[0] = '\0';
+ }
+ sprintf(line, "%s%s%s",
+ (first_Accept ?
+ "Accept: " : ", "),
+ HTAtom_name(pres->rep),
+ temp);
+ len += strlen(line);
+ if (len > 252 && !first_Accept) {
+ StrAllocCat(command, crlf);
+ sprintf(line, "Accept: %s%s",
+ HTAtom_name(pres->rep),
+ temp);
+ len = strlen(line);
+ }
+ StrAllocCat(command, line);
+ first_Accept = FALSE;
+ }
+ }
+ }
+ sprintf(line, "%s*/*;q=0.01%c%c",
+ (first_Accept ?
+ "Accept: " : ", "), CR, LF);
+ StrAllocCat(command, line);
+ first_Accept = FALSE;
+ len = 0;
+
+ sprintf(line, "Accept-Encoding: %s, %s%c%c",
+ "gzip", "compress", CR, LF);
+ StrAllocCat(command, line);
+
+ if (language && *language) {
+ sprintf(line, "Accept-Language: %s%c%c", language, CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ if (pref_charset && *pref_charset) {
+ StrAllocCat(command, "Accept-Charset: ");
+ strcpy(line, pref_charset);
+ if (line[strlen(line)-1] == ',')
+ line[strlen(line)-1] = '\0';
+ for (i = 0; line[i]; i++)
+ line[i] = TOLOWER(line[i]);
+ if (strstr(line, "iso-8859-1") == NULL)
+ strcat(line, ", iso-8859-1;q=0.01");
+ if (strstr(line, "us-ascii") == NULL)
+ strcat(line, ", us-ascii;q=0.01");
+ StrAllocCat(command, line);
+ sprintf(line, "%c%c", CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ /*
+ ** Promote 300 (Multiple Choices) replies, if supported,
+ ** over 406 (Not Acceptable) replies. - FM
+ */
+ if (!do_post) {
+ sprintf(line, "Negotiate: trans%c%c", CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ /*
+ ** When reloading give no-cache pragma to proxy server to make
+ ** it refresh its cache. -- Ari L. <luotonen@dxcern.cern.ch>
+ **
+ ** Also send it as a Cache-Control header for HTTP/1.1. - FM
+ */
+ if (reloading) {
+ sprintf(line, "Pragma: no-cache%c%c", CR, LF);
+ StrAllocCat(command, line);
+ sprintf(line, "Cache-Control: no-cache%c%c", CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ if (LYUserAgent && *LYUserAgent) {
+ sprintf(line, "User-Agent: %s%c%c", LYUserAgent, CR, LF);
+ } else {
+ sprintf(line, "User-Agent: %s/%s libwww-FM/%s%c%c",
+ HTAppName ? HTAppName : "unknown",
+ HTAppVersion ? HTAppVersion : "0.0",
+ HTLibraryVersion, CR, LF);
+ }
+ StrAllocCat(command, line);
+
+ if (personal_mail_address && !LYNoFromHeader) {
+ sprintf(line, "From: %s%c%c", personal_mail_address, CR,LF);
+ StrAllocCat(command, line);
+ }
+
+ if (!(LYUserSpecifiedURL ||
+ LYNoRefererHeader || LYNoRefererForThis) &&
+ strcmp(HTLoadedDocumentURL(), "")) {
+ char *cp = HTLoadedDocumentURL();
+ StrAllocCat(command, "Referer: ");
+ if (!strncasecomp(cp, "LYNXIMGMAP:", 11)) {
+ char *cp1 = strchr(cp, '#');
+ if (cp1)
+ *cp1 = '\0';
+ StrAllocCat(command, cp + 11);
+ if (cp1)
+ *cp1 = '#';
+ } else {
+ StrAllocCat(command, cp);
+ }
+ sprintf(line, "%c%c", CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ {
+ char *abspath;
+ char *docname;
+ char *hostname;
+ char *colon;
+ int portnumber;
+ char *auth, *cookie = NULL;
+ BOOL secure = (strncmp(anAnchor->address, "https", 5) ?
+ FALSE : TRUE);
+
+ abspath = HTParse(arg, "", PARSE_PATH|PARSE_PUNCTUATION);
+ docname = HTParse(arg, "", PARSE_PATH);
+ hostname = HTParse(arg, "", PARSE_HOST);
+ if (hostname &&
+ NULL != (colon = strchr(hostname, ':'))) {
+ *(colon++) = '\0'; /* Chop off port number */
+ portnumber = atoi(colon);
+ } else if (!strncmp(arg, "https", 5)) {
+ portnumber = HTTPS_PORT;
+ } else {
+ portnumber = HTTP_PORT;
+ }
+
+ /*
+ ** Add Authorization, Proxy-Authorization,
+ ** and/or Cookie headers, if applicable.
+ */
+ if (using_proxy) {
+ /*
+ ** If we are using a proxy, first determine if
+ ** we should include an Authorization header
+ ** and/or Cookie header for the ultimate target
+ ** of this request. - FM & AJL
+ */
+ char *host2 = NULL, *path2 = NULL;
+ int port2 = (strncmp(docname, "https", 5) ?
+ HTTP_PORT : HTTPS_PORT);
+ host2 = HTParse(docname, "", PARSE_HOST);
+ path2 = HTParse(docname, "", PARSE_PATH|PARSE_PUNCTUATION);
+ if (host2) {
+ if ((colon = strchr(host2, ':')) != NULL) {
+ /* Use non-default port number */
+ *colon = '\0';
+ colon++;
+ port2 = atoi(colon);
+ }
+ }
+ /*
+ ** This composeAuth() does file access, i.e., for
+ ** the ultimate target of the request. - AJL
+ */
+ auth_proxy = NO;
+ if ((auth = HTAA_composeAuth(host2, port2, path2,
+ auth_proxy)) != NULL &&
+ *auth != '\0') {
+ /*
+ ** If auth is not NULL nor zero-length, it's
+ ** an Authorization header to be included. - FM
+ */
+ sprintf(line, "%s%c%c", auth, CR, LF);
+ StrAllocCat(command, line);
+ if (TRACE)
+ fprintf(stderr, "HTTP: Sending authorization: %s\n", auth);
+ } else if (auth && *auth == '\0') {
+ /*
+ ** If auth is a zero-length string, the user either
+ ** cancelled or goofed at the username and password
+ ** prompt. - FM
+ */
+ if (!(traversal || dump_output_immediately) &&
+ HTConfirm(
+ "Proceed without a username and password?")) {
+ show_401 = TRUE;
+ } else {
+ if (traversal || dump_output_immediately)
+ HTAlert(
+ "Can't proceed without a username and password.");
+ FREE(command);
+ FREE(hostname);
+ FREE(docname);
+ FREE(host2);
+ FREE(path2);
+ status = HT_NOT_LOADED;
+ goto done;
+ }
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Not sending authorization (yet).\n");
+ }
+ /*
+ ** Add 'Cookie:' header, if it's HTTP or HTTPS
+ ** document being proxied.
+ */
+ if (!strncmp(docname, "http", 4)) {
+ cookie = LYCookie(host2, path2, port2, secure);
+ }
+ FREE(host2);
+ FREE(path2);
+ /*
+ ** The next composeAuth() will be for the proxy. - AJL
+ */
+ auth_proxy = YES;
+ } else {
+ /*
+ ** Add cookie for a non-proxied request. - FM
+ */
+ cookie = LYCookie(hostname, abspath, portnumber, secure);
+ auth_proxy = NO;
+ }
+ /*
+ ** If we do have a cookie set, add it to the request buffer. - FM
+ */
+ if (cookie != NULL) {
+ if (*cookie != '$') {
+ /*
+ ** It's a historical cookie, so signal to the
+ ** server that we support modern cookies. - FM
+ */
+ StrAllocCat(command, "Cookie2: $Version=\"1\"");
+ StrAllocCat(command, crlf);
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Sending Cookie2: $Version =\"1\"\n");
+ }
+ if (*cookie != '\0') {
+ /*
+ ** It's not a zero-length string, so add the header.
+ ** Note that any folding of long strings has been
+ ** done already in LYCookie.c. - FM
+ */
+ StrAllocCat(command, "Cookie: ");
+ StrAllocCat(command, cookie);
+ StrAllocCat(command, crlf);
+ if (TRACE)
+ fprintf(stderr, "HTTP: Sending Cookie: %s\n", cookie);
+ }
+ FREE(cookie);
+ }
+ FREE(abspath);
+
+ /*
+ ** If we are using a proxy, auth_proxy should be YES, and
+ ** we check here whether we want a Proxy-Authorization header
+ ** for it. If we are not using a proxy, auth_proxy should
+ ** still be NO, and we check here for whether we want an
+ ** Authorization header. - FM & AJL
+ */
+ if ((auth = HTAA_composeAuth(hostname,
+ portnumber,
+ docname,
+ auth_proxy)) != NULL &&
+ *auth != '\0') {
+ /*
+ ** If auth is not NULL nor zero-length, it's
+ ** an Authorization or Proxy-Authorization
+ ** header to be included. - FM
+ */
+ sprintf(line, "%s%c%c", auth, CR, LF);
+ StrAllocCat(command, line);
+ if (TRACE)
+ fprintf(stderr,
+ (auth_proxy ?
+ "HTTP: Sending proxy authorization: %s\n" :
+ "HTTP: Sending authorization: %s\n"),
+ auth);
+ } else if (auth && *auth == '\0') {
+ /*
+ ** If auth is a zero-length string, the user either
+ ** cancelled or goofed at the username and password
+ ** prompt. - FM
+ */
+ if (!(traversal || dump_output_immediately) &&
+ HTConfirm("Proceed without a username and password?")) {
+ if (auth_proxy == TRUE) {
+ show_407 = TRUE;
+ } else {
+ show_401 = TRUE;
+ }
+ } else {
+ if (traversal || dump_output_immediately)
+ HTAlert("Can't proceed without a username and password.");
+ FREE(command);
+ FREE(hostname);
+ FREE(docname);
+ status = HT_NOT_LOADED;
+ goto done;
+ }
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ (auth_proxy ?
+ "HTTP: Not sending proxy authorization (yet).\n" :
+ "HTTP: Not sending authorization (yet).\n"));
+ }
+ FREE(hostname);
+ FREE(docname);
+ }
+ auth_proxy = NO;
+ }
+
+ if (do_post)
+ {
+ if (TRACE)
+ fprintf (stderr, "HTTP: Doing post, content-type '%s'\n",
+ anAnchor->post_content_type ? anAnchor->post_content_type
+ : "lose");
+ sprintf (line, "Content-type: %s%c%c",
+ anAnchor->post_content_type ? anAnchor->post_content_type
+ : "lose", CR, LF);
+ StrAllocCat(command, line);
+ {
+ int content_length;
+ if (!anAnchor->post_data)
+ content_length = 0;
+ else
+ content_length = strlen (anAnchor->post_data);
+ sprintf (line, "Content-length: %d%c%c",
+ content_length, CR, LF);
+ StrAllocCat(command, line);
+ }
+
+ StrAllocCat(command, crlf); /* Blank line means "end" of headers */
+
+ StrAllocCat(command, anAnchor->post_data);
+ }
+ else
+ StrAllocCat(command, crlf); /* Blank line means "end" of headers */
+
+ if (TRACE) {
+ fprintf (stderr,
+ "Writing:\n%s%s----------------------------------\n",
+ command,
+ (anAnchor->post_data ? crlf : ""));
+ }
+
+ _HTProgress ("Sending HTTP request.");
+
+ status = HTTP_NETWRITE(s, command, (int)strlen(command), handle);
+ FREE(command);
+ if (status <= 0) {
+ if (status == 0) {
+ if (TRACE)
+ fprintf (stderr, "HTTP: Got status 0 in initial write\n");
+ /* Do nothing. */
+ } else if ((SOCKET_ERRNO == ENOTCONN ||
+ SOCKET_ERRNO == ECONNRESET ||
+ SOCKET_ERRNO == EPIPE) &&
+ !already_retrying &&
+ /* Don't retry if we're posting. */ !do_post) {
+ /*
+ ** Arrrrgh, HTTP 0/1 compability problem, maybe.
+ */
+ if (TRACE)
+ fprintf (stderr,
+ "HTTP: BONZO ON WRITE Trying again with HTTP0 request.\n");
+ _HTProgress ("Retrying as HTTP0 request.");
+ HTTP_NETCLOSE(s, handle);
+ extensions = NO;
+ already_retrying = TRUE;
+ goto try_again;
+ } else {
+ if (TRACE)
+ fprintf (stderr,
+ "HTTP: Hit unexpected network WRITE error; aborting connection.\n");
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ HTAlert("Unexpected network write error; connection aborted.");
+ goto done;
+ }
+ }
+
+ if (TRACE)
+ fprintf (stderr, "HTTP: WRITE delivered OK\n");
+ _HTProgress ("HTTP request sent; waiting for response.");
+
+ /* Read the first line of the response
+ ** -----------------------------------
+ */
+ {
+ /* Get numeric status etc */
+ BOOL end_of_file = NO;
+ int buffer_length = INIT_LINE_SIZE;
+
+ line_buffer = (char *)calloc(1, (buffer_length * sizeof(char)));
+
+ do {/* Loop to read in the first line */
+ /*
+ ** Extend line buffer if necessary for those crazy WAIS URLs ;-)
+ */
+ if (buffer_length - length < LINE_EXTEND_THRESH) {
+ buffer_length = buffer_length + buffer_length;
+ line_buffer =
+ (char *)realloc(line_buffer, (buffer_length * sizeof(char)));
+ }
+ if (TRACE)
+ fprintf (stderr, "HTTP: Trying to read %d\n",
+ buffer_length - length - 1);
+ status = HTTP_NETREAD(s, line_buffer + length,
+ buffer_length - length - 1, handle);
+ if (TRACE)
+ fprintf (stderr, "HTTP: Read %d\n", status);
+ if (status <= 0) {
+ /*
+ * Retry if we get nothing back too.
+ * Bomb out if we get nothing twice.
+ */
+ if (status == HT_INTERRUPTED) {
+ if (TRACE)
+ fprintf (stderr, "HTTP: Interrupted initial read.\n");
+ _HTProgress ("Connection interrupted.");
+ HTTP_NETCLOSE(s, handle);
+ status = HT_NO_DATA;
+ goto clean_up;
+ } else if (status < 0 &&
+ (SOCKET_ERRNO == ENOTCONN ||
+ SOCKET_ERRNO == ECONNRESET ||
+ SOCKET_ERRNO == EPIPE) &&
+ !already_retrying && !do_post) {
+ /*
+ ** Arrrrgh, HTTP 0/1 compability problem, maybe.
+ */
+ if (TRACE)
+ fprintf (stderr,
+ "HTTP: BONZO Trying again with HTTP0 request.\n");
+ HTTP_NETCLOSE(s, handle);
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+
+ extensions = NO;
+ already_retrying = TRUE;
+ _HTProgress ("Retrying as HTTP0 request.");
+ goto try_again;
+ } else {
+ if (TRACE)
+ fprintf (stderr,
+ "HTTP: Hit unexpected network read error; aborting connection; status %d.\n",
+ status);
+ HTAlert("Unexpected network read error; connection aborted.");
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ }
+
+ bytes_already_read += status;
+ sprintf (line, "Read %d bytes of data.", bytes_already_read);
+ HTProgress (line);
+
+#ifdef UCX /* UCX returns -1 on EOF */
+ if (status == 0 || status == -1)
+#else
+ if (status == 0)
+#endif
+ {
+ end_of_file = YES;
+ break;
+ }
+ line_buffer[length+status] = 0;
+
+ if (line_buffer) {
+ FREE(line_kept_clean);
+ line_kept_clean = (char *)malloc(buffer_length * sizeof(char));
+ memcpy(line_kept_clean, line_buffer, buffer_length);
+ }
+
+ eol = strchr(line_buffer + length, LF);
+ /* Do we *really* want to do this? */
+ if (eol && eol != line_buffer && *(eol-1) == CR)
+ *(eol-1) = ' ';
+
+ length = length + status;
+
+ /* Do we really want to do *this*? */
+ if (eol)
+ *eol = 0; /* Terminate the line */
+ }
+ /* All we need is the first line of the response. If it's a HTTP/1.0
+ ** response, then the first line will be absurdly short and therefore
+ ** we can safely gate the number of bytes read through this code
+ ** (as opposed to below) to ~1000.
+ **
+ ** Well, let's try 100.
+ */
+ while (!eol && !end_of_file && bytes_already_read < 100);
+ } /* Scope of loop variables */
+
+
+ /* We now have a terminated unfolded line. Parse it.
+ ** -------------------------------------------------
+ */
+ if (TRACE)
+ fprintf(stderr, "HTTP: Rx: %s\n", line_buffer);
+
+ /*
+ ** Kludge to work with old buggy servers and the VMS Help gateway.
+ ** They can't handle the third word, so we try again without it.
+ */
+ if (extensions && /* Old buggy server or Help gateway? */
+ (0==strncmp(line_buffer,"<TITLE>Bad File Request</TITLE>",31) ||
+ 0==strncmp(line_buffer,"Address should begin with",25) ||
+ 0==strncmp(line_buffer,"<TITLE>Help ",12) ||
+ 0==strcmp(line_buffer,
+ "Document address invalid or access not authorised"))) {
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+ extensions = NO;
+ already_retrying = TRUE;
+ if (TRACE)
+ fprintf(stderr, "HTTP: close socket %d to retry with HTTP0\n", s);
+ HTTP_NETCLOSE(s, handle);
+ /* print a progress message */
+ _HTProgress ("Retrying as HTTP0 request.");
+ goto try_again;
+ }
+
+
+ {
+ int fields;
+ char server_version[VERSION_LENGTH+1];
+ int server_status;
+
+ server_version[0] = 0;
+
+ fields = sscanf(line_buffer, "%20s %d",
+ server_version,
+ &server_status);
+
+ if (TRACE)
+ fprintf (stderr, "HTTP: Scanned %d fields from line_buffer\n", fields);
+
+ if (http_error_file) { /* Make the status code externally available */
+ FILE *error_file;
+#ifdef SERVER_STATUS_ONLY
+ error_file = fopen(http_error_file, "w");
+ if (error_file) { /* Managed to open the file */
+ fprintf(error_file, "error=%d\n", server_status);
+ fclose(error_file);
+ }
+#else
+ error_file = fopen(http_error_file, "a");
+ if (error_file) { /* Managed to open the file */
+ fprintf(error_file, " URL=%s (%s)\n", url, METHOD);
+ fprintf(error_file, "STATUS=%s\n", line_buffer);
+ fclose(error_file);
+ }
+#endif /* SERVER_STATUS_ONLY */
+ }
+
+ /*
+ ** Rule out a non-HTTP/1.n reply as best we can.
+ */
+ if (fields < 2 || !server_version[0] || server_version[0] != 'H' ||
+ server_version[1] != 'T' || server_version[2] != 'T' ||
+ server_version[3] != 'P' || server_version[4] != '/' ||
+ server_version[6] != '.') {
+ /*
+ * Ugh! An HTTP0 reply,
+ */
+ HTAtom * encoding;
+
+ if (TRACE)
+ fprintf (stderr, "--- Talking HTTP0.\n");
+
+ format_in = HTFileFormat(url, &encoding, NULL);
+ /*
+ ** Treat all plain text as HTML.
+ ** This sucks but its the only solution without
+ ** without looking at content.
+ */
+ if (!strncmp(HTAtom_name(format_in), "text/plain",10)) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: format_in being changed to text/HTML\n");
+ format_in = WWW_HTML;
+ }
+ if (!IsUnityEnc(encoding)) {
+ /*
+ ** Change the format to that for "www/compressed".
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTTP: format_in is '%s',\n", HTAtom_name(format_in));
+ }
+ StrAllocCopy(anAnchor->content_type, HTAtom_name(format_in));
+ StrAllocCopy(anAnchor->content_encoding, HTAtom_name(encoding));
+ format_in = HTAtom_for("www/compressed");
+ if (TRACE) {
+ fprintf(stderr,
+ " Treating as '%s' with encoding '%s'\n",
+ "www/compressed", HTAtom_name(encoding));
+ }
+ }
+
+ start_of_data = line_kept_clean;
+ } else {
+ /*
+ ** Set up to decode full HTTP/1.n response. - FM
+ */
+ format_in = HTAtom_for("www/mime");
+ if (TRACE)
+ fprintf (stderr, "--- Talking HTTP1.\n");
+
+ /*
+ ** We set start_of_data to "" when !eol here because there
+ ** will be a put_block done below; we do *not* use the value
+ ** of start_of_data (as a pointer) in the computation of
+ ** length (or anything else) when !eol. Otherwise, set the
+ ** value of length to what we have beyond eol (i.e., beyond
+ ** the status line). - FM
+ */
+ start_of_data = eol ? eol + 1 : "";
+ length = eol ? length - (start_of_data - line_buffer) : 0;
+
+ /*
+ ** Trim trailing spaces in line_buffer so that we can use
+ ** it in messages which include the status line. - FM
+ */
+ while (line_buffer[strlen(line_buffer)-1] == ' ')
+ line_buffer[strlen(line_buffer)-1] = '\0';
+
+ /*
+ ** Take appropriate actions based on the status. - FM
+ */
+ switch (server_status/100) {
+ case 1:
+ /*
+ ** HTTP/1.1 Informational statuses.
+ ** 100 Continue.
+ ** 101 Switching Protocols.
+ ** > 101 is unknown.
+ ** We should never get these, and they have only
+ ** the status line and possibly other headers,
+ ** so we'll deal with them by showing the full
+ ** header to the user as text/plain. - FM
+ */
+ HTAlert("Got unexpected Informational Status.");
+ do_head = TRUE;
+ break;
+
+ case 2:
+ /*
+ ** Good: Got MIME object! (Successful) - FM
+ */
+ if (do_head) {
+ /*
+ * If HEAD was requested, show headers (and possibly
+ * bogus body) for all 2xx status codes as text/plain - KW
+ */
+ HTProgress(line_buffer);
+ break;
+ }
+ switch (server_status) {
+ case 204:
+ /*
+ * No Content.
+ */
+ HTAlert(line_buffer);
+ HTTP_NETCLOSE(s, handle);
+ status = HT_NO_DATA;
+ goto clean_up;
+ break;
+
+ case 205:
+ /*
+ * Reset Content. The server has fulfilled the
+ * request but nothing is returned and we should
+ * reset any form content. We'll instruct the
+ * user to do that, and restore the current
+ * document. - FM
+ */
+ HTAlert("Request fulfilled. Reset Content.");
+ HTTP_NETCLOSE(s, handle);
+ status = HT_NO_DATA;
+ goto clean_up;
+ break;
+
+ case 206:
+ /*
+ * Partial Content. We didn't send a Range
+ * so something went wrong somewhere. Show
+ * the status message and restore the current
+ * document. - FM
+ */
+ HTAlert(line_buffer);
+ HTTP_NETCLOSE(s, handle);
+ status = HT_NO_DATA;
+ goto clean_up;
+ break;
+
+ default:
+ /*
+ * 200 OK.
+ * 201 Created.
+ * 202 Accepted.
+ * 203 Non-Authoritative Information.
+ * > 206 is unknown.
+ * All should return something to display.
+ */
+ HTProgress(line_buffer);
+ } /* case 2 switch */
+ break;
+
+ case 3:
+ /*
+ ** Various forms of Redirection. - FM
+ ** 300 Multiple Choices.
+ ** 301 Moved Permanently.
+ ** 302 Found (temporary; we can, and do, use GET).
+ ** 303 See Other (temporary; always use GET).
+ ** 304 Not Modified.
+ ** 305 Use Proxy.
+ ** 306 Set Proxy.
+ ** 307 Temporary Redirect with method retained.
+ ** > 308 is unknown.
+ */
+ if (no_url_redirection || do_head || keep_mime_headers) {
+ /*
+ * If any of these flags are set, we do not redirect,
+ * but instead show what was returned to the user as
+ * text/plain. - FM
+ */
+ HTProgress(line_buffer);
+ break;
+ }
+
+ if (server_status == 300) { /* Multiple Choices */
+ /*
+ * For client driven content negotiation. The server
+ * should be sending some way for the user-agent to
+ * make a selection, so we'll show the user whatever
+ * the server returns. There might be a Location:
+ * header with the server's preference present, but
+ * the choice should be up to the user, someday based
+ * on an Alternates: header, and a body always should
+ * be present with descriptions and links for the
+ * choices (i.e., we use the latter, for now). - FM
+ */
+ HTAlert(line_buffer);
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ }
+
+ if (server_status == 304) { /* Not Modified */
+ /*
+ * We didn't send an "If-Modified-Since" header,
+ * so this status is inappropriate. We'll deal
+ * with it by showing the full header to the user
+ * as text/plain. - FM
+ */
+ HTAlert("Got unexpected 304 Not Modified status.");
+ do_head = TRUE;
+ break;
+ }
+
+ if (server_status == 305 ||
+ server_status == 306 ||
+ server_status > 307) {
+ /*
+ * Show user the content, if any, for 305, 306,
+ * or unknown status. - FM
+ */
+ HTAlert(line_buffer);
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ }
+
+ /*
+ * We do not load the file, but read the headers for
+ * the "Location:", check out that redirecting_url
+ * and if it's acceptible (e.g., not a telnet URL
+ * when we have that disabled), initiate a new fetch.
+ * If that's another redirecting_url, we'll repeat the
+ * checks, and fetch initiations if acceptible, until
+ * we reach the actual URL, or the redirection limit
+ * set in HTAccess.c is exceeded. If the status was 301
+ * indicating that the relocation is permanent, we set
+ * the permanent_redirection flag to make it permanent
+ * for the current anchor tree (i.e., will persist until
+ * the tree is freed or the client exits). If the
+ * redirection would include POST content, we seek
+ * confirmation from an interactive user, with option to
+ * use 303 for 301 (but not for 307), and otherwise refuse
+ * the redirection. We also don't allow permanent
+ * redirection if we keep POST content. If we don't find
+ * the Location header or it's value is zero-length, we
+ * display whatever the server returned, and the user
+ * should RELOAD that to try again, or make a selection
+ * from it if it contains links, or Left-Arrow to the
+ * previous document. - FM
+ */
+ {
+ char *cp;
+
+ if ((dump_output_immediately || traversal) &&
+ do_post &&
+ server_status != 303 &&
+ server_status != 302 &&
+ server_status != 301) {
+ /*
+ * Don't redirect POST content without approval
+ * from an interactive user. - FM
+ */
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ HTAlert(
+ "Redirection of POST content requires user approval.");
+ if (traversal)
+ HTProgress(line_buffer);
+ goto clean_up;
+ }
+
+ /*
+ * Get the rest of the headers and data, if
+ * any, and then close the connection. - FM
+ */
+ while ((status = HTTP_NETREAD(s, line_buffer,
+ (INIT_LINE_SIZE - 1),
+ handle)) > 0) {
+ line_buffer[status] = '\0';
+ StrAllocCat(line_kept_clean, line_buffer);
+ }
+ HTTP_NETCLOSE(s, handle);
+ if (status == HT_INTERRUPTED) {
+ /*
+ * Impatient user. - FM
+ */
+ if (TRACE)
+ fprintf (stderr, "HTTP: Interrupted followup read.\n");
+ _HTProgress ("Connection interrupted.");
+ status = HT_INTERRUPTED;
+ goto clean_up;
+ }
+ doing_redirect = TRUE;
+ if (server_status == 301) { /* Moved Permanently */
+ HTProgress(line_buffer);
+ if (do_post) {
+ /*
+ * Don't make the redirection permanent
+ * if we have POST content. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Have POST content. Treating 301 (Permanent) as Temporary.\n");
+ HTAlert(
+ "Have POST content. Treating Permanent Redirection as Temporary.\n");
+ } else {
+ permanent_redirection = TRUE;
+ }
+ }
+
+ /*
+ ** Look for "Set-Cookie:" and "Set-Cookie2:" headers. - FM
+ */
+ if (LYSetCookies == TRUE) {
+ char *value = NULL;
+ char *SetCookie = NULL;
+ char *SetCookie2 = NULL;
+ cp = line_kept_clean;
+ while (*cp) {
+ /*
+ ** Assume a CRLF pair terminates
+ ** the header section. - FM
+ */
+ if (*cp == CR) {
+ if (*(cp+1) == LF &&
+ *(cp+2) == CR && *(cp+3) == LF) {
+ break;
+ }
+ }
+ if (TOUPPER(*cp) != 'S') {
+ cp++;
+ } else if (!strncasecomp(cp, "Set-Cookie:", 11)) {
+ char *cp1 = NULL, *cp2 = NULL;
+ cp += 11;
+Cookie_continuation:
+ /*
+ * Trim leading spaces. - FM
+ */
+ while (isspace((unsigned char)*cp))
+ cp++;
+ /*
+ ** Accept CRLF, LF, or CR as end of line. - FM
+ */
+ if (((cp1 = strchr(cp, LF)) != NULL) ||
+ (cp2 = strchr(cp, CR)) != NULL) {
+ if (*cp1) {
+ *cp1 = '\0';
+ if ((cp2 = strchr(cp, CR)) != NULL)
+ *cp2 = '\0';
+ } else {
+ *cp2 = '\0';
+ }
+ }
+ if (*cp == '\0') {
+ if (cp1)
+ *cp1 = LF;
+ if (cp2)
+ *cp2 = CR;
+ if (value != NULL) {
+ HTMIME_TrimDoubleQuotes(value);
+ if (SetCookie == NULL) {
+ StrAllocCopy(SetCookie, value);
+ } else {
+ StrAllocCat(SetCookie, ", ");
+ StrAllocCat(SetCookie, value);
+ }
+ FREE(value);
+ }
+ break;
+ }
+ StrAllocCat(value, cp);
+ cp += strlen(cp);
+ if (cp1) {
+ *cp1 = LF;
+ cp1 = NULL;
+ }
+ if (cp2) {
+ *cp2 = CR;
+ cp2 = NULL;
+ }
+ cp1 = cp;
+ if (*cp1 == CR)
+ cp1++;
+ if (*cp1 == LF)
+ cp1++;
+ if (*cp1 == ' ' || *cp1 == '\t') {
+ StrAllocCat(value, " ");
+ cp = cp1;
+ cp++;
+ cp1 = NULL;
+ goto Cookie_continuation;
+ }
+ HTMIME_TrimDoubleQuotes(value);
+ if (SetCookie == NULL) {
+ StrAllocCopy(SetCookie, value);
+ } else {
+ StrAllocCat(SetCookie, ", ");
+ StrAllocCat(SetCookie, value);
+ }
+ FREE(value);
+ } else if (!strncasecomp(cp, "Set-Cookie2:", 12)) {
+ char *cp1 = NULL, *cp2 = NULL;
+ cp += 12;
+Cookie2_continuation:
+ /*
+ * Trim leading spaces. - FM
+ */
+ while (isspace((unsigned char)*cp))
+ cp++;
+ /*
+ ** Accept CRLF, LF, or CR as end of line. - FM
+ */
+ if (((cp1 = strchr(cp, LF)) != NULL) ||
+ (cp2 = strchr(cp, CR)) != NULL) {
+ if (*cp1) {
+ *cp1 = '\0';
+ if ((cp2 = strchr(cp, CR)) != NULL)
+ *cp2 = '\0';
+ } else {
+ *cp2 = '\0';
+ }
+ }
+ if (*cp == '\0') {
+ if (cp1)
+ *cp1 = LF;
+ if (cp2)
+ *cp2 = CR;
+ if (value != NULL) {
+ HTMIME_TrimDoubleQuotes(value);
+ if (SetCookie2 == NULL) {
+ StrAllocCopy(SetCookie2, value);
+ } else {
+ StrAllocCat(SetCookie2, ", ");
+ StrAllocCat(SetCookie2, value);
+ }
+ FREE(value);
+ }
+ break;
+ }
+ StrAllocCat(value, cp);
+ cp += strlen(cp);
+ if (cp1) {
+ *cp1 = LF;
+ cp1 = NULL;
+ }
+ if (cp2) {
+ *cp2 = CR;
+ cp2 = NULL;
+ }
+ cp1 = cp;
+ if (*cp1 == CR)
+ cp1++;
+ if (*cp1 == LF)
+ cp1++;
+ if (*cp1 == ' ' || *cp1 == '\t') {
+ StrAllocCat(value, " ");
+ cp = cp1;
+ cp++;
+ cp1 = NULL;
+ goto Cookie2_continuation;
+ }
+ HTMIME_TrimDoubleQuotes(value);
+ if (SetCookie2 == NULL) {
+ StrAllocCopy(SetCookie2, value);
+ } else {
+ StrAllocCat(SetCookie2, ", ");
+ StrAllocCat(SetCookie2, value);
+ }
+ FREE(value);
+ } else {
+ cp++;
+ }
+ }
+ FREE(value);
+ if (SetCookie != NULL || SetCookie2 != NULL) {
+ LYSetCookie(SetCookie, SetCookie2, anAnchor->address);
+ FREE(SetCookie);
+ FREE(SetCookie2);
+ }
+ }
+
+ /*
+ * Look for the "Location:" in the headers. - FM
+ */
+ cp = line_kept_clean;
+ while (*cp) {
+ if (TOUPPER(*cp) != 'L') {
+ cp++;
+ } else if (!strncasecomp(cp, "Location:", 9)) {
+ char *cp1 = NULL, *cp2 = NULL;
+ cp += 9;
+ /*
+ * Trim leading spaces. - FM
+ */
+ while (isspace((unsigned char)*cp))
+ cp++;
+ /*
+ * Accept CRLF, LF, or CR as end of header. - FM
+ */
+ if (((cp1 = strchr(cp, LF)) != NULL) ||
+ (cp2 = strchr(cp, CR)) != NULL) {
+ if (*cp1) {
+ *cp1 = '\0';
+ if ((cp2 = strchr(cp, CR)) != NULL)
+ *cp2 = '\0';
+ } else {
+ *cp2 = '\0';
+ }
+ /*
+ * Load the new URL into redirecting_url,
+ * and make sure it's not zero-length. - FM
+ */
+ StrAllocCopy(redirecting_url, cp);
+ HTMIME_TrimDoubleQuotes(redirecting_url);
+ if (*redirecting_url == '\0') {
+ /*
+ * The "Location:" value is zero-length, and
+ * thus is probably something in the body, so
+ * we'll show the user what was returned. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: 'Location:' is zero-length!\n");
+ if (cp1)
+ *cp1 = LF;
+ if (cp2)
+ *cp2 = CR;
+ bad_location = TRUE;
+ FREE(redirecting_url);
+ HTAlert(
+ "Got redirection with a bad Location header.");
+ HTProgress(line_buffer);
+ break;
+ }
+
+ /*
+ * Set up for checking redirecting_url in
+ * LYGetFile.c for restrictions before we
+ * seek the document at that Location. - FM
+ */
+ HTProgress(line_buffer);
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Picked up location '%s'\n",
+ redirecting_url);
+ if (cp1)
+ *cp1 = LF;
+ if (cp2)
+ *cp2 = CR;
+ if (server_status == 305) { /* Use Proxy */
+ /*
+ * Make sure the proxy field ends with
+ * a slash. - FM
+ */
+ if (redirecting_url[strlen(redirecting_url)-1]
+ != '/')
+ StrAllocCat(redirecting_url, "/");
+ /*
+ * Append our URL. - FM
+ */
+ StrAllocCat(redirecting_url, anAnchor->address);
+ if (TRACE)
+ fprintf(stderr,
+ "HTTP: Proxy URL is '%s'\n",
+ redirecting_url);
+ }
+ if (!do_post ||
+ server_status == 303 ||
+ server_status == 302) {
+ /*
+ * We don't have POST content (nor support PUT
+ * or DELETE), or the status is "See Other" or
+ * "General Redirection" and we can convert to
+ * GET, so go back and check out the new URL. - FM
+ */
+ status = HT_REDIRECTING;
+ goto clean_up;
+ }
+ /*
+ * Make sure the user wants to redirect
+ * the POST content, or treat as GET - FM & DK
+ */
+ switch (HTConfirmPostRedirect(redirecting_url,
+ server_status)) {
+ /*
+ * User failed to confirm.
+ * Abort the fetch.
+ */
+ case 0:
+ doing_redirect = FALSE;
+ FREE(redirecting_url);
+ status = HT_NO_DATA;
+ goto clean_up;
+
+ /*
+ * User wants to treat as GET with no content.
+ * Go back to check out the URL.
+ */
+ case 303:
+ status = HT_REDIRECTING;
+ goto clean_up;
+
+ /*
+ * Set the flag to retain the POST
+ * content and go back to check out
+ * the URL. - FM
+ */
+ default:
+ status = HT_REDIRECTING;
+ redirect_post_content = TRUE;
+ goto clean_up;
+ }
+ }
+ break;
+ } else {
+ /*
+ * Keep looking for the Location header. - FM
+ */
+ cp++;
+ }
+ }
+
+ /*
+ * If we get to here, we didn't find the Location
+ * header, so we'll show the user what we got, if
+ * anything. - FM
+ */
+ if (TRACE)
+ fprintf (stderr, "HTTP: Failed to pick up location.\n");
+ doing_redirect = FALSE;
+ permanent_redirection = FALSE;
+ start_of_data = line_kept_clean;
+ length = strlen(start_of_data);
+ if (!bad_location) {
+ HTAlert("Got redirection with no Location header.");
+ HTProgress(line_buffer);
+ }
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ }
+
+ case 4:
+ /*
+ ** "I think I goofed!" (Client Error) - FM
+ */
+ switch (server_status) {
+ case 401: /* Unauthorized */
+ /*
+ * Authorization for orgin server required.
+ * If show_401 is set, proceed to showing the
+ * 401 body. Otherwise, if we can set up
+ * authorization based on the WWW-Authenticate
+ * header, and the user provides a username and
+ * password, try again. Otherwise, check whether
+ * to show the 401 body or restore the current
+ * document. - FM
+ */
+ if (show_401)
+ break;
+ if (HTAA_shouldRetryWithAuth(start_of_data, length,
+ (void *)handle, s, NO)) {
+
+ HTTP_NETCLOSE(s, handle);
+ if (dump_output_immediately && !authentication_info[0]) {
+ fprintf(stderr,
+ "HTTP: Access authorization required.\n");
+ fprintf(stderr,
+ " Use the -auth=id:pw parameter.\n");
+ status = HT_NO_DATA;
+ goto clean_up;
+ }
+
+ if (TRACE)
+ fprintf(stderr, "%s %d %s\n",
+ "HTTP: close socket", s,
+ "to retry with Access Authorization");
+
+ _HTProgress (
+ "Retrying with access authorization information.");
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+ goto try_again;
+ break;
+ } else if (!(traversal || dump_output_immediately) &&
+ HTConfirm("Show the 401 message body?")) {
+ break;
+ } else {
+ if (traversal || dump_output_immediately)
+ HTAlert(
+ "Can't retry with authorization! Contact the server's WebMaster.");
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ break;
+
+ case 407:
+ /*
+ * Authorization for proxy server required.
+ * If we are not in fact using a proxy, or
+ * show_407 is set, proceed to showing the
+ * 407 body. Otherwise, if we can set up
+ * authorization based on the Proxy-Authenticate
+ * header, and the user provides a username and
+ * password, try again. Otherwise, check whether
+ * to show the 401 body or restore the current
+ * document. - FM & AJL
+ */
+ if (!using_proxy || show_407)
+ break;
+ if (HTAA_shouldRetryWithAuth(start_of_data, length,
+ (void *)handle, s, YES)) {
+
+ HTTP_NETCLOSE(s, handle);
+ if (dump_output_immediately && !proxyauth_info[0]) {
+ fprintf(stderr,
+ "HTTP: Proxy authorization required.\n");
+ fprintf(stderr,
+ " Use the -pauth=id:pw parameter.\n");
+ status = HT_NO_DATA;
+ goto clean_up;
+ }
+
+ if (TRACE)
+ fprintf(stderr, "%s %d %s\n",
+ "HTTP: close socket", s,
+ "to retry with Proxy Authorization");
+
+ _HTProgress (
+ "Retrying with proxy authorization information.");
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+ goto try_again;
+ break;
+ } else if (!(traversal || dump_output_immediately) &&
+ HTConfirm("Show the 407 message body?")) {
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ } else {
+ if (traversal || dump_output_immediately)
+ HTAlert(
+ "Can't retry with proxy authorization! Contact the server's WebMaster.");
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ break;
+
+ case 408:
+ /*
+ * Request Timeout. Show the status message
+ * and restore the current document. - FM
+ */
+ HTAlert(line_buffer);
+ HTTP_NETCLOSE(s, handle);
+ status = HT_NO_DATA;
+ goto done;
+ break;
+
+ default:
+ /*
+ * 400 Bad Request.
+ * 402 Payment Required.
+ * 403 Forbidden.
+ * 404 Not Found.
+ * 405 Method Not Allowed.
+ * 406 Not Acceptable.
+ * 409 Conflict.
+ * 410 Gone.
+ * 411 Length Required.
+ * 412 Precondition Failed.
+ * 413 Request Entity Too Large.
+ * 414 Request-URI Too Long.
+ * 415 Unsupported Media Type.
+ * 416 List Response (for content negotiation).
+ * > 416 is unknown.
+ * Show the status message, and display
+ * the returned text if we are not doing
+ * a traversal. - FM
+ */
+ HTAlert(line_buffer);
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ } /* case 4 switch */
+ break;
+
+ case 5:
+ /*
+ ** "I think YOU goofed!" (server error)
+ ** 500 Internal Server Error
+ ** 501 Not Implemented
+ ** 502 Bad Gateway
+ ** 503 Service Unavailable
+ ** 504 Gateway Timeout
+ ** 505 HTTP Version Not Supported
+ ** > 505 is unknown.
+ ** Should always include a message, which
+ ** we always should display. - FM
+ */
+ HTAlert(line_buffer);
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+
+ default:
+ /*
+ ** Bad or unknown server_status number.
+ ** Take a chance and hope there is
+ ** something to display. - FM
+ */
+ HTAlert("Unknown status reply from server!");
+ HTAlert(line_buffer);
+ if (traversal) {
+ HTTP_NETCLOSE(s, handle);
+ status = -1;
+ goto clean_up;
+ }
+ if (!dump_output_immediately &&
+ format_out == HTAtom_for("www/download")) {
+ /*
+ * Convert a download request to
+ * a presentation request for
+ * interactive users. - FM
+ */
+ format_out = WWW_PRESENT;
+ }
+ break;
+ } /* Switch on server_status/100 */
+
+ } /* Full HTTP reply */
+ } /* scope of fields */
+
+ /*
+ ** Set up the stream stack to handle the body of the message.
+ */
+ if (do_head || keep_mime_headers) {
+ /*
+ ** It was a HEAD request, or we want the headers and source.
+ */
+ start_of_data = line_kept_clean;
+ length = strlen(start_of_data);
+ format_in = HTAtom_for("text/plain");
+ }
+
+ target = HTStreamStack(format_in,
+ format_out,
+ sink, anAnchor);
+
+ if (!target || target == NULL) {
+ char buffer[1024]; /* @@@@@@@@ */
+
+ HTTP_NETCLOSE(s, handle);
+ sprintf(buffer, "Sorry, no known way of converting %s to %s.",
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ _HTProgress (buffer);
+ status = -1;
+ goto clean_up;
+ }
+
+ /*
+ ** Recycle the first chunk of data, in all cases.
+ */
+ (*target->isa->put_block)(target, start_of_data, length);
+
+ /*
+ ** Go pull the bulk of the data down.
+ */
+ rv = HTCopy(anAnchor, s, (void *)handle, target);
+
+ if (rv == -1) {
+ /*
+ ** Intentional interrupt before data were received, not an error
+ */
+ /* (*target->isa->_abort)(target, NULL); */ /* already done in HTCopy */
+ status = HT_INTERRUPTED;
+ HTTP_NETCLOSE(s, handle);
+ goto clean_up;
+ }
+
+ if (rv == -2) {
+ /*
+ ** Aw hell, a REAL error, maybe cuz it's a dumb HTTP0 server
+ */
+ (*target->isa->_abort)(target, NULL);
+ HTTP_NETCLOSE(s, handle);
+ if (!already_retrying && !do_post) {
+ if (TRACE)
+ fprintf (stderr, "HTTP: Trying again with HTTP0 request.\n");
+ /*
+ ** May as well consider it an interrupt -- right?
+ */
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+ extensions = NO;
+ already_retrying = TRUE;
+ _HTProgress ("Retrying as HTTP0 request.");
+ goto try_again;
+ } else {
+ status = HT_NOT_LOADED;
+ goto clean_up;
+ }
+ }
+
+ /*
+ ** Free if complete transmission (socket was closed before return).
+ ** Close socket if partial transmission (was freed on abort).
+ */
+ if (rv != HT_INTERRUPTED) {
+ (*target->isa->_free)(target);
+ } else {
+ HTTP_NETCLOSE(s, handle);
+ }
+
+ if (doing_redirect) {
+ /*
+ ** We already jumped over all this if the "case 3:" code worked
+ ** above, but we'll check here as a backup in case it fails. - FM
+ */
+ /* Lou's old comment: - FM */
+ /* OK, now we've got the redirection URL temporarily stored
+ in external variable redirecting_url, exported from HTMIME.c,
+ since there's no straightforward way to do this in the library
+ currently. Do the right thing. */
+ status = HT_REDIRECTING;
+ } else {
+ /*
+ ** If any data were received, treat as a complete transmission
+ */
+ status = HT_LOADED;
+ }
+
+ /*
+ ** Clean up
+ */
+clean_up:
+ FREE(line_buffer);
+ FREE(line_kept_clean);
+
+done:
+ /*
+ ** Clear out on exit, just in case.
+ */
+ do_head = FALSE;
+ do_post = FALSE;
+ reloading = FALSE;
+ return status;
+}
+
+/* Protocol descriptor
+*/
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTTP_C_GLOBALDEF_1_INIT { "http", HTLoadHTTP, 0}
+GLOBALDEF (HTProtocol,HTTP,_HTTP_C_GLOBALDEF_1_INIT);
+#define _HTTP_C_GLOBALDEF_2_INIT { "https", HTLoadHTTP, 0}
+GLOBALDEF (HTProtocol,HTTPS,_HTTP_C_GLOBALDEF_2_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTTP = { "http", HTLoadHTTP, 0 };
+GLOBALDEF PUBLIC HTProtocol HTTPS = { "https", HTLoadHTTP, 0 };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.h
new file mode 100644
index 00000000000..92f1951c63b
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTP.h
@@ -0,0 +1,33 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTTP.html
+ HYPERTEXT TRANFER PROTOCOL
+
+ */
+#ifndef HTTP_H
+#define HTTP_H
+
+#include "HTAccess.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol,HTTP);
+extern GLOBALREF (HTProtocol,HTTPS);
+#else
+GLOBALREF HTProtocol HTTP;
+GLOBALREF HTProtocol HTTPS;
+#endif /* GLOBALREF_IS_MACRO */
+
+#define URL_GET_METHOD 1
+#define URL_POST_METHOD 2
+#define URL_MAIL_METHOD 3
+
+extern BOOL reloading;
+extern char * redirecting_url;
+extern BOOL permanent_redirection;
+extern BOOL redirect_post_content;
+
+#endif /* HTTP_H */
+
+/*
+
+ end of HTTP module definition
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.c
new file mode 100644
index 00000000000..140630e1cb3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.c
@@ -0,0 +1,590 @@
+/* Telnet Acees, Roligin, etc HTTelnet.c
+** ==========================
+**
+** Authors
+** TBL Tim Berners-Lee timbl@info.cern.ch
+** JFG Jean-Francois Groff jgh@next.com
+** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
+** History
+** 8 Jun 92 Telnet hopping prohibited as telnet is not secure (TBL)
+** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. (JFG)
+** 6 Oct 92 Moved HTClientHost and logfile into here. (TBL)
+** 17 Dec 92 Tn3270 added, bug fix. (DD)
+** 2 Feb 93 Split from HTAccess.c. Registration.(TBL)
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+/* Implements:
+*/
+#include "HTTelnet.h"
+
+#include "HTParse.h"
+#include "HTAnchor.h"
+#include "HTTP.h"
+#include "HTFile.h"
+/*#include <errno.h> included by tcp.h -- FM */
+/*#include <stdio.h> included by HTUtils.h -- FM */
+
+#include "HText.h"
+
+#include "HTAccess.h"
+#include "HTAlert.h"
+#if !defined (VMS) && !defined (_WINDOWS)
+#include "../../../userdefs.h" /* for TELNET_COMMAND and RLOGIN_COMMAND */
+#endif /* not VMS */
+
+#ifdef _WINDOWS /* ../../.. doesn't work for me */
+#include "userdefs.h" /* for TELNET_COMMAND and RLOGIN_COMMAND */
+#endif
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define HT_NO_DATA -9999
+
+
+/* Telnet or "rlogin" access
+** -------------------------
+*/
+PRIVATE int remote_session ARGS2(char *, acc_method, char *, host)
+{
+ char * user = host;
+ char * password = NULL;
+ char * cp;
+ char * hostname;
+ char * port;
+ char command[256];
+ enum _login_protocol { telnet, rlogin, tn3270 } login_protocol =
+ strcmp(acc_method, "rlogin") == 0 ? rlogin :
+ strcmp(acc_method, "tn3270") == 0 ? tn3270 : telnet;
+#ifdef VMS
+ extern int DCLsystem PARAMS((char *command));
+#define system(a) DCLsystem(a) /* use LYCurses.c routines for spawns */
+#endif /* VMS */
+
+ /*
+ * Modified to allow for odd chars in a username only if exists.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ /* prevent telnet://hostname;rm -rf * URL's (VERY BAD)
+ * *cp=0; / * terminate at any ;,<,>,`,|,",' or space or return
+ * or tab to prevent security whole
+ */
+ for(cp = (strchr(host, '@') ? strchr(host, '@') : host); *cp != '\0';
+ cp++) {
+ if(!isalnum(*cp) && *cp != '_' && *cp != '-' &&
+ *cp != ':' && *cp != '.' && *cp != '@') {
+ *cp = '\0';
+ break;
+ }
+ }
+
+ hostname = strchr(host, '@');
+
+ if (hostname) {
+ *hostname++ = '\0'; /* Split */
+ } else {
+ hostname = host;
+ user = NULL; /* No user specified */
+ }
+
+ port = strchr(hostname, ':');
+ if (port)
+ *port++ = '\0'; /* Split */
+
+ if (!hostname || *hostname == '\0') {
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: No host specified!\n");
+ return HT_NO_DATA;
+ }
+
+ if (user) {
+ password = strchr(user, ':');
+ if (password) {
+ *password++ = '\0';
+ }
+ }
+
+/* If the person is already telnetting etc, forbid hopping */
+/* This is a security precaution, for us and remote site */
+
+ if (HTSecure) {
+
+#ifdef TELNETHOPPER_MAIL
+ sprintf(command,
+ "finger @%s | mail -s \"**telnethopper %s\" tbl@dxcern.cern.ch",
+ HTClientHost, HTClientHost);
+ system(command);
+#endif
+ printf("\n\nSorry, but the service you have selected is one\n");
+ printf("to which you have to log in. If you were running www\n");
+ printf("on your own computer, you would be automatically connected.\n");
+ printf("For security reasons, this is not allowed when\n");
+ printf("you log in to this information service remotely.\n\n");
+
+ printf("You can manually connect to this service using %s\n",
+ acc_method);
+ printf("to host %s", hostname);
+ if (user) printf(", user name %s", user);
+ if (password) printf(", password %s", password);
+ if (port) printf(", port %s", port);
+ printf(".\n\n");
+ return HT_NO_DATA;
+ }
+
+/* Not all telnet servers get it even if user name is specified
+** so we always tell the guy what to log in as
+*/
+ if (user && login_protocol != rlogin)
+ printf("When you are connected, log in as: %s\n", user);
+ if (password && login_protocol != rlogin)
+ printf(" The password is: %s\n", password);
+
+/*
+ * NeXTSTEP is the implied version of the NeXT operating system.
+ * You may need to define this yourself.
+ */
+#if defined(NeXT) && defined(NeXTSTEP) && NeXTSTEP<=20100
+ sprintf(command, "%s%s%s %s %s", TELNET_COMMAND,
+ user ? " -l " : "",
+ user ? user : "",
+ hostname,
+ port ? port : "");
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif
+
+/* Most unix machines suppport username only with rlogin */
+#if defined(unix) || defined(DOSPATH)
+#ifndef TELNET_DONE
+ if (login_protocol == rlogin) {
+ sprintf(command, "%s %s%s%s", RLOGIN_COMMAND,
+ hostname,
+ user ? " -l " : "",
+ user ? user : "");
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "%s %s %s", TN3270_COMMAND,
+ hostname,
+ port ? port : "");
+
+ } else { /* TELNET */
+ sprintf(command, "%s %s %s", TELNET_COMMAND,
+ hostname,
+ port ? port : "");
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Normal: Command is: %s\n\n", command);
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(0);
+ _go32_want_ctrl_break(1);
+#endif /* __DJGPP__ */
+ system(command);
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(1);
+ _go32_want_ctrl_break(0);
+#endif /* __DJGPP__ */
+ return HT_NO_DATA; /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif /* !TELNET_DONE */
+#endif /* unix */
+
+/* VMS varieties */
+#if defined(MULTINET)
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN%s%s%s%s%s %s", /*lm 930713 */
+ user ? "/USERNAME=\"" : "",
+ user ? user : "",
+ user ? "\"" : "",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TELNET/TN3270 %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif /* MULTINET */
+
+#if defined(WIN_TCP)
+ {
+ char *cp;
+
+ if ((cp=getenv("WINTCP_COMMAND_STYLE")) != NULL &&
+ 0==strncasecomp(cp, "VMS", 3)) { /* VMS command syntax */
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN%s%s%s%s%s %s", /*lm 930713 */
+ user ? "/USERNAME=\"" : "",
+ user ? user : "",
+ user ? "\"" : "",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TELNET/TN3270 %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ }
+
+ } else { /* UNIX command syntax */
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN %s%s%s%s%s",
+ hostname,
+ user ? " -l " : "",
+ user ? "\"" : "",
+ user ? user : "",
+ user ? "\"" : "");
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TN3270 %s %s",
+ hostname,
+ port ? port : "");
+
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s %s",
+ hostname,
+ port ? port : "");
+ }
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+#define TELNET_DONE
+#endif /* WIN_TCP */
+
+#ifdef UCX
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN%s%s%s %s %s",
+ user ? "/USERNAME=\"" : "",
+ user ? user : "",
+ user ? "\"" : "",
+ hostname,
+ port ? port : "");
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TN3270 %s %s",
+ hostname,
+ port ? port : "");
+
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s %s",
+ hostname,
+ port ? port : "");
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif /* UCX */
+
+#ifdef CMU_TCP
+ if (login_protocol == telnet) {
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ }
+ else {
+ extern int LYgetch NOPARAMS;
+ extern BOOLEAN HadVMSInterrupt;
+
+ printf(
+ "\nSorry, this browser was compiled without the %s access option.\n",
+ acc_method);
+ printf("\nPress <return> to return to Lynx.");
+ LYgetch();
+ HadVMSInterrupt = FALSE;
+ }
+ return HT_NO_DATA; /* Ok - it was done but no data */
+#define TELNET_DONE
+#endif /* CMU_TCP */
+
+#ifdef SOCKETSHR_TCP
+ {
+ char *cp;
+
+ if (getenv("MULTINET_SOCKET_LIBRARY") != NULL) {
+ if (login_protocol == rlogin) {
+ sprintf(command, "MULTINET RLOGIN%s%s%s%s %s", /*lm 930713 */
+ user ? "/USERNAME=" : "",
+ user ? user : "",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "MULTINET TELNET/TN3270 %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+
+ } else { /* TELNET */
+ sprintf(command, "MULTINET TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+ else if ((cp=getenv("WINTCP_COMMAND_STYLE")) != NULL) {
+ if (0==strncasecomp(cp, "VMS", 3)) { /* VMS command syntax */
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN%s%s%s%s %s", /*lm 930713 */
+ user ? "/USERNAME=" : "",
+ user ? user : "",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TELNET/TN3270 %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ }
+ } else { /* UNIX command syntax */
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN %s%s%s",
+ hostname,
+ user ? " -l " : "",
+ user ? user : "");
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TN3270 %s %s",
+ hostname,
+ port ? port : "");
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s %s",
+ hostname,
+ port ? port : "");
+ }
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+ else if (getenv("UCX$DEVICE") != NULL) {
+ if (login_protocol == rlogin) {
+ sprintf(command, "RLOGIN%s%s %s %s",
+ user ? "/USERNAME=" : "",
+ user ? user : "",
+ hostname,
+ port ? port : "");
+
+ } else if (login_protocol == tn3270) {
+ sprintf(command, "TN3270 %s %s",
+ hostname,
+ port ? port : "");
+
+ } else { /* TELNET */
+ sprintf(command, "TELNET %s %s",
+ hostname,
+ port ? port : "");
+ }
+
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+ else if (getenv("CMUTEK_ROOT") != NULL) {
+ if (login_protocol == telnet) {
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ }
+ else {
+ extern int LYgetch NOPARAMS;
+ extern BOOLEAN HadVMSInterrupt;
+
+ printf(
+ "\nSorry, this browser was compiled without the %s access option.\n",
+ acc_method);
+ printf("\nPress <return> to return to Lynx.");
+ LYgetch();
+ HadVMSInterrupt = FALSE;
+ }
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+ else {
+ if (login_protocol == telnet) {
+ sprintf(command, "TELNET %s%s %s",
+ port ? "/PORT=" : "",
+ port ? port : "",
+ hostname);
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ }
+ else {
+ extern int LYgetch NOPARAMS;
+ extern BOOLEAN HadVMSInterrupt;
+
+ printf(
+ "\nSorry, this browser was compiled without the %s access option.\n",
+ acc_method);
+ printf("\nPress <return> to return to Lynx.");
+ LYgetch();
+ HadVMSInterrupt = FALSE;
+ }
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+ }
+#define TELNET_DONE
+#endif /* SOCKETSHR_TCP */
+
+#ifdef VM
+#define SIMPLE_TELNET
+#endif
+#ifdef SIMPLE_TELNET
+ if (login_protocol == telnet) { /* telnet only */
+ sprintf(command, "TELNET %s", /* @@ Bug: port ignored */
+ hostname);
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: Command is: %s\n\n", command);
+ system(command);
+ return HT_NO_DATA; /* Ok - it was done but no data */
+ }
+#endif
+
+#ifndef TELNET_DONE
+ printf(
+ "\nSorry, this browser was compiled without the %s access option.\n",
+ acc_method);
+ printf(
+ "\nTo access the information you must %s to %s", acc_method, hostname);
+ if (port)
+ printf(" (port %s)", port);
+ if (user)
+ printf("\nlogging in with username %s", user);
+ printf(".\n");
+ {
+ extern int LYgetch NOPARAMS;
+
+ printf("\nPress <return> to return to Lynx.");
+ fflush(stdout);
+ LYgetch();
+#ifdef VMS
+ {
+ extern BOOLEAN HadVMSInterrupt;
+ HadVMSInterrupt = FALSE;
+ }
+#endif /* VMS */
+ }
+ return HT_NO_DATA;
+#endif /* !TELNET_DONE */
+}
+
+/* "Load a document" -- establishes a session
+** ------------------------------------------
+**
+** On entry,
+** addr must point to the fully qualified hypertext reference.
+**
+** On exit,
+** returns <0 Error has occured.
+** >=0 Value of file descriptor or socket to be used
+** to read data.
+** *pFormat Set to the format of the file, if known.
+** (See WWW.h)
+**
+*/
+PRIVATE int HTLoadTelnet
+ARGS4
+(
+ CONST char *, addr,
+ HTParentAnchor *, anchor GCC_UNUSED,
+ HTFormat, format_out GCC_UNUSED,
+ HTStream *, sink /* Ignored */
+)
+{
+ char * acc_method;
+ char * host;
+ int status;
+
+ if (sink) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTTelnet: Can't output a live session -- must be interactive!\n");
+ return HT_NO_DATA;
+ }
+ acc_method = HTParse(addr, "file:", PARSE_ACCESS);
+
+ host = HTParse(addr, "", PARSE_HOST);
+ if (!host || *host == '\0') {
+ status = HT_NO_DATA;
+ if (TRACE)
+ fprintf(stderr, "HTTelnet: No host specified!\n");
+ } else {
+ status = remote_session(acc_method, host);
+ }
+
+ FREE(host);
+ FREE(acc_method);
+ return status;
+}
+
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTTELNET_C_1_INIT { "telnet", HTLoadTelnet, NULL }
+#define _HTTELNET_C_2_INIT { "rlogin", HTLoadTelnet, NULL }
+#define _HTTELNET_C_3_INIT { "tn3270", HTLoadTelnet, NULL }
+GLOBALDEF (HTProtocol, HTTelnet, _HTTELNET_C_1_INIT );
+GLOBALDEF (HTProtocol, HTRlogin, _HTTELNET_C_2_INIT );
+GLOBALDEF (HTProtocol, HTTn3270, _HTTELNET_C_3_INIT );
+#else
+GLOBALDEF PUBLIC HTProtocol HTTelnet = { "telnet", HTLoadTelnet, NULL };
+GLOBALDEF PUBLIC HTProtocol HTRlogin = { "rlogin", HTLoadTelnet, NULL };
+GLOBALDEF PUBLIC HTProtocol HTTn3270 = { "tn3270", HTLoadTelnet, NULL };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.h
new file mode 100644
index 00000000000..4c5de744fc1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTTelnet.h
@@ -0,0 +1,24 @@
+/* /Net/dxcern/userd/timbl/hypertext/WWW/Library/Implementation/HTTelnet.html
+ TELNET AND SIMILAR ACCESS METHODS
+
+ */
+
+#ifndef HTTELNET_H
+#define HTTELNET_H
+
+#include "HTAccess.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF(HTProtocol,HTTelnet);
+extern GLOBALREF(HTProtocol,HTRlogin);
+extern GLOBALREF(HTProtocol,HTTn3270);
+#else
+GLOBALREF HTProtocol HTTelnet;
+GLOBALREF HTProtocol HTRlogin;
+GLOBALREF HTProtocol HTTn3270;
+#endif /* GLOBALREF_IS_MACRO */
+#endif /* HTTELNET_H */
+
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.c
new file mode 100644
index 00000000000..865315cc0aa
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.c
@@ -0,0 +1,207 @@
+
+/* MODULE HTUU.c
+** UUENCODE AND UUDECODE
+**
+** ACKNOWLEDGEMENT:
+** This code is taken from rpem distribution, and was originally
+** written by Mark Riordan.
+**
+** AUTHORS:
+** MR Mark Riordan riordanmr@clvax1.cl.msu.edu
+** AL Ari Luotonen luotonen@dxcern.cern.ch
+**
+** HISTORY:
+** Added as part of the WWW library and edited to conform
+** with the WWW project coding standards by: AL 5 Aug 1993
+** Originally written by: MR 12 Aug 1990
+** Original header text:
+** -------------------------------------------------------------
+** File containing routines to convert a buffer
+** of bytes to/from RFC 1113 printable encoding format.
+**
+** This technique is similar to the familiar Unix uuencode
+** format in that it maps 6 binary bits to one ASCII
+** character (or more aptly, 3 binary bytes to 4 ASCII
+** characters). However, RFC 1113 does not use the same
+** mapping to printable characters as uuencode.
+**
+** Mark Riordan 12 August 1990 and 17 Feb 1991.
+** This code is hereby placed in the public domain.
+** -------------------------------------------------------------
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include "HTUU.h"
+
+#include "LYLeaks.h"
+
+PRIVATE char six2pr[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M',
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+ 'a','b','c','d','e','f','g','h','i','j','k','l','m',
+ 'n','o','p','q','r','s','t','u','v','w','x','y','z',
+ '0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+PRIVATE unsigned char pr2six[256];
+
+
+/*--- function HTUU_encode -----------------------------------------------
+ *
+ * Encode a single line of binary data to a standard format that
+ * uses only printing ASCII characters (but takes up 33% more bytes).
+ *
+ * Entry bufin points to a buffer of bytes. If nbytes is not
+ * a multiple of three, then the byte just beyond
+ * the last byte in the buffer must be 0.
+ * nbytes is the number of bytes in that buffer.
+ * This cannot be more than 48.
+ * bufcoded points to an output buffer. Be sure that this
+ * can hold at least 1 + (4*nbytes)/3 characters.
+ *
+ * Exit bufcoded contains the coded line. The first 4*nbytes/3 bytes
+ * contain printing ASCII characters representing
+ * those binary bytes. This may include one or
+ * two '=' characters used as padding at the end.
+ * The last byte is a zero byte.
+ * Returns the number of ASCII characters in "bufcoded".
+ */
+PUBLIC int HTUU_encode ARGS3(unsigned char *, bufin,
+ unsigned int, nbytes,
+ char *, bufcoded)
+{
+/* ENC is the basic 1 character encoding function to make a char printing */
+#define ENC(c) six2pr[c]
+
+ register char *outptr = bufcoded;
+ unsigned int i;
+ /* This doesn't seem to be needed (AL): register unsigned char *inptr = bufin; */
+
+ for (i=0; i<nbytes; i += 3) {
+ *(outptr++) = ENC(*bufin >> 2); /* c1 */
+ *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/
+ *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/
+ *(outptr++) = ENC(bufin[2] & 077); /* c4 */
+
+ bufin += 3;
+ }
+
+ /* If nbytes was not a multiple of 3, then we have encoded too
+ * many characters. Adjust appropriately.
+ */
+ if(i == nbytes+1) {
+ /* There were only 2 bytes in that last group */
+ outptr[-1] = '=';
+ } else if(i == nbytes+2) {
+ /* There was only 1 byte in that last group */
+ outptr[-1] = '=';
+ outptr[-2] = '=';
+ }
+ *outptr = '\0';
+ return(outptr - bufcoded);
+}
+
+
+/*--- function HTUU_decode ------------------------------------------------
+ *
+ * Decode an ASCII-encoded buffer back to its original binary form.
+ *
+ * Entry bufcoded points to a uuencoded string. It is
+ * terminated by any character not in
+ * the printable character table six2pr, but
+ * leading whitespace is stripped.
+ * bufplain points to the output buffer; must be big
+ * enough to hold the decoded string (generally
+ * shorter than the encoded string) plus
+ * as many as two extra bytes used during
+ * the decoding process.
+ * outbufsize is the maximum number of bytes that
+ * can fit in bufplain.
+ *
+ * Exit Returns the number of binary bytes decoded.
+ * bufplain contains these bytes.
+ */
+PUBLIC int HTUU_decode ARGS3(char *, bufcoded,
+ unsigned char *, bufplain,
+ int, outbufsize)
+{
+/* single character decode */
+#define DEC(c) pr2six[(int)c]
+#define MAXVAL 63
+
+ static int first = 1;
+
+ int nbytesdecoded, j;
+ register char *bufin = bufcoded;
+ register unsigned char *bufout = bufplain;
+ register int nprbytes;
+
+ /* If this is the first call, initialize the mapping table.
+ * This code should work even on non-ASCII machines.
+ */
+ if(first) {
+ first = 0;
+ for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
+
+ for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j;
+#if 0
+ pr2six['A']= 0; pr2six['B']= 1; pr2six['C']= 2; pr2six['D']= 3;
+ pr2six['E']= 4; pr2six['F']= 5; pr2six['G']= 6; pr2six['H']= 7;
+ pr2six['I']= 8; pr2six['J']= 9; pr2six['K']=10; pr2six['L']=11;
+ pr2six['M']=12; pr2six['N']=13; pr2six['O']=14; pr2six['P']=15;
+ pr2six['Q']=16; pr2six['R']=17; pr2six['S']=18; pr2six['T']=19;
+ pr2six['U']=20; pr2six['V']=21; pr2six['W']=22; pr2six['X']=23;
+ pr2six['Y']=24; pr2six['Z']=25; pr2six['a']=26; pr2six['b']=27;
+ pr2six['c']=28; pr2six['d']=29; pr2six['e']=30; pr2six['f']=31;
+ pr2six['g']=32; pr2six['h']=33; pr2six['i']=34; pr2six['j']=35;
+ pr2six['k']=36; pr2six['l']=37; pr2six['m']=38; pr2six['n']=39;
+ pr2six['o']=40; pr2six['p']=41; pr2six['q']=42; pr2six['r']=43;
+ pr2six['s']=44; pr2six['t']=45; pr2six['u']=46; pr2six['v']=47;
+ pr2six['w']=48; pr2six['x']=49; pr2six['y']=50; pr2six['z']=51;
+ pr2six['0']=52; pr2six['1']=53; pr2six['2']=54; pr2six['3']=55;
+ pr2six['4']=56; pr2six['5']=57; pr2six['6']=58; pr2six['7']=59;
+ pr2six['8']=60; pr2six['9']=61; pr2six['+']=62; pr2six['/']=63;
+#endif
+ }
+
+ /* Strip leading whitespace. */
+
+ while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
+
+ /* Figure out how many characters are in the input buffer.
+ * If this would decode into more bytes than would fit into
+ * the output buffer, adjust the number of input bytes downwards.
+ */
+ bufin = bufcoded;
+ while(pr2six[(unsigned char)*(bufin++)] <= MAXVAL);
+ nprbytes = bufin - bufcoded - 1;
+ nbytesdecoded = ((nprbytes+3)/4) * 3;
+ if(nbytesdecoded > outbufsize) {
+ nprbytes = (outbufsize*4)/3;
+ }
+
+ bufin = bufcoded;
+
+ while (nprbytes > 0) {
+ *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
+ *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
+ *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
+ bufin += 4;
+ nprbytes -= 4;
+ }
+
+ if(nprbytes & 03) {
+ if(pr2six[(int)bufin[-2]] > MAXVAL) {
+ nbytesdecoded -= 2;
+ } else {
+ nbytesdecoded -= 1;
+ }
+ }
+
+ return(nbytesdecoded);
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.h
new file mode 100644
index 00000000000..05874e240a5
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUU.h
@@ -0,0 +1,29 @@
+/* ENCODING TO PRINTABLE CHARACTERS
+
+ File module provides functions HTUU_encode() and HTUU_decode() which convert a buffer
+ of bytes to/from RFC 1113 printable encoding format. This technique is similar to the
+ familiar Unix uuencode format in that it maps 6 binary bits to one ASCII character (or
+ more aptly, 3 binary bytes to 4 ASCII characters). However, RFC 1113 does not use the
+ same mapping to printable characters as uuencode.
+
+ */
+
+#ifndef HTUU_H
+#define HTUU_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+PUBLIC int HTUU_encode PARAMS((unsigned char *bufin,
+ unsigned int nbytes,
+ char *bufcoded));
+
+PUBLIC int HTUU_decode PARAMS((char *bufcoded,
+ unsigned char *bufplain,
+ int outbufsize));
+
+#endif
+/*
+
+ End of file. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUtils.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUtils.h
new file mode 100644
index 00000000000..21128bb99f4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTUtils.h
@@ -0,0 +1,447 @@
+/* Utitlity macros for the W3 code library
+ MACROS FOR GENERAL USE
+
+ Generates: HTUtils.h
+
+ See also: the system dependent file "tcp.h"
+
+ */
+
+#ifndef DEBUG
+#define DEBUG /* Noone ever turns this off as trace is too important */
+#endif /* Keep option for really small memory applications tho */
+
+#ifndef HTUTILS_H
+#define HTUTILS_H
+
+#ifdef HAVE_CONFIG_H
+#include <lynx_cfg.h> /* generated by autoconf 'configure' script */
+#include <sys/types.h>
+#else
+
+#define DONT_TRACK_INTERNAL_LINKS 1
+
+/* Explicit system-configure */
+#ifdef VMS
+#define NO_SIZECHANGE
+#define NO_UNISTD_H
+#define NO_KEYPAD
+#define NO_UTMP
+#endif
+
+/* FIXME: these will be removed after completing auto-configure script */
+
+#ifdef _IBMR2
+#define USE_DIRENT /* sys V style directory open */
+#endif /* _IBMR2 */
+
+#ifdef _SYSV3
+#include <fcntl.h>
+#define USE_DIRENT /* sys V style directory open */
+#endif /* _SYSV3 */
+
+/* Solaris. */
+#if defined(sun) && defined(__svr4__) && !defined(USE_DIRENT)
+#define USE_DIRENT /* sys V style directory open */
+#endif /* sun && __svr4__ && !USE_DIRENT */
+
+#ifdef __alpha
+#define USE_DIRENT
+#endif /* __alpha */
+
+#ifndef USE_DIRENT
+#ifdef SVR4
+#define USE_DIRENT
+#endif /* SVR4 */
+#endif /* !USE_DIRENT */
+
+#ifndef SOLARIS2
+#include <string.h> /* For bzero etc */
+#endif /* !SOLARIS2 */
+
+#ifdef SCO
+#define sco
+#endif /* SCO */
+#ifdef sco
+#include <sys/fcntl.h>
+#define USE_DIRENT
+#endif /* sco */
+
+/*
+Intergraph CLIX
+ */
+#ifdef CLIX
+#include <sys/fcntl.h>
+#define USE_DIRENT
+#endif /* CLIX */
+
+#ifdef ISC
+#ifndef NO_UNISTD_H
+#include <sys/unistd.h>
+#endif /* !NO_UNISTD_H */
+#else
+#if !defined(NO_UNISTD_H) && !defined(VMS)
+#include <unistd.h>
+#endif /* !NO_UNISTD_H && !VMS */
+#endif /* ISC */
+
+#if defined(SVR4) || defined(UNIXWARE)
+#include <sys/fcntl.h>
+#ifndef NO_FILIO_H /* BSD Interactive doesn't have filio.h. */
+#include <sys/filio.h>
+#endif /* !NO_FILIO_H */
+#endif /* SVR4 || UNIXWARE */
+
+/*
+SOLARIS 2
+ */
+#ifdef SOLARIS2
+#include <sys/filio.h>
+#endif /* SOLARIS2 */
+
+#ifndef NO_FILIO_H
+#define NO_FILIO_H /* prevent conflict between autoconf & BSDI make */
+#endif
+
+/* Accommodate pre-autoconf Makefile */
+
+#ifndef NO_CBREAK
+#define HAVE_CBREAK 1
+#endif
+
+#ifndef NO_CUSERID
+#define HAVE_CUSERID 1
+#endif
+
+#ifndef NO_FILIO_H
+#define HAVE_SYS_FILIO_H 1
+#endif
+
+#ifndef NO_GETCWD
+#define HAVE_GETCWD 1
+#endif
+
+#ifndef USE_SLANG
+#ifndef NO_KEYPAD
+#define HAVE_KEYPAD 1
+#endif
+#ifndef NO_TTYTYPE
+#define HAVE_TTYTYPE 1
+#endif
+#endif /* USE_SLANG */
+
+#ifndef NO_PUTENV
+#define HAVE_PUTENV 1
+#endif
+
+#ifndef NO_SIZECHANGE
+#define HAVE_SIZECHANGE 1
+#endif
+
+#ifndef NO_UNISTD_H
+#define HAVE_UNISTD_H 1
+#endif
+
+#ifndef NO_UTMP
+#define HAVE_UTMP 1
+#endif
+
+#endif
+
+#ifndef GCC_UNUSED
+#define GCC_UNUSED /* nothing */
+#endif
+
+#ifdef _WINDOWS /* SCW */
+#include "windef.h"
+#define BOOLEAN_DEFINED
+#define va_arg
+#include <dos.h>
+#define popen _popen
+#define pclose _pclose
+#endif /* _WINDOWS */
+
+#ifdef SHORT_NAMES
+#define WWW_TraceFlag HTTrFlag
+#endif
+
+/*
+
+Debug message control.
+
+ */
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif
+
+#ifdef DEBUG
+#define TRACE (WWW_TraceFlag)
+#define PROGRESS(str) printf(str)
+ extern int WWW_TraceFlag;
+#else
+#define TRACE 0
+#define PROGRESS(str) /* nothing for now */
+#endif
+
+#define CTRACE if(TRACE)fprintf
+#define tfp stderr
+
+/*
+
+ ERROR TYPE
+
+ This is passed back when streams are aborted. It might be nice to have some structure
+ of error messages, numbers, and recursive pointers to reasons. Curently this is a
+ placeholder for something more sophisticated.
+
+ */
+typedef void * HTError; /* Unused at present -- best definition? */
+
+/*
+
+Standard C library for malloc() etc
+
+ */
+#ifdef DGUX
+#include <stdlib.h>
+#endif /* DGUX */
+
+#ifdef vax
+#ifdef unix
+#define ultrix /* Assume vax+unix=ultrix */
+#endif /* unix */
+#endif /* vax */
+
+#ifndef VMS
+#ifndef ultrix
+
+#ifdef NeXT
+#include <libc.h> /* NeXT */
+#endif /* NeXT */
+#ifndef MACH /* Vincent.Cate@furmint.nectar.cs.cmu.edu */
+#ifndef __STRICT_BSD__
+#include <stdlib.h>
+#endif /* !__STRICT_BSD__ */
+#endif /* !MACH */
+
+#else /* ultrix: */
+
+#include <malloc.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h> /* ANSI */ /* BSN */
+
+#endif /* !ultrix */
+#else /* VMS: */
+
+#include <stdlib.h>
+#include <unixlib.h>
+#include <ctype.h>
+#if defined(VAXC) && !defined(__DECC)
+#define malloc VAXC$MALLOC_OPT
+#define calloc VAXC$CALLOC_OPT
+#define free VAXC$FREE_OPT
+#define cfree VAXC$CFREE_OPT
+#define realloc VAXC$REALLOC_OPT
+#endif /* VAXC && !__DECC */
+
+#endif /* !VMS */
+
+/*
+
+Macros for declarations
+
+ */
+#define PUBLIC /* Accessible outside this module */
+#define PRIVATE static /* Accessible only within this module */
+
+#ifdef __STDC__
+#define CONST const /* "const" only exists in STDC */
+#define NOPARAMS (void)
+#define PARAMS(parameter_list) parameter_list
+#define NOARGS (void)
+#define ARGS1(t,a) \
+ (t a)
+#define ARGS2(t,a,u,b) \
+ (t a, u b)
+#define ARGS3(t,a,u,b,v,c) \
+ (t a, u b, v c)
+#define ARGS4(t,a,u,b,v,c,w,d) \
+ (t a, u b, v c, w d)
+#define ARGS5(t,a,u,b,v,c,w,d,x,e) \
+ (t a, u b, v c, w d, x e)
+#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) \
+ (t a, u b, v c, w d, x e, y f)
+#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) \
+ (t a, u b, v c, w d, x e, y f, z g)
+#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) \
+ (t a, u b, v c, w d, x e, y f, z g, s h)
+#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) \
+ (t a, u b, v c, w d, x e, y f, z g, s h, r i)
+#define ARGS10(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i,q,j) \
+ (t a, u b, v c, w d, x e, y f, z g, s h, r i, q j)
+
+#else /* not ANSI */
+
+#ifndef _WINDOWS
+#define CONST
+#endif
+#define NOPARAMS ()
+#define PARAMS(parameter_list) ()
+#define NOARGS ()
+#define ARGS1(t,a) (a) \
+ t a;
+#define ARGS2(t,a,u,b) (a,b) \
+ t a; u b;
+#define ARGS3(t,a,u,b,v,c) (a,b,c) \
+ t a; u b; v c;
+#define ARGS4(t,a,u,b,v,c,w,d) (a,b,c,d) \
+ t a; u b; v c; w d;
+#define ARGS5(t,a,u,b,v,c,w,d,x,e) (a,b,c,d,e) \
+ t a; u b; v c; w d; x e;
+#define ARGS6(t,a,u,b,v,c,w,d,x,e,y,f) (a,b,c,d,e,f) \
+ t a; u b; v c; w d; x e; y f;
+#define ARGS7(t,a,u,b,v,c,w,d,x,e,y,f,z,g) (a,b,c,d,e,f,g) \
+ t a; u b; v c; w d; x e; y f; z g;
+#define ARGS8(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h) (a,b,c,d,e,f,g,h) \
+ t a; u b; v c; w d; x e; y f; z g; s h;
+#define ARGS9(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i) (a,b,c,d,e,f,g,h,i) \
+ t a; u b; v c; w d; x e; y f; z g; s h; r i;
+#define ARGS10(t,a,u,b,v,c,w,d,x,e,y,f,z,g,s,h,r,i,q,j) (a,b,c,d,e,f,g,h,i,j) \
+ t a; u b; v c; w d; x e; y f; z g; s h; r i; q j;
+
+
+#endif /* __STDC__ (ANSI) */
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+/*
+
+Booleans
+
+ */
+/* Note: GOOD and BAD are already defined (differently) on RS6000 aix */
+/* #define GOOD(status) ((status)38;1) VMS style status: test bit 0 */
+/* #define BAD(status) (!GOOD(status)) Bit 0 set if OK, otherwise clear */
+
+#ifndef _WINDOWS
+#ifndef BOOLEAN_DEFINED
+ typedef char BOOLEAN; /* Logical value */
+#ifndef CURSES
+#ifndef TRUE
+#define TRUE (BOOLEAN)1
+#define FALSE (BOOLEAN)0
+#endif
+#endif /* CURSES */
+#endif /* _WINDOWS */
+#define BOOLEAN_DEFINED
+#endif
+
+#ifndef BOOL
+#define BOOL BOOLEAN
+#endif
+#ifndef YES
+#define YES (BOOLEAN)1
+#define NO (BOOLEAN)0
+#endif
+
+extern BOOL LYOutOfMemory; /* Declared in LYexit.c - FM */
+
+#define TCP_PORT 80 /* Allocated to http by Jon Postel/ISI 24-Jan-92 */
+#define OLD_TCP_PORT 2784 /* Try the old one if no answer on 80 */
+#define DNP_OBJ 80 /* This one doesn't look busy, but we must check */
+ /* That one was for decnet */
+
+/* Inline Function WHITE: Is character c white space? */
+/* For speed, include all control characters */
+
+#define WHITE(c) (((unsigned char)(TOASCII(c))) <= 32)
+
+
+/*
+
+Sucess (>=0) and failure (<0) codes
+
+ */
+
+#define HT_REDIRECTING 29996
+#define HT_LOADED 29997 /* Instead of a socket */
+#define HT_PARTIAL_CONTENT 206 /* Partial Content */
+#define HT_INTERRUPTED -29998
+#define HT_NOT_LOADED -29999
+#define HT_OK 0 /* Generic success*/
+
+#define HT_ERROR -1 /* Generic failure */
+
+#define HT_NO_ACCESS -10 /* Access not available */
+#define HT_FORBIDDEN -11 /* Access forbidden */
+#define HT_INTERNAL -12 /* Weird -- should never happen. */
+#define HT_BAD_EOF -12 /* Premature EOF */
+
+
+#include "HTString.h" /* String utilities */
+
+#ifndef va_arg
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#endif
+
+/*
+
+Out Of Memory checking for malloc() return:
+
+ */
+#ifndef __FILE__
+#define __FILE__ ""
+#define __LINE__ ""
+#endif
+
+#include "LYexit.h"
+
+#define outofmem(file, func)\
+ { fprintf(stderr,\
+ "\r\n\r\n\r\n%s %s: out of memory. Aborting...\r\n", file, func);\
+ LYOutOfMemory = TRUE; exit(-1);}
+/* extern void outofmem PARAMS((const char *fname, const char *func)); */
+
+/*
+
+Upper- and Lowercase macros
+
+ The problem here is that toupper(x) is not defined officially unless isupper(x) is.
+ These macros are CERTAINLY needed on #if defined(pyr) || define(mips) or BDSI
+ platforms. For safefy, we make them mandatory.
+
+ */
+#include <ctype.h>
+#include <string.h>
+
+#ifndef TOLOWER
+ /* Pyramid and Mips can't uppercase non-alpha */
+#define TOLOWER(c) (isupper((unsigned char)c) ? tolower((unsigned char)c) : ((unsigned char)c))
+#define TOUPPER(c) (islower((unsigned char)c) ? toupper((unsigned char)c) : ((unsigned char)c))
+#endif /* TOLOWER */
+
+/*
+
+The local equivalents of CR and LF
+
+ We can check for these after net ascii text has been converted to the local
+ representation. Similarly, we include them in strings to be sent as net ascii after
+ translation.
+
+ */
+#define LF FROMASCII('\012') /* ASCII line feed LOCAL EQUIVALENT */
+#define CR FROMASCII('\015') /* Will be converted to ^M for transmission */
+
+#endif /* HTUTILS_H */
+
+/*
+
+ end of utilities */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.c
new file mode 100644
index 00000000000..118f95178b2
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.c
@@ -0,0 +1,1264 @@
+
+/* MODULE HTVMSUtil.c
+** VMS Utility Routines
+**
+** AUTHORS:
+** MD Mark Donszelmann duns@vxdeop.cern.ch
+**
+** HISTORY:
+** 14 Nov 93 MD Written
+**
+** BUGS:
+**
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFormat.h"
+#include "HTStream.h"
+#include "UCDefs.h"
+#include "UCMap.h"
+#include "UCAux.h"
+#include "HTVMSUtils.h"
+/*#include <stdio.h> included by HTUtils.h -- FM */
+/*#include <unixlib.h> included by HTUtils.h -- FM */
+#include <ssdef.h>
+#include <jpidef.h>
+#include <prvdef.h>
+#include <acldef.h>
+#include <chpdef.h>
+#include <descrip.h>
+#include <lib$routines.h>
+#include <starlet.h>
+#include <rmsdef.h>
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define INFINITY 512 /* File name length @@ FIXME */
+
+PUBLIC BOOL HTVMSFileVersions=FALSE; /* Include version numbers in listing? */
+
+typedef struct {
+ unsigned long BufferLength : 16;
+ unsigned long ItemCode : 16;
+ unsigned long BufferAddress : 32;
+ unsigned long ReturnLengthAddress : 32;
+} ItemStruct;
+
+extern CONST char * HTHostName NOPARAMS;
+
+/* PUBLIC HTVMS_authSysPrv()
+** CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns YES if SYSPRV is authorized
+*/
+PUBLIC BOOL HTVMS_authSysPrv NOARGS
+{
+unsigned long Result;
+ItemStruct ItemList[2];
+unsigned long Length;
+unsigned long Buffer[2];
+
+ /* fill Item */
+ ItemList[0].BufferLength = sizeof(Buffer);
+ ItemList[0].BufferAddress = (unsigned long)Buffer;
+ ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
+ ItemList[0].ItemCode = JPI$_AUTHPRIV;
+
+ /* terminate list */
+ ItemList[1].ItemCode = 0;
+ ItemList[1].BufferLength = 0;
+
+ /* call system */
+ Result = sys$getjpiw(0, 0, 0, ItemList, 0, 0, 0);
+
+ if (Result != SS$_NORMAL)
+ return(NO);
+
+ if (Buffer[0] & PRV$M_SYSPRV)
+ return(YES);
+
+ return(NO);
+}
+
+
+
+/* PUBLIC HTVMS_enableSysPrv()
+** ENABLES SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+**
+*/
+PUBLIC void HTVMS_enableSysPrv NOARGS
+{
+unsigned long Result;
+unsigned long Prv[2], PreviousPrv[2];
+
+ Prv[0] = PRV$M_SYSPRV;
+ Prv[1] = 0;
+ Result = sys$setprv(1,&Prv,0,&PreviousPrv);
+
+ if (TRACE) {
+ if (Result == SS$_NORMAL) {
+ if (!(PreviousPrv[0] & PRV$M_SYSPRV)) {
+ fprintf(stderr, "HTVMS_enableSysPrv: Enabled SYSPRV\n");
+ }
+ }
+ }
+}
+
+
+
+/* PUBLIC HTVMS_disableSysPrv()
+** DISABLES SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+**
+*/
+PUBLIC void HTVMS_disableSysPrv NOARGS
+{
+unsigned long Result;
+unsigned long Prv[2], PreviousPrv[2];
+
+ Prv[0] = PRV$M_SYSPRV;
+ Prv[1] = 0;
+ Result = sys$setprv(0,&Prv,0,&PreviousPrv);
+
+ if (TRACE) {
+ if (Result == SS$_NORMAL) {
+ if (PreviousPrv[0] & PRV$M_SYSPRV) {
+ fprintf(stderr, "HTVMS_disableSysPrv: Disabled SYSPRV\n");
+ }
+ }
+ }
+}
+
+
+
+/* PUBLIC HTVMS_checkAccess()
+** CHECKS ACCESS TO FILE FOR CERTAIN USER
+** ON ENTRY:
+** FileName The file to be accessed
+** UserName Name of the user to check access for.
+** User nobody, represented by "" is given NO for an answer
+** Method Name of the method to be chceked
+**
+** ON EXIT:
+** returns YES if access is allowed
+**
+*/
+PUBLIC BOOL HTVMS_checkAccess ARGS3(
+ CONST char *, FileName,
+ CONST char *, UserName,
+ CONST char *, Method)
+{
+unsigned long Result;
+ItemStruct ItemList[2];
+unsigned long Length;
+unsigned long Buffer;
+unsigned long ObjType;
+
+char *VmsName;
+
+struct dsc$descriptor_s FileNameDesc;
+struct dsc$descriptor_s UserNameDesc;
+
+char *colon;
+
+ /* user nobody should access as from account under which server is running */
+ if (0 == strcmp(UserName,""))
+ return(NO);
+
+ /* check Filename and convert */
+ colon = strchr(FileName,':');
+ if (colon)
+ VmsName = HTVMS_name("",colon+1);
+ else
+ VmsName = HTVMS_name("",FileName);
+
+ /* check for GET */
+ if (0 == strcmp(Method,"GET"))
+ {
+ /* fill Item */
+ ItemList[0].BufferLength = sizeof(Buffer);
+ ItemList[0].BufferAddress = (unsigned long)&Buffer;
+ ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
+ ItemList[0].ItemCode = CHP$_FLAGS;
+
+ /* terminate list */
+ ItemList[1].ItemCode = 0;
+ ItemList[1].BufferLength = 0;
+
+ /* fill input */
+ ObjType = ACL$C_FILE;
+ Buffer = CHP$M_READ;
+ UserNameDesc.dsc$w_length = strlen(UserName);
+ UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
+ UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
+ UserNameDesc.dsc$a_pointer = (char *)UserName;
+ FileNameDesc.dsc$w_length = strlen(VmsName);
+ FileNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
+ FileNameDesc.dsc$b_class = DSC$K_CLASS_S;
+ FileNameDesc.dsc$a_pointer = VmsName;
+
+ /* call system */
+ Result = sys$check_access(&ObjType,&FileNameDesc,&UserNameDesc,ItemList);
+
+ if (Result == SS$_NORMAL)
+ return(YES);
+ else
+ return(NO);
+ }
+
+ return(NO);
+}
+
+
+
+/* PUBLIC HTVMS_wwwName()
+** CONVERTS VMS Name into WWW Name
+** ON ENTRY:
+** vmsname VMS file specification (NO NODE)
+**
+** ON EXIT:
+** returns www file specification
+**
+** EXAMPLES:
+** vmsname wwwname
+** DISK$USER disk$user
+** DISK$USER: /disk$user/
+** DISK$USER:[DUNS] /disk$user/duns
+** DISK$USER:[DUNS.ECHO] /disk$user/duns/echo
+** [DUNS] duns
+** [DUNS.ECHO] duns/echo
+** [DUNS.ECHO.-.TRANS] duns/echo/../trans
+** [DUNS.ECHO.--.TRANS] duns/echo/../../trans
+** [.DUNS] duns
+** [.DUNS.ECHO] duns/echo
+** [.DUNS.ECHO]TEST.COM duns/echo/test.com
+** TEST.COM test.com
+**
+**
+*/
+PUBLIC char * HTVMS_wwwName ARGS1(
+ char *, vmsname)
+{
+static char wwwname[256];
+char *src, *dst;
+int dir;
+ dst = wwwname;
+ src = vmsname;
+ dir = 0;
+ if (strchr(src,':')) *(dst++) = '/';
+ for ( ; *src != '\0' ; src++)
+ {
+ switch(*src)
+ {
+ case ':': *(dst++) = '/'; break;
+ case '-': if (dir)
+ {
+ if ((*(src-1)=='[' || *(src-1)=='.' || *(src-1)=='-') &&
+ (*(src+1)=='.' || *(src+1)=='-'))
+ {
+ *(dst++) = '/';
+ *(dst++) = '.';
+ *(dst++) = '.';
+ }
+ else
+ *(dst++) = '-';
+ }
+ else
+ {
+ if (*(src-1) == ']') *(dst++) = '/';
+ *(dst++) = '-';
+ }
+ break;
+ case '.': if (dir)
+ {
+ if (*(src-1) != '[') *(dst++) = '/';
+ }
+ else
+ {
+ if (*(src-1) == ']') *(dst++) = '/';
+ *(dst++) = '.';
+ }
+ break;
+ case '[': dir = 1; break;
+ case ']': dir = 0; break;
+ default: if (*(src-1) == ']') *(dst++) = '/';
+ *(dst++) = *src;
+ break;
+ }
+ }
+ *(dst++) = '\0';
+ return(wwwname);
+}
+
+
+/* PUBLIC HTVMS_name()
+** CONVERTS WWW name into a VMS name
+** ON ENTRY:
+** nn Node Name (optional)
+** fn WWW file name
+**
+** ON EXIT:
+** returns vms file specification
+**
+** Bug: Returns pointer to static -- non-reentrant
+*/
+PUBLIC char * HTVMS_name ARGS2(
+ CONST char *, nn,
+ CONST char *, fn)
+{
+
+/* We try converting the filename into Files-11 syntax. That is, we assume
+** first that the file is, like us, on a VMS node. We try remote
+** (or local) DECnet access. Files-11, VMS, VAX and DECnet
+** are trademarks of Digital Equipment Corporation.
+** The node is assumed to be local if the hostname WITHOUT DOMAIN
+** matches the local one. @@@
+*/
+ static char vmsname[INFINITY]; /* returned */
+ char * filename = (char*)malloc(strlen(fn)+1);
+ char * nodename = (char*)malloc(strlen(nn)+2+1); /* Copies to hack */
+ char *second; /* 2nd slash */
+ char *last; /* last slash */
+
+ char * hostname = (char *)HTHostName();
+
+ if (!filename || !nodename) outofmem(__FILE__, "HTVMSname");
+ strcpy(filename, fn);
+ strcpy(nodename, ""); /* On same node? Yes if node names match */
+ if (strncmp(nn,"localhost",9)) {
+ char *p, *q;
+ for (p=hostname, q=(char *)nn;
+ *p && *p!='.' && *q && *q!='.'; p++, q++){
+ if (TOUPPER(*p)!=TOUPPER(*q)) {
+ strcpy(nodename, nn);
+ q = strchr(nodename, '.'); /* Mismatch */
+ if (q) *q=0; /* Chop domain */
+ strcat(nodename, "::"); /* Try decnet anyway */
+ break;
+ }
+ }
+ }
+
+ second = strchr(filename+1, '/'); /* 2nd slash */
+ last = strrchr(filename, '/'); /* last slash */
+
+ if (!second) { /* Only one slash */
+ sprintf(vmsname, "%s%s", nodename, filename + 1);
+ } else if(second==last) { /* Exactly two slashes */
+ *second = 0; /* Split filename from disk */
+ sprintf(vmsname, "%s%s:%s", nodename, filename+1, second+1);
+ *second = '/'; /* restore */
+ } else { /* More than two slashes */
+ char * p;
+ *second = 0; /* Split disk from directories */
+ *last = 0; /* Split dir from filename */
+ sprintf(vmsname, "%s%s:[%s]%s",
+ nodename, filename+1, second+1, last+1);
+ *second = *last = '/'; /* restore filename */
+ for (p=strchr(vmsname, '['); *p!=']'; p++)
+ if (*p=='/') *p='.'; /* Convert dir sep. to dots */
+ }
+ FREE(nodename);
+ FREE(filename);
+ return vmsname;
+}
+
+/*
+** The code below is for directory browsing by VMS Curses clients.
+** It is based on the newer WWWLib's HTDirBrw.c. - Foteos Macrides
+*/
+PUBLIC int HTStat ARGS2(
+ CONST char *, filename,
+ stat_t *, info)
+{
+ /*
+ the following stuff does not work in VMS with a normal stat...
+ --> /disk$user/duns/www if www is a directory
+ is statted like: /disk$user/duns/www.dir
+ after a normal stat has failed
+ --> /disk$user/duns if duns is a toplevel directory
+ is statted like: /disk$user/000000/duns.dir
+ --> /disk$user since disk$user is a device
+ is statted like: /disk$user/000000/000000.dir
+ --> /
+ searches all devices, no solution yet...
+ --> /vxcern!/disk$cr/wwwteam/login.com
+ is not statted but granted with fake information...
+ */
+int Result;
+int Len;
+char *Ptr, *Ptr2;
+char Name[256];
+
+ /* try normal stat... */
+ Result = stat((char *)filename,info);
+ if (Result == 0)
+ return(Result);
+
+ /* make local copy */
+ strcpy(Name,filename);
+
+#ifdef NOT_USED
+ /* if filename contains a node specification (! or ::), we will try to access
+ the file via DECNET, but we do not stat it..., just return success
+ with some fake information... */
+ if (HTVMS_checkDecnet(Name))
+ {
+ /* set up fake info, only the one we use... */
+ info->st_dev = NULL;
+ info->st_ino[0] = 0;
+ info->st_ino[1] = 0;
+ info->st_ino[2] = 0;
+ info->st_mode = S_IFREG | S_IREAD; /* assume it is a regular Readable file */
+ info->st_nlink = NULL;
+ info->st_uid = 0;
+ info->st_gid = 0;
+ info->st_rdev = 0;
+ info->st_size = 0;
+ info->st_atime = time(NULL);
+ info->st_mtime = time(NULL);
+ info->st_ctime = time(NULL);
+
+ return(0);
+ }
+#endif /* NOT_USED */
+
+ /* failed,so do device search in case root is requested */
+ if (!strcmp(Name,"/"))
+ { /* root requested */
+ return(-1);
+ }
+
+ /* failed so this might be a directory, add '.dir' */
+ Len = strlen(Name);
+ if (Name[Len-1] == '/')
+ Name[Len-1] = '\0';
+
+ /* fail in case of device */
+ Ptr = strchr(Name+1,'/');
+ if ((Ptr == NULL) && (Name[0] == '/'))
+ { /* device only... */
+ strcat(Name,"/000000/000000");
+ }
+
+ if (Ptr != NULL)
+ { /* correct filename in case of toplevel dir */
+ Ptr2 = strchr(Ptr+1,'/');
+ if ((Ptr2 == NULL) && (Name[0] == '/'))
+ {
+ char End[256];
+ strcpy(End,Ptr);
+ *(Ptr+1) = '\0';
+ strcat(Name,"000000");
+ strcat(Name,End);
+ }
+ }
+
+ /* try in case a file on toplevel directory or .DIR was alreadyt specified */
+ Result = stat(Name,info);
+ if (Result == 0)
+ return(Result);
+
+ /* add .DIR and try again */
+ strcat(Name,".dir");
+ Result = stat(Name,info);
+ return(Result);
+}
+
+/*** "dirent.h" ***/
+/* #include <types.h> already in tcp.h */
+
+#ifndef _POSIX_SOURCE
+#define d_ino d_fileno /* compatability */
+#ifndef NULL
+#define NULL 0
+#endif
+#endif /* !_POSIX_SOURCE */
+
+typedef struct __dirdesc {
+#if 0
+ int dd_fd; /* file descriptor */
+ long dd_loc; /* buf offset of entry from last readddir() */
+ long dd_size; /* amount of valid data in buffer */
+ long dd_bsize; /* amount of entries read at a time */
+ long dd_off; /* Current offset in dir (for telldir) */
+ char *dd_buf; /* directory data buffer */
+#endif
+ long context; /* context descriptor for LIB$FIND_FILE calls */
+ char dirname[255+1]; /* keeps the directory name, including *.* */
+ struct dsc$descriptor_s dirname_desc; /* descriptor of dirname */
+} DIR;
+
+PRIVATE DIR *HTVMSopendir(char *dirname);
+PRIVATE struct dirent *HTVMSreaddir(DIR *dirp);
+PRIVATE int HTVMSclosedir(DIR *dirp);
+#if 0
+#ifndef _POSIX_SOURCE
+extern void seekdir(/* DIR *dirp, int loc */);
+extern long telldir(/* DIR *dirp */);
+#endif /* POSIX_SOURCE */
+extern void rewinddir(/* DIR *dirp */);
+
+#ifndef lint
+#define rewinddir(dirp) seekdir((dirp), (long)0)
+#endif
+#endif /* not defined for VMS */
+
+/*** #include "sys_dirent.h" ***/
+/*** "sys_dirent.h" ***/
+struct dirent {
+#if 0
+ off_t d_off; /* offset of next disk dir entry */
+#endif
+ unsigned long d_fileno; /* file number of entry */
+#if 0
+ unsigned short d_reclen; /* length of this record */
+#endif
+ unsigned short d_namlen; /* length of string in d_name */
+ char d_name[255+1]; /* name (up to MAXNAMLEN + 1) */
+};
+
+#ifndef _POSIX_SOURCE
+/*
+ * It's unlikely to change, but make sure that sizeof d_name above is
+ * at least MAXNAMLEN + 1 (more may be added for padding).
+ */
+#define MAXNAMLEN 255
+/*
+ * The macro DIRSIZ(dp) gives the minimum amount of space required to represent
+ * a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp).
+ * Specific filesystem types may use this macro to construct the value
+ * for d_reclen.
+ */
+#undef DIRSIZ
+#define DIRSIZ(dp) \
+ (((sizeof(struct dirent) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) +3) & ~3)
+
+#endif /* !_POSIX_SOURCE */
+
+
+PRIVATE DIR *HTVMSopendir(char *dirname)
+{
+static DIR dir;
+char *closebracket;
+long status;
+struct dsc$descriptor_s entryname_desc;
+struct dsc$descriptor_s dirname_desc;
+char DirEntry[256];
+char VMSentry[256];
+char UnixEntry[256];
+int index;
+char *dot;
+
+ /* check if directory exists */
+ /* dirname can look like /disk$user/duns/www/test/multi */
+ /* or like /disk$user/duns/www/test/multi/ */
+ /* DirEntry should look like disk$user:[duns.www.test]multi in both cases */
+ /* dir.dirname should look like disk$user:[duns.www.test.multi] */
+ strcpy(UnixEntry,dirname);
+ if (UnixEntry[strlen(UnixEntry)-1] != '/')
+ strcat(UnixEntry,"/");
+
+ strcpy(DirEntry, HTVMS_name("",UnixEntry));
+ strcpy(dir.dirname, DirEntry);
+ index = strlen(DirEntry) - 1;
+
+ if (DirEntry[index] == ']')
+ DirEntry[index] = '\0';
+
+ if ((dot = strrchr(DirEntry,'.')) == NULL)
+ { /* convert disk$user:[duns] into disk$user:[000000]duns.dir */
+ char *openbr = strrchr(DirEntry,'[');
+ if (!openbr)
+ { /* convert disk$user: into disk$user:[000000]000000.dir */
+ strcpy(dir.dirname, DirEntry);
+ strcat(dir.dirname, "[000000]");
+ strcat(DirEntry,"[000000]000000.dir");
+ }
+ else
+ {
+ char End[256];
+ strcpy(End,openbr+1);
+ *(openbr+1) = '\0';
+ strcat(DirEntry,"000000]");
+ strcat(DirEntry,End);
+ strcat(DirEntry,".dir");
+ }
+ }
+ else
+ {
+ *dot = ']';
+ strcat(DirEntry,".dir");
+ }
+
+ dir.context = 0;
+ dirname_desc.dsc$w_length = strlen(DirEntry);
+ dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
+ dirname_desc.dsc$b_class = DSC$K_CLASS_S;
+ dirname_desc.dsc$a_pointer = (char *)&(DirEntry);
+
+ /* look for the directory */
+ entryname_desc.dsc$w_length = 255;
+ entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
+ entryname_desc.dsc$b_class = DSC$K_CLASS_S;
+ entryname_desc.dsc$a_pointer = VMSentry;
+
+ status = lib$find_file(&(dirname_desc),
+ &entryname_desc,
+ &(dir.context),
+ 0,0,0,0);
+ if (!(status & 0x01))
+ { /* directory not found */
+ return(NULL);
+ }
+
+#if 0
+ /* now correct dirname, which looks like disk$user:[duns.www.test]multi */
+ /* and should look like disk$user:[duns.www.test.multi] */
+ closebracket = strchr(dir.dirname,']');
+ *closebracket = '.';
+ closebracket = strstr(dir.dirname,".dir");
+ *closebracket = '\0';
+ strcat(dir.dirname,"]");
+#endif
+
+ if (HTVMSFileVersions)
+ strcat(dir.dirname,"*.*;*");
+ else
+ strcat(dir.dirname,"*.*");
+ dir.context = 0;
+ dir.dirname_desc.dsc$w_length = strlen(dir.dirname);
+ dir.dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
+ dir.dirname_desc.dsc$b_class = DSC$K_CLASS_S;
+ dir.dirname_desc.dsc$a_pointer = (char *)&(dir.dirname);
+ return(&dir);
+}
+
+PRIVATE struct dirent *HTVMSreaddir(DIR *dirp)
+{
+static struct dirent entry;
+long status;
+struct dsc$descriptor_s entryname_desc;
+char *space, *slash;
+char VMSentry[256];
+char *UnixEntry;
+
+ entryname_desc.dsc$w_length = 255;
+ entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
+ entryname_desc.dsc$b_class = DSC$K_CLASS_S;
+ entryname_desc.dsc$a_pointer = VMSentry;
+
+ status = lib$find_file(&(dirp->dirname_desc),
+ &entryname_desc,
+ &(dirp->context),
+ 0,0,0,0);
+ if (status == RMS$_NMF)
+ { /* no more files */
+ return(NULL);
+ }
+ else
+ { /* ok */
+ if (!(status & 0x01)) return(0);
+ if (HTVMSFileVersions)
+ space = strchr(VMSentry,' ');
+ else
+ space = strchr(VMSentry,';');
+ if (space)
+ *space = '\0';
+
+ /* convert to unix style... */
+ UnixEntry = HTVMS_wwwName(VMSentry);
+ slash = strrchr(UnixEntry,'/') + 1;
+ strcpy(entry.d_name,slash);
+ entry.d_namlen = strlen(entry.d_name);
+ entry.d_fileno = 1;
+ return(&entry);
+ }
+}
+
+PRIVATE int HTVMSclosedir(DIR *dirp)
+{
+long status;
+
+ status = lib$find_file_end(&(dirp->context));
+ if (!(status & 0x01)) exit(status);
+ dirp->context = 0;
+ return(0);
+}
+
+#include "HTAnchor.h"
+#include "HTParse.h"
+#include "HTBTree.h"
+#include "HTFile.h" /* For HTFileFormat() */
+#include "HTAlert.h"
+/*
+** Hypertext object building machinery.
+*/
+#include "HTML.h"
+#define PUTC(c) (*targetClass.put_character)(target, c)
+#define PUTS(s) (*targetClass.put_string)(target, s)
+#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*targetClass.end_element)(target, e, 0)
+#define FREE_TARGET (*targetClass._free)(target)
+#define ABORT_TARGET (*targetClass._free)(target)
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+
+#define STRUCT_DIRENT struct dirent
+
+PRIVATE char * months[12] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+typedef struct _VMSEntryInfo {
+ char * filename;
+ char * type;
+ char * date;
+ unsigned int size;
+ BOOLEAN display; /* show this entry? */
+} VMSEntryInfo;
+
+PRIVATE void free_VMSEntryInfo_struct_contents ARGS1(VMSEntryInfo *,entry_info)
+{
+ if (entry_info) {
+ FREE(entry_info->filename);
+ FREE(entry_info->type);
+ FREE(entry_info->date);
+ }
+ /* dont free the struct */
+}
+
+#define FILE_BY_NAME 0
+#define FILE_BY_TYPE 1
+#define FILE_BY_SIZE 2
+#define FILE_BY_DATE 3
+extern BOOLEAN HTfileSortMethod; /* specifies the method of sorting */
+
+PUBLIC int compare_VMSEntryInfo_structs ARGS2(VMSEntryInfo *,entry1,
+ VMSEntryInfo *,entry2)
+{
+ int i, status;
+ char date1[16], date2[16], time1[8], time2[8], month[4];
+
+ switch(HTfileSortMethod)
+ {
+ case FILE_BY_SIZE:
+ /* both equal or both 0 */
+ if(entry1->size == entry2->size)
+ return(strcasecomp(entry1->filename,
+ entry2->filename));
+ else
+ if(entry1->size > entry2->size)
+ return(1);
+ else
+ return(-1);
+ break;
+ case FILE_BY_TYPE:
+ if(entry1->type && entry2->type) {
+ status = strcasecomp(entry1->type, entry2->type);
+ if(status)
+ return(status);
+ /* else fall to filename comparison */
+ }
+ return (strcasecomp(entry1->filename,
+ entry2->filename));
+ break;
+ case FILE_BY_DATE:
+ if(entry1->date && entry2->date) {
+ /*
+ ** Make sure we have the correct length. - FM
+ */
+ if (strlen(entry1->date) != 12 ||
+ strlen(entry2->date) != 12) {
+ return (strcasecomp(entry1->filename,
+ entry2->filename));
+ }
+ /*
+ ** Set up for sorting in reverse
+ ** chronological order. - FM
+ */
+ if (entry1->date[7] != ' ') {
+ strcpy(date1, "9999");
+ strcpy(time1, (char *)&entry1->date[7]);
+ } else {
+ strcpy(date1, (char *)&entry1->date[8]);
+ strcpy(time1, "00:00");
+ }
+ strncpy(month, entry1->date, 3);
+ month[3] = '\0';
+ for (i = 0; i < 12; i++) {
+ if (!strcasecomp(month, months[i])) {
+ break;
+ }
+ }
+ i++;
+ sprintf(month, "%s%d", (i < 10 ? "0" : ""), i);
+ strcat(date1, month);
+ strncat(date1, (char *)&entry1->date[4], 2);
+ date1[8] = '\0';
+ if (date1[6] == ' ') {
+ date1[6] = '0';
+ }
+ strcat(date1, time1);
+ if (entry2->date[7] != ' ') {
+ strcpy(date2, "9999");
+ strcpy(time2, (char *)&entry2->date[7]);
+ } else {
+ strcpy(date2, (char *)&entry2->date[8]);
+ strcpy(time2, "00:00");
+ }
+ strncpy(month, entry2->date, 3);
+ month[3] = '\0';
+ for (i = 0; i < 12; i++) {
+ if (!strcasecomp(month, months[i])) {
+ break;
+ }
+ }
+ i++;
+ sprintf(month, "%s%d", (i < 10 ? "0" : ""), i);
+ strcat(date2, month);
+ strncat(date2, (char *)&entry2->date[4], 2);
+ date2[8] = '\0';
+ if (date2[6] == ' ') {
+ date2[6] = '0';
+ }
+ strcat(date2, time2);
+ /*
+ ** Do the comparison. - FM
+ */
+ status = strcasecomp(date2, date1);
+ if(status)
+ return(status);
+ /* else fall to filename comparison */
+ }
+ return (strcasecomp(entry1->filename,
+ entry2->filename));
+ break;
+ case FILE_BY_NAME:
+ default:
+ return (strcmp(entry1->filename,
+ entry2->filename));
+ }
+}
+
+
+/* HTVMSBrowseDir()
+**
+** This function generates a directory listing as an HTML-object
+** for local file URL's. It assumes the first two elements of
+** of the path are a device followed by a directory:
+**
+** file://localhost/device/directory[/[foo]]
+**
+** Will not accept 000000 as a directory name.
+** Will offer links to parent through the top directory, unless
+** a terminal slash was included in the calling URL.
+**
+** Returns HT_LOADED on success, HTLoadError() messages on error.
+**
+** Developed for Lynx by Foteos Macrides (macrides@sci.wfeb.edu).
+*/
+PUBLIC int HTVMSBrowseDir ARGS4(
+ CONST char *, address,
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream *, sink
+)
+{
+ HTStructured* target;
+ HTStructuredClass targetClass;
+ char *pathname = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
+ char *tail = NULL;
+ char *title = NULL;
+ char *header = NULL;
+ char *parent = NULL;
+ char *relative = NULL;
+ char *cp, *cp1;
+ int pathend, len;
+ DIR *dp;
+ struct stat file_info;
+ time_t NowTime;
+ static char ThisYear[8];
+ VMSEntryInfo *entry_info=0;
+ char string_buffer[64];
+ extern BOOLEAN no_dotfiles, show_dotfiles;
+
+ HTUnEscape(pathname);
+ CTRACE(stderr,"HTVMSBrowseDir: Browsing `%s\'\n", pathname);
+
+ /*
+ * Require at least two elements (presumably a device and directory)
+ * and disallow the device root (000000 directory). Symbolic paths
+ * (e.g., sys$help) should have been translated and expanded (e.g.,
+ * to /sys$sysroot/syshlp) before calling this routine.
+ */
+ if (((*pathname != '/') ||
+ (cp=strchr(pathname+1, '/')) == NULL ||
+ *(cp+1) == '\0' ||
+ 0==strncmp((cp+1), "000000", 6)) ||
+ (dp=HTVMSopendir(pathname)) == NULL) {
+ FREE(pathname);
+ return HTLoadError(sink, 403, "Could not access directory.");
+ }
+
+ /*
+ * Set up the output stream.
+ */
+ _HTProgress ("Building directory listing...");
+ if (UCLYhndl_HTFile_for_unspec >= 0) {
+ HTAnchor_setUCInfoStage(anchor,
+ UCLYhndl_HTFile_for_unspec,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT);
+ }
+ target = HTML_new(anchor, format_out, sink);
+ targetClass = *(target->isa);
+
+ /*
+ * Set up the offset string of the anchor reference,
+ * and strings for the title and header.
+ */
+ cp = strrchr(pathname, '/'); /* find lastslash */
+ StrAllocCopy(tail, (cp+1)); /* take slash off the beginning */
+ if (*tail != '\0') {
+ StrAllocCopy(title, tail);
+ *cp = '\0';
+ if ((cp1=strrchr(pathname, '/')) != NULL &&
+ cp1 != pathname &&
+ strncmp((cp1+1), "000000", 6))
+ StrAllocCopy(parent, (cp1+1));
+ *cp = '/';
+ } else {
+ pathname[strlen(pathname)-1] = '\0';
+ cp = strrchr(pathname, '/');
+ StrAllocCopy(title, (cp+1));
+ pathname[strlen(pathname)] = '/';
+ }
+ StrAllocCopy(header, pathname);
+
+ /*
+ * Initialize path name for HTStat().
+ */
+ pathend = strlen(pathname);
+ if (*(pathname+pathend-1) != '/') {
+ StrAllocCat(pathname, "/");
+ pathend++;
+ }
+
+ /*
+ * Output the title and header.
+ */
+ START(HTML_HTML);
+ PUTS("\n");
+ START(HTML_HEAD);
+ PUTS("\n");
+ HTUnEscape(title);
+ START(HTML_TITLE);
+ PUTS(title);
+ PUTS(" directory");
+ END(HTML_TITLE);
+ PUTS("\n");
+ FREE(title);
+ END(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_BODY);
+ PUTS("\n");
+ HTUnEscape(header);
+ START(HTML_H1);
+ PUTS(header);
+ END(HTML_H1);
+ PUTS("\n");
+ if (HTDirReadme == HT_DIR_README_TOP) {
+ FILE * fp;
+ if (header[strlen(header)-1] != '/')
+ StrAllocCat(header, "/");
+ StrAllocCat(header, HT_DIR_README_FILE);
+ if ((fp = fopen(header, "r")) != NULL) {
+ START(HTML_PRE);
+ for(;;) {
+ char c = fgetc(fp);
+ if (c == (char)EOF)
+ break;
+#ifdef NOTDEFINED
+ switch (c) {
+ case '&':
+ case '<':
+ case '>':
+ PUTC('&');
+ PUTC('#');
+ PUTC((char)(c / 10));
+ PUTC((char) (c % 10));
+ PUTC(';');
+ break;
+ default:
+ PUTC(c);
+ }
+#else
+ PUTC(c);
+#endif /* NOTDEFINED */
+ }
+ END(HTML_PRE);
+ fclose(fp);
+ }
+ }
+ FREE(header);
+ if (parent) {
+ relative = (char*) malloc(strlen(tail) + 4);
+ if (relative == NULL)
+ outofmem(__FILE__, "HTVMSBrowseDir");
+ sprintf(relative, "%s/..", tail);
+ HTStartAnchor(target, "", relative);
+ PUTS("Up to ");
+ HTUnEscape(parent);
+ PUTS(parent);
+ END(HTML_A);
+ START(HTML_P);
+ PUTS("\n");
+ FREE(relative);
+ FREE(parent);
+ }
+
+ /*
+ * Set up the date comparison.
+ */
+ NowTime = time(NULL);
+ strcpy(ThisYear, (char *)ctime(&NowTime)+20);
+ ThisYear[4] = '\0';
+
+ /*
+ * Now, generate the Btree and put it out to the output stream.
+ */
+ {
+ char dottest = 2; /* To avoid two strcmp() each time */
+ STRUCT_DIRENT *dirbuf;
+ HTBTree *bt;
+
+ /* Set up sort key and initialize BTree */
+ bt = HTBTree_new((HTComparer) compare_VMSEntryInfo_structs);
+
+ /* Build tree */
+ while ((dirbuf = HTVMSreaddir(dp))) {
+ HTAtom *encoding = NULL;
+ HTFormat format;
+
+ /* Skip if not used */
+ if (!dirbuf->d_ino) {
+ continue;
+ }
+
+ /* Current and parent directories are never shown in list */
+ if (dottest && (!strcmp(dirbuf->d_name, ".") ||
+ !strcmp(dirbuf->d_name, ".."))) {
+ dottest--;
+ continue;
+ }
+
+ /* Don't show the selective enabling file
+ * unless version numbers are included */
+ if (!strcasecomp(dirbuf->d_name, HT_DIR_ENABLE_FILE)) {
+ continue;
+ }
+
+ /* Skip files beginning with a dot? */
+ if ((no_dotfiles || !show_dotfiles) && *dirbuf->d_name == '.') {
+ continue;
+ }
+
+ /* OK, make an lstat() and get a key ready. */
+ *(pathname+pathend) = '\0';
+ StrAllocCat(pathname, dirbuf->d_name);
+ if (HTStat(pathname, &file_info)) {
+ /* for VMS the failure here means the file is not readable...
+ we however continue to browse through the directory... */
+ continue;
+ }
+ entry_info = (VMSEntryInfo *)malloc(sizeof(VMSEntryInfo));
+ if (entry_info == NULL)
+ outofmem(__FILE__, "HTVMSBrowseDir");
+ entry_info->type = 0;
+ entry_info->size = 0;
+ entry_info->date = 0;
+ entry_info->filename = 0;
+ entry_info->display = TRUE;
+
+ /* Get the type */
+ format = HTFileFormat(dirbuf->d_name, &encoding,
+ (CONST char **)&cp);
+ if (!cp) {
+ if(!strncmp(HTAtom_name(format), "application",11))
+ {
+ cp = HTAtom_name(format) + 12;
+ if(!strncmp(cp,"x-", 2))
+ cp += 2;
+ }
+ else
+ cp = HTAtom_name(format);
+ }
+ StrAllocCopy(entry_info->type, cp);
+
+ StrAllocCopy(entry_info->filename, dirbuf->d_name);
+ if ((file_info.st_mode & S_IFMT) == S_IFDIR) {
+ /* strip .DIR part... */
+ char *dot;
+ dot = strstr(entry_info->filename, ".DIR");
+ if (dot)
+ *dot = '\0';
+ cp = entry_info->filename;
+ while (cp && *cp) {
+ *cp = TOLOWER(*cp);
+ cp++;
+ }
+ StrAllocCopy(entry_info->type, "Directory");
+ } else {
+ if ((cp = strstr(entry_info->filename, "READ")) == NULL) {
+ cp = entry_info->filename;
+ } else {
+ cp += 4;
+ if (!strncmp(cp, "ME", 2)) {
+ cp += 2;
+ while (cp && *cp && *cp != '.') {
+ cp++;
+ }
+ } else if (!strncmp(cp, ".ME", 3)) {
+ cp = (entry_info->filename +
+ strlen(entry_info->filename));
+ } else {
+ cp = entry_info->filename;
+ }
+ }
+ while (cp && *cp) {
+ *cp = TOLOWER(*cp);
+ cp++;
+ }
+ if (((len = strlen(entry_info->filename)) > 2) &&
+ entry_info->filename[len-1] == 'z') {
+ if (entry_info->filename[len-2] == '.' ||
+ entry_info->filename[len-2] == '_')
+ entry_info->filename[len-1] = 'Z';
+ }
+ }
+
+ /* Get the date */
+ {
+ char *t = (char *)ctime((CONST time_t *)&file_info.st_ctime);
+ *(t+24) = '\0';
+
+ StrAllocCopy(entry_info->date, (t+4));
+ *((entry_info->date)+7) = '\0';
+ if ((atoi((t+19))) < atoi(ThisYear))
+ StrAllocCat(entry_info->date, (t+19));
+ else {
+ StrAllocCat(entry_info->date, (t+11));
+ *((entry_info->date)+12) = '\0';
+ }
+ }
+
+ /* Get the size */
+ if ((file_info.st_mode & S_IFMT) != S_IFDIR)
+ entry_info->size = (unsigned int)file_info.st_size;
+ else
+ entry_info->size = 0;
+
+ /* Now, update the BTree etc. */
+ if(entry_info->display)
+ {
+ CTRACE(stderr,"Adding file to BTree: %s\n",
+ entry_info->filename);
+ HTBTree_add(bt, (VMSEntryInfo *)entry_info);
+ }
+
+ } /* End while HTVMSreaddir() */
+
+ FREE(pathname);
+ HTVMSclosedir(dp);
+
+ START(HTML_PRE);
+ /*
+ * Run through the BTree printing out in order
+ */
+ {
+ HTBTElement * ele;
+ int i;
+ for (ele = HTBTree_next(bt, NULL);
+ ele != NULL;
+ ele = HTBTree_next(bt, ele))
+ {
+ entry_info = (VMSEntryInfo *)HTBTree_object(ele);
+
+ /* Output the date */
+ if(entry_info->date)
+ {
+ PUTS(entry_info->date);
+ PUTS(" ");
+ }
+ else
+ PUTS(" * ");
+
+ /* Output the type */
+ if(entry_info->type)
+ {
+ for(i = 0; entry_info->type[i] != '\0' && i < 15; i++)
+ PUTC(entry_info->type[i]);
+ for(; i < 17; i++)
+ PUTC(' ');
+
+ }
+
+ /* Output the link for the name */
+ HTDirEntry(target, tail, entry_info->filename);
+ PUTS(entry_info->filename);
+ END(HTML_A);
+
+ /* Output the size */
+ if(entry_info->size)
+ {
+ if(entry_info->size < 1024)
+ sprintf(string_buffer," %d bytes",
+ entry_info->size);
+ else
+ sprintf(string_buffer," %dKb",
+ entry_info->size/1024);
+ PUTS(string_buffer);
+ }
+
+ PUTC('\n'); /* end of this entry */
+
+ free_VMSEntryInfo_struct_contents(entry_info);
+ }
+ }
+
+ HTBTreeAndObject_free(bt);
+
+ } /* End of both BTree loops */
+
+ /*
+ * Complete the output stream.
+ */
+ END(HTML_PRE);
+ PUTS("\n");
+ END(HTML_BODY);
+ PUTS("\n");
+ END(HTML_HTML);
+ PUTS("\n");
+ FREE(tail);
+ FREE_TARGET;
+
+ return HT_LOADED;
+
+} /* End of directory reading section */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.h
new file mode 100644
index 00000000000..e055d6724c6
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMSUtils.h
@@ -0,0 +1,116 @@
+/* VMS specific routines
+
+ */
+
+#ifndef HTVMSUTIL_H
+#define HTVMSUTIL_H
+
+#include <stat.h>
+
+extern BOOL HTVMSFileVersions; /* Include version numbers in listing? */
+
+/* PUBLIC HTVMS_authSysPrv()
+** CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+** returns YES if SYSPRV is authorized
+*/
+PUBLIC BOOL HTVMS_authSysPrv NOPARAMS;
+
+
+/* PUBLIC HTVMS_enableSysPrv()
+** ENABLES SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+**
+*/
+PUBLIC void HTVMS_enableSysPrv NOPARAMS;
+
+
+/* PUBLIC HTVMS_disableSysPrv()
+** DISABLES SYSPRV
+** ON ENTRY:
+** No arguments.
+**
+** ON EXIT:
+**
+*/
+PUBLIC void HTVMS_disableSysPrv NOPARAMS;
+
+/* PUBLIC HTVMS_checkAccess()
+** CHECKS ACCESS TO FILE FOR CERTAIN USER
+** ON ENTRY:
+** FileName The file to be accessed
+** UserName Name of the user to check access for
+**
+** ON EXIT:
+** returns YES if access is allowed
+**
+*/
+PUBLIC BOOL HTVMS_checkAccess PARAMS((
+ CONST char * FileName,
+ CONST char * UserName,
+ CONST char * Method));
+
+
+/* PUBLIC HTVMS_wwwName()
+** CONVERTS VMS Name into WWW Name
+** ON ENTRY:
+** vmsname VMS file specification (NO NODE)
+**
+** ON EXIT:
+** returns www file specification
+**
+** EXAMPLES:
+** vmsname wwwname
+** DISK$USER disk$user
+** DISK$USER: /disk$user/
+** DISK$USER:[DUNS] /disk$user/duns
+** DISK$USER:[DUNS.ECHO] /disk$user/duns/echo
+** [DUNS] duns
+** [DUNS.ECHO] duns/echo
+** [DUNS.ECHO.-.TRANS] duns/echo/../trans
+** [DUNS.ECHO.--.TRANS] duns/echo/../../trans
+** [.DUNS] duns
+** [.DUNS.ECHO] duns/echo
+** [.DUNS.ECHO]TEST.COM duns/echo/test.com
+** TEST.COM test.com
+**
+**
+*/
+PUBLIC char * HTVMS_wwwName PARAMS((
+ char * vmsname));
+
+/* PUBLIC HTVMS_name()
+** CONVERTS WWW name into a VMS name
+** ON ENTRY:
+** nn Node Name (optional)
+** fn WWW file name
+**
+** ON EXIT:
+** returns vms file specification
+**
+** Bug: Returns pointer to static -- non-reentrant
+*/
+PUBLIC char * HTVMS_name PARAMS((
+ CONST char * nn,
+ CONST char * fn));
+
+PUBLIC int HTStat PARAMS((
+ CONST char * filename,
+ stat_t * info));
+
+PUBLIC int HTVMSBrowseDir PARAMS((
+ CONST char * address,
+ HTParentAnchor * anchor,
+ HTFormat format_out,
+ HTStream * sink));
+
+#endif /* not HTVMSUTIL_H */
+/*
+
+ End of file HTVMSUtil.h. */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.c
new file mode 100644
index 00000000000..ee3a51c0e14
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.c
@@ -0,0 +1,2501 @@
+/* HTVMS_WAISProt.c
+**
+** Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
+**
+** 31-May-1994 FM Initial version.
+**
+**----------------------------------------------------------------------*/
+
+/*
+** Routines originally from WProt.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 3.30.90 Harry Morris
+ - removed chunk code from WAISSearchAPDU,
+ - added makeWAISQueryType1Query() and readWAISType1Query() which replace
+ makeWAISQueryTerms() and makeWAISQueryDocs().
+ 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
+ - renamed makeWAISType1Query() to makeWAISTextQuery()
+ renamed readWAISType1Query() to readWAISTextQuery()
+ 5.29.90 TS - fixed bug in makeWAISQueryDocs
+ added CSTFreeWAISFoo functions
+*/
+
+#define _C_WAIS_protocol_
+
+/* This file implements the Z39.50 extensions required for WAIS
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTVMS_WaisUI.h"
+#include "HTVMS_WaisProt.h"
+
+#include "LYLeaks.h"
+
+
+/* very rough estimates of the size of an object */
+#define DefWAISInitResponseSize (size_t)200
+#define DefWAISSearchSize (size_t)3000
+#define DefWAISSearchResponseSize (size_t)6000
+#define DefWAISPresentSize (size_t)1000
+#define DefWAISPresentResponseSize (size_t)6000
+#define DefWAISDocHeaderSize (size_t)500
+#define DefWAISShortHeaderSize (size_t)200
+#define DefWAISLongHeaderSize (size_t)800
+#define DefWAISDocTextSize (size_t)6000
+#define DefWAISDocHeadlineSize (size_t)500
+#define DefWAISDocCodeSize (size_t)500
+
+#define RESERVE_SPACE_FOR_WAIS_HEADER(len) \
+ if (*len > 0) \
+ *len -= header_len;
+
+/*----------------------------------------------------------------------*/
+
+static unsigned long userInfoTagSize _AP((data_tag tag,
+ unsigned long length));
+
+static unsigned long
+userInfoTagSize(tag,length)
+data_tag tag;
+unsigned long length;
+/* return the number of bytes required to write the user info tag and
+ length
+ */
+{
+ unsigned long size;
+
+ /* calculate bytes required to represent tag. max tag is 16K */
+ size = writtenCompressedIntSize(tag);
+ size += writtenCompressedIntSize(length);
+
+ return(size);
+}
+
+/*----------------------------------------------------------------------*/
+
+static char* writeUserInfoHeader _AP((data_tag tag,long infoSize,
+ long estHeaderSize,char* buffer,
+ long* len));
+
+static char*
+writeUserInfoHeader(tag,infoSize,estHeaderSize,buffer,len)
+data_tag tag;
+long infoSize;
+long estHeaderSize;
+char* buffer;
+long* len;
+/* write the tag and size, making sure the info fits. return the true end
+ of the info (after adjustment) note that the argument infoSize includes
+ estHeaderSize. Note that the argument len is the number of bytes remaining
+ in the buffer. Since we write the tag and size at the begining of the
+ buffer (in space that we reserved) we don't want to pass len the calls which
+ do that writing.
+ */
+{
+ long dummyLen = 100; /* plenty of space for a tag and size */
+ char* buf = buffer;
+ long realSize = infoSize - estHeaderSize;
+ long realHeaderSize = userInfoTagSize(tag,realSize);
+
+ if (buffer == NULL || *len == 0)
+ return(NULL);
+
+ /* write the tag */
+ buf = writeTag(tag,buf,&dummyLen);
+
+ /* see if the if the header size was correct. if not,
+ we have to shift the info to fit the real header size */
+ if (estHeaderSize != realHeaderSize)
+ { /* make sure there is enough space */
+ CHECK_FOR_SPACE_LEFT(realHeaderSize - estHeaderSize,len);
+ memmove(buffer + realHeaderSize,buffer + estHeaderSize,(size_t)(realSize));
+ }
+
+ /* write the size */
+ writeCompressedInteger(realSize,buf,&dummyLen);
+
+ /* return the true end of buffer */
+ return(buffer + realHeaderSize + realSize);
+}
+
+/*----------------------------------------------------------------------*/
+
+static char* readUserInfoHeader _AP((data_tag* tag,unsigned long* num,
+ char* buffer));
+
+static char*
+readUserInfoHeader(tag,num,buffer)
+data_tag* tag;
+unsigned long* num;
+char* buffer;
+/* read the tag and size */
+{
+ char* buf = buffer;
+ buf = readTag(tag,buf);
+ buf = readCompressedInteger(num,buf);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISInitResponse*
+makeWAISInitResponse(chunkCode,
+ chunkIDLen,
+ chunkMarker,
+ highlightMarker,
+ deHighlightMarker,
+ newLineChars)
+long chunkCode;
+long chunkIDLen;
+char* chunkMarker;
+char* highlightMarker;
+char* deHighlightMarker;
+char* newLineChars;
+/* create a WAIS init response object */
+{
+ WAISInitResponse* init = (WAISInitResponse*)s_malloc((size_t)sizeof(WAISInitResponse));
+
+ init->ChunkCode = chunkCode; /* note: none are copied! */
+ init->ChunkIDLength = chunkIDLen;
+ init->ChunkMarker = chunkMarker;
+ init->HighlightMarker = highlightMarker;
+ init->DeHighlightMarker = deHighlightMarker;
+ init->NewlineCharacters = newLineChars;
+
+ return(init);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISInitResponse(init)
+WAISInitResponse* init;
+/* free an object made with makeWAISInitResponse */
+{
+ s_free(init->ChunkMarker);
+ s_free(init->HighlightMarker);
+ s_free(init->DeHighlightMarker);
+ s_free(init->NewlineCharacters);
+ s_free(init);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeInitResponseInfo(init,buffer,len)
+InitResponseAPDU* init;
+char* buffer;
+long* len;
+/* write an init response object */
+{
+ unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
+ DefWAISInitResponseSize);
+ char* buf = buffer + header_len;
+ WAISInitResponse* info = (WAISInitResponse*)init->UserInformationField;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeNum(info->ChunkCode,DT_ChunkCode,buf,len);
+ buf = writeNum(info->ChunkIDLength,DT_ChunkIDLength,buf,len);
+ buf = writeString(info->ChunkMarker,DT_ChunkMarker,buf,len);
+ buf = writeString(info->HighlightMarker,DT_HighlightMarker,buf,len);
+ buf = writeString(info->DeHighlightMarker,DT_DeHighlightMarker,buf,len);
+ buf = writeString(info->NewlineCharacters,DT_NewlineCharacters,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readInitResponseInfo(info,buffer)
+void** info;
+char* buffer;
+/* read an init response object */
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ long chunkCode,chunkIDLen;
+ char* chunkMarker = NULL;
+ char* highlightMarker = NULL;
+ char* deHighlightMarker = NULL;
+ char* newLineChars = NULL;
+
+ chunkCode = chunkIDLen = UNUSED;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_ChunkCode:
+ buf = readNum(&chunkCode,buf);
+ break;
+ case DT_ChunkIDLength:
+ buf = readNum(&chunkIDLen,buf);
+ break;
+ case DT_ChunkMarker:
+ buf = readString(&chunkMarker,buf);
+ break;
+ case DT_HighlightMarker:
+ buf = readString(&highlightMarker,buf);
+ break;
+ case DT_DeHighlightMarker:
+ buf = readString(&deHighlightMarker,buf);
+ break;
+ case DT_NewlineCharacters:
+ buf = readString(&newLineChars,buf);
+ break;
+ default:
+ s_free(highlightMarker);
+ s_free(deHighlightMarker);
+ s_free(newLineChars);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *info = (void *)makeWAISInitResponse(chunkCode,chunkIDLen,chunkMarker,
+ highlightMarker,deHighlightMarker,
+ newLineChars);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISSearch*
+makeWAISSearch(seedWords,
+ docs,
+ textList,
+ dateFactor,
+ beginDateRange,
+ endDateRange,
+ maxDocsRetrieved)
+char* seedWords;
+DocObj** docs;
+char** textList;
+long dateFactor;
+char* beginDateRange;
+char* endDateRange;
+long maxDocsRetrieved;
+
+/* create a type 3 query object */
+{
+ WAISSearch* query = (WAISSearch*)s_malloc((size_t)sizeof(WAISSearch));
+
+ query->SeedWords = seedWords; /* not copied! */
+ query->Docs = docs; /* not copied! */
+ query->TextList = textList; /* not copied! */
+ query->DateFactor = dateFactor;
+ query->BeginDateRange = beginDateRange;
+ query->EndDateRange = endDateRange;
+ query->MaxDocumentsRetrieved = maxDocsRetrieved;
+
+ return(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISSearch(query)
+WAISSearch* query;
+
+/* destroy an object made with makeWAISSearch() */
+{
+ void* ptr = NULL;
+ long i;
+
+ s_free(query->SeedWords);
+
+ if (query->Docs != NULL)
+ for (i = 0,ptr = (void *)query->Docs[i]; ptr != NULL; ptr = (void *)query->Docs[++i])
+ freeDocObj((DocObj*)ptr);
+ s_free(query->Docs);
+
+ if (query->TextList != NULL) /* XXX revisit when textlist is fully defined */
+ for (i = 0,ptr = (void *)query->TextList[i]; ptr != NULL; ptr = (void *)query->TextList[++i])
+ s_free(ptr);
+ s_free(query->TextList);
+
+ s_free(query->BeginDateRange);
+ s_free(query->EndDateRange);
+ s_free(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+DocObj*
+makeDocObjUsingWholeDocument(docID,type)
+any* docID;
+char* type;
+
+/* construct a document object using byte chunks - only for use by
+ servers */
+{
+ DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
+ doc->DocumentID = docID; /* not copied! */
+ doc->Type = type; /* not copied! */
+ doc->ChunkCode = CT_document;
+ return(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+DocObj*
+makeDocObjUsingLines(docID,type,start,end)
+any* docID;
+char* type;
+long start;
+long end;
+
+/* construct a document object using line chunks - only for use by
+ servers */
+{
+ DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
+ doc->ChunkCode = CT_line;
+ doc->DocumentID = docID; /* not copied */
+ doc->Type = type; /* not copied! */
+ doc->ChunkStart.Pos = start;
+ doc->ChunkEnd.Pos = end;
+ return(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+DocObj*
+makeDocObjUsingBytes(docID,type,start,end)
+any* docID;
+char* type;
+long start;
+long end;
+
+/* construct a document object using byte chunks - only for use by
+ servers */
+{
+ DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
+ doc->ChunkCode = CT_byte;
+ doc->DocumentID = docID; /* not copied */
+ doc->Type = type; /* not copied! */
+ doc->ChunkStart.Pos = start;
+ doc->ChunkEnd.Pos = end;
+ return(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+DocObj*
+makeDocObjUsingParagraphs(docID,type,start,end)
+any* docID;
+char* type;
+any* start;
+any* end;
+
+/* construct a document object using byte chunks - only for use by
+ servers */
+{
+ DocObj* doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
+ doc->ChunkCode = CT_paragraph;
+ doc->DocumentID = docID; /* not copied */
+ doc->Type = type;
+ doc->ChunkStart.ID = start;
+ doc->ChunkEnd.ID = end;
+ return(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeDocObj(doc)
+DocObj* doc;
+
+/* free a docObj */
+{
+ freeAny(doc->DocumentID);
+ s_free(doc->Type);
+ if (doc->ChunkCode == CT_paragraph)
+ { freeAny(doc->ChunkStart.ID);
+ freeAny(doc->ChunkEnd.ID);
+ }
+ s_free(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+static char* writeDocObj _AP((DocObj* doc,char* buffer,long* len));
+
+static char*
+writeDocObj(doc,buffer,len)
+DocObj* doc;
+char* buffer;
+long* len;
+
+/* write as little as we can about the doc obj */
+{
+ char* buf = buffer;
+
+ /* we alwasy have to write the id, but its tag depends on if its a chunk */
+ if (doc->ChunkCode == CT_document)
+ buf = writeAny(doc->DocumentID,DT_DocumentID,buf,len);
+ else
+ buf = writeAny(doc->DocumentID,DT_DocumentIDChunk,buf,len);
+
+ if (doc->Type != NULL)
+ buf = writeString(doc->Type,DT_TYPE,buf,len);
+
+ switch (doc->ChunkCode)
+ { case CT_document:
+ /* do nothing - there is no chunk data */
+ break;
+ case CT_byte:
+ case CT_line:
+ buf = writeNum(doc->ChunkCode,DT_ChunkCode,buf,len);
+ buf = writeNum(doc->ChunkStart.Pos,DT_ChunkStartID,buf,len);
+ buf = writeNum(doc->ChunkEnd.Pos,DT_ChunkEndID,buf,len);
+ break;
+ case CT_paragraph:
+ buf = writeNum(doc->ChunkCode,DT_ChunkCode,buf,len);
+ buf = writeAny(doc->ChunkStart.ID,DT_ChunkStartID,buf,len);
+ buf = writeAny(doc->ChunkEnd.ID,DT_ChunkEndID,buf,len);
+ break;
+ default:
+ panic("Implementation error: unknown chuck type %ld",
+ doc->ChunkCode);
+ break;
+ }
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+static char* readDocObj _AP((DocObj** doc,char* buffer));
+
+static char*
+readDocObj(doc,buffer)
+DocObj** doc;
+char* buffer;
+
+/* read whatever we have about the new document */
+{
+ char* buf = buffer;
+ data_tag tag;
+
+ *doc = (DocObj*)s_malloc((size_t)sizeof(DocObj));
+
+ tag = peekTag(buf);
+ buf = readAny(&((*doc)->DocumentID),buf);
+
+ if (tag == DT_DocumentID)
+ { (*doc)->ChunkCode = CT_document;
+ tag = peekTag(buf);
+ if (tag == DT_TYPE) /* XXX depends on DT_TYPE != what comes next */
+ buf = readString(&((*doc)->Type),buf);
+ /* ChunkStart and ChunkEnd are undefined */
+ }
+ else if (tag == DT_DocumentIDChunk)
+ { boolean readParagraphs = false; /* for cleanup */
+ tag = peekTag(buf);
+ if (tag == DT_TYPE) /* XXX depends on DT_TYPE != CT_FOO */
+ buf = readString(&((*doc)->Type),buf);
+ buf = readNum(&((*doc)->ChunkCode),buf);
+ switch ((*doc)->ChunkCode)
+ { case CT_byte:
+ case CT_line:
+ buf = readNum(&((*doc)->ChunkStart.Pos),buf);
+ buf = readNum(&((*doc)->ChunkEnd.Pos),buf);
+ break;
+ case CT_paragraph:
+ readParagraphs = true;
+ buf = readAny(&((*doc)->ChunkStart.ID),buf);
+ buf = readAny(&((*doc)->ChunkEnd.ID),buf);
+ break;
+ default:
+ freeAny((*doc)->DocumentID);
+ if (readParagraphs)
+ { freeAny((*doc)->ChunkStart.ID);
+ freeAny((*doc)->ChunkEnd.ID);
+ }
+ s_free(doc);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+ else
+ { freeAny((*doc)->DocumentID);
+ s_free(*doc);
+ REPORT_READ_ERROR(buf);
+ }
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeSearchInfo(query,buffer,len)
+SearchAPDU* query;
+char* buffer;
+long* len;
+
+/* write out a WAIS query (type 1 or 3) */
+{
+ if (strcmp(query->QueryType,QT_TextRetrievalQuery) == 0)
+ { return(writeAny((any*)query->Query,DT_Query,buffer,len));
+ }
+ else
+ { unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
+ DefWAISSearchSize);
+ char* buf = buffer + header_len;
+ WAISSearch* info = (WAISSearch*)query->Query;
+ unsigned long size;
+ long i;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeString(info->SeedWords,DT_SeedWords,buf,len);
+
+ if (info->Docs != NULL)
+ { for (i = 0; info->Docs[i] != NULL; i++)
+ { buf = writeDocObj(info->Docs[i],buf,len);
+ }
+ }
+
+ /* XXX text list */
+
+ buf = writeNum(info->DateFactor,DT_DateFactor,buf,len);
+ buf = writeString(info->BeginDateRange,DT_BeginDateRange,buf,len);
+ buf = writeString(info->EndDateRange,DT_EndDateRange,buf,len);
+ buf = writeNum(info->MaxDocumentsRetrieved,DT_MaxDocumentsRetrieved,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
+
+ return(buf);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readSearchInfo(info,buffer)
+void** info;
+char* buffer;
+
+/* read a WAIS query (type 1 or 3) */
+{
+ data_tag type = peekTag(buffer);
+ if (type == DT_Query) /* this is a type 1 query */
+ { char* buf = buffer;
+ any* query = NULL;
+ buf = readAny(&query,buf);
+ *info = (void *)query;
+ return(buf);
+ }
+ else /* a type 3 query */
+ { char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ char* seedWords = NULL;
+ char* beginDateRange = NULL;
+ char* endDateRange = NULL;
+ long dateFactor,maxDocsRetrieved;
+ char** textList = NULL;
+ DocObj** docIDs = NULL;
+ DocObj* doc = NULL;
+ long docs = 0;
+ long i;
+ void* ptr = NULL;
+
+ dateFactor = maxDocsRetrieved = UNUSED;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_SeedWords:
+ buf = readString(&seedWords,buf);
+ break;
+ case DT_DocumentID:
+ case DT_DocumentIDChunk:
+ if (docIDs == NULL) /* create a new doc list */
+ { docIDs = (DocObj**)s_malloc((size_t)sizeof(DocObj*) * 2);
+ }
+ else /* grow the doc list */
+ { docIDs = (DocObj**)s_realloc((char*)docIDs,(size_t)(sizeof(DocObj*) * (docs + 2)));
+ }
+ buf = readDocObj(&doc,buf);
+ if (buf == NULL)
+ { s_free(seedWords);
+ s_free(beginDateRange);
+ s_free(endDateRange);
+ if (docIDs != NULL)
+ for (i = 0,ptr = (void *)docIDs[i]; ptr != NULL; ptr = (void *)docIDs[++i])
+ freeDocObj((DocObj*)ptr);
+ s_free(docIDs);
+ /* XXX should also free textlist when it is fully defined */
+ }
+ RETURN_ON_NULL(buf);
+ docIDs[docs++] = doc; /* put it in the list */
+ docIDs[docs] = NULL;
+ break;
+ case DT_TextList:
+ /* XXX */
+ break;
+ case DT_DateFactor:
+ buf = readNum(&dateFactor,buf);
+ break;
+ case DT_BeginDateRange:
+ buf = readString(&beginDateRange,buf);
+ break;
+ case DT_EndDateRange:
+ buf = readString(&endDateRange,buf);
+ break;
+ case DT_MaxDocumentsRetrieved:
+ buf = readNum(&maxDocsRetrieved,buf);
+ break;
+ default:
+ s_free(seedWords);
+ s_free(beginDateRange);
+ s_free(endDateRange);
+ if (docIDs != NULL)
+ for (i = 0,ptr = (void *)docIDs[i]; ptr != NULL; ptr = (void *)docIDs[++i])
+ freeDocObj((DocObj*)ptr);
+ s_free(docIDs);
+ /* XXX should also free textlist when it is fully defined */
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *info = (void *)makeWAISSearch(seedWords,docIDs,textList,
+ dateFactor,beginDateRange,endDateRange,
+ maxDocsRetrieved);
+ return(buf);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentHeader*
+makeWAISDocumentHeader(docID,
+ versionNumber,
+ score,
+ bestMatch,
+ docLen,
+ lines,
+ types,
+ source,
+ date,
+ headline,
+ originCity)
+any* docID;
+long versionNumber;
+long score;
+long bestMatch;
+long docLen;
+long lines;
+char** types;
+char* source;
+char* date;
+char* headline;
+char* originCity;
+
+/* construct a standard document header, note that no fields are copied!
+ if the application needs to save these fields, it should copy them,
+ or set the field in this object to NULL before freeing it.
+ */
+{
+ WAISDocumentHeader* header =
+ (WAISDocumentHeader*)s_malloc((size_t)sizeof(WAISDocumentHeader));
+
+ header->DocumentID = docID;
+ header->VersionNumber = versionNumber;
+ header->Score = score;
+ header->BestMatch = bestMatch;
+ header->DocumentLength = docLen;
+ header->Lines = lines;
+ header->Types = types;
+ header->Source = source;
+ header->Date = date;
+ header->Headline = headline;
+ header->OriginCity = originCity;
+
+ return(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentHeader(header)
+WAISDocumentHeader* header;
+
+{
+ freeAny(header->DocumentID);
+ doList((void**)header->Types,fs_free); /* can't use the macro here ! */
+ s_free(header->Types);
+ s_free(header->Source);
+ s_free(header->Date);
+ s_free(header->Headline);
+ s_free(header->OriginCity);
+ s_free(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentHeader(header,buffer,len)
+WAISDocumentHeader* header;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentHeaderGroup ,
+ DefWAISDocHeaderSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeNum(header->Score,DT_Score,buf,len);
+ buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
+ buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
+ buf = writeNum(header->Lines,DT_Lines,buf,len);
+ if (header->Types != NULL)
+ { long size;
+ char* ptr = NULL;
+ long i;
+ buf = writeTag(DT_TYPE_BLOCK,buf,len);
+ for (i = 0,size = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
+ { long typeSize = strlen(ptr);
+ size += writtenTagSize(DT_TYPE);
+ size += writtenCompressedIntSize(typeSize);
+ size += typeSize;
+ }
+ buf = writeCompressedInteger((unsigned long)size,buf,len);
+ for (i = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
+ buf = writeString(ptr,DT_TYPE,buf,len);
+ }
+ buf = writeString(header->Source,DT_Source,buf,len);
+ buf = writeString(header->Date,DT_Date,buf,len);
+ buf = writeString(header->Headline,DT_Headline,buf,len);
+ buf = writeString(header->OriginCity,DT_OriginCity,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentHeaderGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentHeader(header,buffer)
+WAISDocumentHeader** header;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any* docID = NULL;
+ long versionNumber,score,bestMatch,docLength,lines;
+ char** types = NULL;
+ char *source = NULL;
+ char *date = NULL;
+ char *headline = NULL;
+ char *originCity = NULL;
+
+ versionNumber = score = bestMatch = docLength = lines = UNUSED;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_Score:
+ buf = readNum(&score,buf);
+ break;
+ case DT_BestMatch:
+ buf = readNum(&bestMatch,buf);
+ break;
+ case DT_DocumentLength:
+ buf = readNum(&docLength,buf);
+ break;
+ case DT_Lines:
+ buf = readNum(&lines,buf);
+ break;
+ case DT_TYPE_BLOCK:
+ { unsigned long size = -1;
+ long numTypes = 0;
+ buf = readTag(&tag,buf);
+ buf = readCompressedInteger(&size,buf);
+ while (size > 0)
+ { char* type = NULL;
+ char* originalBuf = buf;
+ buf = readString(&type,buf);
+ types = (char**)s_realloc(types,(size_t)(sizeof(char*) * (numTypes + 2)));
+ types[numTypes++] = type;
+ types[numTypes] = NULL;
+ size -= (buf - originalBuf);
+ }
+ }
+ case DT_Source:
+ buf = readString(&source,buf);
+ break;
+ case DT_Date:
+ buf = readString(&date,buf);
+ break;
+ case DT_Headline:
+ buf = readString(&headline,buf);
+ break;
+ case DT_OriginCity:
+ buf = readString(&originCity,buf);
+ break;
+ default:
+ freeAny(docID);
+ s_free(source);
+ s_free(date);
+ s_free(headline);
+ s_free(originCity);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *header = makeWAISDocumentHeader(docID,versionNumber,score,bestMatch,
+ docLength,lines,types,source,date,headline,
+ originCity);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentShortHeader*
+makeWAISDocumentShortHeader(docID,
+ versionNumber,
+ score,
+ bestMatch,
+ docLen,
+ lines)
+any* docID;
+long versionNumber;
+long score;
+long bestMatch;
+long docLen;
+long lines;
+/* construct a short document header, note that no fields are copied!
+ if the application needs to save these fields, it should copy them,
+ or set the field in this object to NULL before freeing it.
+ */
+{
+ WAISDocumentShortHeader* header =
+ (WAISDocumentShortHeader*)s_malloc((size_t)sizeof(WAISDocumentShortHeader));
+
+ header->DocumentID = docID;
+ header->VersionNumber = versionNumber;
+ header->Score = score;
+ header->BestMatch = bestMatch;
+ header->DocumentLength = docLen;
+ header->Lines = lines;
+
+ return(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentShortHeader(header)
+WAISDocumentShortHeader* header;
+{
+ freeAny(header->DocumentID);
+ s_free(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentShortHeader(header,buffer,len)
+WAISDocumentShortHeader* header;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentShortHeaderGroup ,
+ DefWAISShortHeaderSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeNum(header->Score,DT_Score,buf,len);
+ buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
+ buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
+ buf = writeNum(header->Lines,DT_Lines,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentShortHeaderGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentShortHeader(header,buffer)
+WAISDocumentShortHeader** header;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any* docID = NULL;
+ long versionNumber,score,bestMatch,docLength,lines;
+
+ versionNumber = score = bestMatch = docLength = lines = UNUSED;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_Score:
+ buf = readNum(&score,buf);
+ break;
+ case DT_BestMatch:
+ buf = readNum(&bestMatch,buf);
+ break;
+ case DT_DocumentLength:
+ buf = readNum(&docLength,buf);
+ break;
+ case DT_Lines:
+ buf = readNum(&lines,buf);
+ break;
+ default:
+ freeAny(docID);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *header = makeWAISDocumentShortHeader(docID,versionNumber,score,bestMatch,
+ docLength,lines);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentLongHeader*
+makeWAISDocumentLongHeader(docID,
+ versionNumber,
+ score,
+ bestMatch,
+ docLen,
+ lines,
+ types,
+ source,
+ date,
+ headline,
+ originCity,
+ stockCodes,
+ companyCodes,
+ industryCodes)
+any* docID;
+long versionNumber;
+long score;
+long bestMatch;
+long docLen;
+long lines;
+char** types;
+char* source;
+char* date;
+char* headline;
+char* originCity;
+char* stockCodes;
+char* companyCodes;
+char* industryCodes;
+/* construct a long document header, note that no fields are copied!
+ if the application needs to save these fields, it should copy them,
+ or set the field in this object to NULL before freeing it.
+ */
+{
+ WAISDocumentLongHeader* header =
+ (WAISDocumentLongHeader*)s_malloc((size_t)sizeof(WAISDocumentLongHeader));
+
+ header->DocumentID = docID;
+ header->VersionNumber = versionNumber;
+ header->Score = score;
+ header->BestMatch = bestMatch;
+ header->DocumentLength = docLen;
+ header->Lines = lines;
+ header->Types = types;
+ header->Source = source;
+ header->Date = date;
+ header->Headline = headline;
+ header->OriginCity = originCity;
+ header->StockCodes = stockCodes;
+ header->CompanyCodes = companyCodes;
+ header->IndustryCodes = industryCodes;
+
+ return(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentLongHeader(header)
+WAISDocumentLongHeader* header;
+{
+ freeAny(header->DocumentID);
+ doList((void**)header->Types,fs_free); /* can't use the macro here! */
+ s_free(header->Source);
+ s_free(header->Date);
+ s_free(header->Headline);
+ s_free(header->OriginCity);
+ s_free(header->StockCodes);
+ s_free(header->CompanyCodes);
+ s_free(header->IndustryCodes);
+ s_free(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentLongHeader(header,buffer,len)
+WAISDocumentLongHeader* header;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentLongHeaderGroup ,
+ DefWAISLongHeaderSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(header->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(header->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeNum(header->Score,DT_Score,buf,len);
+ buf = writeNum(header->BestMatch,DT_BestMatch,buf,len);
+ buf = writeNum(header->DocumentLength,DT_DocumentLength,buf,len);
+ buf = writeNum(header->Lines,DT_Lines,buf,len);
+ if (header->Types != NULL)
+ { long size;
+ char* ptr = NULL;
+ long i;
+ buf = writeTag(DT_TYPE_BLOCK,buf,len);
+ for (i = 0,size = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
+ { long typeSize = strlen(ptr);
+ size += writtenTagSize(DT_TYPE);
+ size += writtenCompressedIntSize(typeSize);
+ size += typeSize;
+ }
+ buf = writeCompressedInteger((unsigned long)size,buf,len);
+ for (i = 0,ptr = header->Types[i]; ptr != NULL; ptr = header->Types[++i])
+ buf = writeString(ptr,DT_TYPE,buf,len);
+ }
+ buf = writeString(header->Source,DT_Source,buf,len);
+ buf = writeString(header->Date,DT_Date,buf,len);
+ buf = writeString(header->Headline,DT_Headline,buf,len);
+ buf = writeString(header->OriginCity,DT_OriginCity,buf,len);
+ buf = writeString(header->StockCodes,DT_StockCodes,buf,len);
+ buf = writeString(header->CompanyCodes,DT_CompanyCodes,buf,len);
+ buf = writeString(header->IndustryCodes,DT_IndustryCodes,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentLongHeaderGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentLongHeader(header,buffer)
+WAISDocumentLongHeader** header;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any* docID;
+ long versionNumber,score,bestMatch,docLength,lines;
+ char **types;
+ char *source,*date,*headline,*originCity,*stockCodes,*companyCodes,*industryCodes;
+
+ docID = NULL;
+ versionNumber = score = bestMatch = docLength = lines = UNUSED;
+ types = NULL;
+ source = date = headline = originCity = stockCodes = companyCodes = industryCodes = NULL;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_Score:
+ buf = readNum(&score,buf);
+ break;
+ case DT_BestMatch:
+ buf = readNum(&bestMatch,buf);
+ break;
+ case DT_DocumentLength:
+ buf = readNum(&docLength,buf);
+ break;
+ case DT_Lines:
+ buf = readNum(&lines,buf);
+ break;
+ case DT_TYPE_BLOCK:
+ { unsigned long size = -1;
+ long numTypes = 0;
+ buf = readTag(&tag,buf);
+ readCompressedInteger(&size,buf);
+ while (size > 0)
+ { char* type = NULL;
+ char* originalBuf = buf;
+ buf = readString(&type,buf);
+ types = (char**)s_realloc(types,(size_t)(sizeof(char*) * (numTypes + 2)));
+ types[numTypes++] = type;
+ types[numTypes] = NULL;
+ size -= (buf - originalBuf);
+ }
+ }
+ case DT_Source:
+ buf = readString(&source,buf);
+ break;
+ case DT_Date:
+ buf = readString(&date,buf);
+ break;
+ case DT_Headline:
+ buf = readString(&headline,buf);
+ break;
+ case DT_OriginCity:
+ buf = readString(&originCity,buf);
+ break;
+ case DT_StockCodes:
+ buf = readString(&stockCodes,buf);
+ break;
+ case DT_CompanyCodes:
+ buf = readString(&companyCodes,buf);
+ break;
+ case DT_IndustryCodes:
+ buf = readString(&industryCodes,buf);
+ break;
+ default:
+ freeAny(docID);
+ s_free(source);
+ s_free(date);
+ s_free(headline);
+ s_free(originCity);
+ s_free(stockCodes);
+ s_free(companyCodes);
+ s_free(industryCodes);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *header = makeWAISDocumentLongHeader(docID,versionNumber,score,bestMatch,
+ docLength,lines,types,source,date,headline,
+ originCity,stockCodes,companyCodes,
+ industryCodes);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISSearchResponse*
+makeWAISSearchResponse(seedWordsUsed,
+ docHeaders,
+ shortHeaders,
+ longHeaders,
+ text,
+ headlines,
+ codes,
+ diagnostics)
+char* seedWordsUsed;
+WAISDocumentHeader** docHeaders;
+WAISDocumentShortHeader** shortHeaders;
+WAISDocumentLongHeader** longHeaders;
+WAISDocumentText** text;
+WAISDocumentHeadlines** headlines;
+WAISDocumentCodes** codes;
+diagnosticRecord** diagnostics;
+{
+ WAISSearchResponse* response = (WAISSearchResponse*)s_malloc((size_t)sizeof(WAISSearchResponse));
+
+ response->SeedWordsUsed = seedWordsUsed;
+ response->DocHeaders = docHeaders;
+ response->ShortHeaders = shortHeaders;
+ response->LongHeaders = longHeaders;
+ response->Text = text;
+ response->Headlines = headlines;
+ response->Codes = codes;
+ response->Diagnostics = diagnostics;
+
+ return(response);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISSearchResponse(response)
+WAISSearchResponse* response;
+{
+ void* ptr = NULL;
+ long i;
+
+ s_free(response->SeedWordsUsed);
+
+ if (response->DocHeaders != NULL)
+ for (i = 0,ptr = (void *)response->DocHeaders[i]; ptr != NULL; ptr = (void *)response->DocHeaders[++i])
+ freeWAISDocumentHeader((WAISDocumentHeader*)ptr);
+ s_free(response->DocHeaders);
+
+ if (response->ShortHeaders != NULL)
+ for (i = 0,ptr = (void *)response->ShortHeaders[i]; ptr != NULL; ptr = (void *)response->ShortHeaders[++i])
+ freeWAISDocumentShortHeader((WAISDocumentShortHeader*)ptr);
+ s_free(response->ShortHeaders);
+
+ if (response->LongHeaders != NULL)
+ for (i = 0,ptr = (void *)response->LongHeaders[i]; ptr != NULL; ptr = (void *)response->LongHeaders[++i])
+ freeWAISDocumentLongHeader((WAISDocumentLongHeader*)ptr);
+ s_free(response->LongHeaders);
+
+ if (response->Text != NULL)
+ for (i = 0,ptr = (void *)response->Text[i]; ptr != NULL; ptr = (void *)response->Text[++i])
+ freeWAISDocumentText((WAISDocumentText*)ptr);
+ s_free(response->Text);
+
+ if (response->Headlines != NULL)
+ for (i = 0,ptr = (void *)response->Headlines[i]; ptr != NULL; ptr = (void *)response->Headlines[++i])
+ freeWAISDocumentHeadlines((WAISDocumentHeadlines*)ptr);
+ s_free(response->Headlines);
+
+ if (response->Codes != NULL)
+ for (i = 0,ptr = (void *)response->Codes[i]; ptr != NULL; ptr = (void *)response->Codes[++i])
+ freeWAISDocumentCodes((WAISDocumentCodes*)ptr);
+ s_free(response->Codes);
+
+ if (response->Diagnostics != NULL)
+ for (i = 0,ptr = (void *)response->Diagnostics[i]; ptr != NULL; ptr = (void *)response->Diagnostics[++i])
+ freeDiag((diagnosticRecord*)ptr);
+ s_free(response->Diagnostics);
+
+ s_free(response);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeSearchResponseInfo(query,buffer,len)
+SearchResponseAPDU* query;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_UserInformationLength,
+ DefWAISSearchResponseSize);
+ char* buf = buffer + header_len;
+ WAISSearchResponse* info = (WAISSearchResponse*)query->DatabaseDiagnosticRecords;
+ unsigned long size;
+ void* header = NULL;
+ long i;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeString(info->SeedWordsUsed,DT_SeedWordsUsed,buf,len);
+
+ /* write out all the headers */
+ if (info->DocHeaders != NULL)
+ { for (i = 0,header = (void *)info->DocHeaders[i]; header != NULL; header = (void *)info->DocHeaders[++i])
+ buf = writeWAISDocumentHeader((WAISDocumentHeader*)header,buf,len);
+ }
+
+ if (info->ShortHeaders != NULL)
+ { for (i = 0,header = (void *)info->ShortHeaders[i]; header != NULL; header = (void *)info->ShortHeaders[++i])
+ buf = writeWAISDocumentShortHeader((WAISDocumentShortHeader*)header,buf,len);
+ }
+
+ if (info->LongHeaders != NULL)
+ { for (i = 0,header = (void *)info->LongHeaders[i]; header != NULL; header = (void *)info->LongHeaders[++i])
+ buf = writeWAISDocumentLongHeader((WAISDocumentLongHeader*)header,buf,len);
+ }
+
+ if (info->Text != NULL)
+ { for (i = 0,header = (void *)info->Text[i]; header != NULL; header = (void *)info->Text[++i])
+ buf = writeWAISDocumentText((WAISDocumentText*)header,buf,len);
+ }
+
+ if (info->Headlines != NULL)
+ { for (i = 0,header = (void *)info->Headlines[i]; header != NULL; header = (void *)info->Headlines[++i])
+ buf = writeWAISDocumentHeadlines((WAISDocumentHeadlines*)header,buf,len);
+ }
+
+ if (info->Codes != NULL)
+ { for (i = 0,header = (void *)info->Codes[i]; header != NULL;header = (void *)info->Codes[++i])
+ buf = writeWAISDocumentCodes((WAISDocumentCodes*)header,buf,len);
+ }
+
+ if (info->Diagnostics != NULL)
+ { for (i = 0, header = (void *)info->Diagnostics[i]; header != NULL; header = (void *)info->Diagnostics[++i])
+ buf = writeDiag((diagnosticRecord*)header,buf,len);
+ }
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_UserInformationLength,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+static void
+cleanUpWaisSearchResponse _AP((char* buf,char* seedWordsUsed,
+ WAISDocumentHeader** docHeaders,
+ WAISDocumentShortHeader** shortHeaders,
+ WAISDocumentLongHeader** longHeaders,
+ WAISDocumentText** text,
+ WAISDocumentHeadlines** headlines,
+ WAISDocumentCodes** codes,
+ diagnosticRecord**diags));
+
+static void
+cleanUpWaisSearchResponse (buf,seedWordsUsed,docHeaders,shortHeaders,
+ longHeaders,text,headlines,codes,diags)
+char* buf;
+char* seedWordsUsed;
+WAISDocumentHeader** docHeaders;
+WAISDocumentShortHeader** shortHeaders;
+WAISDocumentLongHeader** longHeaders;
+WAISDocumentText** text;
+WAISDocumentHeadlines** headlines;
+WAISDocumentCodes** codes;
+diagnosticRecord** diags;
+/* if buf is NULL, we have just gotten a read error, and need to clean up
+ any state we have built. If not, then everything is going fine, and
+ we should just hang loose
+ */
+{
+ void* ptr = NULL;
+ long i;
+
+ if (buf == NULL)
+ { s_free(seedWordsUsed);
+ if (docHeaders != NULL)
+ for (i = 0,ptr = (void *)docHeaders[i]; ptr != NULL;
+ ptr = (void *)docHeaders[++i])
+ freeWAISDocumentHeader((WAISDocumentHeader*)ptr);
+ s_free(docHeaders);
+ if (shortHeaders != NULL)
+ for (i = 0,ptr = (void *)shortHeaders[i]; ptr != NULL;
+ ptr = (void *)shortHeaders[++i])
+ freeWAISDocumentShortHeader((WAISDocumentShortHeader*)ptr);
+ s_free(shortHeaders);
+ if (longHeaders != NULL)
+ for (i = 0,ptr = (void *)longHeaders[i]; ptr != NULL;
+ ptr = (void *)longHeaders[++i])
+ freeWAISDocumentLongHeader((WAISDocumentLongHeader*)ptr);
+ s_free(longHeaders);
+ if (text != NULL)
+ for (i = 0,ptr = (void *)text[i]; ptr != NULL; ptr = (void *)text[++i])
+ freeWAISDocumentText((WAISDocumentText*)ptr);
+ s_free(text);
+ if (headlines != NULL)
+ for (i = 0,ptr = (void *)headlines[i]; ptr != NULL;
+ ptr = (void *)headlines[++i])
+ freeWAISDocumentHeadlines((WAISDocumentHeadlines*)ptr);
+ s_free(headlines);
+ if (codes != NULL)
+ for (i = 0,ptr = (void *)codes[i]; ptr != NULL;
+ ptr = (void *)codes[++i])
+ freeWAISDocumentCodes((WAISDocumentCodes*)ptr);
+ s_free(codes);
+ if (diags != NULL)
+ for (i = 0,ptr = (void *)diags[i]; ptr != NULL;
+ ptr = (void *)diags[++i])
+ freeDiag((diagnosticRecord*)ptr);
+ s_free(diags);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readSearchResponseInfo(info,buffer)
+void** info;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ void* header = NULL;
+ WAISDocumentHeader** docHeaders = NULL;
+ WAISDocumentShortHeader** shortHeaders = NULL;
+ WAISDocumentLongHeader** longHeaders = NULL;
+ WAISDocumentText** text = NULL;
+ WAISDocumentHeadlines** headlines = NULL;
+ WAISDocumentCodes** codes = NULL;
+ long numDocHeaders,numLongHeaders,numShortHeaders,numText,numHeadlines;
+ long numCodes;
+ char* seedWordsUsed = NULL;
+ diagnosticRecord** diags = NULL;
+ diagnosticRecord* diag = NULL;
+ long numDiags = 0;
+
+ numDocHeaders = numLongHeaders = numShortHeaders = numText = numHeadlines = numCodes = 0;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_SeedWordsUsed:
+ buf = readString(&seedWordsUsed,buf);
+ break;
+ case DT_DatabaseDiagnosticRecords:
+ if (diags == NULL) /* create a new diag list */
+ { diags = (diagnosticRecord**)s_malloc((size_t)sizeof(diagnosticRecord*) * 2);
+ }
+ else /* grow the diag list */
+ { diags = (diagnosticRecord**)s_realloc((char*)diags,(size_t)(sizeof(diagnosticRecord*) * (numDiags + 2)));
+ }
+ buf = readDiag(&diag,buf);
+ diags[numDiags++] = diag; /* put it in the list */
+ diags[numDiags] = NULL;
+ break;
+ case DT_DocumentHeaderGroup:
+ if (docHeaders == NULL) /* create a new header list */
+ { docHeaders = (WAISDocumentHeader**)s_malloc((size_t)sizeof(WAISDocumentHeader*) * 2);
+ }
+ else /* grow the doc list */
+ { docHeaders = (WAISDocumentHeader**)s_realloc((char*)docHeaders,(size_t)(sizeof(WAISDocumentHeader*) * (numDocHeaders + 2)));
+ }
+ buf = readWAISDocumentHeader((WAISDocumentHeader**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ docHeaders[numDocHeaders++] =
+ (WAISDocumentHeader*)header; /* put it in the list */
+ docHeaders[numDocHeaders] = NULL;
+ break;
+ case DT_DocumentShortHeaderGroup:
+ if (shortHeaders == NULL) /* create a new header list */
+ { shortHeaders = (WAISDocumentShortHeader**)s_malloc((size_t)sizeof(WAISDocumentShortHeader*) * 2);
+ }
+ else /* grow the doc list */
+ { shortHeaders = (WAISDocumentShortHeader**)s_realloc((char*)shortHeaders,(size_t)(sizeof(WAISDocumentShortHeader*) * (numShortHeaders + 2)));
+ }
+ buf = readWAISDocumentShortHeader((WAISDocumentShortHeader**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ shortHeaders[numShortHeaders++] =
+ (WAISDocumentShortHeader*)header; /* put it in the list */
+ shortHeaders[numShortHeaders] = NULL;
+ break;
+ case DT_DocumentLongHeaderGroup:
+ if (longHeaders == NULL) /* create a new header list */
+ { longHeaders = (WAISDocumentLongHeader**)s_malloc((size_t)sizeof(WAISDocumentLongHeader*) * 2);
+ }
+ else /* grow the doc list */
+ { longHeaders = (WAISDocumentLongHeader**)s_realloc((char*)longHeaders,(size_t)(sizeof(WAISDocumentLongHeader*) * (numLongHeaders + 2)));
+ }
+ buf = readWAISDocumentLongHeader((WAISDocumentLongHeader**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ longHeaders[numLongHeaders++] =
+ (WAISDocumentLongHeader*)header; /* put it in the list */
+ longHeaders[numLongHeaders] = NULL;
+ break;
+ case DT_DocumentTextGroup:
+ if (text == NULL) /* create a new list */
+ { text = (WAISDocumentText**)s_malloc((size_t)sizeof(WAISDocumentText*) * 2);
+ }
+ else /* grow the list */
+ { text = (WAISDocumentText**)s_realloc((char*)text,(size_t)(sizeof(WAISDocumentText*) * (numText + 2)));
+ }
+ buf = readWAISDocumentText((WAISDocumentText**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ text[numText++] =
+ (WAISDocumentText*)header; /* put it in the list */
+ text[numText] = NULL;
+ break;
+ case DT_DocumentHeadlineGroup:
+ if (headlines == NULL) /* create a new list */
+ { headlines = (WAISDocumentHeadlines**)s_malloc((size_t)sizeof(WAISDocumentHeadlines*) * 2);
+ }
+ else /* grow the list */
+ { headlines = (WAISDocumentHeadlines**)s_realloc((char*)headlines,(size_t)(sizeof(WAISDocumentHeadlines*) * (numHeadlines + 2)));
+ }
+ buf = readWAISDocumentHeadlines((WAISDocumentHeadlines**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ headlines[numHeadlines++] =
+ (WAISDocumentHeadlines*)header; /* put it in the list */
+ headlines[numHeadlines] = NULL;
+ break;
+ case DT_DocumentCodeGroup:
+ if (codes == NULL) /* create a new list */
+ { codes = (WAISDocumentCodes**)s_malloc((size_t)sizeof(WAISDocumentCodes*) * 2);
+ }
+ else /* grow the list */
+ { codes = (WAISDocumentCodes**)s_realloc((char*)codes,(size_t)(sizeof(WAISDocumentCodes*) * (numCodes + 2)));
+ }
+ buf = readWAISDocumentCodes((WAISDocumentCodes**)&header,buf);
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ RETURN_ON_NULL(buf);
+ codes[numCodes++] =
+ (WAISDocumentCodes*)header; /* put it in the list */
+ codes[numCodes] = NULL;
+ break;
+ default:
+ cleanUpWaisSearchResponse(buf,seedWordsUsed,docHeaders,shortHeaders,longHeaders,text,headlines,codes,diags);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *info = (void *)makeWAISSearchResponse(seedWordsUsed,docHeaders,shortHeaders,
+ longHeaders,text,headlines,codes,diags);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentText*
+makeWAISDocumentText(docID,versionNumber,documentText)
+any* docID;
+long versionNumber;
+any* documentText;
+{
+ WAISDocumentText* docText = (WAISDocumentText*)s_malloc((size_t)sizeof(WAISDocumentText));
+
+ docText->DocumentID = docID;
+ docText->VersionNumber = versionNumber;
+ docText->DocumentText = documentText;
+
+ return(docText);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentText(docText)
+WAISDocumentText* docText;
+{
+ freeAny(docText->DocumentID);
+ freeAny(docText->DocumentText);
+ s_free(docText);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentText(docText,buffer,len)
+WAISDocumentText* docText;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentTextGroup,
+ DefWAISDocTextSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(docText->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(docText->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeAny(docText->DocumentText,DT_DocumentText,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentTextGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentText(docText,buffer)
+WAISDocumentText** docText;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any *docID,*documentText;
+ long versionNumber;
+
+ docID = documentText = NULL;
+ versionNumber = UNUSED;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_DocumentText:
+ buf = readAny(&documentText,buf);
+ break;
+ default:
+ freeAny(docID);
+ freeAny(documentText);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *docText = makeWAISDocumentText(docID,versionNumber,documentText);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentHeadlines*
+makeWAISDocumentHeadlines(docID,
+ versionNumber,
+ source,
+ date,
+ headline,
+ originCity)
+any* docID;
+long versionNumber;
+char* source;
+char* date;
+char* headline;
+char* originCity;
+{
+ WAISDocumentHeadlines* docHeadline =
+ (WAISDocumentHeadlines*)s_malloc((size_t)sizeof(WAISDocumentHeadlines));
+
+ docHeadline->DocumentID = docID;
+ docHeadline->VersionNumber = versionNumber;
+ docHeadline->Source = source;
+ docHeadline->Date = date;
+ docHeadline->Headline = headline;
+ docHeadline->OriginCity = originCity;
+
+ return(docHeadline);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentHeadlines(docHeadline)
+WAISDocumentHeadlines* docHeadline;
+{
+ freeAny(docHeadline->DocumentID);
+ s_free(docHeadline->Source);
+ s_free(docHeadline->Date);
+ s_free(docHeadline->Headline);
+ s_free(docHeadline->OriginCity);
+ s_free(docHeadline);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentHeadlines(docHeadline,buffer,len)
+WAISDocumentHeadlines* docHeadline;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentHeadlineGroup,
+ DefWAISDocHeadlineSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(docHeadline->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(docHeadline->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeString(docHeadline->Source,DT_Source,buf,len);
+ buf = writeString(docHeadline->Date,DT_Date,buf,len);
+ buf = writeString(docHeadline->Headline,DT_Headline,buf,len);
+ buf = writeString(docHeadline->OriginCity,DT_OriginCity,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentHeadlineGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentHeadlines(docHeadline,buffer)
+WAISDocumentHeadlines** docHeadline;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any* docID;
+ long versionNumber;
+ char *source,*date,*headline,*originCity;
+
+ docID = NULL;
+ versionNumber = UNUSED;
+ source = date = headline = originCity = NULL;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_Source:
+ buf = readString(&source,buf);
+ break;
+ case DT_Date:
+ buf = readString(&date,buf);
+ break;
+ case DT_Headline:
+ buf = readString(&headline,buf);
+ break;
+ case DT_OriginCity:
+ buf = readString(&originCity,buf);
+ break;
+ default:
+ freeAny(docID);
+ s_free(source);
+ s_free(date);
+ s_free(headline);
+ s_free(originCity);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *docHeadline = makeWAISDocumentHeadlines(docID,versionNumber,source,date,
+ headline,originCity);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+WAISDocumentCodes*
+makeWAISDocumentCodes(docID,
+ versionNumber,
+ stockCodes,
+ companyCodes,
+ industryCodes)
+any* docID;
+long versionNumber;
+char* stockCodes;
+char* companyCodes;
+char* industryCodes;
+{
+ WAISDocumentCodes* docCodes = (WAISDocumentCodes*)s_malloc((size_t)sizeof(WAISDocumentCodes));
+
+ docCodes->DocumentID = docID;
+ docCodes->VersionNumber = versionNumber;
+ docCodes->StockCodes = stockCodes;
+ docCodes->CompanyCodes = companyCodes;
+ docCodes->IndustryCodes = industryCodes;
+
+ return(docCodes);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeWAISDocumentCodes(docCodes)
+WAISDocumentCodes* docCodes;
+{
+ freeAny(docCodes->DocumentID);
+ s_free(docCodes->StockCodes);
+ s_free(docCodes->CompanyCodes);
+ s_free(docCodes->IndustryCodes);
+ s_free(docCodes);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeWAISDocumentCodes(docCodes,buffer,len)
+WAISDocumentCodes* docCodes;
+char* buffer;
+long* len;
+{
+ unsigned long header_len = userInfoTagSize(DT_DocumentCodeGroup ,
+ DefWAISDocCodeSize);
+ char* buf = buffer + header_len;
+ unsigned long size;
+
+ RESERVE_SPACE_FOR_WAIS_HEADER(len);
+
+ buf = writeAny(docCodes->DocumentID,DT_DocumentID,buf,len);
+ buf = writeNum(docCodes->VersionNumber,DT_VersionNumber,buf,len);
+ buf = writeString(docCodes->StockCodes,DT_StockCodes,buf,len);
+ buf = writeString(docCodes->CompanyCodes,DT_CompanyCodes,buf,len);
+ buf = writeString(docCodes->IndustryCodes,DT_IndustryCodes,buf,len);
+
+ /* now write the header and size */
+ size = buf - buffer;
+ buf = writeUserInfoHeader(DT_DocumentCodeGroup,size,header_len,buffer,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readWAISDocumentCodes(docCodes,buffer)
+WAISDocumentCodes** docCodes;
+char* buffer;
+{
+ char* buf = buffer;
+ unsigned long size;
+ unsigned long headerSize;
+ data_tag tag;
+ any* docID;
+ long versionNumber;
+ char *stockCodes,*companyCodes,*industryCodes;
+
+ docID = NULL;
+ versionNumber = UNUSED;
+ stockCodes = companyCodes = industryCodes = NULL;
+
+ buf = readUserInfoHeader(&tag,&size,buf);
+ headerSize = buf - buffer;
+
+ while (buf < (buffer + size + headerSize))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_DocumentID:
+ buf = readAny(&docID,buf);
+ break;
+ case DT_VersionNumber:
+ buf = readNum(&versionNumber,buf);
+ break;
+ case DT_StockCodes:
+ buf = readString(&stockCodes,buf);
+ break;
+ case DT_CompanyCodes:
+ buf = readString(&companyCodes,buf);
+ break;
+ case DT_IndustryCodes:
+ buf = readString(&industryCodes,buf);
+ break;
+ default:
+ freeAny(docID);
+ s_free(stockCodes);
+ s_free(companyCodes);
+ s_free(industryCodes);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ *docCodes = makeWAISDocumentCodes(docID,versionNumber,stockCodes,
+ companyCodes,industryCodes);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writePresentInfo(present,buffer,len)
+PresentAPDU* present;
+char* buffer;
+long* len;
+{
+ /* The WAIS protocol doesn't use present info */
+ return(buffer);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readPresentInfo(info,buffer)
+void** info;
+char* buffer;
+{
+ /* The WAIS protocol doesn't use present info */
+ *info = NULL;
+ return(buffer);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writePresentResponseInfo(response,buffer,len)
+PresentResponseAPDU* response;
+char* buffer;
+long* len;
+{
+ /* The WAIS protocol doesn't use presentResponse info */
+ return(buffer);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readPresentResponseInfo(info,buffer)
+void** info;
+char* buffer;
+{
+ /* The WAIS protocol doesn't use presentResponse info */
+ *info = NULL;
+ return(buffer);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* support for type 1 queries */
+
+/* new use values (for the chunk types) */
+#define BYTE "wb"
+#define LINE "wl"
+#define PARAGRAPH "wp"
+#define DATA_TYPE "wt"
+
+/* WAIS supports the following semantics for type 1 queries:
+
+ 1. retrieve the header/codes from a document:
+
+ System_Control_Number = docID
+ Data Type = type (optional)
+ And
+
+ 2. retrieve a fragment of the text of a document:
+
+ System_Control_Number = docID
+ Data Type = type (optional)
+ And
+ Chunk >= start
+ And
+ Chunk < end
+ And
+
+ Information from multiple documents may be requested by using
+ groups of the above joined by:
+
+ OR
+
+ ( XXX does an OR come after every group but the first, or do they
+ all come at the end? )
+
+ ( XXX return type could be in the element set)
+*/
+
+static query_term** makeWAISQueryTerms _AP((DocObj** docs));
+
+static query_term**
+makeWAISQueryTerms(docs)
+DocObj** docs;
+/* given a null terminated list of docObjs, construct the appropriate
+ query of the form given above
+ */
+{
+ query_term** terms = NULL;
+ long numTerms = 0;
+ DocObj* doc = NULL;
+ long i;
+
+ if (docs == NULL)
+ return((query_term**)NULL);
+
+ terms = (query_term**)s_malloc((size_t)(sizeof(query_term*) * 1));
+ terms[numTerms] = NULL;
+
+ /* loop through the docs making terms for them all */
+ for (i = 0,doc = docs[i]; doc != NULL; doc = docs[++i])
+ { any* type = NULL;
+
+ if (doc->Type != NULL)
+ type = stringToAny(doc->Type);
+
+ if (doc->ChunkCode == CT_document) /* a whole document */
+ { terms = (query_term**)s_realloc((char*)terms,
+ (size_t)(sizeof(query_term*) *
+ (numTerms + 3 + 1)));
+ terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
+ EQUAL,IGNORE,IGNORE,
+ IGNORE,IGNORE,doc->DocumentID);
+ if (type != NULL)
+ { terms[numTerms++] = makeAttributeTerm(DATA_TYPE,EQUAL,
+ IGNORE,IGNORE,IGNORE,
+ IGNORE,type);
+ terms[numTerms++] = makeOperatorTerm(AND);
+ }
+ terms[numTerms] = NULL;
+ }
+ else /* a document fragment */
+ { char chunk_att[ATTRIBUTE_SIZE];
+ any* startChunk = NULL;
+ any* endChunk = NULL;
+
+ terms = (query_term**)s_realloc((char*)terms,
+ (size_t)(sizeof(query_term*) *
+ (numTerms + 7 + 1)));
+
+ switch (doc->ChunkCode)
+ { case CT_byte:
+ case CT_line:
+ { char start[20],end[20];
+ (doc->ChunkCode == CT_byte) ?
+ strncpy(chunk_att,BYTE,ATTRIBUTE_SIZE) :
+ strncpy(chunk_att,LINE,ATTRIBUTE_SIZE);
+ sprintf(start,"%ld",doc->ChunkStart.Pos);
+ startChunk = stringToAny(start);
+ sprintf(end,"%ld",doc->ChunkEnd.Pos);
+ endChunk = stringToAny(end);
+ }
+ break;
+ case CT_paragraph:
+ strncpy(chunk_att,PARAGRAPH,ATTRIBUTE_SIZE);
+ startChunk = doc->ChunkStart.ID;
+ endChunk = doc->ChunkEnd.ID;
+ break;
+ default:
+ /* error */
+ break;
+ }
+
+ terms[numTerms++] = makeAttributeTerm(SYSTEM_CONTROL_NUMBER,
+ EQUAL,IGNORE,IGNORE,
+ IGNORE,
+ IGNORE,doc->DocumentID);
+ if (type != NULL)
+ { terms[numTerms++] = makeAttributeTerm(DATA_TYPE,EQUAL,IGNORE,
+ IGNORE,IGNORE,IGNORE,
+ type);
+ terms[numTerms++] = makeOperatorTerm(AND);
+ }
+ terms[numTerms++] = makeAttributeTerm(chunk_att,
+ GREATER_THAN_OR_EQUAL,
+ IGNORE,IGNORE,IGNORE,
+ IGNORE,
+ startChunk);
+ terms[numTerms++] = makeOperatorTerm(AND);
+ terms[numTerms++] = makeAttributeTerm(chunk_att,LESS_THAN,
+ IGNORE,IGNORE,IGNORE,
+ IGNORE,
+ endChunk);
+ terms[numTerms++] = makeOperatorTerm(AND);
+ terms[numTerms] = NULL;
+
+ if (doc->ChunkCode == CT_byte || doc->ChunkCode == CT_line)
+ { freeAny(startChunk);
+ freeAny(endChunk);
+ }
+ }
+
+ freeAny(type);
+
+ if (i != 0) /* multiple independent queries, need a disjunction */
+ { terms = (query_term**)s_realloc((char*)terms,
+ (size_t)(sizeof(query_term*) *
+ (numTerms + 1 + 1)));
+ terms[numTerms++] = makeOperatorTerm(OR);
+ terms[numTerms] = NULL;
+ }
+ }
+
+ return(terms);
+}
+
+/*----------------------------------------------------------------------*/
+
+static DocObj** makeWAISQueryDocs _AP((query_term** terms));
+
+static DocObj**
+makeWAISQueryDocs(terms)
+query_term** terms;
+/* given a list of terms in the form given above, convert them to
+ DocObjs.
+ */
+{
+ query_term* docTerm = NULL;
+ query_term* fragmentTerm = NULL;
+ DocObj** docs = NULL;
+ DocObj* doc = NULL;
+ long docNum,termNum;
+
+ docNum = termNum = 0;
+
+ docs = (DocObj**)s_malloc((size_t)(sizeof(DocObj*) * 1));
+ docs[docNum] = NULL;
+
+ /* translate the terms into DocObjs */
+ while (true)
+ {
+ query_term* typeTerm = NULL;
+ char* type = NULL;
+ long startTermOffset;
+
+ docTerm = terms[termNum];
+
+ if (docTerm == NULL)
+ break; /* we're done converting */;
+
+ typeTerm = terms[termNum + 1]; /* get the lead Term if it exists */
+
+ if (strcmp(typeTerm->Use,DATA_TYPE) == 0) /* we do have a type */
+ { startTermOffset = 3;
+ type = anyToString(typeTerm->Term);
+ }
+ else /* no type */
+ { startTermOffset = 1;
+ typeTerm = NULL;
+ type = NULL;
+ }
+
+ /* grow the doc list */
+ docs = (DocObj**)s_realloc((char*)docs,(size_t)(sizeof(DocObj*) *
+ (docNum + 1 + 1)));
+
+ /* figure out what kind of docObj to build - and build it */
+ fragmentTerm = terms[termNum + startTermOffset];
+ if (fragmentTerm != NULL && fragmentTerm->TermType == TT_Attribute)
+ { /* build a document fragment */
+ query_term* startTerm = fragmentTerm;
+ query_term* endTerm = terms[termNum + startTermOffset + 2];
+
+ if (strcmp(startTerm->Use,BYTE) == 0){ /* a byte chunk */
+ doc = makeDocObjUsingBytes(duplicateAny(docTerm->Term),
+ type,
+ anyToLong(startTerm->Term),
+ anyToLong(endTerm->Term));
+ log_write("byte");
+ }else if (strcmp(startTerm->Use,LINE) == 0){ /* a line chunk */
+ doc = makeDocObjUsingLines(duplicateAny(docTerm->Term),
+ type,
+ anyToLong(startTerm->Term),
+ anyToLong(endTerm->Term));
+ log_write("line");
+ }else{
+ log_write("chunk"); /* a paragraph chunk */
+ doc = makeDocObjUsingParagraphs(duplicateAny(docTerm->Term),
+ type,
+ duplicateAny(startTerm->Term),
+ duplicateAny(endTerm->Term));
+}
+ termNum += (startTermOffset + 4); /* point to next term */
+ }
+ else /* build a full document */
+ {
+ doc = makeDocObjUsingWholeDocument(duplicateAny(docTerm->Term),
+ type);
+log_write("whole doc");
+ termNum += startTermOffset; /* point to next term */
+ }
+
+ docs[docNum++] = doc; /* insert the new document */
+
+ docs[docNum] = NULL; /* keep the doc list terminated */
+
+
+ if (terms[termNum] != NULL)
+ termNum++; /* skip the OR operator it necessary */
+ else
+ break; /* we are done */
+ }
+
+ return(docs);
+}
+
+/*----------------------------------------------------------------------*/
+
+any*
+makeWAISTextQuery(docs)
+DocObj** docs;
+/* given a list of DocObjs, return an any whose contents is the corresponding
+ type 1 query
+ */
+{
+ any *buf = NULL;
+ query_term** terms = NULL;
+
+ terms = makeWAISQueryTerms(docs);
+ buf = writeQuery(terms);
+
+ doList((void**)terms,freeTerm);
+ s_free(terms);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+DocObj**
+readWAISTextQuery(buf)
+any* buf;
+/* given an any whose contents are type 1 queries of the WAIS sort,
+ construct a list of the corresponding DocObjs
+ */
+{
+ query_term** terms = NULL;
+ DocObj** docs = NULL;
+
+ terms = readQuery(buf);
+ docs = makeWAISQueryDocs(terms);
+
+ doList((void**)terms,freeTerm);
+ s_free(terms);
+
+ return(docs);
+}
+
+/*----------------------------------------------------------------------*/
+/* Customized free WAIS object routines: */
+/* */
+/* This set of procedures is for applications to free a WAIS object */
+/* which was made with makeWAISFOO. */
+/* Each procedure frees only the memory that was allocated in its */
+/* associated makeWAISFOO routine, thus it's not necessary for the */
+/* caller to assign nulls to the pointer fields of the WAIS object. */
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISInitResponse(init)
+WAISInitResponse* init;
+/* free an object made with makeWAISInitResponse */
+{
+ s_free(init);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISSearch(query)
+WAISSearch* query;
+/* destroy an object made with makeWAISSearch() */
+{
+ s_free(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeDocObj(doc)
+DocObj* doc;
+/* free a docObj */
+{
+ s_free(doc);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocumentHeader(header)
+WAISDocumentHeader* header;
+{
+ s_free(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocumentShortHeader(header)
+WAISDocumentShortHeader* header;
+{
+ s_free(header);
+}
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocumentLongHeader(header)
+WAISDocumentLongHeader* header;
+{
+ s_free(header);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISSearchResponse(response)
+WAISSearchResponse* response;
+{
+ s_free(response);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocumentText(docText)
+WAISDocumentText* docText;
+{
+ s_free(docText);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocHeadlines(docHeadline)
+WAISDocumentHeadlines* docHeadline;
+{
+ s_free(docHeadline);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISDocumentCodes(docCodes)
+WAISDocumentCodes* docCodes;
+{
+ s_free(docCodes);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+CSTFreeWAISTextQuery(query)
+any* query;
+{
+ freeAny(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from WMessage.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+ 3.26.90
+*/
+
+/* This file is for reading and writing the wais packet header.
+ * Morris@think.com
+ */
+
+/* to do:
+ * add check sum
+ * what do you do when checksum is wrong?
+ */
+
+/*---------------------------------------------------------------------*/
+
+void
+readWAISPacketHeader(msgBuffer,header_struct)
+char* msgBuffer;
+WAISMessage *header_struct;
+{
+ /* msgBuffer is a string containing at least HEADER_LENGTH bytes. */
+
+ memmove(header_struct->msg_len,msgBuffer,(size_t)10);
+ header_struct->msg_type = char_downcase((unsigned long)msgBuffer[10]);
+ header_struct->hdr_vers = char_downcase((unsigned long)msgBuffer[11]);
+ memmove(header_struct->server,(void*)(msgBuffer + 12),(size_t)10);
+ header_struct->compression = char_downcase((unsigned long)msgBuffer[22]);
+ header_struct->encoding = char_downcase((unsigned long)msgBuffer[23]);
+ header_struct->msg_checksum = char_downcase((unsigned long)msgBuffer[24]);
+}
+
+/*---------------------------------------------------------------------*/
+
+/* this modifies the header argument. See wais-message.h for the different
+ * options for the arguments.
+ */
+
+void
+writeWAISPacketHeader(header,
+ dataLen,
+ type,
+ server,
+ compression,
+ encoding,
+ version)
+char* header;
+long dataLen;
+long type;
+char* server;
+long compression;
+long encoding;
+long version;
+/* Puts together the new wais before-the-z39-packet header. */
+{
+ char lengthBuf[11];
+ char serverBuf[11];
+
+ long serverLen = strlen(server);
+ if (serverLen > 10)
+ serverLen = 10;
+
+ sprintf(lengthBuf, "%010ld", dataLen);
+ strncpy(header,lengthBuf,10);
+
+ header[10] = type & 0xFF;
+ header[11] = version & 0xFF;
+
+ strncpy(serverBuf,server,serverLen);
+ strncpy((char*)(header + 12),serverBuf,serverLen);
+
+ header[22] = compression & 0xFF;
+ header[23] = encoding & 0xFF;
+ header[24] = '0'; /* checkSum(header + HEADER_LENGTH,dataLen); XXX the result must be ascii */
+}
+
+/*---------------------------------------------------------------------*/
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.h
new file mode 100644
index 00000000000..1a4e83d50f1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisProt.h
@@ -0,0 +1,376 @@
+/* HTVMS_WAISProt.h
+**
+** Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
+**
+** 31-May-1994 FM Initial version.
+**
+**----------------------------------------------------------------------*/
+
+/*
+** Routines originally from WProt.h -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 3.30.90 Harry Morris
+ - removed chunk code from WAISSearchAPDU,
+ - added makeWAISQueryType1Query() and readWAISType1Query() which
+ replace makeWAISQueryTerms() and makeWAISQueryDocs().
+ 4.11.90 HWM - added definitions of wais element set names
+ 4.14.90 HWM - changed symbol for relevance feedback query from QT_3 to
+ QT_RelevanceFeedbackQuery added QT_TextRetrievalQuery as a
+ synonym for QT_BooleanQuery
+ - renamed makeWAISType1Query() to makeWAISTextQuery()
+ renamed readWAISType1Query() to readWAISTextQuery()
+ 5.29.90 TS - added CSTFreeWAISFoo functions
+*/
+
+#ifndef _H_WAIS_protocol_
+
+#define _H_WAIS_protocol_
+
+/*----------------------------------------------------------------------*/
+/* Data types / constants */
+
+/* date factor constants */
+#define DF_INDEPENDENT 1
+#define DF_LATER 2
+#define DF_EARLIER 3
+#define DF_SPECIFIED_RANGE 4
+
+/* chunk types */
+#define CT_document 0
+#define CT_byte 1
+#define CT_line 2
+#define CT_paragraph 3
+
+/* relevance feedback query */
+#define QT_RelevanceFeedbackQuery "3"
+#define QT_TextRetrievalQuery QT_BooleanQuery
+
+/* new data tags */
+#define DT_UserInformationLength (data_tag)99
+#define DT_ChunkCode (data_tag)100
+#define DT_ChunkIDLength (data_tag)101
+#define DT_ChunkMarker (data_tag)102
+#define DT_HighlightMarker (data_tag)103
+#define DT_DeHighlightMarker (data_tag)104
+#define DT_NewlineCharacters (data_tag)105
+#define DT_SeedWords (data_tag)106
+#define DT_DocumentIDChunk (data_tag)107
+#define DT_ChunkStartID (data_tag)108
+#define DT_ChunkEndID (data_tag)109
+#define DT_TextList (data_tag)110
+#define DT_DateFactor (data_tag)111
+#define DT_BeginDateRange (data_tag)112
+#define DT_EndDateRange (data_tag)113
+#define DT_MaxDocumentsRetrieved (data_tag)114
+#define DT_SeedWordsUsed (data_tag)115
+#define DT_DocumentID (data_tag)116
+#define DT_VersionNumber (data_tag)117
+#define DT_Score (data_tag)118
+#define DT_BestMatch (data_tag)119
+#define DT_DocumentLength (data_tag)120
+#define DT_Source (data_tag)121
+#define DT_Date (data_tag)122
+#define DT_Headline (data_tag)123
+#define DT_OriginCity (data_tag)124
+#define DT_PresentStartByte (data_tag)125
+#define DT_TextLength (data_tag)126
+#define DT_DocumentText (data_tag)127
+#define DT_StockCodes (data_tag)128
+#define DT_CompanyCodes (data_tag)129
+#define DT_IndustryCodes (data_tag)130
+
+/* added by harry */
+#define DT_DocumentHeaderGroup (data_tag)150
+#define DT_DocumentShortHeaderGroup (data_tag)151
+#define DT_DocumentLongHeaderGroup (data_tag)152
+#define DT_DocumentTextGroup (data_tag)153
+#define DT_DocumentHeadlineGroup (data_tag)154
+#define DT_DocumentCodeGroup (data_tag)155
+#define DT_Lines (data_tag)131
+#define DT_TYPE_BLOCK (data_tag)132
+#define DT_TYPE (data_tag)133
+
+/* wais element sets */
+#define ES_DocumentHeader "Document Header"
+#define ES_DocumentShortHeader "Document Short Header"
+#define ES_DocumentLongHeader "Document Long Header"
+#define ES_DocumentText "Document Text"
+#define ES_DocumentHeadline "Document Headline"
+#define ES_DocumentCodes "Document Codes"
+
+typedef struct DocObj { /* specifies a section of a document */
+ any* DocumentID;
+ char* Type;
+ long ChunkCode;
+ union {
+ long Pos;
+ any* ID;
+ } ChunkStart;
+ union {
+ long Pos;
+ any* ID;
+ } ChunkEnd;
+ } DocObj;
+
+/*----------------------------------------------------------------------*/
+/* WAIS APDU extensions */
+
+typedef struct WAISInitResponse {
+ long ChunkCode;
+ long ChunkIDLength;
+ char* ChunkMarker;
+ char* HighlightMarker;
+ char* DeHighlightMarker;
+ char* NewlineCharacters;
+ /* XXX need to add UpdateFrequency and Update Time */
+ } WAISInitResponse;
+
+typedef struct WAISSearch {
+ char* SeedWords;
+ DocObj** Docs;
+ char** TextList;
+ long DateFactor;
+ char* BeginDateRange;
+ char* EndDateRange;
+ long MaxDocumentsRetrieved;
+ } WAISSearch;
+
+typedef struct WAISDocumentHeader {
+ any* DocumentID;
+ long VersionNumber;
+ long Score;
+ long BestMatch;
+ long DocumentLength;
+ long Lines;
+ char** Types;
+ char* Source;
+ char* Date;
+ char* Headline;
+ char* OriginCity;
+ } WAISDocumentHeader;
+
+typedef struct WAISDocumentShortHeader {
+ any* DocumentID;
+ long VersionNumber;
+ long Score;
+ long BestMatch;
+ long DocumentLength;
+ long Lines;
+ } WAISDocumentShortHeader;
+
+typedef struct WAISDocumentLongHeader {
+ any* DocumentID;
+ long VersionNumber;
+ long Score;
+ long BestMatch;
+ long DocumentLength;
+ long Lines;
+ char** Types;
+ char* Source;
+ char* Date;
+ char* Headline;
+ char* OriginCity;
+ char* StockCodes;
+ char* CompanyCodes;
+ char* IndustryCodes;
+ } WAISDocumentLongHeader;
+
+typedef struct WAISDocumentText {
+ any* DocumentID;
+ long VersionNumber;
+ any* DocumentText;
+ } WAISDocumentText;
+
+typedef struct WAISDocumentHeadlines {
+ any* DocumentID;
+ long VersionNumber;
+ char* Source;
+ char* Date;
+ char* Headline;
+ char* OriginCity;
+ } WAISDocumentHeadlines;
+
+typedef struct WAISDocumentCodes {
+ any* DocumentID;
+ long VersionNumber;
+ char* StockCodes;
+ char* CompanyCodes;
+ char* IndustryCodes;
+ } WAISDocumentCodes;
+
+typedef struct WAISSearchResponse {
+ char* SeedWordsUsed;
+ WAISDocumentHeader** DocHeaders;
+ WAISDocumentShortHeader** ShortHeaders;
+ WAISDocumentLongHeader** LongHeaders;
+ WAISDocumentText** Text;
+ WAISDocumentHeadlines** Headlines;
+ WAISDocumentCodes** Codes;
+ diagnosticRecord** Diagnostics;
+ } WAISSearchResponse;
+
+/*----------------------------------------------------------------------*/
+/* Functions */
+
+DocObj* makeDocObjUsingWholeDocument _AP((any* aDocID,char* type));
+DocObj* makeDocObjUsingBytes _AP((any* aDocID,char* type,long start,long end));
+DocObj* makeDocObjUsingLines _AP((any* aDocID,char* type,long start,long end));
+DocObj* makeDocObjUsingParagraphs _AP((any* aDocID,char* type,any* start,any* end));
+void freeDocObj _AP((DocObj* doc));
+
+WAISInitResponse* makeWAISInitResponse _AP((long chunkCode,long chunkIDLen,
+ char* chunkMarker,char* highlightMarker,
+ char* deHighlightMarker,char* newLineChars));
+void freeWAISInitResponse _AP((WAISInitResponse* init));
+
+WAISSearch* makeWAISSearch _AP((
+ char* seedWords,DocObj** docs,char** textList,
+ long dateFactor,char* beginDateRange,char* endDateRange,
+ long maxDocsRetrieved));
+void freeWAISSearch _AP((WAISSearch* query));
+
+WAISDocumentHeader* makeWAISDocumentHeader _AP((
+ any* aDocID,long versionNumber,long score,long bestMatch,long docLen,
+ long lines,char** types,char* source,char* date,char* headline,char* originCity));
+void freeWAISDocumentHeader _AP((WAISDocumentHeader* header));
+char* writeWAISDocumentHeader _AP((WAISDocumentHeader* header,char* buffer,long* len));
+char* readWAISDocumentHeader _AP((WAISDocumentHeader** header,char* buffer));
+
+WAISDocumentShortHeader* makeWAISDocumentShortHeader _AP((
+ any* aDocID,long versionNumber,long score,long bestMatch,long docLen,long lines));
+void freeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header));
+char* writeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header,
+ char* buffer,long* len));
+char* readWAISDocumentShortHeader _AP((WAISDocumentShortHeader** header,char* buffer));
+
+WAISDocumentLongHeader* makeWAISDocumentLongHeader _AP((
+ any* aDocID,long versionNumber,long score,long bestMatch,long docLen,
+ long lines,char** types,char* source,char* date, char* headline,char* originCity,
+ char* stockCodes,char* companyCodes,char* industryCodes));
+void freeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header));
+char* writeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header,char* buffer,long* len));
+char* readWAISDocumentLongHeader _AP((WAISDocumentLongHeader** header,char* buffer));
+
+WAISSearchResponse* makeWAISSearchResponse _AP((
+ char* seedWordsUsed,WAISDocumentHeader** docHeaders,
+ WAISDocumentShortHeader** shortHeaders,
+ WAISDocumentLongHeader** longHeaders,
+ WAISDocumentText** text,WAISDocumentHeadlines** headlines,
+ WAISDocumentCodes** codes,
+ diagnosticRecord** diagnostics));
+void freeWAISSearchResponse _AP((WAISSearchResponse* response));
+
+WAISDocumentText* makeWAISDocumentText _AP((any* aDocID,long versionNumber,
+ any* documentText));
+void freeWAISDocumentText _AP((WAISDocumentText* docText));
+char* writeWAISDocumentText _AP((WAISDocumentText* docText,char* buffer,long* len));
+char* readWAISDocumentText _AP((WAISDocumentText** docText,char* buffer));
+
+WAISDocumentHeadlines* makeWAISDocumentHeadlines _AP((
+ any* aDocID,long versionNumber,char* source,char* date,char* headline,
+ char* originCity));
+void freeWAISDocumentHeadlines _AP((WAISDocumentHeadlines* docHeadline));
+char* writeWAISDocumentHeadlines _AP((WAISDocumentHeadlines* docHeadline,char* buffer,long* len));
+char* readWAISDocumentHeadlines _AP((WAISDocumentHeadlines** docHeadline,char* buffer));
+
+WAISDocumentCodes* makeWAISDocumentCodes _AP((
+ any* aDocID,long versionNumber,char* stockCodes,char* companyCodes,
+ char* industryCodes));
+void freeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes));
+char* writeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes,char* buffer,long* len));
+char* readWAISDocumentCodes _AP((WAISDocumentCodes** docCodes,char* buffer));
+
+any* makeWAISTextQuery _AP((DocObj** docs));
+DocObj** readWAISTextQuery _AP((any* terms));
+
+void CSTFreeWAISInitResponse _AP((WAISInitResponse* init));
+void CSTFreeWAISSearch _AP((WAISSearch* query));
+void CSTFreeDocObj _AP((DocObj* doc));
+void CSTFreeWAISDocumentHeader _AP((WAISDocumentHeader* header));
+void CSTFreeWAISDocumentShortHeader _AP((WAISDocumentShortHeader* header));
+void CSTFreeWAISDocumentLongHeader _AP((WAISDocumentLongHeader* header));
+void CSTFreeWAISSearchResponse _AP((WAISSearchResponse* response));
+void CSTFreeWAISDocumentText _AP((WAISDocumentText* docText));
+void CSTFreeWAISDocHeadlines _AP((WAISDocumentHeadlines* docHeadline));
+void CSTFreeWAISDocumentCodes _AP((WAISDocumentCodes* docCodes));
+void CSTFreeWAISTextQuery _AP(( any* query));
+
+/*----------------------------------------------------------------------*/
+
+#endif /* ndef _H_WAIS_protocol_ */
+
+
+/*
+** Routines originally from WMessage.h -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+ 3.26.90
+*/
+
+/* wais-message.h
+ *
+ * This is the header outside of WAIS Z39.50 messages. The header will be
+ * printable ascii, so as to be transportable. This header will precede each
+ * Z39.50 APDU, or zero-length message if it is an ACK or NACK. Be sure to
+ * change hdr_vers current value if you change the structure of the header.
+ *
+ * The characters in the header are case insensitive so that the systems from
+ * the past that only handle one case can at least read the header.
+ *
+ * 7.5.90 HWM - added constants
+ * 7/5/90 brewster added funtion prototypes and comments
+ * 11/30/90 HWM - went to version 2 (inits and typed retrieval)
+ */
+
+#ifndef WMESSAGE_H
+#define WMESSAGE_H
+
+typedef struct wais_header {
+ char msg_len[10]; /* length in bytes of following message */
+ char msg_type; /* type of message: 'z'=Z39.50 APDU,
+ 'a'=ACK, 'n'=NACK */
+ char hdr_vers; /* version of this header, currently = '2' */
+ char server[10]; /* name or address of server */
+ char compression; /* <sp>=no compression, 'u'=unix compress */
+ char encoding; /* <sp>=no encoding, 'h'=hexize,
+ 'u'=uuencode */
+ char msg_checksum; /* XOR of every byte of message */
+ } WAISMessage;
+
+#define HEADER_LENGTH 25 /* number of bytes needed to write a
+ wais-header (not sizeof(wais_header)) */
+
+#define HEADER_VERSION (long)'2'
+
+/* message type */
+#define Z3950 'z'
+#define ACK 'a'
+#define NAK 'n'
+
+/* compression */
+#define NO_COMPRESSION ' '
+#define UNIX_COMPRESSION 'u'
+
+/* encoding */
+#define NO_ENCODING ' '
+#define HEX_ENCODING 'h' /* Swartz 4/3 encoding */
+#define IBM_HEXCODING 'i' /* same as h but uses characters acceptable for IBM mainframes */
+#define UUENCODE 'u'
+
+
+void readWAISPacketHeader _AP((char* msgBuffer,WAISMessage *header_struct));
+long getWAISPacketLength _AP((WAISMessage* header));
+void writeWAISPacketHeader _AP((char* header,long dataLen,long type,
+ char* server,long compression,
+ long encoding,long version));
+
+#endif /* ndef WMESSAGE_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.c
new file mode 100644
index 00000000000..81c097070c9
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.c
@@ -0,0 +1,2448 @@
+/* HTVMS_WAISUI.c
+**
+** Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
+**
+** 30-May-1994 FM Initial version.
+**
+**----------------------------------------------------------------------*/
+
+/*
+** Routines originally from UI.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ Brewster@think.com
+*/
+
+/*
+ * this is a simple ui toolkit for building other ui's on top.
+ * -brewster
+ *
+ * top level functions:
+ * generate_search_apdu
+ * generate_retrieval_apdu
+ * interpret_message
+ *
+ */
+
+/* to do:
+ * generate multiple queries for long documents.
+ * this will crash if the file being retrieved is larger than 100k.
+ * do log_write()
+ *
+ */
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTVMS_WaisUI.h"
+#include "HTVMS_WaisProt.h"
+#include "HTTCP.h"
+/*#include <stdio> included by HTUtils.h -- FM */
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+void
+log_write(s)
+char *s;
+{
+ return;
+}
+
+/*----------------------------------------------------------------------*/
+
+/* returns a pointer in the buffer of the first free byte.
+ if it overflows, then NULL is returned
+ */
+char *
+generate_search_apdu(buff,
+ buff_len,
+ seed_words,
+ database_name,
+ docobjs,
+ maxDocsRetrieved)
+char* buff; /* buffer to hold the apdu */
+long *buff_len; /* length of the buffer changed to reflect new data written */
+char *seed_words; /* string of the seed words */
+char *database_name;
+DocObj** docobjs;
+long maxDocsRetrieved;
+{
+ /* local variables */
+
+ SearchAPDU *search3;
+ char *end_ptr;
+ static char *database_names[2] = {"", 0};
+ any refID;
+ WAISSearch *query;
+ refID.size = 1;
+ refID.bytes = "3";
+
+ database_names[0] = database_name;
+ query = makeWAISSearch(seed_words,
+ docobjs, /* DocObjsPtr */
+ 0,
+ 1, /* DateFactor */
+ 0, /* BeginDateRange */
+ 0, /* EndDateRange */
+ maxDocsRetrieved
+ );
+
+ search3 = makeSearchAPDU(30,
+ 5000, /* should be large */
+ 30,
+ 1, /* replace indicator */
+ "", /* result set name */
+ database_names, /* database name */
+ QT_RelevanceFeedbackQuery, /* query_type */
+ 0, /* element name */
+ NULL, /* reference ID */
+ query);
+
+ end_ptr = writeSearchAPDU(search3, buff, buff_len);
+
+ CSTFreeWAISSearch(query);
+ freeSearchAPDU(search3);
+ return(end_ptr);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* returns a pointer into the buffer of the next free byte.
+ if it overflowed, then NULL is returned
+ */
+
+char *
+generate_retrieval_apdu(buff,
+ buff_len,
+ docID,
+ chunk_type,
+ start,
+ end,
+ type,
+ database_name)
+char *buff;
+long *buff_len; /* length of the buffer changed to reflect new data written */
+any *docID;
+long chunk_type;
+long start;
+long end;
+char *type;
+char *database_name;
+{
+ SearchAPDU *search;
+ char *end_ptr;
+
+ static char *database_names[2];
+ static char *element_names[3];
+ any refID;
+
+ DocObj *DocObjs[2];
+ any *query; /* changed from char* by brewster */
+
+ if(NULL == type)
+ type = s_strdup("TEXT");
+
+ database_names[0] = database_name;
+ database_names[1] = NULL;
+
+ element_names[0] = " ";
+ element_names[1] = ES_DocumentText;
+ element_names[2] = NULL;
+
+ refID.size = 1;
+ refID.bytes = "3";
+
+ switch(chunk_type){
+ case CT_line:
+ DocObjs[0] = makeDocObjUsingLines(docID, type, start, end);
+ break;
+ case CT_byte:
+ DocObjs[0] = makeDocObjUsingBytes(docID, type, start, end);
+ break;
+ }
+ DocObjs[1] = NULL;
+
+ query = makeWAISTextQuery(DocObjs);
+ search = makeSearchAPDU( 10, 16, 15,
+ 1, /* replace indicator */
+ "FOO", /* result set name */
+ database_names, /* database name */
+ QT_TextRetrievalQuery, /* query_type */
+ element_names, /* element name */
+ &refID, /* reference ID */
+ query);
+ end_ptr = writeSearchAPDU(search, buff, buff_len);
+ CSTFreeWAISTextQuery(query);
+ freeSearchAPDU(search);
+ return(end_ptr);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* this is a safe version of unix 'read' it does all the checking
+ * and looping necessary
+ * to those trying to modify the transport code to use non-UNIX streams:
+ * This is the function to modify!
+ */
+long read_from_stream(d,buf,nbytes)
+int d; /* this is the stream */
+char *buf;
+long nbytes;
+{
+ long didRead;
+ long toRead = nbytes;
+ long totalRead = 0; /* paranoia */
+
+ while (toRead > 0){
+ didRead = NETREAD (d, buf, (int)toRead);
+ if(didRead == HT_INTERRUPTED)
+ return(HT_INTERRUPTED);
+ if(didRead == -1) /* error*/
+ return(-1);
+ if(didRead == 0) /* eof */
+ return(-2); /* maybe this should return 0? */
+ toRead -= didRead;
+ buf += didRead;
+ totalRead += didRead;
+ }
+ if(totalRead != nbytes) /* we overread for some reason */
+ return(- totalRead); /* bad news */
+ return(totalRead);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* returns the length of the response, 0 if an error */
+
+long
+transport_message(connection,
+ request_message,
+ request_length,
+ response_message,
+ response_buffer_length)
+int connection;
+char *request_message;
+long request_length;
+char *response_message;
+long response_buffer_length;
+{
+ WAISMessage header;
+ long response_length;
+ int rv;
+
+
+ /* Write out message. Read back header. Figure out response length. */
+
+ if( request_length + HEADER_LENGTH !=
+ NETWRITE(connection,request_message,
+ (int)( request_length +HEADER_LENGTH)) )
+ return 0;
+
+ /* read for the first '0' */
+
+ while(1){
+ rv = read_from_stream(connection, response_message, 1);
+ if (rv == HT_INTERRUPTED)
+ return HT_INTERRUPTED;
+ if (rv < 0)
+ return 0;
+ if('0' == response_message[0])
+ break;
+ }
+
+ rv = read_from_stream(connection, response_message + 1, HEADER_LENGTH -1);
+ if (rv == HT_INTERRUPTED)
+ return HT_INTERRUPTED;
+ if (rv < 0)
+ return 0;
+
+ readWAISPacketHeader(response_message, &header);
+ {
+ char length_array[11];
+ strncpy(length_array, header.msg_len, 10);
+ length_array[10] = '\0';
+ response_length = atol(length_array);
+ /*
+ if(verbose){
+ printf("WAIS header: '%s' length_array: '%s'\n",
+ response_message, length_array);
+ }
+ */
+ if(response_length > response_buffer_length){
+ /* we got a message that is too long, therefore empty the message out,
+ and return 0 */
+ long i;
+ for(i = 0; i < response_length; i++){
+ rv = read_from_stream(connection,
+ response_message + HEADER_LENGTH,
+ 1);
+ if (rv == HT_INTERRUPTED)
+ return HT_INTERRUPTED;
+ if (rv < 0)
+ return 0;
+ }
+ return(0);
+ }
+ }
+ rv = read_from_stream(connection,
+ response_message + HEADER_LENGTH,
+ response_length);
+ if (rv == HT_INTERRUPTED)
+ return HT_INTERRUPTED;
+ if (rv < 0)
+ return 0;
+ return(response_length);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* returns the number of bytes writen. 0 if an error */
+long
+interpret_message(request_message,request_length,
+ response_message,
+ response_buffer_length,
+ connection,
+ verbose)
+char *request_message;
+long request_length; /* length of the buffer */
+char *response_message;
+long response_buffer_length;
+int connection;
+boolean verbose;
+{
+ long response_length;
+
+ /* ?
+ if(verbose){
+ printf ("sending");
+ if(hostname_internal && strlen(hostname_internal) > 0)
+ printf(" to host %s", hostname_internal);
+ if(service_name && strlen(service_name) > 0)
+ printf(" for service %s", service_name);
+ printf("\n");
+ twais_dsply_rsp_apdu(request_message + HEADER_LENGTH,
+ request_length);
+ }
+
+ */
+
+ writeWAISPacketHeader(request_message,
+ request_length,
+ (long)'z', /* Z39.50 */
+ "wais ", /* server name */
+ (long)NO_COMPRESSION, /* no compression */
+ (long)NO_ENCODING,(long)HEADER_VERSION);
+ if(connection != 0) {
+ response_length = transport_message(connection, request_message,
+ request_length,
+ response_message,
+ response_buffer_length);
+ if (response_length == HT_INTERRUPTED)
+ return(HT_INTERRUPTED);
+ }
+ else
+ return(0);
+
+ return(response_length);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* modifies the string to exclude all seeker codes. sets length to
+ the new length. */
+char *delete_seeker_codes(string,length)
+char *string;
+long *length;
+{
+ long original_count; /* index into the original string */
+ long new_count = 0; /* index into the collapsed string */
+ for(original_count = 0; original_count < *length; original_count++){
+ if(27 == string[original_count]){
+ /* then we have an escape code */
+ /* if the next letter is '(' or ')', then ignore two letters */
+ if('(' == string[original_count + 1] ||
+ ')' == string[original_count + 1])
+ original_count += 1; /* it is a term marker */
+ else original_count += 4; /* it is a paragraph marker */
+ }
+ else string[new_count++] = string[original_count];
+ }
+ *length = new_count;
+ return(string);
+}
+
+/*----------------------------------------------------------------------*/
+
+#if defined(VMS) && defined(__GNUC__) /* 10-AUG-1995 [pr] */
+/*
+ Workaround for an obscure bug in gcc's 2.6.[123] and 2.7.0 vax/vms port;
+ sometimes global variables will end up not being defined properly,
+ causing first gas to assume they're routines, then the linker to complain
+ about unresolved symbols, and finally the program to reference the wrong
+ objects (provoking ACCVIO). It's triggered by the specific ordering of
+ variable usage in the source code, hence rarely appears. This bug is
+ fixed in gcc 2.7.1, and was not present in 2.6.0 and earlier.
+
+ Make a reference to VAXCRTL's _ctype_[], and also one to this dummy
+ variable itself to prevent any "defined but not used" warning.
+ */
+static __const void *__const ctype_dummy[] = { &_ctype_, &ctype_dummy };
+#endif /* VMS && __GNUC__ */
+
+/* returns a pointer to a string with good stuff */
+char *trim_junk(headline)
+char *headline;
+{
+ long length = strlen(headline) + 1; /* include the trailing null */
+ long i;
+ headline = delete_seeker_codes(headline, &length);
+ /* delete leading spaces */
+ for(i=0; i < strlen(headline); i++){
+ if(isprint(headline[i])){
+ break;
+ }
+ }
+ headline = headline + i;
+ /* delete trailing stuff */
+ for(i=strlen(headline) - 1 ; i > 0; i--){
+ if(isprint(headline[i])){
+ break;
+ }
+ headline[i] = '\0';
+ }
+ return(headline);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from ZProt.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:`
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 3.30.90 Harry Morris - Changed any->bits to any->bytes
+ 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
+*/
+
+#define RESERVE_SPACE_FOR_HEADER(spaceLeft) \
+ *spaceLeft -= HEADER_LEN;
+
+#define RELEASE_HEADER_SPACE(spaceLeft) \
+ if (*spaceLeft > 0) \
+ *spaceLeft += HEADER_LEN;
+
+/*----------------------------------------------------------------------*/
+
+InitResponseAPDU*
+makeInitResponseAPDU(result,
+ search,
+ present,
+ deleteIt,
+ accessControl,
+ resourceControl,
+ prefSize,
+ maxMsgSize,
+ auth,
+ id,
+ name,
+ version,
+ refID,
+ userInfo)
+boolean result;
+boolean search;
+boolean present;
+boolean deleteIt;
+boolean accessControl;
+boolean resourceControl;
+long prefSize;
+long maxMsgSize;
+char* auth;
+char* id;
+char* name;
+char* version;
+any* refID;
+void* userInfo;
+/* build an initResponse APDU with user specified information */
+{
+ InitResponseAPDU* init = (InitResponseAPDU*)s_malloc((size_t)sizeof(InitResponseAPDU));
+
+ init->PDUType = initResponseAPDU;
+ init->Result = result;
+ init->willSearch = search;
+ init->willPresent = present;
+ init->willDelete = deleteIt;
+ init->supportAccessControl = accessControl;
+ init->supportResourceControl = resourceControl;
+ init->PreferredMessageSize = prefSize;
+ init->MaximumRecordSize = maxMsgSize;
+ init->IDAuthentication = s_strdup(auth);
+ init->ImplementationID = s_strdup(id);
+ init->ImplementationName = s_strdup(name);
+ init->ImplementationVersion = s_strdup(version);
+ init->ReferenceID = duplicateAny(refID);
+ init->UserInformationField = userInfo; /* not copied! */
+
+ return(init);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeInitResponseAPDU(init)
+InitResponseAPDU* init;
+/* free an initAPDU */
+{
+ s_free(init->IDAuthentication);
+ s_free(init->ImplementationID);
+ s_free(init->ImplementationName);
+ s_free(init->ImplementationVersion);
+ freeAny(init->ReferenceID);
+ s_free(init);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeInitResponseAPDU(init,buffer,len)
+InitResponseAPDU* init;
+char* buffer;
+long* len;
+/* write the initResponse to a buffer, adding system information */
+{
+ char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
+ long size;
+ bit_map* optionsBM = NULL;
+
+ RESERVE_SPACE_FOR_HEADER(len);
+
+ buf = writePDUType(init->PDUType,buf,len);
+ buf = writeBoolean(init->Result,buf,len);
+ buf = writeProtocolVersion(buf,len);
+
+ optionsBM = makeBitMap((unsigned long)5,init->willSearch,init->willPresent,
+ init->willDelete,init->supportAccessControl,
+ init->supportResourceControl);
+ buf = writeBitMap(optionsBM,DT_Options,buf,len);
+ freeBitMap(optionsBM);
+
+ buf = writeNum(init->PreferredMessageSize,DT_PreferredMessageSize,buf,len);
+ buf = writeNum(init->MaximumRecordSize,DT_MaximumRecordSize,buf,len);
+ buf = writeString(init->IDAuthentication,DT_IDAuthentication,buf,len);
+ buf = writeString(init->ImplementationID,DT_ImplementationID,buf,len);
+ buf = writeString(init->ImplementationName,DT_ImplementationName,buf,len);
+ buf = writeString(init->ImplementationVersion,DT_ImplementationVersion,buf,len);
+ buf = writeAny(init->ReferenceID,DT_ReferenceID,buf,len);
+
+ /* go back and write the header-length-indicator */
+ RELEASE_HEADER_SPACE(len);
+ size = buf - buffer - HEADER_LEN;
+ writeBinaryInteger(size,HEADER_LEN,buffer,len);
+
+ if (init->UserInformationField != NULL)
+ buf = writeInitResponseInfo(init,buf,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readInitResponseAPDU(init,buffer)
+InitResponseAPDU** init;
+char* buffer;
+{
+ char* buf = buffer;
+ boolean search,present,delete,accessControl,resourceControl;
+ long prefSize,maxMsgSize;
+ char *auth,*id,*name,*version;
+ long size;
+ pdu_type pduType;
+ bit_map* versionBM = NULL;
+ bit_map* optionsBM = NULL;
+ boolean result;
+ any *refID = NULL;
+ void* userInfo = NULL;
+
+ auth = id = name = version = NULL;
+ refID = NULL;
+
+ /* read required part */
+ buf = readBinaryInteger(&size,HEADER_LEN,buf);
+ buf = readPDUType(&pduType,buf);
+ buf = readBoolean(&result,buf);
+ buf = readBitMap(&versionBM,buf);
+ buf = readBitMap(&optionsBM,buf);
+ buf = readNum(&prefSize,buf);
+ buf = readNum(&maxMsgSize,buf);
+
+ /* decode optionsBM */
+ search = bitAtPos(0,optionsBM);
+ present = bitAtPos(1,optionsBM);
+ delete = bitAtPos(2,optionsBM);
+ accessControl = bitAtPos(3,optionsBM);
+ resourceControl = bitAtPos(4,optionsBM);
+
+ /* read optional part */
+ while (buf < (buffer + size + HEADER_LEN))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_IDAuthentication:
+ buf = readString(&auth,buf);
+ break;
+ case DT_ImplementationID:
+ buf = readString(&id,buf);
+ break;
+ case DT_ImplementationName:
+ buf = readString(&name,buf);
+ break;
+ case DT_ImplementationVersion:
+ buf = readString(&version,buf);
+ break;
+ case DT_ReferenceID:
+ buf = readAny(&refID,buf);
+ break;
+ default:
+ freeBitMap(versionBM);
+ freeBitMap(optionsBM);
+ s_free(auth);
+ s_free(id);
+ s_free(name);
+ s_free(version);
+ freeAny(refID);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ buf = readInitResponseInfo(&userInfo,buf);
+ if (buf == NULL)
+ { freeBitMap(versionBM);
+ freeBitMap(optionsBM);
+ s_free(auth);
+ s_free(id);
+ s_free(name);
+ s_free(version);
+ freeAny(refID);
+ }
+ RETURN_ON_NULL(buf);
+
+ /* construct the basic init object */
+ *init = makeInitResponseAPDU(result,
+ search,present,delete,accessControl,resourceControl,
+ prefSize,maxMsgSize,auth,id,name,version,refID,userInfo);
+
+ freeBitMap(versionBM);
+ freeBitMap(optionsBM);
+ s_free(auth);
+ s_free(id);
+ s_free(name);
+ s_free(version);
+ freeAny(refID);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+InitResponseAPDU*
+replyToInitAPDU(init,result,userInfo)
+InitAPDU* init;
+boolean result;
+void* userInfo;
+/* respond to an init message in the default way - echoing back
+ the init info
+ */
+{
+ InitResponseAPDU* initResp;
+ initResp = makeInitResponseAPDU(result,
+ init->willSearch,init->willPresent,init->willDelete,
+ init->supportAccessControl,init->supportResourceControl,
+ init->PreferredMessageSize,init->MaximumRecordSize,
+ init->IDAuthentication,defaultImplementationID(),defaultImplementationName(),
+ defaultImplementationVersion(),
+ init->ReferenceID,userInfo);
+ return(initResp);
+}
+
+/*----------------------------------------------------------------------*/
+
+SearchAPDU*
+makeSearchAPDU(small,
+ large,
+ medium,
+ replace,
+ name,
+ databases,
+ type,
+ elements,
+ refID,
+ queryInfo)
+long small;
+long large;
+long medium;
+boolean replace;
+char* name;
+char** databases;
+char* type;
+char** elements;
+any* refID;
+void* queryInfo;
+{
+ char* ptr = NULL;
+ long i;
+ SearchAPDU* query = (SearchAPDU*)s_malloc((size_t)sizeof(SearchAPDU));
+ query->PDUType = searchAPDU;
+ query->SmallSetUpperBound = small;
+ query->LargeSetLowerBound = large;
+ query->MediumSetPresentNumber = medium;
+ query->ReplaceIndicator = replace;
+ query->ResultSetName = s_strdup(name);
+ query->DatabaseNames = NULL;
+ if (databases != NULL)
+ { for (i = 0, ptr = databases[i]; ptr != NULL; ptr = databases[++i])
+ { if (query->DatabaseNames == NULL)
+ query->DatabaseNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
+ else
+ query->DatabaseNames = (char**)s_realloc((char*)query->DatabaseNames,
+ (size_t)(sizeof(char*) * (i + 2)));
+ query->DatabaseNames[i] = s_strdup(ptr);
+ query->DatabaseNames[i+1] = NULL;
+ }
+ }
+ query->QueryType = s_strdup(type);
+ query->ElementSetNames = NULL;
+ if (elements != NULL)
+ { for (i = 0, ptr = elements[i]; ptr != NULL; ptr = elements[++i])
+ { if (query->ElementSetNames == NULL)
+ query->ElementSetNames = (char**)s_malloc((size_t)(sizeof(char*) * 2));
+ else
+ query->ElementSetNames = (char**)s_realloc((char*)query->ElementSetNames,
+ (size_t)(sizeof(char*) * (i + 2)));
+ query->ElementSetNames[i] = s_strdup(ptr);
+ query->ElementSetNames[i+1] = NULL;
+ }
+ }
+ query->ReferenceID = duplicateAny(refID);
+ query->Query = queryInfo; /* not copied! */
+ return(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeSearchAPDU(query)
+SearchAPDU* query;
+{
+ s_free(query->ResultSetName);
+ s_free(query->QueryType);
+ doList((void**)query->DatabaseNames,fs_free); /* can't use the macro here ! */
+ s_free(query->DatabaseNames);
+ doList((void**)query->ElementSetNames,fs_free); /* can't use the macro here ! */
+ s_free(query->ElementSetNames);
+ freeAny(query->ReferenceID);
+ s_free(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define DB_DELIMITER "\037" /* hex 1F occurs between each database name */
+#define ES_DELIMITER_1 "\037" /* separates database name from element name */
+#define ES_DELIMITER_2 "\036" /* hex 1E separates <db,es> groups from one another */
+
+char*
+writeSearchAPDU(query,buffer,len)
+SearchAPDU* query;
+char* buffer;
+long* len;
+{
+ char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
+ long size,i;
+ char* ptr = NULL;
+ char* scratch = NULL;
+
+ RESERVE_SPACE_FOR_HEADER(len);
+
+ buf = writePDUType(query->PDUType,buf,len);
+ buf = writeBinaryInteger(query->SmallSetUpperBound,(size_t)3,buf,len);
+ buf = writeBinaryInteger(query->LargeSetLowerBound,(size_t)3,buf,len);
+ buf = writeBinaryInteger(query->MediumSetPresentNumber,(size_t)3,buf,len);
+ buf = writeBoolean(query->ReplaceIndicator,buf,len);
+ buf = writeString(query->ResultSetName,DT_ResultSetName,buf,len);
+ /* write database names */
+ if (query->DatabaseNames != NULL)
+ { for (i = 0,scratch = NULL, ptr = query->DatabaseNames[i]; ptr != NULL; ptr = query->DatabaseNames[++i])
+ { if (scratch == NULL)
+ scratch = s_strdup(ptr);
+ else
+ { size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + 2);
+ scratch = (char*)s_realloc(scratch,newScratchSize);
+ s_strncat(scratch,DB_DELIMITER,2,newScratchSize);
+ s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
+ }
+ }
+ buf = writeString(scratch,DT_DatabaseNames,buf,len);
+ s_free(scratch);
+ }
+ buf = writeString(query->QueryType,DT_QueryType,buf,len);
+ /* write element set names */
+ if (query->ElementSetNames != NULL)
+ { for (i = 0,scratch = NULL, ptr = query->ElementSetNames[i]; ptr != NULL; ptr = query->ElementSetNames[++i])
+ { if (scratch == NULL)
+ { if (query->ElementSetNames[i+1] == NULL) /* there is a single element set name */
+ { scratch = (char*)s_malloc((size_t)strlen(ptr) + 2);
+ strncpy(scratch,ES_DELIMITER_1,2);
+ s_strncat(scratch,ptr,strlen(ptr) + 1,strlen(ptr) + 2);
+ }
+ else /* this is the first of a series of element set names */
+ { size_t newScratchSize = (size_t)(strlen(ptr) + strlen(query->ElementSetNames[i + 1]) + 2);
+ scratch = s_strdup(ptr); /* the database name */
+ ptr = query->ElementSetNames[++i]; /* the element set name */
+ scratch = (char*)s_realloc(scratch,newScratchSize);
+ s_strncat(scratch,ES_DELIMITER_1,2,newScratchSize);
+ s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
+ }
+ }
+ else
+ { char* esPtr = query->ElementSetNames[++i]; /* the element set name */
+ size_t newScratchSize = (size_t)(strlen(scratch) + strlen(ptr) + strlen(esPtr) + 3);
+ scratch = (char*)s_realloc(scratch,newScratchSize);
+ s_strncat(scratch,ES_DELIMITER_2,2,newScratchSize);
+ s_strncat(scratch,ptr,strlen(ptr) + 1,newScratchSize);
+ s_strncat(scratch,ES_DELIMITER_1,2,newScratchSize);
+ s_strncat(scratch,esPtr,strlen(esPtr) + 1,newScratchSize);
+ }
+ }
+ buf = writeString(scratch,DT_ElementSetNames,buf,len);
+ s_free(scratch);
+ }
+ buf = writeAny(query->ReferenceID,DT_ReferenceID,buf,len);
+
+ /* go back and write the header-length-indicator */
+ RELEASE_HEADER_SPACE(len);
+ size = buf - buffer - HEADER_LEN;
+ writeBinaryInteger(size,HEADER_LEN,buffer,len);
+
+ if (query->Query != NULL)
+ buf = writeSearchInfo(query,buf,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+SearchResponseAPDU*
+makeSearchResponseAPDU(result,count,recordsReturned,nextPos,resultStatus,
+ presentStatus,refID,records)
+long result;
+long count;
+long recordsReturned;
+long nextPos;
+long resultStatus;
+long presentStatus;
+any* refID;
+void* records;
+{
+ SearchResponseAPDU* query = (SearchResponseAPDU*)s_malloc((size_t)sizeof(SearchResponseAPDU));
+ query->PDUType = searchResponseAPDU;
+ query->SearchStatus = result;
+ query->ResultCount = count;
+ query->NumberOfRecordsReturned = recordsReturned;
+ query->NextResultSetPosition = nextPos;
+ query->ResultSetStatus = resultStatus;
+ query->PresentStatus = presentStatus;
+ query->ReferenceID = duplicateAny(refID);
+ query->DatabaseDiagnosticRecords = records;
+ return(query);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeSearchResponseAPDU(queryResponse)
+SearchResponseAPDU* queryResponse;
+{
+ freeAny(queryResponse->ReferenceID);
+ s_free(queryResponse);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeSearchResponseAPDU(queryResponse,buffer,len)
+SearchResponseAPDU* queryResponse;
+char* buffer;
+long* len;
+{
+ char* buf = buffer + HEADER_LEN; /* leave room for the header-length-indicator */
+ long size;
+
+ RESERVE_SPACE_FOR_HEADER(len);
+
+ buf = writePDUType(queryResponse->PDUType,buf,len);
+ buf = writeBinaryInteger(queryResponse->SearchStatus,(size_t)1,buf,len);
+ buf = writeBinaryInteger(queryResponse->ResultCount,(size_t)3,buf,len);
+ buf = writeBinaryInteger(queryResponse->NumberOfRecordsReturned,(size_t)3,buf,len);
+ buf = writeBinaryInteger(queryResponse->NextResultSetPosition,(size_t)3,buf,len);
+ buf = writeNum(queryResponse->ResultSetStatus,DT_ResultSetStatus,buf,len);
+ buf = writeNum(queryResponse->PresentStatus,DT_PresentStatus,buf,len);
+ buf = writeAny(queryResponse->ReferenceID,DT_ReferenceID,buf,len);
+
+ /* go back and write the header-length-indicator */
+ RELEASE_HEADER_SPACE(len);
+ size = buf - buffer - HEADER_LEN;
+ writeBinaryInteger(size,HEADER_LEN,buffer,len);
+
+ if (queryResponse->DatabaseDiagnosticRecords != NULL)
+ buf = writeSearchResponseInfo(queryResponse,buf,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readSearchResponseAPDU(queryResponse,buffer)
+SearchResponseAPDU** queryResponse;
+char* buffer;
+{
+ char* buf = buffer;
+ long size;
+ pdu_type pduType;
+ long result,count,recordsReturned,nextPos;
+ long resultStatus,presentStatus;
+ any *refID = NULL;
+ void* userInfo = NULL;
+
+ /* read required part */
+ buf = readBinaryInteger(&size,HEADER_LEN,buf);
+ buf = readPDUType(&pduType,buf);
+ buf = readBinaryInteger(&result,(size_t)1,buf);
+ buf = readBinaryInteger(&count,(size_t)3,buf);
+ buf = readBinaryInteger(&recordsReturned,(size_t)3,buf);
+ buf = readBinaryInteger(&nextPos,(size_t)3,buf);
+
+ resultStatus = presentStatus = UNUSED;
+ refID = NULL;
+
+ /* read optional part */
+ while (buf < (buffer + size + HEADER_LEN))
+ { data_tag tag = peekTag(buf);
+ switch (tag)
+ { case DT_ResultSetStatus:
+ buf = readNum(&resultStatus,buf);
+ break;
+ case DT_PresentStatus:
+ buf = readNum(&presentStatus,buf);
+ break;
+ case DT_ReferenceID:
+ buf = readAny(&refID,buf);
+ break;
+ default:
+ freeAny(refID);
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+ }
+
+ buf = readSearchResponseInfo(&userInfo,buf);
+ if (buf == NULL)
+ freeAny(refID);
+ RETURN_ON_NULL(buf);
+
+ /* construct the search object */
+ *queryResponse = makeSearchResponseAPDU(result,count,recordsReturned,nextPos,
+ (long)resultStatus,(long)presentStatus,refID,userInfo);
+
+ freeAny(refID);
+
+ return(buf);
+}
+
+
+/*
+** Routines originally from ZUtil.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 3.30.90 Harry Morris - Changed any->bits to any->bytes
+ 4.11.90 HWM - fixed include file names, changed
+ - writeCompressedIntegerWithPadding() to
+ writeCompressedIntWithPadding()
+ - generalized conditional includes (see c-dialect.h)
+ 3.7.91 Jonny Goldman. Replaced "short" in makeBitMap with "int" line 632.
+*/
+
+char* readErrorPosition = NULL; /* pos where buf stoped making sense */
+
+/*----------------------------------------------------------------------*/
+/* A note on error handling
+ read - these are low level routines, they do not check the type tags
+ which (sometimes) preceed the data (this is done by the higher
+ level functions which call these functions). There is no
+ attempt made to check that the reading does not exceed the read
+ buffer. Such cases should be very rare and usually will be
+ caught by the calling functions. (note - it is unlikely that
+ a series of low level reads will go far off the edge without
+ triggering a type error. However, it is possible for a single
+ bad read in an array function (eg. readAny) to attempt to read a
+ large ammount, possibly causing a segmentation violation or out
+ of memory condition.
+ */
+/*----------------------------------------------------------------------*/
+
+diagnosticRecord*
+makeDiag(surrogate,code,addInfo)
+boolean surrogate;
+char* code;
+char* addInfo;
+{
+ diagnosticRecord* diag =
+ (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
+
+ diag->SURROGATE = surrogate;
+ memcpy(diag->DIAG,code,DIAGNOSTIC_CODE_SIZE);
+ diag->ADDINFO = s_strdup(addInfo);
+
+ return(diag);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeDiag(diag)
+diagnosticRecord* diag;
+{
+ if (diag != NULL)
+ { if (diag->ADDINFO != NULL)
+ s_free(diag->ADDINFO);
+ s_free(diag);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+#define END_OF_RECORD 0x1D
+
+char*
+writeDiag(diag,buffer,len)
+diagnosticRecord* diag;
+char* buffer;
+long* len;
+/* diagnostics (as per Appendix D) have a very weird format - this changes
+ in SR-1
+ */
+{
+ char* buf = buffer;
+ long length;
+
+ if (diag == NULL) /* handle unspecified optional args */
+ return(buf);
+
+ buf = writeTag(DT_DatabaseDiagnosticRecords,buf,len);
+ CHECK_FOR_SPACE_LEFT(0,len);
+
+ length = 3;
+ if (diag->ADDINFO != NULL)
+ length += strlen(diag->ADDINFO);
+
+ if (length >= 0xFFFF ) /* make sure the length is reasonable */
+ { length = 0xFFFF - 1;
+ diag->ADDINFO[0xFFFF - 3 - 1] = '\0';
+ }
+
+ buf = writeBinaryInteger(length,2,buf,len);
+
+ CHECK_FOR_SPACE_LEFT(1,len);
+ buf[0] = diag->DIAG[0];
+ buf++;
+
+ CHECK_FOR_SPACE_LEFT(1,len);
+ buf[0] = diag->DIAG[1];
+ buf++;
+
+ if (length > 3)
+ { CHECK_FOR_SPACE_LEFT(3,len);
+ memcpy(buf,diag->ADDINFO,(size_t)length - 3);
+ buf += length - 3;
+ }
+
+ CHECK_FOR_SPACE_LEFT(1,len);
+ buf[0] = diag->SURROGATE;
+ buf++;
+
+ CHECK_FOR_SPACE_LEFT(1,len);
+ buf[0] = END_OF_RECORD;
+ buf++;
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readDiag(diag,buffer)
+diagnosticRecord** diag;
+char* buffer;
+{
+ char* buf = buffer;
+ diagnosticRecord* d
+ = (diagnosticRecord*)s_malloc((size_t)sizeof(diagnosticRecord));
+ data_tag tag;
+ long len;
+
+ buf = readTag(&tag,buf);
+
+ buf = readBinaryInteger(&len,2,buf);
+
+ d->DIAG[0] = buf[0];
+ d->DIAG[1] = buf[1];
+ d->DIAG[2] = '\0';
+
+ if (len > 3)
+ { d->ADDINFO = (char*)s_malloc((size_t)(len - 3 + 1));
+ memcpy(d->ADDINFO,(char*)(buf + 2),(size_t)(len - 3));
+ d->ADDINFO[len - 3] = '\0';
+ }
+ else
+ d->ADDINFO = NULL;
+
+ d->SURROGATE = buf[len - 1];
+
+ *diag = d;
+
+ return(buf + len + 1);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define continueBit 0x80
+#define dataMask 0x7F
+#define dataBits 7
+
+char*
+writeCompressedInteger(num,buf,len)
+unsigned long num;
+char* buf;
+long* len;
+/* write a binary integer in the format described on p. 40.
+ this might be sped up
+*/
+{
+ char byte;
+ long i;
+ unsigned long size;
+
+ size = writtenCompressedIntSize(num);
+ CHECK_FOR_SPACE_LEFT(size,len);
+
+ for (i = size - 1; i >= 0; i--)
+ { byte = num & dataMask;
+ if (i != (size-1)) /* turn on continue bit */
+ byte = (char)(byte | continueBit);
+ buf[i] = byte;
+ num = num >> dataBits; /* don't and here */
+ }
+
+ return(buf + size);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readCompressedInteger(num,buf)
+unsigned long *num;
+char* buf;
+/* read a binary integer in the format described on p. 40.
+ this might be sped up
+*/
+{
+ long i = 0;
+ unsigned char byte;
+
+ *num = 0;
+
+ do
+ { byte = buf[i++];
+ *num = *num << dataBits;
+ *num += (byte & dataMask);
+ }
+ while (byte & continueBit);
+
+ return(buf + i);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define pad 128 /* high bit is set */
+
+char*
+writeCompressedIntWithPadding(num,size,buffer,len)
+unsigned long num;
+unsigned long size;
+char* buffer;
+long* len;
+/* Like writeCompressedInteger, except writes padding (128) to make
+ sure that size bytes are used. This can be read correctly by
+ readCompressedInteger()
+*/
+{
+ char* buf = buffer;
+ unsigned long needed,padding;
+ long i;
+
+ CHECK_FOR_SPACE_LEFT(size,len);
+
+ needed = writtenCompressedIntSize(num);
+ padding = size - needed;
+ i = padding - 1;
+
+ for (i = padding - 1;i >= 0;i--)
+ { buf[i] = pad;
+ }
+
+ buf = writeCompressedInteger(num,buf + padding,len);
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenCompressedIntSize(num)
+unsigned long num;
+/* return the number of bytes needed to represnet the value num in
+ compressed format. curently limited to 4 bytes
+ */
+{
+ if (num < CompressedInt1Byte)
+ return(1);
+ else if (num < CompressedInt2Byte)
+ return(2);
+ else if (num < CompressedInt3Byte)
+ return(3);
+ else
+ return(4);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeTag(tag,buf,len)
+data_tag tag;
+char* buf;
+long* len;
+/* write out a data tag */
+{
+ return(writeCompressedInteger(tag,buf,len));
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readTag(tag,buf)
+data_tag* tag;
+char* buf;
+/* read a data tag */
+{
+ return(readCompressedInteger(tag,buf));
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenTagSize(tag)
+data_tag tag;
+{
+ return(writtenCompressedIntSize(tag));
+}
+
+/*----------------------------------------------------------------------*/
+
+data_tag
+peekTag(buf)
+char* buf;
+/* read a data tag without advancing the buffer */
+{
+ data_tag tag;
+ readTag(&tag,buf);
+ return(tag);
+}
+
+/*----------------------------------------------------------------------*/
+
+any*
+makeAny(size,data)
+unsigned long size;
+char* data;
+{
+ any* a = (any*)s_malloc((size_t)sizeof(any));
+ a->size = size;
+ a->bytes = data;
+ return(a);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeAny(a)
+any* a;
+/* destroy an any and its associated data. Assumes a->bytes was
+ allocated using the s_malloc family of libraries
+ */
+{
+ if (a != NULL)
+ { if (a->bytes != NULL)
+ s_free(a->bytes);
+ s_free(a);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+any*
+duplicateAny(a)
+any* a;
+{
+ any* copy = NULL;
+
+ if (a == NULL)
+ return(NULL);
+
+ copy = (any*)s_malloc((size_t)sizeof(any));
+ copy->size = a->size;
+ if (a->bytes == NULL)
+ copy->bytes = NULL;
+ else
+ { copy->bytes = (char*)s_malloc((size_t)copy->size);
+ memcpy(copy->bytes,a->bytes,(size_t)copy->size);
+ }
+ return(copy);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeAny(a,tag,buffer,len)
+any* a;
+data_tag tag;
+char* buffer;
+long* len;
+/* write an any + tag and size info */
+{
+ char* buf = buffer;
+
+ if (a == NULL) /* handle unspecified optional args */
+ return(buf);
+
+ /* write the tags */
+ buf = writeTag(tag,buf,len);
+ buf = writeCompressedInteger(a->size,buf,len);
+
+ /* write the bytes */
+ CHECK_FOR_SPACE_LEFT(a->size,len);
+ memcpy(buf,a->bytes,(size_t)a->size);
+
+ return(buf+a->size);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+char *readAny(anAny,buffer)
+any** anAny;
+char* buffer;
+/* read an any + tag and size info */
+{
+ char *buf;
+ any* a;
+ data_tag tag;
+
+
+
+a=(any*)s_malloc((size_t)sizeof(any));
+
+ buf=buffer;
+
+ buf = readTag(&tag,buf);
+
+ buf = readCompressedInteger(&a->size,buf);
+
+ /* now simply copy the bytes */
+ a->bytes = (char*)s_malloc((size_t)a->size);
+ memcpy(a->bytes,buf,(size_t)a->size);
+ *anAny = a;
+
+ return(buf+a->size);
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenAnySize(tag,a)
+data_tag tag;
+any* a;
+{
+ unsigned long size;
+
+ if (a == NULL)
+ return(0);
+
+ size = writtenTagSize(tag);
+ size += writtenCompressedIntSize(a->size);
+ size += a->size;
+ return(size);
+}
+
+/*----------------------------------------------------------------------*/
+
+any*
+stringToAny(s)
+char* s;
+{
+ any* a = NULL;
+
+ if (s == NULL)
+ return(NULL);
+
+ a = (any*)s_malloc((size_t)sizeof(any));
+ a->size = strlen(s);
+ a->bytes = (char*)s_malloc((size_t)a->size);
+ memcpy(a->bytes,s,(size_t)a->size);
+ return(a);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+anyToString(a)
+any* a;
+{
+ char* s = NULL;
+
+ if (a == NULL)
+ return(NULL);
+
+ s = s_malloc((size_t)(a->size + 1));
+ memcpy(s,a->bytes,(size_t)a->size);
+ s[a->size] = '\0';
+ return(s);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeString(s,tag,buffer,len)
+char* s;
+data_tag tag;
+char* buffer;
+long* len;
+/* Write a C style string. The terminating null is not written.
+ This function is not part of the Z39.50 spec. It is provided
+ for the convienience of those wishing to pass C strings in
+ the place of an any.
+ */
+{
+ char* buf = buffer;
+ any* data = NULL;
+ if (s == NULL)
+ return(buffer); /* handle unused optional item before making an any */
+ data = (any*)s_malloc((size_t)sizeof(any));
+ data->size = strlen(s);
+ data->bytes = s; /* save a copy here by not using stringToAny() */
+ buf = writeAny(data,tag,buf,len);
+ s_free(data); /* don't use freeAny() since it will free s too */
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readString(s ,buffer)
+char** s ;
+char* buffer;
+/* Read an any and convert it into a C style string.
+ This function is not part of the Z39.50 spec. It is provided
+ for the convienience of those wishing to pass C strings in
+ the place of an any.
+ */
+{
+ any* data = NULL;
+ char* buf = readAny(&data,buffer);
+ *s = anyToString(data);
+ freeAny(data);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenStringSize(tag,s)
+data_tag tag;
+char* s;
+{
+ unsigned long size;
+
+ if (s == NULL)
+ return(0);
+
+ size = writtenTagSize(tag);
+ size += writtenCompressedIntSize(size);
+ size += strlen(s);
+ return(size);
+}
+
+/*----------------------------------------------------------------------*/
+
+any*
+longToAny(num)
+long num;
+/* a convienience function */
+{
+ char s[40];
+
+ sprintf(s,"%ld",num);
+
+ return(stringToAny(s));
+}
+
+/*----------------------------------------------------------------------*/
+
+long
+anyToLong(a)
+any* a;
+/* a convienience function */
+{
+ long num;
+ char* str = NULL;
+ str = anyToString(a);
+ sscanf(str,"%ld",&num); /* could check the result and return
+ an error */
+ s_free(str);
+ return(num);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define bitsPerByte 8
+
+bit_map*
+makeBitMap(unsigned long numBits, ...)
+/* construct and return a bitmap with numBits elements */
+{
+ va_list ap;
+ long i,j;
+ bit_map* bm = NULL;
+
+ va_start(ap,numBits);
+
+ bm = (bit_map*)s_malloc((size_t)sizeof(bit_map));
+ bm->size = (unsigned long)ceil((double)numBits / bitsPerByte);
+ bm->bytes = (char*)s_malloc((size_t)bm->size);
+
+ /* fill up the bits */
+ for (i = 0; i < bm->size; i++) /* iterate over bytes */
+ { char byte = 0;
+ for (j = 0; j < bitsPerByte; j++) /* iterate over bits */
+ { if ((i * bitsPerByte + j) < numBits)
+ { boolean bit = false;
+ bit = (boolean)va_arg(ap,boolean);
+ if (bit)
+ { byte = byte | (1 << (bitsPerByte - j - 1));
+ }
+ }
+ }
+ bm->bytes[i] = byte;
+ }
+
+ va_end(ap);
+ return(bm);
+}
+
+
+/*----------------------------------------------------------------------*/
+
+void
+freeBitMap(bm)
+bit_map* bm;
+/* destroy a bit map created by makeBitMap() */
+{
+ s_free(bm->bytes);
+ s_free(bm);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* use this routine to interpret a bit map. pos specifies the bit
+ number. bit 0 is the Leftmost bit of the first byte.
+ Could do bounds checking.
+ */
+
+boolean
+bitAtPos(pos,bm)
+long pos;
+bit_map* bm;
+{
+ if (pos > bm->size*bitsPerByte)
+ return false;
+ else
+ return((bm->bytes[(pos / bitsPerByte)] &
+ (0x80>>(pos % bitsPerByte))) ?
+ true : false);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeBitMap(bm,tag,buffer,len)
+bit_map* bm;
+data_tag tag;
+char* buffer;
+long* len;
+/* write a bitmap + type and size info */
+{
+ return(writeAny((any*)bm,tag,buffer,len));
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readBitMap(bm,buffer)
+bit_map** bm;
+char* buffer;
+/* read a bitmap + type and size info */
+{
+ char *c;
+
+
+
+c=readAny((any**)bm,buffer);
+
+ return(c);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeByte(byte,buf,len)
+unsigned long byte;
+char* buf;
+long* len;
+{
+ CHECK_FOR_SPACE_LEFT(1,len);
+ buf[0] = byte & 0xFF; /* we really only want the first byte */
+ return(buf + 1);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readByte(byte,buf)
+unsigned char* byte;
+char* buf;
+{
+ *byte = buf[0];
+ return(buf + 1);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeBoolean(flag,buf,len)
+boolean flag;
+char* buf;
+long* len;
+{
+ return(writeByte(flag,buf,len));
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readBoolean(flag,buffer)
+boolean* flag;
+char* buffer;
+{
+ unsigned char byte;
+ char* buf = readByte(&byte,buffer);
+ *flag = (byte == true) ? true : false;
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writePDUType(pduType,buf,len)
+pdu_type pduType;
+char* buf;
+long* len;
+/* PDUType is a single byte */
+{
+ return(writeBinaryInteger((long)pduType,(unsigned long)1,buf,len));
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readPDUType(pduType,buf)
+pdu_type* pduType;
+char* buf;
+/* PDUType is a single byte */
+{
+ return(readBinaryInteger((long*)pduType,(unsigned long)1,buf));
+}
+
+/*----------------------------------------------------------------------*/
+
+pdu_type
+peekPDUType(buf)
+char* buf;
+/* read the next pdu without advancing the buffer, Note that this
+ function is to be used on a buffer that is known to contain an
+ APDU. The pdu_type is written HEADER_LEN bytes into the buffer
+ */
+{
+ pdu_type pdu;
+ readPDUType(&pdu,buf + HEADER_LEN);
+ return(pdu);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define BINARY_INTEGER_BYTES sizeof(long) /* the number of bytes used by
+ a "binary integer" */
+char*
+writeBinaryInteger(num,size,buf,len)
+long num;
+unsigned long size;
+char* buf;
+long* len;
+/* write out first size bytes of num - no type info
+ XXX should this take unsigned longs instead ??? */
+{
+ long i;
+ char byte;
+
+ if (size < 1 || size > BINARY_INTEGER_BYTES)
+ return(NULL); /* error */
+
+ CHECK_FOR_SPACE_LEFT(size,len);
+
+ for (i = size - 1; i >= 0; i--)
+ { byte = (char)(num & 255);
+ buf[i] = byte;
+ num = num >> bitsPerByte; /* don't and here */
+ }
+
+ return(buf + size);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readBinaryInteger(num,size,buf)
+long* num;
+unsigned long size;
+char* buf;
+/* read in first size bytes of num - no type info
+ XXX this should take unsigned longs instead !!! */
+{
+ long i;
+ unsigned char byte;
+
+ if (size < 1 || size > BINARY_INTEGER_BYTES)
+ return(buf); /* error */
+ *num = 0;
+
+ for (i = 0; i < size; i++)
+ { byte = buf[i];
+ *num = *num << bitsPerByte;
+ *num += byte;
+ }
+
+ return(buf + size);
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenCompressedBinIntSize(num)
+long num;
+/* return the number of bytes needed to represent the value num.
+ currently limited to max of 4 bytes
+ Only compresses for positive nums - negatives get whole 4 bytes
+ */
+{
+ if (num < 0L)
+ return(4);
+ else if (num < 256L) /* 2**8 */
+ return(1);
+ else if (num < 65536L) /* 2**16 */
+ return(2);
+ else if (num < 16777216L) /* 2**24 */
+ return(3);
+ else
+ return(4);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeNum(num,tag,buffer,len)
+long num;
+data_tag tag;
+char* buffer;
+long* len;
+/* write a binary integer + size and tag info */
+{
+ char* buf = buffer;
+ long size = writtenCompressedBinIntSize(num);
+
+ if (num == UNUSED)
+ return(buffer);
+
+ buf = writeTag(tag,buf,len);
+ buf = writeCompressedInteger(size,buf,len);
+ buf = writeBinaryInteger(num,(unsigned long)size,buf,len);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readNum(num,buffer)
+long* num;
+char* buffer;
+/* read a binary integer + size and tag info */
+{
+ char* buf = buffer;
+ data_tag tag;
+ unsigned long size;
+ unsigned long val;
+
+ buf = readTag(&tag,buf);
+ buf = readCompressedInteger(&val,buf);
+ size = (unsigned long)val;
+ buf = readBinaryInteger(num,size,buf);
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+unsigned long
+writtenNumSize(tag,num)
+data_tag tag;
+long num;
+{
+ long dataSize = writtenCompressedBinIntSize(num);
+ long size;
+
+ size = writtenTagSize(tag); /* space for the tag */
+ size += writtenCompressedIntSize(dataSize); /* space for the size */
+ size += dataSize; /* space for the data */
+
+ return(size);
+}
+
+/*----------------------------------------------------------------------*/
+
+typedef void (voidfunc)();
+
+void
+doList(list,func)
+void** list;
+voidfunc *func;
+/* call func on each element of the NULL terminated list of pointers */
+{
+ register long i;
+ register void* ptr = NULL;
+ if (list == NULL)
+ return;
+ for (i = 0,ptr = list[i]; ptr != NULL; ptr = list[++i])
+ (*func)(ptr);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+writeProtocolVersion(buf,len)
+char* buf;
+long* len;
+/* write a bitmap describing the protocols available */
+{
+ static bit_map* version = NULL;
+
+ if (version == NULL)
+ { version = makeBitMap((unsigned long)1,true); /* version 1! */
+ }
+
+ return(writeBitMap(version,DT_ProtocolVersion,buf,len));
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+defaultImplementationID()
+{
+ static char ImplementationID[] = "TMC";
+ return(ImplementationID);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+defaultImplementationName()
+{
+ static char ImplementationName[] = "Thinking Machines Corporation Z39.50";
+ return(ImplementationName);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+defaultImplementationVersion()
+{
+ static char ImplementationVersion[] = "2.0A";
+ return(ImplementationVersion);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from ZType1.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
+*/
+/*----------------------------------------------------------------------*/
+
+query_term*
+makeAttributeTerm(use,
+ relation,
+ position,
+ structure,
+ truncation,
+ completeness,
+ term)
+char* use;
+char* relation;
+char* position;
+char* structure;
+char* truncation;
+char* completeness;
+any* term;
+{
+ query_term* qt = (query_term*)s_malloc((size_t)sizeof(query_term));
+
+ qt->TermType = TT_Attribute;
+
+ /* copy in the attributes */
+ strncpy(qt->Use,use,ATTRIBUTE_SIZE);
+ strncpy(qt->Relation,relation,ATTRIBUTE_SIZE);
+ strncpy(qt->Position,position,ATTRIBUTE_SIZE);
+ strncpy(qt->Structure,structure,ATTRIBUTE_SIZE);
+ strncpy(qt->Truncation,truncation,ATTRIBUTE_SIZE);
+ strncpy(qt->Completeness,completeness,ATTRIBUTE_SIZE);
+
+ qt->Term = duplicateAny(term);
+
+ qt->ResultSetID = NULL;
+
+ return(qt);
+}
+
+/*----------------------------------------------------------------------*/
+
+query_term*
+makeResultSetTerm(resultSet)
+any* resultSet;
+{
+ query_term* qt = (query_term*)s_malloc((size_t)sizeof(query_term));
+
+ qt->TermType = TT_ResultSetID;
+
+ qt->ResultSetID = duplicateAny(resultSet);
+
+ qt->Term = NULL;
+
+ return(qt);
+}
+
+/*----------------------------------------------------------------------*/
+
+query_term*
+makeOperatorTerm(operatorCode)
+char* operatorCode;
+{
+ query_term* qt = (query_term*)s_malloc((size_t)sizeof(query_term));
+
+ qt->TermType = TT_Operator;
+
+ strncpy(qt->Operator,operatorCode,OPERATOR_SIZE);
+
+ qt->Term = NULL;
+ qt->ResultSetID = NULL;
+
+ return(qt);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+freeTerm(qt)
+query_term* qt;
+{
+ switch (qt->TermType)
+ { case TT_Attribute:
+ freeAny(qt->Term);
+ break;
+ case TT_ResultSetID:
+ freeAny(qt->ResultSetID);
+ break;
+ case TT_Operator:
+ /* do nothing */
+ break;
+ default:
+ panic("Implementation error: Unknown term type %ld",
+ qt->TermType);
+ break;
+ }
+ s_free(qt);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define ATTRIBUTE_LIST_SIZE ATTRIBUTE_SIZE * 6
+#define AT_DELIMITER " "
+
+char*
+writeQueryTerm(qt,buffer,len)
+query_term* qt;
+char* buffer;
+long* len;
+{
+ char* buf = buffer;
+ char attributes[ATTRIBUTE_LIST_SIZE];
+
+ switch (qt->TermType)
+ { case TT_Attribute:
+ strncpy(attributes,qt->Use,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,AT_DELIMITER,sizeof(AT_DELIMITER) + 1,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,qt->Relation,ATTRIBUTE_SIZE,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,AT_DELIMITER,sizeof(AT_DELIMITER) + 1,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,qt->Position,ATTRIBUTE_SIZE,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,AT_DELIMITER,sizeof(AT_DELIMITER) + 1,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,qt->Structure,ATTRIBUTE_SIZE,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,AT_DELIMITER,sizeof(AT_DELIMITER) + 1,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,qt->Truncation,ATTRIBUTE_SIZE,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,AT_DELIMITER,sizeof(AT_DELIMITER) + 1,ATTRIBUTE_LIST_SIZE);
+ s_strncat(attributes,qt->Completeness,ATTRIBUTE_SIZE,ATTRIBUTE_LIST_SIZE);
+ buf = writeString(attributes,DT_AttributeList,buf,len);
+ buf = writeAny(qt->Term,DT_Term,buf,len);
+ break;
+ case TT_ResultSetID:
+ buf = writeAny(qt->ResultSetID,DT_ResultSetID,buf,len);
+ break;
+ case TT_Operator:
+ buf = writeString(qt->Operator,DT_Operator,buf,len);
+ break;
+ default:
+ panic("Implementation error: Unknown term type %ld",
+ qt->TermType);
+ break;
+ }
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+readQueryTerm(qt,buffer)
+query_term** qt;
+char* buffer;
+{
+ char* buf = buffer;
+ char *attributeList = NULL;
+ char* operator = NULL;
+ any* term;
+ char* use = NULL;
+ char* relation = NULL;
+ char* position = NULL;
+ char* structure = NULL;
+ char* truncation = NULL;
+ char* completeness;
+ any* resultSetID = NULL;
+ data_tag tag;
+
+
+ tag = peekTag(buffer);
+
+ switch(tag)
+ { case DT_AttributeList:
+ buf = readString(&attributeList,buf);
+ buf = readAny(&term,buf);
+ use = strtok(attributeList,AT_DELIMITER);
+ relation = strtok(NULL,AT_DELIMITER);
+ position = strtok(NULL,AT_DELIMITER);
+ structure = strtok(NULL,AT_DELIMITER);
+ truncation = strtok(NULL,AT_DELIMITER);
+ completeness = strtok(NULL,AT_DELIMITER);
+ *qt = makeAttributeTerm(use,relation,position,structure,
+ truncation,completeness,term);
+ s_free(attributeList);
+ freeAny(term);
+ break;
+ case DT_ResultSetID:
+ buf = readAny(&resultSetID,buf);
+ *qt = makeResultSetTerm(resultSetID);
+ freeAny(resultSetID);
+ break;
+ case DT_Operator:
+ buf = readString(&operator,buf);
+ *qt = makeOperatorTerm(operator);
+ s_free(operator);
+ break;
+ default:
+ REPORT_READ_ERROR(buf);
+ break;
+ }
+
+ return(buf);
+}
+
+/*----------------------------------------------------------------------*/
+
+static unsigned long getQueryTermSize _AP((query_term* qt));
+
+static unsigned long
+getQueryTermSize(qt)
+query_term* qt;
+/* figure out how many bytes it will take to write this query */
+{
+ unsigned long size;
+ static char attributes[] = "11 22 33 44 55 66"; /* we just need this to
+ calculate its written
+ size */
+
+ switch (qt->TermType)
+ { case TT_Attribute:
+ size = writtenStringSize(DT_AttributeList,attributes);
+ size += writtenAnySize(DT_Term,qt->Term);
+ break;
+ case TT_ResultSetID:
+ size = writtenAnySize(DT_ResultSetID,qt->ResultSetID);
+ break;
+ case TT_Operator:
+ size = writtenStringSize(DT_Operator,qt->Operator);
+ break;
+ default:
+ panic("Implementation error: Unknown term type %ld",
+ qt->TermType);
+ break;
+ }
+
+ return(size);
+}
+
+/*----------------------------------------------------------------------*/
+
+/* A query is simply a null terminated list of query terms. For
+ transmission, a query is written into an any which is sent as
+ the user information field. */
+
+any*
+writeQuery(terms)
+query_term** terms;
+{
+ any* info = NULL;
+ char* writePos = NULL;
+ char* data = NULL;
+ unsigned long size = 0;
+ long remaining = 0;
+ long i;
+ query_term* qt = NULL;
+
+ if (terms == NULL)
+ return(NULL);
+
+ /* calculate the size of write buffer */
+ for (i = 0,qt = terms[i]; qt != NULL; qt = terms[++i])
+ size += getQueryTermSize(qt);
+
+ data = (char*)s_malloc((size_t)size);
+
+ /* write the terms */
+ writePos = data;
+ remaining = size;
+ for (i = 0,qt = terms[i]; qt != NULL; qt = terms[++i])
+ writePos = writeQueryTerm(qt,writePos,&remaining);
+
+ info = makeAny(size,data);
+
+ return(info);
+}
+
+/*----------------------------------------------------------------------*/
+
+query_term**
+readQuery(info)
+any *info;
+{
+ char* readPos = info->bytes;
+ query_term** terms = NULL;
+ query_term* qt = NULL;
+ long numTerms = 0L;
+char tmp[100];
+
+sprintf(tmp,"readquery: bytes: %ld",info->size);
+log_write(tmp);
+
+ while (readPos < info->bytes + info->size)
+ { readPos = readQueryTerm(&qt,readPos);
+
+ if (terms == NULL)
+ { terms = (query_term**)s_malloc((size_t)(sizeof(query_term*)*2));
+ }
+ else
+ { terms =
+ (query_term**)s_realloc((char*)terms,
+ (size_t)(sizeof(query_term*)*(numTerms+2)));
+ }
+if(qt==NULL)
+ log_write("qt = null");
+ terms[numTerms++] = qt;
+ terms[numTerms] = NULL;
+ }
+
+ return(terms);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from panic.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ Morris@think.com
+*/
+
+/* panic is an error system interface. On the Mac, it will pop
+ * up a little window to explain the problem.
+ * On a unix box, it will print out the error and call perror()
+ */
+
+/*----------------------------------------------------------------------*/
+
+static void exitAction _AP((long error));
+
+static void
+exitAction(error)
+long error;
+{
+ long i;
+ for (i = 0; i < 100000; i++)
+ ;
+ exit(0);
+}
+
+/*----------------------------------------------------------------------*/
+
+#define PANIC_HEADER "Fatal Error: "
+
+void
+panic(char *format, ...)
+{
+ va_list ap; /* the variable arguments */
+
+ fprintf(stderr,PANIC_HEADER);
+ va_start(ap, format); /* init ap */
+ vfprintf(stderr,format,ap); /* print the contents */
+ va_end(ap); /* free ap */
+ fflush(stderr);
+
+ exitAction(0);
+}
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from cutil.c -- FM
+**
+**----------------------------------------------------------------------*/
+/* Wide AREA INFORMATION SERVER SOFTWARE
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ 3.26.90 Harry Morris, morris@think.com
+ 4.11.90 HWM - generalized conditional includes (see c-dialect.h)
+*/
+
+#include <varargs.h>
+
+
+/*----------------------------------------------------------------------*/
+
+void
+fs_checkPtr(ptr)
+void* ptr;
+/* If the ptr is NULL, give an error */
+{
+ if (ptr == NULL)
+ panic("checkPtr found a NULL pointer");
+}
+
+/*----------------------------------------------------------------------*/
+
+void*
+fs_malloc(size)
+size_t size;
+/* does safety checks and optional accounting */
+{
+ register void* ptr = NULL;
+
+ ptr = (void*)calloc((size_t)size,(size_t)1);
+ s_checkPtr(ptr);
+
+ return(ptr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void*
+fs_realloc(ptr,size)
+void* ptr;
+size_t size;
+/* does safety checks and optional accounting
+ note - we don't know how big ptr's memory is, so we can't ensure
+ that any new memory allocated is NULLed!
+ */
+{
+ register void* nptr = NULL;
+
+ if (ptr == NULL) /* this is really a malloc */
+ return(s_malloc(size));
+
+ nptr = (void*)realloc(ptr,size);
+ s_checkPtr(ptr);
+
+ return(nptr);
+}
+
+/*----------------------------------------------------------------------*/
+
+void
+fs_free(ptr)
+void* ptr;
+/* does safety checks and optional accounting */
+{
+ if (ptr != NULL) /* some non-ansi compilers/os's cant handle freeing null */
+ { /* if we knew the size of this block of memory, we could clear it - oh well */
+ free(ptr);
+ ptr = NULL;
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+s_strdup(s)
+char* s;
+
+/* return a copy of s. This is identical to the standard library routine
+ strdup(), except that it is safe. If s == NULL or malloc fails,
+ appropriate action is taken.
+ */
+{
+ unsigned long len;
+ char* copy = NULL;
+
+ if (s == NULL) /* saftey check to postpone stupid errors */
+ return(NULL);
+
+ len = strlen(s); /* length of string - terminator */
+ copy = (char*)s_malloc((size_t)(sizeof(char)*(len + 1)));
+ strncpy(copy,s,len + 1);
+ return(copy);
+}
+
+/*----------------------------------------------------------------------*/
+
+char*
+fs_strncat(dst,src,maxToAdd,maxTotal)
+char* dst;
+ char* src;
+ size_t maxToAdd;
+ size_t maxTotal;
+
+/* like strncat, except the fourth argument limits the maximum total
+ length of the resulting string
+ */
+{
+ size_t dstSize = strlen(dst);
+ size_t srcSize = strlen(src);
+
+ if (dstSize + srcSize < maxTotal) /* use regular old strncat */
+ return(strncat(dst,src,maxToAdd));
+ else
+ { size_t truncateTo = maxTotal - dstSize - 1;
+ char saveChar = src[truncateTo];
+ char* result = NULL;
+ src[truncateTo] = '\0';
+ result = strncat(dst,src,maxToAdd);
+ src[truncateTo] = saveChar;
+ return(result);
+ }
+}
+
+/*----------------------------------------------------------------------*/
+
+char char_downcase(long_ch)
+unsigned long long_ch;
+{
+ unsigned char ch = long_ch & 0xFF; /* just want one byte */
+ /* when ansi is the way of the world, this can be tolower */
+ return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' -'A') : ch);
+}
+
+char *string_downcase(word)
+char *word;
+{
+ long i = 0;
+ while(word[i] != '\0'){
+ word[i] = char_downcase((unsigned long)word[i]);
+ i++;
+ }
+ return(word);
+}
+
+/*----------------------------------------------------------------------*/
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.h
new file mode 100644
index 00000000000..6f492b878e4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTVMS_WaisUI.h
@@ -0,0 +1,674 @@
+/* HTVMS_WAISUI.h
+**
+** Adaptation for Lynx by F.Macrides (macrides@sci.wfeb.edu)
+**
+** 31-May-1994 FM Initial version.
+*/
+
+#ifndef HTVMSWAIS_H
+#define HTVMSWAIS_H
+
+#ifndef __STDLIB_LOADED
+#include <stdlib.h>
+#endif /* __STDLIB_LOADED */
+
+#define _AP(args) ()
+
+void log_write _AP((char *));
+
+/*
+** Routines originally from Panic.h -- FM
+**
+**----------------------------------------------------------------------*/
+
+void panic (char* format,...);
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from CUtil.h -- FM
+**
+**----------------------------------------------------------------------*/
+
+/* types and constants */
+
+#ifndef boolean
+#define boolean unsigned long
+#endif /* boolean */
+
+#ifndef true
+#define true (boolean)1L
+#endif /* true */
+
+#ifndef false
+#define false (boolean)0L /* used to be (!true), but broke
+ some compilers */
+#endif /* false */
+
+#ifndef TRUE
+#define TRUE true
+#endif /* TRUE */
+
+#ifndef FALSE
+#define FALSE false
+#endif /* FALSE */
+
+/*----------------------------------------------------------------------*/
+/* functions */
+
+/* enhanced memory handling functions - don't call them directly, use the
+ macros below */
+void fs_checkPtr _AP((void* ptr));
+void* fs_malloc _AP((size_t size));
+void* fs_realloc _AP((void* ptr,size_t size));
+void fs_free _AP((void* ptr));
+char* fs_strncat _AP((char* dst,char* src,size_t maxToAdd,size_t maxTotal));
+
+/* macros for memory functions. call these in your program. */
+#define s_checkPtr(ptr) fs_checkPtr(ptr)
+#define s_malloc(size) fs_malloc(size)
+#define s_realloc(ptr,size) fs_realloc((ptr),(size))
+#define s_free(ptr) { fs_free((char*)ptr); ptr = NULL; }
+#define s_strncat(dst,src,maxToAdd,maxTotal) fs_strncat((dst),(src),(maxToAdd),(maxTotal))
+
+char* s_strdup _AP((char* s));
+
+#define IS_DELIMITER 1
+#define NOT_DELIMITER !IS_DELIMITER
+
+char char_downcase _AP((unsigned long ch));
+char *string_downcase _AP((char* word));
+
+/*----------------------------------------------------------------------*/
+
+
+
+/*
+** Routines originally from ZUtil.c -- FM
+**
+**----------------------------------------------------------------------*/
+
+/* Data types / constants */
+
+/* bytes to leave for the header size info */
+#define HEADER_LEN (size_t)2
+
+typedef long pdu_type;
+
+#define initAPDU (pdu_type)20
+#define initResponseAPDU (pdu_type)21
+#define searchAPDU (pdu_type)22
+#define searchResponseAPDU (pdu_type)23
+#define presentAPDU (pdu_type)24
+#define presentResponseAPDU (pdu_type)25
+#define deteteAPDU (pdu_type)26
+#define deleteResponseAPDU (pdu_type)27
+#define accessControlAPDU (pdu_type)28
+#define accessControlResponseAPDU (pdu_type)29
+#define resourceControlAPDU (pdu_type)30
+#define resourceControlResponseAPDU (pdu_type)31
+
+typedef struct any { /* an any is a non-ascii string of characters */
+ unsigned long size;
+ char* bytes;
+ } any;
+
+typedef any bit_map; /* a bit_map is a group of packed bits */
+
+typedef unsigned long data_tag;
+
+#define DT_PDUType (data_tag)1
+#define DT_ReferenceID (data_tag)2
+#define DT_ProtocolVersion (data_tag)3
+#define DT_Options (data_tag)4
+#define DT_PreferredMessageSize (data_tag)5
+#define DT_MaximumRecordSize (data_tag)6
+#define DT_IDAuthentication (data_tag)7
+#define DT_ImplementationID (data_tag)8
+#define DT_ImplementationName (data_tag)9
+#define DT_ImplementationVersion (data_tag)10
+#define DT_UserInformationField (data_tag)11
+#define DT_Result (data_tag)12
+#define DT_SmallSetUpperBound (data_tag)13
+#define DT_LargeSetLowerBound (data_tag)14
+#define DT_MediumSetPresentNumber (data_tag)15
+#define DT_ReplaceIndicator (data_tag)16
+#define DT_ResultSetName (data_tag)17
+#define DT_DatabaseNames (data_tag)18
+#define DT_ElementSetNames (data_tag)19
+#define DT_QueryType (data_tag)20
+#define DT_Query (data_tag)21
+#define DT_SearchStatus (data_tag)22
+#define DT_ResultCount (data_tag)23
+#define DT_NumberOfRecordsReturned (data_tag)24
+#define DT_NextResultSetPosition (data_tag)25
+#define DT_ResultSetStatus (data_tag)26
+#define DT_PresentStatus (data_tag)27
+#define DT_DatabaseDiagnosticRecords (data_tag)28
+#define DT_NumberOfRecordsRequested (data_tag)29
+#define DT_ResultSetStartPosition (data_tag)30
+#define DT_ResultSetID (data_tag)31
+#define DT_DeleteOperation (data_tag)32
+#define DT_DeleteStatus (data_tag)33
+#define DT_NumberNotDeleted (data_tag)34
+#define DT_BulkStatuses (data_tag)35
+#define DT_DeleteMSG (data_tag)36
+#define DT_SecurityChallenge (data_tag)37
+#define DT_SecurityChallengeResponse (data_tag)38
+#define DT_SuspendedFlag (data_tag)39
+#define DT_ResourceReport (data_tag)40
+#define DT_PartialResultsAvailable (data_tag)41
+#define DT_ContinueFlag (data_tag)42
+#define DT_ResultSetWanted (data_tag)43
+
+#define UNUSED -1
+
+/* number of bytes required to represent the following sizes in compressed
+ integer format
+ */
+#define CompressedInt1Byte 128 /* 2 ^ 7 */
+#define CompressedInt2Byte 16384 /* 2 ^ 14 */
+#define CompressedInt3Byte 2097152 /* 2 ^ 21 */
+/* others may follow ... */
+
+/* types of query */
+#define QT_0 "0" /* query whose non-standard format has been agreed upon
+ client and server */
+/* values for InitAPDU option element */
+#define WILL_USE TRUE
+#define WILL_NOT_USE FALSE
+#define WILL_SUPPORT TRUE
+#define WILL_NOT_SUPPORT FALSE
+
+/* values for InitResponseAPDU result element */
+#define ACCEPT TRUE
+#define REJECT FALSE
+
+/* values for SearchAPDU replace indicator element */
+#define ON TRUE
+#define OFF FALSE
+
+/* values for SearchResponseAPDU search status element */
+#define SUCCESS 0 /* intuitive huh? */
+#define FAILURE 1
+
+/* values for SearchResponseAPDU result set status element */
+#define SUBSET 1
+#define INTERIM 2
+#define NONE 3
+
+/* values for SearchResponseAPDU present status element */
+/* SUCCESS already defined */
+#define PARTIAL_1 1
+#define PARTIAL_2 2
+#define PARTIAL_3 3
+#define PARTIAL_4 4
+#define PS_NONE 5 /* can't use NONE since it was used by result
+ set status */
+
+#define DIAGNOSTIC_CODE_SIZE (size_t)3
+
+typedef struct diagnosticRecord
+ { boolean SURROGATE;
+ char DIAG[DIAGNOSTIC_CODE_SIZE];
+ char* ADDINFO;
+ } diagnosticRecord;
+
+#define D_PermanentSystemError "S1"
+#define D_TemporarySystemError "S2"
+#define D_UnsupportedSearch "S3"
+#define D_TermsOnlyStopWords "S5"
+#define D_TooManyArgumentWords "S6"
+#define D_TooManyBooleanOperators "S7"
+#define D_TooManyTruncatedWords "S8"
+#define D_TooMany IncompleteSubfields "S9"
+#define D_TruncatedWordsTooShort "SA"
+#define D_InvalidFormatForRecordNumber "SB"
+#define D_TooManyCharactersInSearch "SC"
+#define D_TooManyRecordsRetrieved "SD"
+#define D_PresentRequestOutOfRange "SF"
+#define D_SystemErrorInPresentRecords "SG"
+#define D_RecordNotAuthorizedToBeSent "SH"
+#define D_RecordExceedsPrefMessageSize "SI"
+#define D_RecordExceedsMaxRecordSize "SJ"
+#define D_ResultSetNotSuppAsSearchTerm "SK"
+#define D_OnlyOneRsltSetAsSrchTermSupp "SL"
+#define D_OnlyANDingOfASnglRsltSetSupp "SM"
+#define D_RsltSetExistsNoReplace "SN"
+#define D_ResultSetNamingNotSupported "SO"
+#define D_CombinationDatabasesNotSupp "SP"
+#define D_ElementSetNamesNotSupported "SQ"
+#define D_ElementSetNameNotValid "SR"
+#define D_OnlyASingleElmntSetNameSupp "SS"
+#define D_ResultSetDeletedByTarget "ST"
+#define D_ResultSetIsInUse "SU"
+#define D_DatabasesIsLocked "SV"
+#define D_TerminatedByNoContinueResp "SW"
+#define D_ResultSetDoesNotExist "SX"
+#define D_ResExNoResultsAvailable "SY"
+#define D_ResExUnpredictableResults "SZ"
+#define D_ResExValidSubsetOfResults "T1"
+#define D_AccessControlFailure "T2"
+#define D_SecurityNotIssuedReqTerm "T3"
+#define D_SecurityNotBeIssuedRecNotInc "T4"
+
+/*----------------------------------------------------------------------*/
+
+/* for internal error handling */
+
+extern char* readErrorPosition; /* pos where buf stoped making sense */
+
+/* the following are macros so that they can return OUT of the function
+ which calls them
+ */
+
+#define RETURN_ON_NULL(var) \
+ if (var == NULL) \
+ return(NULL); /* jump out of caller */
+
+#define REPORT_READ_ERROR(pos) \
+ { readErrorPosition = (pos); \
+ return(NULL); /* jump out of caller */ \
+ }
+
+#define CHECK_FOR_SPACE_LEFT(spaceNeeded,spaceLeft) \
+ { if (*spaceLeft >= spaceNeeded) \
+ (*spaceLeft) -= spaceNeeded; \
+ else \
+ { *spaceLeft = 0; \
+ return(NULL); /* jump out of the caller */ \
+ } \
+ }
+
+/*----------------------------------------------------------------------*/
+
+diagnosticRecord* makeDiag _AP((boolean surrogate,char* code,char* addInfo));
+void freeDiag _AP((diagnosticRecord* diag));
+char* writeDiag _AP((diagnosticRecord* diag,char* buffer,long* len));
+char* readDiag _AP((diagnosticRecord** diag,char* buffer));
+
+char* writeCompressedInteger _AP((unsigned long num,char* buf,long* len));
+char* readCompressedInteger _AP((unsigned long *num,char* buf));
+char* writeCompressedIntWithPadding _AP((unsigned long num,unsigned long size,
+ char* buffer,long* len));
+unsigned long writtenCompressedIntSize _AP((unsigned long num));
+
+char* writeTag _AP((data_tag tag,char* buf,long* len));
+char* readTag _AP((data_tag* tag,char* buf));
+data_tag peekTag _AP((char* buf));
+unsigned long writtenTagSize _AP((data_tag tag));
+
+any* makeAny _AP((unsigned long size,char* data));
+void freeAny _AP((any* a));
+any* duplicateAny _AP((any* a));
+char* writeAny _AP((any* a,data_tag tag,char* buffer,long* len));
+char* readAny _AP((any** anAny,char* buffer));
+unsigned long writtenAnySize _AP((data_tag tag,any* a));
+
+any* stringToAny _AP((char* s));
+char* anyToString _AP((any* a));
+unsigned long writtenStringSize _AP((data_tag tag,char* s));
+
+any* longToAny _AP((long Num));
+long anyToLong _AP((any* a));
+
+char* writeString _AP((char* s,data_tag tag,char* buffer,long* len));
+char* readString _AP((char** s,char* buffer));
+
+bit_map* makeBitMap (unsigned long numBits,...);
+
+void freeBitMap _AP((bit_map* bm));
+boolean bitAtPos _AP((long pos,bit_map* bm));
+char* writeBitMap _AP((bit_map* bm,data_tag tag,char* buffer,long* len));
+char* readBitMap _AP((bit_map** bm,char* buffer));
+
+char* writeByte _AP((unsigned long byte,char* buf,long* len));
+char* readByte _AP((unsigned char* byte,char* buf));
+
+char* writeBoolean _AP((boolean flag,char* buf,long* len));
+char* readBoolean _AP((boolean* flag,char* buf));
+
+char* writePDUType _AP((pdu_type pduType,char* buf,long* len));
+char* readPDUType _AP((pdu_type* pduType,char* buf));
+pdu_type peekPDUType _AP((char* buf));
+
+char* writeBinaryInteger _AP((long num,unsigned long size,
+ char* buf,long* len));
+char* readBinaryInteger _AP((long* num,unsigned long size,char* buf));
+unsigned long writtenCompressedBinIntSize _AP((long num));
+
+char* writeNum _AP((long num,data_tag tag,char* buffer,long* len));
+char* readNum _AP((long* num,char* buffer));
+unsigned long writtenNumSize _AP((data_tag tag,long num));
+
+void doList _AP((void** list,void (*func)()));
+
+char* writeProtocolVersion _AP((char* buf,long* len));
+char* defaultImplementationID _AP((void));
+char* defaultImplementationName _AP((void));
+char* defaultImplementationVersion _AP((void));
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from ZType1.c -- FM
+**
+**----------------------------------------------------------------------*/
+
+/* This file implements the type 1 query defined in appendices B & C
+ of the SR 1 spec.
+ */
+
+/*----------------------------------------------------------------------*/
+/* types and constants */
+
+/* new data tags */
+#define DT_AttributeList (data_tag)44
+#define DT_Term (data_tag)45
+#define DT_Operator (data_tag)46
+
+#define QT_BooleanQuery "1" /* standard boolean query */
+
+/* general attribute code - use in place of any attribute */
+#define IGNORE "ig"
+
+/* use value codes */
+#define UV_ISBN "ub"
+#define CORPORATE_NAME "uc"
+#define ISSN "us"
+#define PERSONAL_NAME "up"
+#define SUBJECT "uj"
+#define TITLE "ut"
+#define GEOGRAPHIC_NAME "ug"
+#define CODEN "ud"
+#define SUBJECT_SUBDIVISION "ue"
+#define SERIES_TITLE "uf"
+#define MICROFORM_GENERATION "uh"
+#define PLACE_OF_PUBLICATION "ui"
+#define NUC_CODE "uk"
+#define LANGUAGE "ul"
+#define COMBINATION_OF_USE_VALUES "um"
+#define SYSTEM_CONTROL_NUMBER "un"
+#define DATE "uo"
+#define LC_CONTROL_NUMBER "ur"
+#define MUSIC_PUBLISHERS_NUMBER "uu"
+#define GOVERNMENT_DOCUMENTS_NUMBER "uv"
+#define SUBJECT_CLASSIFICATION "uw"
+#define RECORD_TYPE "uy"
+
+/* relation value codes */
+#define EQUAL "re"
+#define GREATER_THAN "rg"
+#define GREATER_THAN_OR_EQUAL "ro"
+#define LESS_THAN "rl"
+#define LESS_THAN_OR_EQUAL "rp"
+#define NOT_EQUAL "rn"
+
+/* position value codes */
+#define FIRST_IN_FIELD "pf"
+#define FIRST_IN_SUBFIELD "ps"
+#define FIRST_IN_A_SUBFIELD "pa"
+#define FIRST_IN_NOT_A_SUBFIELD "pt"
+#define ANY_POSITION_IN_FIELD "py"
+
+/* structure value codes */
+#define PHRASE "sp"
+#define WORD "sw"
+#define KEY "sk"
+#define WORD_LIST "sl"
+
+/* truncation value codes */
+#define NO_TRUNCATION "tn"
+#define RIGHT_TRUNCATION "tr"
+#define PROC_NUM_INCLUDED_IN_SEARCH_ARG "ti"
+
+/* completeness value codes */
+#define INCOMPLETE_SUBFIELD "ci"
+#define COMPLETE_SUBFIELD "cs"
+#define COMPLETEFIELD "cf"
+
+/* operator codes */
+#define AND "a"
+#define OR "o"
+#define AND_NOT "n"
+
+/* term types */
+#define TT_Attribute 1
+#define TT_ResultSetID 2
+#define TT_Operator 3
+
+#define ATTRIBUTE_SIZE 3
+#define OPERATOR_SIZE 2
+
+typedef struct query_term {
+ /* type */
+ long TermType;
+ /* for term */
+ char Use[ATTRIBUTE_SIZE];
+ char Relation[ATTRIBUTE_SIZE];
+ char Position[ATTRIBUTE_SIZE];
+ char Structure[ATTRIBUTE_SIZE];
+ char Truncation[ATTRIBUTE_SIZE];
+ char Completeness[ATTRIBUTE_SIZE];
+ any* Term;
+ /* for result set */
+ any* ResultSetID;
+ /* for operator */
+ char Operator[OPERATOR_SIZE];
+} query_term;
+
+/*----------------------------------------------------------------------*/
+/* functions */
+
+query_term* makeAttributeTerm _AP((
+ char* use,char* relation,char* position,char* structure,
+ char* truncation,char* completeness,any* term));
+query_term* makeResultSetTerm _AP((any* resultSet));
+query_term* makeOperatorTerm _AP((char* operatorCode));
+void freeTerm _AP((query_term* qt));
+char* writeQueryTerm _AP((query_term* qt,char* buffer,long* len));
+char* readQueryTerm _AP((query_term** qt,char* buffer));
+any* writeQuery _AP((query_term** terms));
+query_term** readQuery _AP((any* info));
+
+/*----------------------------------------------------------------------*/
+
+
+/*
+** Routines originally from UI.c -- FM
+**
+**----------------------------------------------------------------------*/
+
+char *
+generate_search_apdu _AP((char* buff, /* buffer to hold the apdu */
+ long *buff_len, /* number of bytes written to the buffer */
+ char *seed_words, /* string of the seed words */
+ char *database_name,
+ DocObj** docobjs,
+ long maxDocsRetrieved
+ ));
+
+char *
+generate_retrieval_apdu _AP((char *buff,
+ long *buff_len,
+ any *docID,
+ long chunk_type,
+ long start_line, long end_line,
+ char *type,
+ char *database_name));
+
+
+long
+interpret_message _AP((char *request_message,
+ long request_length,
+ char *response_message,
+ long response_buffer_length, /* length of the buffer (modified)*/
+ FILE *connection,
+ boolean verbose));
+
+
+void
+display_text_record_completely _AP((WAISDocumentText *record,
+ boolean quote_string_quotes));
+
+char *trim_junk _AP((char *headline));
+
+
+
+/*
+** Routines originally from ZProt.c -- FM
+**
+**----------------------------------------------------------------------*/
+
+/* APDU types */
+
+typedef struct InitAPDU {
+ pdu_type PDUType;
+ boolean willSearch,willPresent,willDelete;
+ boolean supportAccessControl,supportResourceControl;
+ long PreferredMessageSize;
+ long MaximumRecordSize;
+ char* IDAuthentication;
+ char* ImplementationID;
+ char* ImplementationName;
+ char* ImplementationVersion;
+ any* ReferenceID;
+ void* UserInformationField;
+ } InitAPDU;
+
+typedef struct InitResponseAPDU {
+ pdu_type PDUType;
+ boolean Result;
+ boolean willSearch,willPresent,willDelete;
+ boolean supportAccessControl,supportResourceControl;
+ long PreferredMessageSize;
+ long MaximumRecordSize;
+ char* IDAuthentication;
+ char* ImplementationID;
+ char* ImplementationName;
+ char* ImplementationVersion;
+ any* ReferenceID;
+ void* UserInformationField;
+ } InitResponseAPDU;
+
+typedef struct SearchAPDU {
+ pdu_type PDUType;
+ long SmallSetUpperBound;
+ long LargeSetLowerBound;
+ long MediumSetPresentNumber;
+ boolean ReplaceIndicator;
+ char* ResultSetName;
+ char** DatabaseNames;
+ char* QueryType;
+ char** ElementSetNames;
+ any* ReferenceID;
+ void* Query;
+ } SearchAPDU;
+
+typedef struct SearchResponseAPDU {
+ pdu_type PDUType;
+ long SearchStatus;
+ long ResultCount;
+ long NumberOfRecordsReturned;
+ long NextResultSetPosition;
+ long ResultSetStatus;
+ long PresentStatus;
+ any* ReferenceID;
+ void* DatabaseDiagnosticRecords;
+ } SearchResponseAPDU;
+
+typedef struct PresentAPDU {
+ pdu_type PDUType;
+ long NumberOfRecordsRequested;
+ long ResultSetStartPosition;
+ char* ResultSetID;
+ char* ElementSetNames;
+ any* ReferenceID;
+ void* PresentInfo;
+ } PresentAPDU;
+
+typedef struct PresentResponseAPDU {
+ pdu_type PDUType;
+ boolean PresentStatus;
+ long NumberOfRecordsReturned;
+ long NextResultSetPosition;
+ any* ReferenceID;
+ void* DatabaseDiagnosticRecords;
+ } PresentResponseAPDU;
+
+/*----------------------------------------------------------------------*/
+/* Functions */
+
+InitAPDU* makeInitAPDU _AP((boolean search,boolean present,boolean deleteIt,
+ boolean accessControl,boolean resourceControl,
+ long prefMsgSize,long maxMsgSize,
+ char* auth,char* id,char* name, char* version,
+ any* refID,void* userInfo));
+void freeInitAPDU _AP((InitAPDU* init));
+char* writeInitAPDU _AP((InitAPDU* init,char* buffer,long* len));
+char* readInitAPDU _AP((InitAPDU** init,char* buffer));
+
+InitResponseAPDU* makeInitResponseAPDU _AP((boolean result,
+ boolean search,boolean present,boolean deleteIt,
+ boolean accessControl,boolean resourceControl,
+ long prefMsgSize,long maxMsgSize,
+ char* auth,char* id,char* name, char* version,
+ any* refID,void* userInfo));
+void freeInitResponseAPDU _AP((InitResponseAPDU* init));
+char* writeInitResponseAPDU _AP((InitResponseAPDU* init,char* buffer,long* len));
+char* readInitResponseAPDU _AP((InitResponseAPDU** init,char* buffer));
+InitResponseAPDU* replyToInitAPDU _AP((InitAPDU* init,boolean result,void* userInfo));
+
+SearchAPDU* makeSearchAPDU _AP((long small,long large, long medium,
+ boolean replace,char* name,char** databases,
+ char* type,char** elements,any* refID,void* queryInfo));
+void freeSearchAPDU _AP((SearchAPDU* query));
+char* writeSearchAPDU _AP((SearchAPDU* query,char* buffer,long* len));
+char* readSearchAPDU _AP((SearchAPDU** query,char* buffer));
+
+SearchResponseAPDU* makeSearchResponseAPDU _AP((long result,long count,
+ long recordsReturned,long nextPos,
+ long resultStatus,long presentStatus,
+ any* refID,void* records));
+void freeSearchResponseAPDU _AP((SearchResponseAPDU* queryResponse));
+char* writeSearchResponseAPDU _AP((SearchResponseAPDU* queryResponse,char* buffer,long* len));
+char* readSearchResponseAPDU _AP((SearchResponseAPDU** queryResponse,char* buffer));
+
+PresentAPDU* makePresentAPDU _AP((long recsReq, long startPos,
+ char* resultID,any* refID,void* info));
+void freePresentAPDU _AP((PresentAPDU* present));
+char* writePresentAPDU _AP((PresentAPDU* present,char* buffer,long* len));
+char* readPresentAPDU _AP((PresentAPDU** present,char* buffer));
+
+PresentResponseAPDU* makePresentResponseAPDU _AP((boolean status,long recsRet,
+ long nextPos,any* refID,
+ void* records));
+void freePresentResponseAPDU _AP((PresentResponseAPDU* present));
+char* writePresentResponseAPDU _AP((PresentResponseAPDU* present,char* buffer,long* len));
+char* readPresentResponseAPDU _AP((PresentResponseAPDU** present,char* buffer));
+
+/*----------------------------------------------------------------------*/
+/* user extension hooks: */
+
+extern char* writeInitInfo _AP((InitAPDU* init,char* buffer,long* len));
+extern char* readInitInfo _AP((void** info,char* buffer));
+
+extern char* writeInitResponseInfo _AP((InitResponseAPDU* init,char* buffer,long* len));
+extern char* readInitResponseInfo _AP((void** info,char* buffer));
+
+extern char* writeSearchInfo _AP((SearchAPDU* query,char* buffer,long* len));
+extern char* readSearchInfo _AP((void** info,char* buffer));
+
+extern char* writeSearchResponseInfo _AP((SearchResponseAPDU* query,char* buffer,long* len));
+extern char* readSearchResponseInfo _AP((void** info,char* buffer));
+
+extern char* writePresentInfo _AP((PresentAPDU* present,char* buffer,long* len));
+extern char* readPresentInfo _AP((void** info,char* buffer));
+
+extern char* writePresentResponseInfo _AP((PresentResponseAPDU* present,char* buffer,long* len));
+extern char* readPresentResponseInfo _AP((void** info,char* buffer));
+
+
+#endif /* HTVMSWAIS_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.c
new file mode 100644
index 00000000000..b4a668ce775
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.c
@@ -0,0 +1,1093 @@
+/* WorldWideWeb - Wide Area Informaion Server Access HTWAIS.c
+** ==================================================
+**
+** This module allows a WWW server or client to read data from a
+** remote WAIS
+** server, and provide that data to a WWW client in hypertext form.
+** Source files, once retrieved, are stored and used to provide
+** information about the index when that is acessed.
+**
+** Authors
+** BK Brewster Kahle, Thinking Machines, <Brewster@think.com>
+** TBL Tim Berners-Lee, CERN <timbl@info.cern.ch>
+** FM Foteos Macrides, WFEB <macrides@sci.wfeb.edu>
+**
+** History
+** Sep 91 TBL adapted shell-ui.c (BK) with HTRetrieve.c from WWW.
+** Feb 91 TBL Generated HTML cleaned up a bit (quotes, escaping)
+** Refers to lists of sources.
+** Mar 93 TBL Lib 2.0 compatible module made.
+** May 94 FM Added DIRECT_WAIS support for VMS.
+**
+** Bugs
+** Uses C stream i/o to read and write sockets, which won't work
+** on VMS TCP systems.
+**
+** Should cache connections.
+**
+** ANSI C only as written
+**
+** Bugs fixed
+** NT Nathan Torkington (Nathan.Torkington@vuw.ac.nz)
+**
+** WAIS comments:
+**
+** 1. Separate directories for different system's .o would help
+** 2. Document ids are rather long!
+**
+** W WW Address mapping convention:
+**
+** /servername/database/type/length/document-id
+**
+** /servername/database?word+word+word
+*/
+/* WIDE AREA INFORMATION SERVER SOFTWARE:
+ No guarantees or restrictions. See the readme file for the full standard
+ disclaimer.
+
+ Brewster@think.com
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTAccess.h" /* We implement a protocol */
+#include "HTML.h" /* The object we will generate */
+#include "HTWSRC.h"
+#include "HTTCP.h"
+#include "HTCJK.h"
+#include "HTAlert.h"
+
+/* From WAIS
+** ---------
+*/
+#ifdef VMS
+#include "HTVMS_WaisUI.h"
+#include "HTVMS_WaisProt.h"
+#else
+#include <ui.h>
+#endif /* VMS */
+
+#define MAX_MESSAGE_LEN 100000
+#define CHARS_PER_PAGE 10000 /* number of chars retrieved in each request */
+
+#define WAISSEARCH_DATE "Fri Jul 19 1991"
+
+/* FROM WWW
+** --------
+*/
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern int HTCheckForInterrupt NOPARAMS;
+
+#define DIRECTORY "/cnidr.org:210/directory-of-servers"
+/* #define DIRECTORY "/quake.think.com:210/directory-of-servers" */
+
+#define BIG 1024 /* identifier size limit @@@@@ */
+
+#define BUFFER_SIZE 4096 /* Arbitrary size for efficiency */
+
+#define HEX_ESCAPE '%'
+
+extern HTCJKlang HTCJK;
+
+extern int WWW_TraceFlag; /* Control diagnostic output */
+extern FILE * logfile; /* Log file output */
+
+PRIVATE BOOL as_gate; /* Client is using us as gateway */
+
+PRIVATE char line[2048]; /* For building strings to display */
+ /* Must be able to take id */
+
+#define PUTC(c) (*target->isa->put_character)(target, c)
+#define PUTS(s) (*target->isa->put_string)(target, s)
+#define START(e) (*target->isa->start_element)(target, e, 0, 0, -1, 0)
+#define END(e) (*target->isa->end_element)(target, e, 0)
+#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
+ (*target->isa->end_element)(target, e, 0)
+#define FREE_TARGET (*target->isa->_free)(target)
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ /* ... */
+};
+
+/* ------------------------------------------------------------------------ */
+/* ---------------- Local copy of connect_to_server calls ----------------- */
+/* ------------------------------------------------------------------------ */
+/* Returns 1 on success, 0 on fail, -1 on interrupt. */
+PRIVATE int fd_mosaic_connect_to_server ARGS3(
+ char *, host_name,
+ long, port,
+ long *, fd)
+{
+ /*
+ ** New version.
+ */
+ char dummy[256];
+ int status;
+
+ sprintf (dummy, "wais://%s:%d/", host_name, port);
+
+ status = HTDoConnect (dummy, "WAIS", 210, (int *)fd);
+ if (status == HT_INTERRUPTED) {
+ return -1;
+ }
+ if (status < 0)
+ return 0;
+ return 1;
+}
+
+/* Returns 1 on success, 0 on fail, -1 on interrupt. */
+#ifdef VMS
+PRIVATE int mosaic_connect_to_server ARGS3(
+ char *, host_name,
+ long, port,
+ long *, fdp)
+#else
+PRIVATE int mosaic_connect_to_server ARGS3(
+ char *, host_name,
+ long, port,
+ FILE **, fp)
+#endif /* VMS */
+{
+#ifndef VMS
+ FILE* file;
+#endif /* VMS */
+ long fd;
+ int rv;
+
+ rv = fd_mosaic_connect_to_server (host_name, port, &fd);
+ if (rv == 0) {
+ HTAlert ("Could not connect to WAIS server.");
+ return 0;
+ } else if (rv == -1) {
+ HTAlert ("Connection interrupted.");
+ return -1;
+ }
+
+#ifndef VMS
+ if ((file = fdopen(fd,"r+")) == NULL) {
+ HTAlert ("Could not open WAIS connection for reading.");
+ return 0;
+ }
+
+ *fp = file;
+#else
+ *fdp = fd;
+#endif /* VMS */
+ return 1;
+}
+/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------------------ */
+
+/* showDiags
+*/
+/* modified from Jonny G's version in ui/question.c */
+PRIVATE void showDiags ARGS2(
+ HTStream *, target,
+ diagnosticRecord **, d)
+{
+ long i;
+
+ for (i = 0; d[i] != NULL; i++) {
+ if (d[i]->ADDINFO != NULL) {
+ PUTS("Diagnostic code is ");
+ PUTS(d[i]->DIAG);
+ PUTC(' ');
+ PUTS(d[i]->ADDINFO);
+ PUTC('\n'); ;
+ }
+ }
+}
+
+/* Matrix of allowed characters in filenames
+** -----------------------------------------
+*/
+
+PRIVATE BOOL acceptable[256];
+PRIVATE BOOL acceptable_inited = NO;
+
+PRIVATE void init_acceptable NOARGS
+{
+ unsigned int i;
+ char * good =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./-_$";
+ for(i=0; i<256; i++) acceptable[i] = NO;
+ for(;*good; good++) acceptable[(unsigned int)*good] = YES;
+ acceptable_inited = YES;
+}
+
+/* Transform file identifier into WWW address
+** ------------------------------------------
+**
+**
+** On exit,
+** returns nil if error
+** pointer to malloced string (must be freed) if ok
+*/
+PRIVATE char * WWW_from_archie ARGS1(
+ char *, file)
+{
+ char * end;
+ char * result;
+ char * colon;
+ for(end=file; *end > ' '; end++); /* assumes ASCII encoding*/
+ result = (char *)malloc(10 + (end-file));
+ if (!result) return result; /* Malloc error */
+ strcpy(result, "file://");
+ strncat(result, file, end-file);
+ colon = strchr(result+7, ':'); /* Expect colon after host */
+ if (colon) {
+ for(; colon[0]; colon[0]=colon[1], colon++); /* move down */
+ }
+ return result;
+} /* WWW_from_archie */
+
+/* Transform document identifier into URL
+** --------------------------------------
+**
+** Bugs: A static buffer of finite size is used!
+** The format of the docid MUST be good!
+**
+** On exit,
+** returns nil if error
+** pointer to malloced string (must be freed) if ok
+*/
+PRIVATE char hex [17] = "0123456789ABCDEF";
+
+PRIVATE char * WWW_from_WAIS ARGS1(
+ any *, docid)
+{
+ static char buf[BIG];
+ char * q = buf;
+ char * p = (docid->bytes);
+ int i, l;
+ if (TRACE) {
+ char *p;
+ fprintf(stderr, "WAIS id (%d bytes) is ", (int)docid->size);
+ for (p = docid->bytes; p < docid->bytes+docid->size; p++) {
+ if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */
+ fprintf(stderr, "%c", *p);
+ else
+ fprintf(stderr, "<%x>", (unsigned)*p);
+ }
+ fprintf(stderr, "\n");
+ }
+ for (p = docid->bytes;
+ (p < docid->bytes+docid->size) && (q < &buf[BIG]);) {
+ if (TRACE)
+ fprintf(stderr, " Record type %d, length %d\n", p[0], p[1]);
+ if (*p > 10) {
+ if (TRACE)
+ fprintf(stderr, "Eh? DOCID record type of %d!\n", *p);
+ return 0;
+ }
+ { /* Bug fix -- allow any byte value 15 Apr 93 */
+ unsigned int i = (unsigned) *p++;
+
+ if (i > 99) {
+ *q++ = (i/100) + '0';
+ i = i % 100;
+ }
+ if (i > 9) {
+ *q++ = (i/10) + '0';
+ i = i % 10;
+ }
+ *q++ = i + '0'; /* Record type */
+ }
+ *q++ = '='; /* Separate */
+ l = *p++; /* Length */
+ for (i = 0; i < l; i++, p++){
+ if (!acceptable[*p]) {
+ *q++ = HEX_ESCAPE; /* Means hex commming */
+ *q++ = hex[(*p) >> 4];
+ *q++ = hex[(*p) & 15];
+ }
+ else *q++ = *p;
+ }
+ *q++= ';'; /* Terminate field */
+ }
+ *q++ = 0; /* Terminate string */
+ if (TRACE)
+ fprintf(stderr, "WWW form of id: %s\n", buf);
+ {
+ char * result = (char *)malloc(strlen(buf)+1);
+ if (!result)
+ outofmem(__FILE__, "WWW_from_WAIS");
+ strcpy(result, buf);
+ return result;
+ }
+} /* WWW_from_WAIS */
+
+/* Transform URL into WAIS document identifier
+** -------------------------------------------
+**
+** On entry,
+** docname points to valid name produced originally by
+** WWW_from_WAIS
+** On exit,
+** docid->size is valid
+** docid->bytes is malloced and must later be freed.
+*/
+PRIVATE any * WAIS_from_WWW ARGS2(
+ any *, docid,
+ char *, docname)
+{
+ char *z; /* Output pointer */
+ char *sor; /* Start of record - points to size field. */
+ char *p; /* Input pointer */
+ char *q; /* Poisition of "=" */
+ char *s; /* Position of semicolon */
+ int n; /* size */
+ if (TRACE)
+ fprintf(stderr, "WWW id (to become WAIS id): %s\n", docname);
+ for (n = 0, p = docname; *p; p++) { /* Count sizes of strings */
+ n++;
+ if (*p == ';')
+ n--; /* Not converted */
+ else if (*p == HEX_ESCAPE)
+ n = n-2; /* Save two bytes */
+ docid->size = n;
+ }
+
+ if (!(docid->bytes = (char *) malloc(docid->size))) /* result record */
+ outofmem(__FILE__, "WAIS_from_WWW");
+ z = docid->bytes;
+
+ for (p = docname; *p; ) { /* Convert of strings */
+ /* Record type */
+
+ *z = 0; /* Initialize record type */
+ while (*p >= '0' && *p <= '9') {
+ *z = *z*10 + (*p++ - '0'); /* Decode decimal record type */
+ }
+ z++;
+ if (*p != '=')
+ return 0;
+ q = p;
+
+/* *z++ = *p++ - '0';
+ q = strchr(p , '=');
+ if (!q) return 0;
+*/
+ s = strchr(q, ';'); /* (Check only) */
+ if (!s)
+ return 0; /* Bad! No ';'; */
+ sor = z; /* Remember where the size field was */
+ z++; /* Skip record size for now */
+ for (p = q+1; *p != ';';) {
+ if (*p == HEX_ESCAPE) {
+ char c;
+ unsigned int b;
+ p++;
+ c = *p++;
+ b = from_hex(c);
+ c = *p++;
+ if (!c)
+ break; /* Odd number of chars! */
+ *z++ = (b<<4) + from_hex(c);
+ } else {
+ *z++ = *p++; /* Record */
+ }
+ }
+ *sor = (z-sor-1); /* Fill in size -- not counting size itself */
+ p++; /* After semicolon: start of next record */
+ }
+
+ if (TRACE) {
+ char *p;
+ fprintf(stderr, "WAIS id (%d bytes) is ", (int)docid->size);
+ for (p = docid->bytes; p < docid->bytes+docid->size; p++) {
+ if ((*p >= ' ') && (*p<= '~')) /* Assume ASCII! */
+ fprintf(stderr, "%c", *p);
+ else
+ fprintf(stderr, "<%x>", (unsigned)*p);
+ }
+ fprintf(stderr, "\n");
+ }
+ return docid; /* Ok */
+
+} /* WAIS_from_WWW */
+
+/* Send a plain text record to the client output_text_record()
+** --------------------------------------
+*/
+PRIVATE void output_text_record ARGS4(
+ HTStream *, target,
+ WAISDocumentText *, record,
+ boolean, quote_string_quotes,
+ boolean, binary)
+{
+ long count;
+ /* printf(" Text\n");
+ print_any(" DocumentID: ", record->DocumentID);
+ printf(" VersionNumber: %d\n", record->VersionNumber);
+ */
+
+ if (binary) {
+ (*target->isa->put_block)(target,
+ record->DocumentText->bytes,
+ record->DocumentText->size);
+ return;
+ }
+
+ for (count = 0; count < record->DocumentText->size; count++){
+ long ch = (unsigned char)record->DocumentText->bytes[count];
+ if (ch == 27) { /* What is this in for? Tim */
+ /* then we have an escape code */
+ /* if the next letter is '(' or ')', then ignore two letters */
+ if ('(' == record->DocumentText->bytes[count + 1] ||
+ ')' == record->DocumentText->bytes[count + 1])
+ count += 1; /* it is a term marker */
+ else count += 4; /* it is a paragraph marker */
+ } else if (ch == '\n' || ch == '\r') {
+ PUTC('\n');
+ } else if (HTCJK != NOCJK || ch == '\t' || isprint(ch)){
+ PUTC(ch);
+ }
+ }
+} /* output text record */
+
+/* Format A Search response for the client display_search_response
+** ---------------------------------------
+*/
+/* modified from tracy shen's version in wutil.c
+ * displays either a text record or a set of headlines.
+ */
+PRIVATE void display_search_response ARGS4(
+ HTStructured *, target,
+ SearchResponseAPDU *, response,
+ char *, database,
+ char *, keywords)
+{
+ WAISSearchResponse *info;
+ long i, k;
+
+ BOOL archie = strstr(database, "archie")!=0; /* Specical handling */
+
+ if (TRACE)
+ fprintf(stderr, "HTWAIS: Displaying search response\n");
+ PUTS("Index ");
+ START(HTML_EM);
+ PUTS(database);
+ END(HTML_EM);
+ sprintf(line, " contains the following %d item%s relevant to \"",
+ (int)(response->NumberOfRecordsReturned),
+ response->NumberOfRecordsReturned ==1 ? "" : "s");
+ PUTS(line);
+ START(HTML_EM);
+ PUTS(keywords);
+ END(HTML_EM);
+ PUTS("\".\n");
+ PUTS("The first figure after each entry is its relative score, ");
+ PUTS("the second is the number of lines in the item.");
+ START(HTML_BR);
+ START(HTML_BR);
+ PUTS("\n");
+ START(HTML_OL);
+
+ if (response->DatabaseDiagnosticRecords != 0) {
+ info = (WAISSearchResponse *)response->DatabaseDiagnosticRecords;
+ i =0;
+
+ if (info->Diagnostics != NULL)
+ showDiags((HTStream*)target, info->Diagnostics);
+
+ if (info->DocHeaders != 0) {
+ for (k = 0; info->DocHeaders[k] != 0; k++ ) {
+ WAISDocumentHeader* head = info->DocHeaders[k];
+ char * headline = trim_junk(head->Headline);
+ any * docid = head->DocumentID;
+ char * docname; /* printable version of docid */
+
+ i++;
+ /*
+ ** Make a printable string out of the document id.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTWAIS: %2ld: Score: %4ld, lines:%4ld '%s'\n",
+ i,
+ (long int)(info->DocHeaders[k]->Score),
+ (long int)(info->DocHeaders[k]->Lines),
+ headline);
+
+ START(HTML_LI);
+
+ if (archie) {
+ char * www_name = WWW_from_archie(headline);
+ if (www_name) {
+ HTStartAnchor(target, NULL, www_name);
+ PUTS(headline);
+ END(HTML_A);
+ FREE(www_name);
+ } else {
+ PUTS(headline);
+ PUTS(" (bad file name)");
+ }
+ } else { /* Not archie */
+ docname = WWW_from_WAIS(docid);
+ if (docname) {
+ char * dbname = HTEscape(database, URL_XPALPHAS);
+ sprintf(line,
+ "/%s/%s/%d/%s", /* W3 address */
+ dbname,
+ head->Types ? head->Types[0] : "TEXT",
+ (int)(head->DocumentLength),
+ docname);
+ HTStartAnchor(target, NULL,
+ ((head->Types) &&
+ (!strcmp(head->Types[0], "URL")))
+ ?
+ headline : line); /* NT, Sep 93 */
+ PUTS(headline);
+ END(HTML_A);
+ FREE(dbname);
+ FREE(docname);
+ } else {
+ PUTS("(bad doc id)");
+ }
+ }
+
+ sprintf(line, "%5ld %5ld ",
+ head->Score,
+ head->Lines);
+ PUTS( line);
+ MAYBE_END(HTML_LI);
+ } /* next document header */
+ } /* if there were any document headers */
+
+ if (info->ShortHeaders != 0) {
+ k = 0;
+ while (info->ShortHeaders[k] != 0) {
+ i++;
+ PUTS( "(Short Header record, can't display)");
+ }
+ }
+ if (info->LongHeaders != 0) {
+ k = 0;
+ while (info->LongHeaders[k] != 0) {
+ i++;
+ PUTS( "\nLong Header record, can't display\n");
+ }
+ }
+ if (info->Text != 0) {
+ k = 0;
+ while (info->Text[k] != 0) {
+ i++;
+ PUTS( "\nText record\n");
+ output_text_record((HTStream*)target,
+ info->Text[k++], false, false);
+ }
+ }
+ if (info->Headlines != 0) {
+ k = 0;
+ while (info->Headlines[k] != 0) {
+ i++;
+ PUTS( "\nHeadline record, can't display\n");
+ /* dsply_headline_record( info->Headlines[k++]); */
+ }
+ }
+ if (info->Codes != 0) {
+ k = 0;
+ while (info->Codes[k] != 0) {
+ i++;
+ PUTS( "\nCode record, can't display\n");
+ /* dsply_code_record( info->Codes[k++]); */
+ }
+ }
+ } /* Loop: display user info */
+ END(HTML_OL);
+ PUTC('\n'); ;
+}
+
+/* Load by name HTLoadWAIS
+** ============
+**
+** This renders any object or search as required.
+*/
+PUBLIC int HTLoadWAIS ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+
+#define MAX_KEYWORDS_LENGTH 1000
+#define MAX_SERVER_LENGTH 1000
+#define MAX_DATABASE_LENGTH 1000
+#define MAX_SERVICE_LENGTH 1000
+#define MAXDOCS 200
+
+{
+ static CONST char * error_header =
+"<h1>Access error</h1>\nThe following error occured in accesing a WAIS server:<P>\n";
+ char * key; /* pointer to keywords in URL */
+ char* request_message = NULL; /* arbitrary message limit */
+ char* response_message = NULL; /* arbitrary message limit */
+ long request_buffer_length; /* how of the request is left */
+ SearchResponseAPDU *retrieval_response = 0;
+ char keywords[MAX_KEYWORDS_LENGTH + 1];
+ char *server_name;
+ char *wais_database = NULL; /* name of current database */
+ char *www_database; /* Same name escaped */
+ char *service;
+ char *doctype;
+ char *doclength;
+ long document_length;
+ char *docname;
+#ifdef VMS
+ long connection = 0;
+#else
+ FILE *connection = NULL;
+#endif /* VMS */
+ char * names; /* Copy of arg to be hacked up */
+ BOOL ok = NO;
+ int return_status = HT_LOADED;
+ int rv;
+
+ extern FILE * connect_to_server();
+
+ if (!acceptable_inited)
+ init_acceptable();
+
+ /* Decipher and check syntax of WWW address:
+ ** ----------------------------------------
+ **
+ ** First we remove the "wais:" if it was spcified. 920110
+ */
+ names = HTParse(arg, "", PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION);
+ key = strchr(names, '?');
+
+ if (key) {
+ char * p;
+ *key++ = 0; /* Split off keywords */
+ for (p=key; *p; p++) if (*p == '+') *p = ' ';
+ HTUnEscape(key);
+ }
+ if (names[0] == '/') {
+ server_name = names+1;
+ if (as_gate =(*server_name == '/'))
+ server_name++; /* Accept one or two */
+ www_database = strchr(server_name,'/');
+ if (www_database) {
+ *www_database++ = 0; /* Separate database name */
+ doctype = strchr(www_database, '/');
+ if (key) ok = YES; /* Don't need doc details */
+ else if (doctype) { /* If not search parse doc details */
+ *doctype++ = 0; /* Separate rest of doc address */
+ doclength = strchr(doctype, '/');
+ if (doclength) {
+ *doclength++ = 0;
+ document_length = atol(doclength);
+ if (document_length) {
+ docname = strchr(doclength, '/');
+ if (docname) {
+ *docname++ = 0;
+ ok = YES; /* To avoid a goto! */
+ } /* if docname */
+ } /* if document_length valid */
+ } /* if doclength */
+ } else { /* no doctype? Assume index required */
+ if (!key)
+ key = "";
+ ok = YES;
+ } /* if doctype */
+ } /* if database */
+ }
+
+ if (!ok)
+ return HTLoadError(sink, 500, "Syntax error in WAIS URL");
+
+ if (TRACE)
+ fprintf(stderr, "HTWAIS: Parsed OK\n");
+
+ service = strchr(names, ':');
+ if (service)
+ *service++ = 0;
+ else
+ service = "210";
+
+ if (server_name[0] == 0) {
+#ifdef VMS
+ connection = 0;
+#else
+ connection = NULL;
+#endif /* VMS */
+
+ } else if (!(key && !*key)) {
+ int status;
+ if (TRACE)
+ fprintf (stderr, "===WAIS=== calling mosaic_connect_to_server\n");
+ status = mosaic_connect_to_server(server_name,
+ atoi(service),
+ &connection);
+ if (status == 0) {
+ if (TRACE)
+ fprintf (stderr, "===WAIS=== connection failed\n");
+ FREE(names);
+ return HT_NOT_LOADED;
+ } else if (status == -1) {
+ if (TRACE)
+ fprintf (stderr, "===WAIS=== connection interrupted\n");
+ FREE(names);
+ return HT_NOT_LOADED;
+ }
+ }
+
+ StrAllocCopy(wais_database,www_database);
+ HTUnEscape(wais_database);
+
+ /*
+ ** This below fixed size stuff is terrible.
+ */
+#ifdef VMS
+ if (!(request_message =
+ (char*)calloc((size_t)MAX_MESSAGE_LEN*sizeof(char),1)))
+ outofmem(__FILE__, "HTLoadWAIS");
+ if (!(response_message =
+ (char*)calloc((size_t)MAX_MESSAGE_LEN*sizeof(char),1)))
+ outofmem(__FILE__, "HTLoadWAIS");
+#else
+ request_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
+ response_message = (char*)s_malloc((size_t)MAX_MESSAGE_LEN * sizeof(char));
+#endif /* VMS */
+
+ /*
+ ** If keyword search is performed but there are no keywords,
+ ** the user has followed a link to the index itself. It would be
+ ** appropriate at this point to send him the .SRC file - how?
+ */
+ if (key && !*key) { /* I N D E X */
+#ifdef CACHE_FILE_PREFIX
+ char filename[256];
+ FILE * fp;
+#endif
+ HTStructured * target = HTML_new(anAnchor, format_out, sink);
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ HTStartIsIndex(target, "Enter WAIS query: ", NULL);
+ PUTS("\n");
+
+ {
+ START(HTML_TITLE);
+ PUTS(wais_database);
+ PUTS(" (WAIS Index)");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+
+ START(HTML_H1);
+ PUTS("WAIS Index: ");
+ START(HTML_EM);
+ PUTS(wais_database);
+ END(HTML_EM);
+ END(HTML_H1);
+ PUTS("\n");
+ PUTS("This is a link for searching the ");
+ START(HTML_EM);
+ PUTS(wais_database);
+ END(HTML_EM);
+ PUTS(" WAIS Index.\n");
+
+ }
+ /*
+ ** If we have seen a source file for this database, use that.
+ */
+#ifdef CACHE_FILE_PREFIX
+ sprintf(filename, "%sWSRC-%s:%s:%.100s.txt",
+ CACHE_FILE_PREFIX,
+ server_name, service, www_database);
+
+ fp = fopen(filename, "r"); /* Have we found this already? */
+ if (TRACE) fprintf(stderr,
+ "HTWAIS: Description of server %s %s.\n",
+ filename,
+ fp ? "exists already" : "does NOT exist!");
+
+ if (fp) {
+ char c;
+ START(HTML_PRE); /* Preformatted description */
+ PUTS("\n");
+ while((c=getc(fp))!=EOF) PUTC(c); /* Transfer file */
+ END(HTML_PRE);
+ fclose(fp);
+#endif
+ START(HTML_P);
+ PUTS("\nEnter the 's'earch command and then specify search words.\n");
+
+ FREE_TARGET;
+ } else if (key) { /* S E A R C H */
+ char *p;
+ HTStructured * target;
+
+ strncpy(keywords, key, MAX_KEYWORDS_LENGTH);
+ while(p=strchr(keywords, '+')) *p = ' ';
+
+ /*
+ ** Send advance title to get something fast to the other end.
+ */
+ target = HTML_new(anAnchor, format_out, sink);
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ HTStartIsIndex(target, "Enter WAIS query: ", NULL);
+ PUTS("\n");
+ START(HTML_TITLE);
+ PUTS(keywords);
+ PUTS(" (in ");
+ PUTS(wais_database);
+ PUTS(")");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+ PUTS("\n");
+
+ START(HTML_H1);
+ PUTS("WAIS Search of \"");
+ START(HTML_EM);
+ PUTS(keywords);
+ END(HTML_EM);
+ PUTS("\" in: ");
+ START(HTML_EM);
+ PUTS(wais_database);
+ END(HTML_EM);
+ END(HTML_H1);
+ PUTS("\n");
+
+ request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
+ if (TRACE) fprintf(stderr, "HTWAIS: Search for `%s' in `%s'\n",
+ keywords, wais_database);
+ if(NULL ==
+ generate_search_apdu(request_message + HEADER_LENGTH,
+ &request_buffer_length,
+ keywords, wais_database, NULL, MAXDOCS)) {
+#ifdef VMS
+ HTAlert ("HTWAIS: Request too large.");
+ return_status = HT_NOT_LOADED;
+ FREE_TARGET;
+ goto CleanUp;
+#else
+ panic("request too large");
+#endif /* VMS */
+ }
+
+ HTProgress("Searching WAIS database...");
+ rv = interpret_message (request_message,
+ MAX_MESSAGE_LEN - request_buffer_length,
+ response_message,
+ MAX_MESSAGE_LEN,
+ connection,
+ false /* true verbose */
+ );
+
+ if (rv == HT_INTERRUPTED) {
+ HTAlert ("Search interrupted.");
+ return_status = HT_INTERRUPTED;
+ FREE_TARGET;
+ goto CleanUp;
+ } else if (!rv) {
+#ifdef VMS
+ HTAlert ("HTWAIS: Return message too large.");
+ return_status = HT_NOT_LOADED;
+ FREE_TARGET;
+ goto CleanUp;
+#else
+ panic("returned message too large");
+#endif /* VMS */
+ } else { /* returned message ok */
+ SearchResponseAPDU *query_response = 0;
+ readSearchResponseAPDU(&query_response,
+ response_message + HEADER_LENGTH);
+ display_search_response(target,
+ query_response, wais_database, keywords);
+ if (query_response->DatabaseDiagnosticRecords)
+ freeWAISSearchResponse(
+ query_response->DatabaseDiagnosticRecords);
+ freeSearchResponseAPDU( query_response);
+ } /* returned message not too large */
+ FREE_TARGET;
+ } else { /* D O C U M E N T F E T C H */
+ HTFormat format_in;
+ boolean binary; /* how to transfer stuff coming over */
+ HTStream * target;
+ long count;
+ any doc_chunk;
+ any * docid = &doc_chunk;
+
+ if (TRACE) fprintf(stderr,
+ "HTWAIS: Retrieve document id `%s' type `%s' length %ld\n",
+ docname, doctype, document_length);
+
+ format_in =
+ !strcmp(doctype, "WSRC") ? HTAtom_for("application/x-wais-source") :
+ !strcmp(doctype, "TEXT") ? HTAtom_for("text/plain") :
+ !strcmp(doctype, "HTML") ? HTAtom_for("text/html") :
+ !strcmp(doctype, "GIF") ? HTAtom_for("image/gif") :
+ HTAtom_for("application/octet-stream");
+ binary =
+ 0 != strcmp(doctype, "WSRC") &&
+ 0 != strcmp(doctype, "TEXT") &&
+ 0 != strcmp(doctype, "HTML") ;
+
+ target = HTStreamStack(format_in, format_out, sink, anAnchor);
+ if (!target)
+ return HTLoadError(sink, 500,
+ "Can't convert format of WAIS document");
+ /*
+ ** Decode hex or litteral format for document ID.
+ */
+ WAIS_from_WWW(docid, docname);
+
+ /*
+ ** Loop over slices of the document.
+ */
+ for (count = 0;
+ count * CHARS_PER_PAGE < document_length;
+ count++) {
+#ifdef VMS
+ char *type = NULL;
+
+ StrAllocCopy(type, doctype);
+#else
+ char *type = s_strdup(doctype); /* Gets freed I guess */
+#endif /* VMS */
+ request_buffer_length = MAX_MESSAGE_LEN; /* Amount left */
+ if (TRACE)
+ fprintf(stderr, "HTWAIS: Slice number %ld\n", count);
+
+ if (HTCheckForInterrupt()) {
+ HTAlert ("Data transfer interrupted.");
+ (*target->isa->_abort)(target, NULL);
+#ifdef VMS
+ FREE(type);
+#endif /* VMS */
+ return_status = HT_NOT_LOADED;
+ goto CleanUp;
+ }
+
+ if (0 ==
+ generate_retrieval_apdu(request_message + HEADER_LENGTH,
+ &request_buffer_length,
+ docid,
+ CT_byte,
+ count * CHARS_PER_PAGE,
+ ((count + 1) * CHARS_PER_PAGE <= document_length ?
+ (count + 1) * CHARS_PER_PAGE :
+ document_length),
+ type,
+ wais_database)) {
+#ifdef VMS
+ HTAlert ("HTWAIS: Request too long.");
+ return_status = HT_NOT_LOADED;
+ FREE_TARGET;
+ FREE(type);
+ FREE(docid->bytes);
+ goto CleanUp;
+#else
+ panic("request too long");
+#endif /* VMS */
+ }
+
+ /*
+ ** Actually do the transaction given by request_message.
+ */
+ HTProgress("Fetching WAIS document...");
+ rv = interpret_message(request_message,
+ MAX_MESSAGE_LEN - request_buffer_length,
+ response_message,
+ MAX_MESSAGE_LEN,
+ connection,
+ false /* true verbose */
+ );
+ if (rv == HT_INTERRUPTED) {
+ HTAlert ("Data transfer interrupted.");
+ return_status = HT_INTERRUPTED;
+ FREE_TARGET;
+ FREE(type);
+ FREE(docid->bytes);
+ goto CleanUp;
+ } else if (!rv) {
+#ifdef VMS
+ HTAlert ("HTWAIS: Return message too large.");
+ return_status = HT_NOT_LOADED;
+ FREE_TARGET;
+ FREE(type);
+ FREE(docid->bytes);
+ goto CleanUp;
+#else
+ panic("Returned message too large");
+#endif /* VMS */
+ }
+
+ /*
+ ** Parse the result which came back into memory.
+ */
+ readSearchResponseAPDU(&retrieval_response,
+ response_message + HEADER_LENGTH);
+
+ if (NULL ==
+ ((WAISSearchResponse *)
+ retrieval_response->DatabaseDiagnosticRecords)->Text) {
+ /* display_search_response(target, retrieval_response,
+ wais_database, keywords); */
+ PUTS("No text was returned!\n");
+ /* panic("No text was returned"); */
+ } else {
+ output_text_record(target,
+ ((WAISSearchResponse *)
+ retrieval_response->DatabaseDiagnosticRecords)->Text[0],
+ false, binary);
+ } /* If text existed */
+
+#ifdef VMS
+ FREE(type);
+#endif /* VMS */
+ } /* Loop over slices */
+
+ FREE_TARGET;
+ FREE(docid->bytes);
+
+ freeWAISSearchResponse( retrieval_response->DatabaseDiagnosticRecords);
+ freeSearchResponseAPDU( retrieval_response);
+
+ } /* If document rather than search */
+
+CleanUp:
+ /*
+ ** (This postponed until later, after a timeout:)
+ */
+#ifdef VMS
+ if (connection)
+ NETCLOSE((int)connection);
+#else
+ if (connection)
+ fclose(connection);
+#endif /* VMS */
+ FREE(wais_database);
+#ifdef VMS
+ FREE(request_message);
+ FREE(response_message);
+#else
+ s_free(request_message);
+ s_free(response_message);
+#endif /* VMS */
+ FREE(names);
+ return (return_status);
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _HTWAIS_C_1_INIT { "wais", HTLoadWAIS, NULL }
+GLOBALDEF(HTProtocol, HTWAIS, _HTWAIS_C_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol HTWAIS = { "wais", HTLoadWAIS, NULL };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.h
new file mode 100644
index 00000000000..4aa885dcbed
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWAIS.h
@@ -0,0 +1,44 @@
+/* WAIS protocol module for the W3 library
+ WAIS PROTOCOL INTERFACE
+
+ This module does not actually perform the WAIS protocol directly, but it does using one
+ or more libraries of the freeWAIS distribution. The ui.a library came with the old free
+ WAIS from TMC, the client.a and wais.a libraries are needed from the freeWAIS from
+ CNIDR.
+
+ If you include this module in the library, you must also
+
+ Register the HTWAIS protocol at initialisation (e.g. HTInit or HTSInit) by compiling
+ it with -DDIRECT_WAIS
+
+ Link with the WAIS libraries
+
+ The wais source files are parsed by a separate and independent module, HTWSRC . You
+ can include HTWSRC without including direct wais using this module, and your WWW code
+ will be able to read source files, and access WAIS indexes through a gateway.
+
+ A WAIS-WWW gateway is just a normal W3 server with a libwww compiled with this module.
+
+ Anyways, this interface won't change much:
+
+ */
+#ifndef HTWAIS_H
+#define HTWAIS_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTAccess.h"
+
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF(HTProtocol, HTWAIS);
+#else
+GLOBALREF HTProtocol HTWAIS;
+#endif /* GLOBALDEF_IS_MACRO */
+
+#endif /* HTWAIS_H */
+
+/*
+ Tim BL
+
+*/
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.c
new file mode 100644
index 00000000000..e7f15dad511
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.c
@@ -0,0 +1,473 @@
+/* Parse WAIS Source file HTWSRC.c
+** ======================
+**
+** This module parses a stream with WAIS source file
+** format information on it and creates a structured stream.
+** That structured stream is then converted into whatever.
+**
+** 3 June 93 Bug fix: Won't crash if no description
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTWSRC.h"
+
+
+#include "HTML.h"
+#include "HTParse.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#define BIG 10000 /* Arbitrary limit to value length */
+#define PARAM_MAX BIG
+#define CACHE_PERIOD (7*86400) /* Time to keep .src file in seconds */
+
+#define HEX_ESCAPE '%'
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ /* ... */
+};
+
+#define PUTC(c) (*me->target->isa->put_character)(me->target, c)
+#define PUTS(s) (*me->target->isa->put_string)(me->target, s)
+#define START(e) (*me->target->isa->start_element)(me->target, e, 0, 0, -1, 0)
+#define END(e) (*me->target->isa->end_element)(me->target, e, 0)
+#define MAYBE_END(e) if (HTML_dtd.tags[e].contents != SGML_EMPTY) \
+ (*me->target->isa->end_element)(me->target, e, 0)
+
+
+/* Here are the parameters which can be specified in a source file
+*/
+PRIVATE CONST char* par_name[] = {
+ "version",
+ "ip-address",
+#define PAR_IP_NAME 2
+ "ip-name",
+#define PAR_TCP_PORT 3
+ "tcp-port",
+#define PAR_DATABASE_NAME 4
+ "database-name",
+#define PAR_COST 5
+ "cost",
+#define PAR_COST_UNIT 6
+ "cost-unit",
+#define PAR_FREE 7
+ "free",
+#define PAR_MAINTAINER 8
+ "maintainer",
+#define PAR_DESCRIPTION 9
+ "description",
+ "keyword-list",
+ "source",
+ "window-geometry",
+ "configuration",
+ "script",
+ "update-time",
+ "contact-at",
+ "last-contacted",
+ "confidence",
+ "num-docs-to-request",
+ "font",
+ "font-size",
+#define PAR_UNKNOWN 22
+ "unknown",
+ 0, /* Terminate list */
+#define PAR_COUNT 23
+} ;
+
+
+enum tokenstate { beginning, before_tag, colon, before_value,
+ value, bracketed_value, quoted_value, escape_in_quoted, done };
+
+
+/* Stream Object
+** ------------
+**
+** The target is the structured stream down which the
+** parsed results will go.
+**
+** all the static stuff below should go in here to make it reentrant
+*/
+
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ HTStructured * target;
+ char * par_value[PAR_COUNT];
+ enum tokenstate state;
+ char param[BIG+1];
+ int param_number;
+ int param_count;
+};
+
+
+
+
+PUBLIC CONST char * hex = "0123456789ABCDEF";
+
+/* Decode one hex character
+*/
+
+PUBLIC char from_hex ARGS1(char, c)
+{
+ return (c>='0')&&(c<='9') ? c-'0'
+ : (c>='A')&&(c<='F') ? c-'A'+10
+ : (c>='a')&&(c<='f') ? c-'a'+10
+ : 0;
+}
+
+
+/* State machine
+** -------------
+**
+** On entry,
+** me->state is a valid state (see WSRC_init)
+** c is the next character
+** On exit,
+** returns 1 Done with file
+** 0 Continue. me->state is updated if necessary.
+** -1 Syntax error error
+*/
+
+
+/* Treat One Character
+** -------------------
+*/
+PRIVATE void WSRCParser_put_character ARGS2(HTStream*, me, char, c)
+{
+ switch (me->state) {
+ case beginning:
+ if (c=='(') me->state = before_tag;
+ break;
+
+ case before_tag:
+ if (c==')') {
+ me->state = done;
+ return; /* Done with input file */
+ } else if (c==':') {
+ me->param_count = 0;
+ me->state = colon;
+ } /* Ignore other text */
+ break;
+
+ case colon:
+ if (WHITE(c)) {
+ me->param[me->param_count++] = 0; /* Terminate */
+ for(me->param_number = 0; par_name[me->param_number]; me->param_number++) {
+ if (0==strcmp(par_name[me->param_number], me->param)) {
+ break;
+ }
+ }
+ if (!par_name[me->param_number]) { /* Unknown field */
+ if (TRACE) fprintf(stderr,
+ "HTWSRC: Unknown field `%s' in source file\n",
+ me->param);
+ me->param_number = PAR_UNKNOWN;
+ me->state = before_value; /* Could be better ignore */
+ return;
+ }
+ me->state = before_value;
+ } else {
+ if (me->param_count < PARAM_MAX) me->param[me->param_count++] = c;
+ }
+ break;
+
+ case before_value:
+ if (c==')') {
+ me->state = done;
+ return; /* Done with input file */
+ }
+ if (WHITE(c)) return; /* Skip white space */
+ me->param_count = 0;
+ if (c=='"') {
+ me->state = quoted_value;
+ break;
+ }
+ me->state = (c=='"') ? quoted_value :
+ (c=='(') ? bracketed_value : value;
+ me->param[me->param_count++] = c; /* Don't miss first character */
+ break;
+
+ case value:
+ if (WHITE(c)) {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ } else {
+ if (me->param_count < PARAM_MAX) me->param[me->param_count++] = c;
+ }
+ break;
+
+ case bracketed_value:
+ if (c==')') {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ break;
+ }
+ if (me->param_count < PARAM_MAX) me->param[me->param_count++] = c;
+ break;
+
+ case quoted_value:
+ if (c=='"') {
+ me->param[me->param_count] = 0;
+ StrAllocCopy(me->par_value[me->param_number], me->param);
+ me->state = before_tag;
+ break;
+ }
+
+ if (c=='\\') { /* Ignore escape but switch state */
+ me->state = escape_in_quoted;
+ break;
+ }
+ /* Fall through! */
+
+ case escape_in_quoted:
+ if (me->param_count < PARAM_MAX) me->param[me->param_count++] = c;
+ me->state = quoted_value;
+ break;
+
+ case done: /* Ignore anything after EOF */
+ return;
+
+ } /* switch me->state */
+}
+
+
+/* Open Cache file
+** ===============
+**
+** Bugs: Maybe for filesystem-challenged platforms (MSDOS for example) we
+** should make a hash code for the filename.
+*/
+
+#ifdef CACHE_FILE_PREFIX
+PRIVATE BOOL write_cache ARGS1(HTStream *, me)
+{
+ FILE * fp;
+ char cache_file_name[256];
+ char * www_database;
+ if (!me->par_value[PAR_DATABASE_NAME]
+ || !me->par_value[PAR_IP_NAME]
+ ) return NO;
+
+ www_database = HTEscape(me->par_value[PAR_DATABASE_NAME], URL_XALPHAS);
+ sprintf(cache_file_name, "%sWSRC-%s:%s:%.100s.txt",
+ CACHE_FILE_PREFIX,
+ me->par_value[PAR_IP_NAME],
+ me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] : "210",
+ www_database);
+ FREE(www_database);
+ fp = fopen(cache_file_name, "w");
+ if (!fp) return NO;
+
+ if (me->par_value[PAR_DESCRIPTION])
+ fputs(me->par_value[PAR_DESCRIPTION], fp);
+ else
+ fputs("Description not available\n", fp);
+ fclose(fp);
+ return YES;
+}
+#endif
+
+/* Output equivalent HTML
+** ----------------------
+**
+*/
+
+PRIVATE void give_parameter ARGS2(HTStream *, me, int, p)
+{
+ PUTS(par_name[p]);
+ if (me->par_value[p]) {
+ PUTS(": ");
+ PUTS(me->par_value[p]);
+ PUTS("; ");
+ } else {
+ PUTS(" NOT GIVEN in source file; ");
+ }
+}
+
+
+/* Generate Outout
+** ===============
+*/
+PRIVATE void WSRC_gen_html ARGS2(HTStream *, me, BOOL, source_file)
+
+{
+ if (me->par_value[PAR_DATABASE_NAME]) {
+ char * shortname = 0;
+ int l;
+ StrAllocCopy(shortname, me->par_value[PAR_DATABASE_NAME]);
+ l = strlen(shortname);
+ if ( l > 4 && !strcasecomp(shortname + l -4, ".src")) {
+ shortname[l-4] = 0; /* Chop of .src -- boring! */
+ }
+
+ START(HTML_HEAD);
+ PUTS("\n");
+ START(HTML_TITLE);
+ PUTS(shortname);
+ PUTS(source_file ? " WAIS source file" : " index");
+ END(HTML_TITLE);
+ PUTS("\n");
+ END(HTML_HEAD);
+
+ START(HTML_H1);
+ PUTS(shortname);
+ PUTS(source_file ? " description" : " index");
+ END(HTML_H1);
+ PUTS("\n");
+ FREE(shortname);
+ }
+
+ START(HTML_DL); /* Definition list of details */
+
+ if (source_file) {
+ START(HTML_DT);
+ PUTS("Access links");
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ if (me->par_value[PAR_IP_NAME] &&
+ me->par_value[PAR_DATABASE_NAME]) {
+
+ char WSRC_address[256];
+ char * www_database;
+ www_database = HTEscape(me->par_value[PAR_DATABASE_NAME],
+ URL_XALPHAS);
+ sprintf(WSRC_address, "wais://%s%s%s/%s",
+ me->par_value[PAR_IP_NAME],
+ me->par_value[PAR_TCP_PORT] ? ":" : "",
+ me->par_value[PAR_TCP_PORT] ? me->par_value[PAR_TCP_PORT] :"",
+ www_database);
+
+ HTStartAnchor(me->target, NULL, WSRC_address);
+ PUTS("Direct access");
+ END(HTML_A);
+ /** Proxy will be used if defined, so let user know that - FM **/
+ PUTS(" (or via proxy server, if defined)");
+
+ FREE(www_database);
+
+ } else {
+ give_parameter(me, PAR_IP_NAME);
+ give_parameter(me, PAR_DATABASE_NAME);
+ }
+ MAYBE_END(HTML_DD);
+
+ } /* end if source_file */
+
+ if (me->par_value[PAR_MAINTAINER]) {
+ START(HTML_DT);
+ PUTS("Maintainer");
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ PUTS(me->par_value[PAR_MAINTAINER]);
+ MAYBE_END(HTML_DD);
+ }
+ if (me->par_value[PAR_IP_NAME]) {
+ START(HTML_DT);
+ PUTS("Host");
+ MAYBE_END(HTML_DT);
+ START(HTML_DD);
+ PUTS(me->par_value[PAR_IP_NAME]);
+ MAYBE_END(HTML_DD);
+ }
+
+ END(HTML_DL);
+
+ if (me->par_value[PAR_DESCRIPTION]) {
+ START(HTML_PRE); /* Preformatted description */
+ PUTS(me->par_value[PAR_DESCRIPTION]);
+ END(HTML_PRE);
+ }
+
+ (*me->target->isa->_free)(me->target);
+
+ return;
+} /* generate html */
+
+
+PRIVATE void WSRCParser_put_string ARGS2(HTStream *, context, CONST char*, str)
+{
+ CONST char *p;
+ for(p=str; *p; p++)
+ WSRCParser_put_character(context, *p);
+}
+
+
+PRIVATE void WSRCParser_write ARGS3(
+ HTStream *, context,
+ CONST char*, str,
+ int, l)
+{
+ CONST char *p;
+ CONST char *e = str+l;
+ for(p=str; p<e; p++)
+ WSRCParser_put_character(context, *p);
+}
+
+
+PRIVATE void WSRCParser_free ARGS1(HTStream *, me)
+{
+ WSRC_gen_html(me, YES);
+#ifdef CACHE_FILE_PREFIX
+ write_cache(me);
+#endif
+ {
+ int p;
+ for (p = 0; par_name[p]; p++) { /* Clear out old values */
+ FREE(me->par_value[p]);
+ }
+ }
+ FREE(me);
+}
+
+PRIVATE void WSRCParser_abort ARGS2(HTStream *, me, HTError, e GCC_UNUSED)
+{
+ WSRCParser_free(me);
+}
+
+
+/* Stream subclass -- method routines
+** ---------------
+*/
+
+HTStreamClass WSRCParserClass = {
+ "WSRCParser",
+ WSRCParser_free,
+ WSRCParser_abort,
+ WSRCParser_put_character,
+ WSRCParser_put_string,
+ WSRCParser_write
+
+};
+
+
+/* Converter from WAIS Source to whatever
+** --------------------------------------
+*/
+PUBLIC HTStream* HTWSRCConvert ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream * me = (HTStream*) malloc(sizeof(*me));
+ if (!me) outofmem(__FILE__, "HTWSRCConvert");
+
+ me->isa = &WSRCParserClass;
+ me->target = HTML_new(anchor, pres->rep_out, sink);
+
+ {
+ int p;
+ for(p=0; p < PAR_COUNT; p++) { /* Clear out parameter values */
+ me->par_value[p] = 0;
+ }
+ }
+ me->state = beginning;
+
+ return me;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.h
new file mode 100644
index 00000000000..9241b321c0b
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWSRC.h
@@ -0,0 +1,48 @@
+/* A parser for WAIS source files
+ WAIS SOURCE FILE PARSER
+
+ This converter returns a stream object into which a WAIS source file can be written.
+ The result is put via a structured stream into whatever format was required for the
+ output stream.
+
+ See also: HTWAIS protocol interface module
+
+ */
+#ifndef HTWSRC_H
+#define HTWSRC_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+#include "HTFormat.h"
+
+extern char from_hex PARAMS((char c));
+
+extern HTStream* HTWSRCConvert PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+/*
+
+Escaping Strings
+
+ HTDeSlash takes out the invlaid characters in a URL path ELEMENT by converting them
+ into hex-escaped characters. HTEnSlash does the reverse.
+
+ Each returns a pointer to a newly allocated string which must eventually be freed by
+ the caller.
+
+ */
+extern char * HTDeSlash PARAMS((CONST char * str));
+
+extern char * HTEnSlash PARAMS((CONST char * str));
+
+#endif
+
+/*
+
+ Tim BL
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.c
new file mode 100644
index 00000000000..f803920f808
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.c
@@ -0,0 +1,189 @@
+/* FILE WRITER HTWrite.c
+** ===========
+**
+*/
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTWriter.h"
+
+#define BUFFER_SIZE 4096 /* Tradeoff */
+
+/*#include <stdio.h> included by HTUtils.h -- FM */
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* HTML Object
+** -----------
+*/
+
+struct _HTStream {
+ CONST HTStreamClass * isa;
+
+ int soc;
+ char *write_pointer;
+ char buffer[BUFFER_SIZE];
+#ifdef NOT_ASCII
+ BOOL make_ascii; /* Are we writing to the net? */
+#endif
+};
+
+
+/* Write the buffer out to the socket
+** ----------------------------------
+*/
+
+PRIVATE void flush ARGS1(HTStream *, me)
+{
+ char *read_pointer = me->buffer;
+ char *write_pointer = me->write_pointer;
+
+#ifdef NOT_ASCII
+ if (me->make_ascii) {
+ char * p;
+ for(p = me->buffer; p < me->write_pointer; p++)
+ *p = TOASCII(*p);
+ }
+#endif
+ while (read_pointer < write_pointer) {
+ int status;
+ status = NETWRITE(me->soc, me->buffer, /* Put timeout? @@@ */
+ write_pointer - read_pointer);
+ if (status<0) {
+ if(TRACE) fprintf(stderr,
+ "HTWrite: Error: write() on socket returns %d !!!\n", status);
+ return;
+ }
+ read_pointer = read_pointer + status;
+ }
+ me->write_pointer = me->buffer;
+}
+
+
+/*_________________________________________________________________________
+**
+** A C T I O N R O U T I N E S
+*/
+
+/* Character handling
+** ------------------
+*/
+
+PRIVATE void HTWriter_put_character ARGS2(HTStream *, me, char, c)
+{
+ if (me->write_pointer == &me->buffer[BUFFER_SIZE]) flush(me);
+ *me->write_pointer++ = c;
+}
+
+
+
+/* String handling
+** ---------------
+**
+** Strings must be smaller than this buffer size.
+*/
+PRIVATE void HTWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
+{
+ int l = strlen(s);
+ if (me->write_pointer + l > &me->buffer[BUFFER_SIZE]) flush(me);
+ strcpy(me->write_pointer, s);
+ me->write_pointer = me->write_pointer + l;
+}
+
+
+/* Buffer write. Buffers can (and should!) be big.
+** ------------
+*/
+PRIVATE void HTWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
+{
+
+ CONST char *read_pointer = s;
+ CONST char *write_pointer = s+l;
+
+ flush(me); /* First get rid of our buffer */
+
+ while (read_pointer < write_pointer) {
+ int status = NETWRITE(me->soc, (char *)read_pointer,
+ write_pointer - read_pointer);
+ if (status<0) {
+ if(TRACE) fprintf(stderr,
+ "HTWriter_write: Error on socket output stream!!!\n");
+ return;
+ }
+ read_pointer = read_pointer + status;
+ }
+}
+
+
+
+
+/* Free an HTML object
+** -------------------
+**
+** Note that the SGML parsing context is freed, but the created object is not,
+** as it takes on an existence of its own unless explicitly freed.
+*/
+PRIVATE void HTWriter_free ARGS1(HTStream *, me)
+{
+ flush(me);
+ NETCLOSE(me->soc);
+ FREE(me);
+}
+
+PRIVATE void HTWriter_abort ARGS2(HTStream *, me, HTError, e GCC_UNUSED)
+{
+ HTWriter_free(me);
+}
+
+
+/* Structured Object Class
+** -----------------------
+*/
+PRIVATE CONST HTStreamClass HTWriter = /* As opposed to print etc */
+{
+ "SocketWriter",
+ HTWriter_free,
+ HTWriter_abort,
+ HTWriter_put_character, HTWriter_put_string,
+ HTWriter_write
+};
+
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+
+PUBLIC HTStream* HTWriter_new ARGS1(int, soc)
+{
+ HTStream* me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL) outofmem(__FILE__, "HTML_new");
+ me->isa = &HTWriter;
+
+#ifdef NOT_ASCII
+ me->make_ascii = NO;
+#endif
+ me->soc = soc;
+ me->write_pointer = me->buffer;
+ return me;
+}
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+
+PUBLIC HTStream* HTASCIIWriter ARGS1(int, soc)
+{
+ HTStream* me = (HTStream*)malloc(sizeof(*me));
+ if (me == NULL) outofmem(__FILE__, "HTML_new");
+ me->isa = &HTWriter;
+
+#ifdef NOT_ASCII
+ me->make_ascii = YES;
+#endif
+ me->soc = soc;
+ me->write_pointer = me->buffer;
+ return me;
+}
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.h
new file mode 100644
index 00000000000..9fa5f8c6191
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HTWriter.h
@@ -0,0 +1,28 @@
+/* */
+
+/* Unix File or Socket Writer HTWriter.c
+** --------------------------
+**
+** This version of the stream object just writes to a socket.
+** The socket is assumed open and closed afterward.
+**
+** There are two versions (identical on ASCII machines)
+** one of which converts to ASCII on output.
+**
+** Bugs:
+** strings written must be less than buffer size.
+*/
+
+#ifndef HTWRITE_H
+#define HTWRITE_H
+
+#include "HTStream.h"
+
+extern HTStream * HTWriter_new PARAMS((int soc));
+
+extern HTStream * HTASCIIWriter PARAMS((int soc));
+
+#endif
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/HText.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/HText.h
new file mode 100644
index 00000000000..64000eab7d0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/HText.h
@@ -0,0 +1,265 @@
+/* Rich Hypertext object for libWWW
+ RICH HYPERTEXT OBJECT
+
+ */
+
+/*
+
+ This is the C interface to the Objective-C (or whatever) Style-oriented HyperText
+ class. It is used when a style-oriented text object is available or craeted in order to
+ display hypertext.
+
+ */
+#ifndef HTEXT_H
+#define HTEXT_H
+#include "HTAnchor.h"
+#include "HTStyle.h"
+#include "HTStream.h"
+#include "SGML.h"
+
+#ifdef SHORT_NAMES
+#define HTMainText HTMaText
+#define HTMainAnchor HtMaAnch
+#define HText_new HTHTNew
+#define HText_new2 HTHTNew2
+#define HText_free HTHTFree
+#define HText_beginAppend HTHTBeAp
+#define HText_endAppend HTHTEnAp
+#define HText_setStyle HTHTSeSt
+#define HText_appendCharacter HTHTApCh
+#define HText_appendImage HTHTApIm
+#define HText_appendText HTHTApTe
+#define HText_appendParagraph HTHTApPa
+#define HText_beginAnchor HTHTBeAn
+#define HText_endAnchor HTHTEnAn
+#define HText_dump HTHTDump
+#define HText_nodeAnchor HTHTNoAn
+#define HText_select HTHTSele
+#define HText_selectAnchor HTHTSeAn
+#define HText_applyStyle HTHTApSt
+#define HText_updateStyle HTHTUpSt
+#define HText_selectionStyle HTHTStyl
+#define HText_replaceSel HTHTRepl
+#define HText_applyToSimilar HTHTApTo
+#define HText_selectUnstyled HTHTSeUn
+#define HText_unlinkSelection HTHTUnSe
+#define HText_linkSelTo HTHTLiSe
+#define HText_referenceSelected HTHTRefS
+#endif
+
+#ifndef THINK_C
+#ifndef HyperText /* Objective C version defined HyperText */
+typedef struct _HText HText; /* Normal Library */
+#endif
+#else
+class CHyperText; /* Mac Think-C browser hook */
+typedef CHyperText HText;
+#endif
+
+extern HText * HTMainText; /* Pointer to current main text */
+extern HTParentAnchor * HTMainAnchor; /* Pointer to current text's anchor */
+
+/*
+
+Creation and deletion
+
+ HTEXT_NEW: CREATE HYPERTEXT OBJECT
+
+ There are several methods depending on how much you want to specify. The output stream
+ is used with objects which need to output the hypertext to a stream. The structure is
+ for objects which need to refer to the structure which is kep by the creating stream.
+
+ */
+ extern HText * HText_new PARAMS((HTParentAnchor * anchor));
+
+ extern HText * HText_new2 PARAMS((HTParentAnchor * anchor,
+ HTStream * output_stream));
+
+ extern HText * HText_new3 PARAMS((HTParentAnchor * anchor,
+ HTStream * output_stream,
+ HTStructured * structure));
+
+/*
+
+ FREE HYPERTEXT OBJECT
+
+ */
+extern void HText_free PARAMS((HText * me));
+
+
+/*
+
+Object Building methods
+
+ These are used by a parser to build the text in an object HText_beginAppend must be
+ called, then any combination of other append calls, then HText_endAppend. This allows
+ optimised handling using buffers and caches which are flushed at the end.
+
+ */
+extern void HText_beginAppend PARAMS((HText * text));
+
+extern void HText_endAppend PARAMS((HText * text));
+
+/*
+
+ SET THE STYLE FOR FUTURE TEXT
+
+ */
+
+extern void HText_setStyle PARAMS((HText * text, HTStyle * style));
+
+/*
+
+ ADD ONE CHARACTER
+
+ */
+extern void HText_appendCharacter PARAMS((HText * text, char ch));
+
+/*
+
+ ADD A ZERO-TERMINATED STRING
+
+ */
+
+extern void HText_appendText PARAMS((HText * text, CONST char * str));
+
+/*
+
+ NEW PARAGRAPH
+
+ and similar things
+
+ */
+extern void HText_appendParagraph PARAMS((HText * text));
+
+extern void HText_appendLineBreak PARAMS((HText * text));
+
+extern void HText_appendHorizontalRule PARAMS((HText * text));
+
+
+
+/*
+
+ START/END SENSITIVE TEXT
+
+ */
+
+/*
+
+ The anchor object is created and passed to HText_beginAnchor. The senstive text is
+ added to the text object, and then HText_endAnchor is called. Anchors may not be
+ nested.
+
+ */
+extern int HText_beginAnchor PARAMS((
+ HText * text,
+ BOOL underline,
+ HTChildAnchor * anc));
+extern void HText_endAnchor PARAMS((HText * text, int number));
+
+
+/*
+
+ APPEND AN INLINE IMAGE
+
+ The image is handled by the creation of an anchor whose destination is the image
+ document to be included. The semantics is the intended inline display of the image.
+
+ An alternative implementation could be, for example, to begin an anchor, append the
+ alternative text or "IMAGE", then end the anchor. This would simply generate some text
+ linked to the image itself as a separate document.
+
+ */
+extern void HText_appendImage PARAMS((
+ HText * text,
+ HTChildAnchor * anc,
+ CONST char * alternative_text,
+ int alignment,
+ BOOL isMap));
+
+/*
+
+ DUMP DIAGNOSTICS TO STDERR
+
+ */
+
+extern void HText_dump PARAMS((HText * me));
+
+/*
+
+ RETURN THE ANCHOR ASSOCIATED WITH THIS NODE
+
+ */
+extern HTParentAnchor * HText_nodeAnchor PARAMS((HText * me));
+
+
+/*
+
+Browsing functions
+
+ */
+
+
+/*
+
+ BRING TO FRONT AND HIGHLIGHT IT
+
+ */
+
+
+extern BOOL HText_select PARAMS((HText * text));
+extern BOOL HText_selectAnchor PARAMS((HText * text, HTChildAnchor* anchor));
+
+/*
+
+Editing functions
+
+ These are called from the application. There are many more functions not included here
+ from the orginal text object. These functions NEED NOT BE IMPLEMENTED in a browser
+ which cannot edit.
+
+ */
+/* Style handling:
+*/
+/* Apply this style to the selection
+*/
+extern void HText_applyStyle PARAMS((HText * me, HTStyle *style));
+
+/* Update all text with changed style.
+*/
+extern void HText_updateStyle PARAMS((HText * me, HTStyle *style));
+
+/* Return style of selection
+*/
+extern HTStyle * HText_selectionStyle PARAMS((
+ HText * me,
+ HTStyleSheet* sheet));
+
+/* Paste in styled text
+*/
+extern void HText_replaceSel PARAMS((HText * me,
+ CONST char *aString,
+ HTStyle* aStyle));
+
+/* Apply this style to the selection and all similarly formatted text
+** (style recovery only)
+*/
+extern void HTextApplyToSimilar PARAMS((HText * me, HTStyle *style));
+
+/* Select the first unstyled run.
+** (style recovery only)
+*/
+extern void HTextSelectUnstyled PARAMS((HText * me, HTStyleSheet *sheet));
+
+
+/* Anchor handling:
+*/
+extern void HText_unlinkSelection PARAMS((HText * me));
+extern HTAnchor * HText_referenceSelected PARAMS((HText * me));
+extern HTAnchor * HText_linkSelTo PARAMS((HText * me, HTAnchor* anchor));
+
+
+#endif /* HTEXT_H */
+/*
+
+ end */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/LYLeaks.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/LYLeaks.h
new file mode 100644
index 00000000000..b181cb7fb0c
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/LYLeaks.h
@@ -0,0 +1,183 @@
+#ifndef __LYLEAKS_H
+/*
+ * Avoid include redundancy
+ * Include only if finding memory leaks.
+ */
+#define __LYLEAKS_H
+
+/*
+** Copyright (c) 1994, University of Kansas, All Rights Reserved
+**
+** Include File: LYLeaks.h
+** Purpose: Header to convert requests for allocation to Lynx
+** custom functions to track memory leaks.
+** Remarks/Portability/Dependencies/Restrictions:
+** For the stdlib.h allocation functions to be overriden by the
+** Lynx memory tracking functions all modules allocating,
+** freeing, or resizing memory must have LY_FIND_LEAKS
+** defined before including this file.
+** This header file should be included in every source file which
+** does any memory manipulation through use of the
+** stdlib.h memory functions.
+** For proper reporting of memory leaks, the function LYLeaks
+** should be registered for execution by atexit as the
+** very first executable statement in main.
+** This code is slow and should not be used except in debugging
+** circumstances (don't define LY_FIND_LEAKS).
+** If you are using LY_FIND_LEAKS and don't want the LYLeak*
+** memory functions to be used in a certain file,
+** define NO_MEMORY_TRACKING before including this file.
+** The only safe way to call the LYLeak* functions is to use
+** the below macros because they depend on the static
+** string created by __FILE__ to not be dynamic in
+** nature (don't free it and assume will exist at all
+** times during execution).
+** Revision History:
+** 05-26-94 created for Lynx 2-3-1, Garrett Arch Blythe
+** 10-30-97 modified to handle StrAllocCopy() and
+** StrAllocCat(). - KW & FM
+*/
+
+/*
+** Required includes
+*/
+#include <stdlib.h>
+#include "HTUtils.h"
+
+/*
+** Constant defines
+*/
+#define MAX_CONTENT_LENGTH 50
+#ifdef VMS
+#define LEAKAGE_SINK "sys$login:Lynx.leaks"
+#else
+#define LEAKAGE_SINK "Lynx.leaks"
+#endif /* VMS */
+
+/*
+** Data structures
+*/
+typedef struct SourceLocation_tag {
+ /*
+ * The file name and line number of where an event took place.
+ */
+ CONST char *cp_FileName;
+ short ssi_LineNumber;
+}
+SourceLocation;
+
+typedef struct AllocationList_tag {
+ /*
+ * A singly linked list.
+ */
+ struct AllocationList_tag *ALp_Next;
+
+ /*
+ * The memory pointer allocated.
+ * If set to NULL, then an invalid request was made.
+ * The invalid pointer also.
+ */
+ void *vp_Alloced;
+ void *vp_BadRequest;
+
+ /*
+ * The size in bytes of the allocated memory.
+ */
+ size_t st_Bytes;
+
+ /*
+ * The source location of specific event (calloc, malloc, free).
+ * realloc kept separate since will track last realloc on pointer.
+ */
+ SourceLocation SL_memory;
+ SourceLocation SL_realloc;
+} AllocationList;
+
+/*
+** Global variable declarations
+*/
+
+/*
+** Macros
+*/
+#if defined(LY_FIND_LEAKS) && !defined(NO_MEMORY_TRACKING)
+/*
+** Only use these macros if we are to track memory allocations.
+** The reason for using a macro instead of a define is that we want
+** to track where the initial allocation took place or where
+** the last reallocation took place.
+** Track where the allocation took place by the __FILE__ and __LINE__
+** defines which are automatic to the compiler.
+*/
+#ifdef malloc
+#undef malloc
+#endif /* malloc */
+#define malloc(st_bytes) LYLeakMalloc(st_bytes, __FILE__, __LINE__)
+
+#ifdef calloc
+#undef calloc
+#endif /* calloc */
+#define calloc(st_number, st_bytes) LYLeakCalloc(st_number, st_bytes, \
+ __FILE__, __LINE__)
+
+#ifdef realloc
+#undef realloc
+#endif /* realloc */
+#define realloc(vp_alloced, st_newbytes) LYLeakRealloc(vp_alloced, \
+ st_newbytes, __FILE__, __LINE__)
+
+#ifdef free
+#undef free
+#endif /* free */
+#define free(vp_alloced) LYLeakFree(vp_alloced, __FILE__, __LINE__)
+
+/*
+** Added the following two defines to track Lynx's frequent use
+** of those macros. - KW 1997-10-12
+*/
+#ifdef StrAllocCopy
+#undef StrAllocCopy
+#endif /* StrAllocCopy */
+#define StrAllocCopy(dest, src) LYLeakSACopy(&(dest), src, __FILE__, __LINE__)
+#ifdef StrAllocCat
+#undef StrAllocCat
+#endif /* StrAllocCat */
+#define StrAllocCat(dest, src) LYLeakSACat(&(dest), src, __FILE__, __LINE__)
+
+#endif /* LY_FIND_LEAKS && !NO_MEMORY_TRACKING */
+
+/*
+** Function declarations
+** See the appropriate source file for usage.
+*/
+extern void LYLeaks NOPARAMS;
+extern void *LYLeakMalloc PARAMS((
+ size_t st_bytes,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+extern void *LYLeakCalloc PARAMS((
+ size_t st_number,
+ size_t st_bytes,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+extern void *LYLeakRealloc PARAMS((
+ void * vp_alloced,
+ size_t st_newbytes,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+extern void LYLeakFree PARAMS((
+ void * vp_alloced,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+extern char * LYLeakSACopy PARAMS((
+ char ** dest,
+ CONST char * src,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+extern char * LYLeakSACat PARAMS((
+ char ** dest,
+ CONST char * src,
+ CONST char * cp_File,
+ CONST short ssi_Line));
+
+#endif /* __LYLEAKS_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/LYexit.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/LYexit.h
new file mode 100644
index 00000000000..7007d615ef6
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/LYexit.h
@@ -0,0 +1,58 @@
+#ifndef __LYEXIT_H
+/*
+ * Avoid include redundancy
+ */
+#define __LYEXIT_H
+
+/*
+ * Copyright (c) 1994, University of Kansas, All Rights Reserved
+ *
+ * Include File: LYexit.h
+ * Purpose: Provide an atexit function for libraries without such.
+ * Remarks/Portability/Dependencies/Restrictions:
+ * Include this header in every file that you have an exit or
+ * atexit statment.
+ * Revision History:
+ * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+
+/*
+ * Required includes
+ */
+#include <stdlib.h>
+#include "HTUtils.h"
+
+/*
+ * Constant defines
+ */
+#ifdef _WINDOWS
+#undef exit
+#endif /* _WINDOWS */
+
+#define exit LYexit
+#define atexit LYatexit
+#define ATEXITSIZE 32
+
+/*
+ * Data structures
+ */
+
+/*
+ * Global variable declarations
+ */
+
+/*
+ * Macros
+ */
+
+/*
+ * Function declarations
+ */
+extern void LYexit PARAMS((int status));
+#ifdef __STDC__
+extern int LYatexit(void (*function)(void));
+#else
+extern int LYatexit();
+#endif /* __STDC__ */
+
+#endif /* __LYEXIT_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.c
new file mode 100644
index 00000000000..713bb905811
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.c
@@ -0,0 +1,3576 @@
+/* General SGML Parser code SGML.c
+** ========================
+**
+** This module implements an HTStream object. To parse an
+** SGML file, create this object which is a parser. The object
+** is (currently) created by being passed a DTD structure,
+** and a target HTStructured oject at which to throw the parsed stuff.
+**
+** 6 Feb 93 Binary seraches used. Intreface modified.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h" /* For FROMASCII */
+
+/* Remove the following to disable the experimental HTML DTD parsing.
+ Currently only used in this source file. - kw */
+
+#ifndef NO_EXTENDED_HTMLDTD
+#define EXTENDED_HTMLDTD
+#endif
+
+#include "SGML.h"
+#include "HTMLDTD.h"
+#include "HTCJK.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include <ctype.h>
+/*#include <stdio.h> included in HTUtils.h -- FM */
+#include "HTChunk.h"
+
+#include "LYCharSets.h"
+#include "LYLeaks.h"
+
+#define INVALID (-1)
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC HTCJKlang HTCJK = NOCJK; /* CJK enum value. */
+PUBLIC BOOL HTPassEightBitRaw = FALSE; /* Pass 161-172,174-255 raw. */
+PUBLIC BOOL HTPassEightBitNum = FALSE; /* Pass ^ numeric entities raw. */
+PUBLIC BOOL HTPassHighCtrlRaw = FALSE; /* Pass 127-160,173,&#127; raw. */
+PUBLIC BOOL HTPassHighCtrlNum = FALSE; /* Pass &#128;-&#159; raw. */
+
+extern int LYlowest_eightbit[];
+
+/* The State (context) of the parser
+**
+** This is passed with each call to make the parser reentrant
+**
+*/
+
+#define MAX_ATTRIBUTES 36 /* Max number of attributes per element */
+
+
+/* Element Stack
+** -------------
+** This allows us to return down the stack reselcting styles.
+** As we return, attribute values will be garbage in general.
+*/
+typedef struct _HTElement HTElement;
+struct _HTElement {
+ HTElement * next; /* Previously nested element or 0 */
+ HTTag* tag; /* The tag at this level */
+};
+
+
+/* Internal Context Data Structure
+** -------------------------------
+*/
+struct _HTStream {
+
+ CONST HTStreamClass * isa; /* inherited from HTStream */
+
+ CONST SGML_dtd *dtd;
+ HTStructuredClass *actions; /* target class */
+ HTStructured *target; /* target object */
+
+ HTTag *current_tag;
+ CONST HTTag *unknown_tag;
+ BOOL inSELECT;
+ int current_attribute_number;
+ HTChunk *string;
+ HTElement *element_stack;
+ enum sgml_state { S_text, S_litteral,
+ S_tag, S_tag_gap, S_attr, S_attr_gap, S_equals, S_value,
+ S_ero, S_cro, S_incro,
+ S_exclamation, S_comment, S_doctype, S_marked,
+ S_sgmlent, S_sgmlele, S_sgmlatt,
+ S_squoted, S_dquoted, S_end, S_entity,
+ S_esc, S_dollar, S_paren, S_nonascii_text,
+ S_dollar_paren,
+ S_esc_sq, S_dollar_sq, S_paren_sq, S_nonascii_text_sq,
+ S_dollar_paren_sq,
+ S_esc_dq, S_dollar_dq, S_paren_dq, S_nonascii_text_dq,
+ S_dollar_paren_dq,
+ S_in_kanji, S_junk_tag} state;
+#ifdef CALLERDATA
+ void * callerData;
+#endif /* CALLERDATA */
+ BOOL present[MAX_ATTRIBUTES]; /* Flags: attribute is present? */
+ char * value[MAX_ATTRIBUTES]; /* malloc'd strings or NULL if none */
+
+ BOOL lead_exclamation;
+ BOOL first_dash;
+ BOOL end_comment;
+ BOOL doctype_bracket;
+ BOOL first_bracket;
+ BOOL second_bracket;
+ BOOL isHex;
+
+ HTParentAnchor * node_anchor;
+ LYUCcharset * inUCI; /* pointer to anchor UCInfo */
+ int inUCLYhndl; /* charset we are fed */
+ LYUCcharset * outUCI; /* anchor UCInfo for target */
+ int outUCLYhndl; /* charset for target */
+ char utf_count;
+ UCode_t utf_char;
+ char utf_buf[8];
+ char * utf_buf_p;
+ UCTransParams T;
+ int current_tag_charset; /* charset to pass attributes */
+
+ char * recover;
+ int recover_index;
+ char * include;
+ int include_index;
+ char * url;
+ char * csi;
+ int csi_index;
+} ;
+
+PRIVATE void set_chartrans_handling ARGS3(
+ HTStream *, context,
+ HTParentAnchor *, anchor,
+ int, chndl)
+{
+ if (chndl < 0) {
+ /*
+ ** Nothing was set for the parser in earlier stages,
+ ** so the HTML parser's UCLYhndl should still be it's
+ ** default. - FM
+ */
+ chndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_STRUCTURED);
+ if (chndl < 0)
+ /*
+ ** That wasn't set either, so seek the HText default. - FM
+ */
+ chndl = HTAnchor_getUCLYhndl(anchor, UCT_STAGE_HTEXT);
+ if (chndl < 0)
+ /*
+ ** That wasn't set either, so assume the current display
+ ** character set. - FM
+ */
+ chndl = current_char_set;
+ /*
+ ** Try to set the HText and HTML stages' chartrans info
+ ** with the default lock level (will not be changed if
+ ** it was set previously with a higher lock level). - FM
+ */
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_setUCInfoStage(anchor, chndl,
+ UCT_STAGE_STRUCTURED,
+ UCT_SETBY_DEFAULT);
+ /*
+ ** Get the chartrans info for output to the HTML parser. - FM
+ */
+ context->outUCI = HTAnchor_getUCInfoStage(anchor,
+ UCT_STAGE_STRUCTURED);
+ context->outUCLYhndl = HTAnchor_getUCLYhndl(context->node_anchor,
+ UCT_STAGE_STRUCTURED);
+ }
+ /*
+ ** Set the in->out transformation parameters. - FM
+ */
+ UCSetTransParams(&context->T,
+ context->inUCLYhndl, context->inUCI,
+ context->outUCLYhndl, context->outUCI);
+ /*
+ ** This is intended for passing the SGML parser's input
+ ** charset as an argument in each call to the HTML
+ ** parser's start tag function, but it would be better
+ ** to call a Lynx_HTML_parser function to set an element
+ ** in its HTStructured object, itself, if this were
+ ** needed. - FM
+ */
+ if (HTCJK != NOCJK) {
+ context->current_tag_charset = -1;
+ } else if (context->T.transp) {
+ context->current_tag_charset = context->inUCLYhndl;
+ } else if (context->T.decode_utf8) {
+ context->current_tag_charset = context->inUCLYhndl;
+ } else if (context->T.do_8bitraw ||
+ context->T.use_raw_char_in) {
+ context->current_tag_charset = context->inUCLYhndl;
+ } else if (context->T.output_utf8 ||
+ context->T.trans_from_uni) {
+ context->current_tag_charset = UCGetLYhndl_byMIME("utf-8");
+ } else {
+ context->current_tag_charset = 0;
+ }
+}
+
+PRIVATE void change_chartrans_handling ARGS1(
+ HTStream *, context)
+{
+ int new_LYhndl = HTAnchor_getUCLYhndl(context->node_anchor,
+ UCT_STAGE_PARSER);
+ if (new_LYhndl != context->inUCLYhndl &&
+ new_LYhndl >= 0) {
+ /*
+ * Something changed. but ignore if a META wants an unknown charset.
+ */
+ LYUCcharset * new_UCI = HTAnchor_getUCInfoStage(context->node_anchor,
+ UCT_STAGE_PARSER);
+ if (new_UCI) {
+ LYUCcharset * next_UCI = HTAnchor_getUCInfoStage(
+ context->node_anchor, UCT_STAGE_STRUCTURED
+ );
+ int next_LYhndl = HTAnchor_getUCLYhndl(
+ context->node_anchor, UCT_STAGE_STRUCTURED
+ );
+ context->inUCI = new_UCI;
+ context->inUCLYhndl = new_LYhndl;
+ context->outUCI = next_UCI;
+ context->outUCLYhndl = next_LYhndl;
+ set_chartrans_handling(context,
+ context->node_anchor, next_LYhndl);
+ }
+ }
+}
+
+#define PUTC(ch) ((*context->actions->put_character)(context->target, ch))
+#define PUTUTF8(code) (UCPutUtf8_charstring((HTStream *)context->target, \
+ (putc_func_t*)(context->actions->put_character), code))
+
+extern BOOL historical_comments;
+extern BOOL minimal_comments;
+extern BOOL soft_dquotes;
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+extern char class_string[TEMPSTRINGSIZE];
+int current_is_class=0;
+#endif
+
+/* Handle Attribute
+** ----------------
+*/
+/* PUBLIC CONST char * SGML_default = ""; ?? */
+
+PRIVATE void handle_attribute_name ARGS2(
+ HTStream *, context,
+ CONST char *, s)
+{
+
+ HTTag * tag = context->current_tag;
+ attr * attributes = tag->attributes;
+ int high, low, i, diff;
+
+ /*
+ ** Ignore unknown tag. - KW
+ */
+ if (tag == context->unknown_tag) {
+ return;
+ }
+
+ /*
+ ** Binary search for attribute name.
+ */
+ for (low = 0, high = tag->number_of_attributes;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) {
+ i = (low + (high-low)/2);
+ diff = strcasecomp(attributes[i].name, s);
+ if (diff == 0) { /* success: found it */
+ context->current_attribute_number = i;
+ context->present[i] = YES;
+ FREE(context->value[i]);
+#ifdef USE_COLOR_STYLE
+ current_is_class=(!strcasecomp("class", s));
+ if (TRACE)
+ fprintf(stderr, "SGML: found attribute %s, %d\n", s, current_is_class);
+#endif
+ return;
+ } /* if */
+
+ } /* for */
+
+ if (TRACE)
+ fprintf(stderr, "SGML: Unknown attribute %s for tag %s\n",
+ s, context->current_tag->name);
+ context->current_attribute_number = INVALID; /* Invalid */
+}
+
+
+/* Handle attribute value
+** ----------------------
+*/
+PRIVATE void handle_attribute_value ARGS2(
+ HTStream *, context,
+ CONST char *, s)
+{
+ if (context->current_attribute_number != INVALID) {
+ StrAllocCopy(context->value[context->current_attribute_number], s);
+#ifdef USE_COLOR_STYLE
+ if (current_is_class)
+ {
+ strncpy (class_string, s, TEMPSTRINGSIZE);
+ if (TRACE)
+ fprintf(stderr, "SGML: class is '%s'\n", s);
+ }
+ else
+ {
+ if (TRACE)
+ fprintf(stderr, "SGML: attribute value is '%s'\n", s);
+ }
+#endif
+ } else {
+ if (TRACE)
+ fprintf(stderr, "SGML: Attribute value %s ignored\n", s);
+ }
+ context->current_attribute_number = INVALID; /* can't have two assignments! */
+}
+
+
+/*
+** Translate some Unicodes to Lynx special codes and output them.
+** Special codes - ones those output depend on parsing.
+**
+** Additional issue, like handling bidirectional text if nesseccery
+** may be called from here: zwnj (8204), zwj (8205), lrm (8206), rlm (8207)
+** - currently they are passed to def7_uni.tbl as regular characters.
+**
+*/
+PRIVATE BOOL put_special_unicodes ARGS2(
+ HTStream *, context,
+ UCode_t, code)
+{
+ if (code == 160) {
+ /*
+ ** Use Lynx special character for nbsp.
+ */
+ PUTC(HT_NON_BREAK_SPACE);
+ } else if (code == 173) {
+ /*
+ ** Use Lynx special character for shy.
+ */
+ PUTC(LY_SOFT_HYPHEN);
+ } else if (code == 8194 || code == 8195 || code == 8201) {
+ /*
+ ** Use Lynx special character for ensp, emsp or thinsp.
+ **
+ ** Originally, Lynx use space '32' as word delimiter and omits this
+ ** space at end of line if word is wrapped to the next line. There
+ ** are several other spaces in the Unicode repertoire and we should
+ ** teach Lynx to understand them, not only as regular characters but
+ ** in the context of line wrapping. Unfortunately, if we use
+ ** HT_EM_SPACE we override the chartrans tables for those spaces
+ ** (e.g., emsp= double space) with a single '32' for all (but do line
+ ** wrapping more fancy). In the future we need HT_SPACE with a
+ ** transferred parameter (Unicode number) which falls back to
+ ** chartrans if line wrapping is not the case.
+ **
+ */
+ PUTC(HT_EM_SPACE);
+#ifdef NOTUSED_FOTEMODS
+ } else if (code == 8211 || code == 8212) {
+ /*
+ ** Use ASCII hyphen for ndash/endash or mdash/emdash.
+ */
+ PUTC('-');
+#endif
+ } else {
+ /*
+ ** Return NO if nothing done.
+ */
+ return NO;
+ }
+ /*
+ ** We have handled it.
+ */
+ return YES;
+}
+
+/* Handle entity
+** -------------
+**
+** On entry,
+** s contains the entity name zero terminated
+** Bugs:
+** If the entity name is unknown, the terminator is treated as
+** a printable non-special character in all cases, even if it is '<'
+** Bug-fix:
+** Modified SGML_character() so we only come here with terminator
+** as '\0' and check a FoundEntity flag. -- Foteos Macrides
+**
+** Modified more (for use with Lynx character translation code):
+*/
+PRIVATE char replace_buf [64]; /* buffer for replacement strings */
+PRIVATE BOOL FoundEntity = FALSE;
+
+#define IncludesLatin1Enc \
+ (context->outUCLYhndl == 0 || \
+ (context->outUCI && \
+ (context->outUCI->enc & (UCT_CP_SUPERSETOF_LAT1))))
+
+PRIVATE void handle_entity ARGS2(
+ HTStream *, context,
+ char, term)
+{
+ UCode_t code;
+ long uck;
+ CONST char *p;
+ CONST char *s = context->string->data;
+#ifdef NOTUSED_FOTEMODS
+ int high, low, i, diff;
+#endif
+
+
+ /*
+ ** Handle all entities normally. - FM
+ */
+ FoundEntity = FALSE;
+ if ((code = HTMLGetEntityUCValue(s)) != 0) {
+ /*
+ ** We got a Unicode value for the entity name.
+ ** Check for special Unicodes. - FM
+ */
+ if (put_special_unicodes(context, code)) {
+ FoundEntity = TRUE;
+ return;
+ }
+ /*
+ ** Seek a translation from the chartrans tables.
+ */
+ if ((uck = UCTransUniChar(code, context->outUCLYhndl)) >= 32 &&
+ uck < 256 &&
+ (uck < 127 ||
+ uck >= LYlowest_eightbit[context->outUCLYhndl])) {
+ PUTC(FROMASCII((char)uck));
+ FoundEntity = TRUE;
+ return;
+ } else if ((uck == -4 ||
+ (context->T.repl_translated_C0 &&
+ uck > 0 && uck < 32)) &&
+ /*
+ ** Not found; look for replacement string.
+ */
+ (uck = UCTransUniCharStr(replace_buf, 60, code,
+ context->outUCLYhndl, 0) >= 0)) {
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ FoundEntity = TRUE;
+ return;
+ }
+ /*
+ ** If we're displaying UTF-8, try that now. - FM
+ */
+ if (context->T.output_utf8 && PUTUTF8(code)) {
+ FoundEntity = TRUE;
+ return;
+ }
+ /*
+ ** If it's safe ASCII, use it. - FM
+ */
+ if (code >= 32 && code < 127) {
+ PUTC(FROMASCII((char)code));
+ FoundEntity = TRUE;
+ return;
+ }
+#ifdef NOTUSED_FOTEMODS
+ /*
+ ** If the value is greater than 255 and we do not
+ ** have the "7-bit approximations" as our output
+ ** character set (in which case we did it already)
+ ** seek a translation for that. - FM
+ */
+ if ((chk = ((code > 255) &&
+ context->outUCLYhndl !=
+ UCGetLYhndl_byMIME("us-ascii"))) &&
+ (uck = UCTransUniChar(code,
+ UCGetLYhndl_byMIME("us-ascii")))>= 32 &&
+ uck < 127) {
+ /*
+ ** Got an ASCII character (yippey). - FM
+ */
+ PUTC(((char)(uck & 0xff)));
+ FoundEntity = TRUE;
+ return;
+ } else if ((chk && uck == -4) &&
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ UCGetLYhndl_byMIME("us-ascii"),
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string (yippey). - FM
+ */
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ FoundEntity = TRUE;
+ return;
+ }
+ }
+ /*
+ ** Ignore zwnj (8204) and zwj (8205), if we get to here.
+ ** Note that zwnj may have been handled as <WBR>
+ ** by the calling function. - FM
+ */
+ if (!strcmp(s, "zwnj") ||
+ !strcmp(s, "zwj")) {
+ if (TRACE) {
+ fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
+ }
+ FoundEntity = TRUE;
+ return;
+ }
+
+ /*
+ ** Ignore lrm (8206), and rln (8207), if we get to here. - FM
+ */
+ if (!strcmp(s, "lrm") ||
+ !strcmp(s, "rlm")) {
+ if (TRACE) {
+ fprintf(stderr, "handle_entity: Ignoring '%s'.\n", s);
+ }
+ FoundEntity = TRUE;
+ return;
+ }
+
+ /*
+ ** We haven't succeeded yet, so try the old LYCharSets
+ ** arrays for translation strings. - FM
+ */
+ for (low = 0, high = context->dtd->number_of_entities;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) { /* Binary search */
+ i = (low + (high-low)/2);
+ diff = strcmp(entities[i], s); /* Case sensitive! */
+ if (diff == 0) { /* success: found it */
+ for (p = LYCharSets[context->outUCLYhndl][i]; *p; p++) {
+ PUTC(*p);
+ }
+ FoundEntity = TRUE;
+ return;
+ }
+#endif
+ }
+
+ /*
+ ** If entity string not found, display as text.
+ */
+ if (TRACE)
+ fprintf(stderr, "SGML: Unknown entity '%s'\n", s);
+ PUTC('&');
+ for (p = s; *p; p++) {
+ PUTC(*p);
+ }
+ if (term != '\0')
+ PUTC(term);
+}
+
+
+/* Handle comment
+** --------------
+*/
+PRIVATE void handle_comment ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Comment:\n<%s>\n", s);
+
+ if (context->csi == NULL &&
+ strncmp(s, "!--#", 4) == 0 &&
+ LYCheckForCSI(context->node_anchor, (char **)&context->url) == TRUE) {
+ LYDoCSI(context->url, s, (char **)&context->csi);
+ }
+
+ return;
+}
+
+
+/* Handle identifier
+** -----------------
+*/
+PRIVATE void handle_identifier ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Identifier\n<%s>\n", s);
+
+ return;
+}
+
+
+/* Handle doctype
+** --------------
+*/
+PRIVATE void handle_doctype ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Doctype\n<%s>\n", s);
+
+ return;
+}
+
+
+/* Handle marked
+** -------------
+*/
+PRIVATE void handle_marked ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Marked Section:\n<%s>\n", s);
+
+ return;
+}
+
+
+/* Handle sgmlent
+** --------------
+*/
+PRIVATE void handle_sgmlent ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Entity Declaration:\n<%s>\n", s);
+
+ return;
+}
+
+
+/* Handle sgmlent
+** --------------
+*/
+PRIVATE void handle_sgmlele ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Element Declaration:\n<%s>\n", s);
+
+ return;
+}
+
+
+/* Handle sgmlatt
+** --------------
+*/
+PRIVATE void handle_sgmlatt ARGS1(
+ HTStream *, context)
+{
+ CONST char *s = context->string->data;
+
+ if (TRACE)
+ fprintf(stderr, "SGML Attribute Declaration:\n<%s>\n", s);
+
+ return;
+}
+
+#ifdef EXTENDED_HTMLDTD
+
+PRIVATE BOOL element_valid_within ARGS3(
+ HTTag *, new_tag,
+ HTTag *, stacked_tag,
+ BOOL, direct)
+{
+ TagClass usecontains, usecontained;
+ if (!stacked_tag || !new_tag)
+ return YES;
+ usecontains = (direct ? stacked_tag->contains : stacked_tag->icontains);
+ usecontained = (direct ? new_tag->contained : new_tag->icontained);
+ if (new_tag == stacked_tag)
+ return ((Tgc_same & usecontains) &&
+ (Tgc_same & usecontained));
+ else
+ return ((new_tag->tagclass & usecontains) &&
+ (stacked_tag->tagclass & usecontained));
+}
+
+extern BOOL New_DTD;
+
+typedef enum {
+ close_NO = 0,
+ close_error = 1,
+ close_valid = 2
+} canclose_t;
+
+PRIVATE canclose_t can_close ARGS2(
+ HTTag *, new_tag,
+ HTTag *, stacked_tag)
+{
+ if (!stacked_tag)
+ return close_NO;
+ if (stacked_tag->flags & Tgf_endO)
+ return close_valid;
+ else if (new_tag == stacked_tag)
+ return ((Tgc_same & new_tag->canclose) ? close_error : close_NO);
+ else
+ return ((stacked_tag->tagclass & new_tag->canclose) ?
+ close_error : close_NO);
+}
+PRIVATE void do_close_stacked ARGS1(
+ HTStream *, context)
+{
+ HTElement * stacked = context->element_stack;
+ if (!stacked)
+ return; /* stack was empty */
+ if (context->inSELECT && !strcasecomp(stacked->tag->name, "SELECT")) {
+ context->inSELECT = FALSE;
+ }
+ (*context->actions->end_element)(
+ context->target,
+ stacked->tag - context->dtd->tags,
+ (char **)&context->include);
+ context->element_stack = stacked->next;
+ FREE(stacked);
+}
+PRIVATE int is_on_stack ARGS2(
+ HTStream *, context,
+ HTTag *, old_tag)
+{
+ HTElement * stacked = context->element_stack;
+ int i = 1;
+ for (; stacked; stacked = stacked->next, i++) {
+ if (stacked->tag == old_tag)
+ return i;
+ }
+ return 0;
+}
+#endif /* EXTENDED_HTMLDTD */
+
+/* End element
+** -----------
+*/
+PRIVATE void end_element ARGS2(
+ HTStream *, context,
+ HTTag *, old_tag)
+{
+#ifdef EXTENDED_HTMLDTD
+
+ BOOL extra_action_taken = NO;
+ canclose_t canclose_check = close_valid;
+ int stackpos = is_on_stack(context, old_tag);
+
+ if (New_DTD) {
+ while (canclose_check != close_NO &&
+ context->element_stack &&
+ (stackpos > 1 || (!extra_action_taken && stackpos == 0))) {
+ canclose_check = can_close(old_tag, context->element_stack->tag);
+ if (canclose_check != close_NO) {
+ if (TRACE)
+ fprintf(stderr, "SGML: End </%s> \t<- %s end </%s>\n",
+ context->element_stack->tag->name,
+ canclose_check == close_valid ? "supplied," : "forced by",
+ old_tag->name);
+ do_close_stacked(context);
+ extra_action_taken = YES;
+ stackpos = is_on_stack(context, old_tag);
+ } else {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s \t<- invalid end </%s>\n",
+ context->element_stack->tag->name,
+ old_tag->name);
+ return;
+ }
+ }
+
+ if (stackpos == 0 && old_tag->contents != SGML_EMPTY) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s, no open %s for </%s>\n",
+ context->element_stack ?
+ context->element_stack->tag->name : "none",
+ old_tag->name,
+ old_tag->name);
+ return;
+ }
+ if (stackpos > 1) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Nesting <%s>...<%s> \t<- invalid end </%s>\n",
+ old_tag->name,
+ context->element_stack->tag->name,
+ old_tag->name);
+ return;
+ }
+ }
+ /* Now let the non-extended code deal with the rest. - kw */
+
+#endif /* EXTENDED_HTMLDTD */
+
+ /*
+ ** If we are in a SELECT block, ignore anything
+ ** but a SELECT end tag. - FM
+ */
+ if (context->inSELECT) {
+ if (!strcasecomp(old_tag->name, "SELECT")) {
+ /*
+ ** Turn off the inSELECT flag and fall through. - FM
+ */
+ context->inSELECT = FALSE;
+ } else {
+ /*
+ ** Ignore the end tag. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML: Ignoring end tag </%s> in SELECT block.\n",
+ old_tag->name);
+ }
+ return;
+ }
+ }
+ /*
+ ** Handle the end tag. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "SGML: End </%s>\n", old_tag->name);
+ if (old_tag->contents == SGML_EMPTY) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Illegal end tag </%s> found.\n",
+ old_tag->name);
+ return;
+ }
+#ifdef WIND_DOWN_STACK
+ while (context->element_stack) { /* Loop is error path only */
+#else
+ if (context->element_stack) { /* Substitute and remove one stack element */
+#endif /* WIND_DOWN_STACK */
+ HTElement * N = context->element_stack;
+ HTTag * t = N->tag;
+
+ if (old_tag != t) { /* Mismatch: syntax error */
+ if (context->element_stack->next) { /* This is not the last level */
+ if (TRACE) fprintf(stderr,
+ "SGML: Found </%s> when expecting </%s>. </%s> assumed.\n",
+ old_tag->name, t->name, t->name);
+ } else { /* last level */
+ if (TRACE) fprintf(stderr,
+ "SGML: Found </%s> when expecting </%s>. </%s> Ignored.\n",
+ old_tag->name, t->name, old_tag->name);
+ return; /* Ignore */
+ }
+ }
+
+ context->element_stack = N->next; /* Remove from stack */
+ FREE(N);
+ (*context->actions->end_element)(context->target,
+ t - context->dtd->tags, (char **)&context->include);
+#ifdef WIND_DOWN_STACK
+ if (old_tag == t)
+ return; /* Correct sequence */
+#else
+ return;
+#endif /* WIND_DOWN_STACK */
+
+ /* Syntax error path only */
+
+ }
+ if (TRACE)
+ fprintf(stderr, "SGML: Extra end tag </%s> found and ignored.\n",
+ old_tag->name);
+}
+
+
+/* Start a element
+*/
+PRIVATE void start_element ARGS1(
+ HTStream *, context)
+{
+ HTTag * new_tag = context->current_tag;
+
+#ifdef EXTENDED_HTMLDTD
+
+ BOOL valid = YES;
+ BOOL direct_container = YES;
+ BOOL extra_action_taken = NO;
+ canclose_t canclose_check = close_valid;
+
+ if (New_DTD) {
+ while (context->element_stack &&
+ (canclose_check == close_valid ||
+ (canclose_check == close_error &&
+ new_tag == context->element_stack->tag)) &&
+ !(valid = element_valid_within(new_tag, context->element_stack->tag,
+ direct_container))) {
+ canclose_check = can_close(new_tag, context->element_stack->tag);
+ if (canclose_check != close_NO) {
+ if (TRACE)
+ fprintf(stderr, "SGML: End </%s> \t<- %s start <%s>\n",
+ context->element_stack->tag->name,
+ canclose_check == close_valid ? "supplied," : "forced by",
+ new_tag->name);
+ do_close_stacked(context);
+ extra_action_taken = YES;
+ if (canclose_check == close_error)
+ direct_container = NO;
+ } else {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s \t<- invalid start <%s>\n",
+ context->element_stack->tag->name,
+ new_tag->name);
+ }
+ }
+ if (context->element_stack && !valid &&
+ (context->element_stack->tag->flags & Tgf_strict) &&
+ !(valid = element_valid_within(new_tag, context->element_stack->tag,
+ direct_container))) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s \t<- ignoring start <%s>\n",
+ context->element_stack->tag->name,
+ new_tag->name);
+ return;
+ }
+
+ if (context->element_stack && !extra_action_taken &&
+ canclose_check == close_NO && !valid && (new_tag->flags & Tgf_mafse)) {
+ BOOL has_attributes = NO;
+ int i = 0;
+ for (; i< new_tag->number_of_attributes && !has_attributes; i++)
+ has_attributes = context->present[i];
+ if (!has_attributes) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s, converting invalid <%s> to </%s>\n",
+ context->element_stack->tag->name,
+ new_tag->name,
+ new_tag->name);
+ end_element(context, new_tag);
+ return;
+ }
+ }
+
+ if (context->element_stack &&
+ canclose_check == close_error && !(valid =
+ element_valid_within(
+ new_tag,
+ context->element_stack->tag,
+ direct_container))) {
+ if (TRACE)
+ fprintf(stderr, "SGML: Still open %s \t<- invalid start <%s>\n",
+ context->element_stack->tag->name,
+ new_tag->name);
+ }
+ }
+ /* Fall through to the non-extended code - kw */
+
+#endif /* EXTENDED_HTMLDTD */
+
+ /*
+ ** If we are not in a SELECT block, check if this is
+ ** a SELECT start tag. Otherwise (i.e., we are in a
+ ** SELECT block) accept only OPTION as valid, terminate
+ ** the SELECT block if it is any other form-related
+ ** element, and otherwise ignore it. - FM
+ */
+ if (!context->inSELECT) {
+ /*
+ ** We are not in a SELECT block, so check if this starts one. - FM
+ */
+ if (!strcasecomp(new_tag->name, "SELECT")) {
+ /*
+ ** Set the inSELECT flag and fall through. - FM
+ */
+ context->inSELECT = TRUE;
+ }
+ } else {
+ /*
+ ** We are in a SELECT block. - FM
+ */
+ if (strcasecomp(new_tag->name, "OPTION")) {
+ /*
+ ** Ugh, it is not an OPTION. - FM
+ */
+ if (!strcasecomp(new_tag->name, "INPUT") ||
+ !strcasecomp(new_tag->name, "TEXTAREA") ||
+ !strcasecomp(new_tag->name, "SELECT") ||
+ !strcasecomp(new_tag->name, "BUTTON") ||
+ !strcasecomp(new_tag->name, "FIELDSET") ||
+ !strcasecomp(new_tag->name, "LABEL") ||
+ !strcasecomp(new_tag->name, "LEGEND") ||
+ !strcasecomp(new_tag->name, "FORM")) {
+ /*
+ ** It is another form-related start tag, so terminate
+ ** the current SELECT block and fall through. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "SGML: Faking SELECT end tag before <%s> start tag.\n",
+ new_tag->name);
+ end_element(context, SGMLFindTag(context->dtd, "SELECT"));
+ } else {
+ /*
+ ** Ignore the start tag. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "SGML: Ignoring start tag <%s> in SELECT block.\n",
+ new_tag->name);
+ return;
+ }
+ }
+ }
+ /*
+ ** Handle the start tag. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "SGML: Start <%s>\n", new_tag->name);
+ (*context->actions->start_element)(
+ context->target,
+ new_tag - context->dtd->tags,
+ context->present,
+ (CONST char**) context->value, /* coerce type for think c */
+ context->current_tag_charset,
+ (char **)&context->include);
+ if (new_tag->contents != SGML_EMPTY) { /* i.e. tag not empty */
+ HTElement * N = (HTElement *)malloc(sizeof(HTElement));
+ if (N == NULL)
+ outofmem(__FILE__, "start_element");
+ N->next = context->element_stack;
+ N->tag = new_tag;
+ context->element_stack = N;
+ } else if (!strcasecomp(new_tag->name, "META")) {
+ /*
+ ** Check for result of META tag. - KW & FM
+ */
+ change_chartrans_handling(context);
+ }
+}
+
+
+/* Find Tag in DTD tag list
+** ------------------------
+**
+** On entry,
+** dtd points to dtd structire including valid tag list
+** string points to name of tag in question
+**
+** On exit,
+** returns:
+** NULL tag not found
+** else address of tag structure in dtd
+*/
+PUBLIC HTTag * SGMLFindTag ARGS2(
+ CONST SGML_dtd*, dtd,
+ CONST char *, string)
+{
+ int high, low, i, diff;
+ for (low = 0, high=dtd->number_of_tags;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) { /* Binary search */
+ i = (low + (high-low)/2);
+ diff = strcasecomp(dtd->tags[i].name, string); /* Case insensitive */
+ if (diff == 0) { /* success: found it */
+ return &dtd->tags[i];
+ }
+ }
+ if (isalpha((unsigned char)string[0])) {
+ /*
+ ** Unrecognized, but may be valid. - KW
+ */
+ return (HTTag *)&HTTag_unrecognized;
+ }
+ return NULL;
+}
+
+/*________________________________________________________________________
+** Public Methods
+*/
+
+
+/* Could check that we are back to bottom of stack! @@ */
+/* Do check! - FM */
+/* */
+PRIVATE void SGML_free ARGS1(
+ HTStream *, context)
+{
+ int i;
+ HTElement * cur;
+ HTTag * t;
+
+ /*
+ ** Free the buffers. - FM
+ */
+ FREE(context->recover);
+ FREE(context->url);
+ FREE(context->csi);
+ FREE(context->include);
+
+ /*
+ ** Wind down stack if any elements are open. - FM
+ */
+ while (context->element_stack) {
+ cur = context->element_stack;
+ t = cur->tag;
+ context->element_stack = cur->next; /* Remove from stack */
+ FREE(cur);
+ (*context->actions->end_element)(context->target,
+ t - context->dtd->tags, (char **)&context->include);
+ FREE(context->include);
+ }
+
+ /*
+ ** Finish off the target. - FM
+ */
+ (*context->actions->_free)(context->target);
+
+ /*
+ ** Free the strings and context structure. - FM
+ */
+ HTChunkFree(context->string);
+ for (i = 0; i < MAX_ATTRIBUTES; i++)
+ FREE(context->value[i]);
+ FREE(context);
+}
+
+PRIVATE void SGML_abort ARGS2(
+ HTStream *, context,
+ HTError, e)
+{
+ int i;
+ HTElement * cur;
+
+ /*
+ ** Abort the target. - FM
+ */
+ (*context->actions->_abort)(context->target, e);
+
+ /*
+ ** Free the buffers. - FM
+ */
+ FREE(context->recover);
+ FREE(context->include);
+ FREE(context->url);
+ FREE(context->csi);
+
+ /*
+ ** Free stack memory if any elements were left open. - KW
+ */
+ while (context->element_stack) {
+ cur = context->element_stack;
+ context->element_stack = cur->next; /* Remove from stack */
+ FREE(cur);
+ }
+
+ /*
+ ** Free the strings and context structure. - FM
+ */
+ HTChunkFree(context->string);
+ for (i = 0; i < MAX_ATTRIBUTES; i++)
+ FREE(context->value[i]);
+ FREE(context);
+}
+
+
+/* Read and write user callback handle
+** -----------------------------------
+**
+** The callbacks from the SGML parser have an SGML context parameter.
+** These calls allow the caller to associate his own context with a
+** particular SGML context.
+*/
+
+#ifdef CALLERDATA
+PUBLIC void* SGML_callerData ARGS1(
+ HTStream *, context)
+{
+ return context->callerData;
+}
+
+PUBLIC void SGML_setCallerData ARGS2(
+ HTStream *, context,
+ void*, data)
+{
+ context->callerData = data;
+}
+#endif /* CALLERDATA */
+
+PRIVATE void SGML_character ARGS2(
+ HTStream *, context,
+ char, c_in)
+{
+ CONST SGML_dtd *dtd = context->dtd;
+ HTChunk *string = context->string;
+ CONST char * EntityName;
+ char * p;
+ BOOLEAN chk; /* Helps (?) walk through all the else ifs... */
+ UCode_t clong, uck; /* Enough bits for UCS4 ... */
+ char c;
+ char saved_char_in = '\0';
+
+ /*
+ ** Now some fun with the preprocessor.
+ ** Use copies for c and unsign_c == clong, so that
+ ** we can revert back to the unchanged c_in. - KW
+ */
+#define unsign_c clong
+
+ c = c_in;
+ clong = (unsigned char)c; /* a.k.a. unsign_c */
+
+ if (context->T.decode_utf8) {
+ /*
+ ** Combine UTF-8 into Unicode.
+ ** Incomplete characters silently ignored.
+ ** From Linux kernel's console.c. - KW
+ */
+ if ((unsigned char)c > 127) {
+ /*
+ ** We have an octet from a multibyte character. - FM
+ */
+ if (context->utf_count > 0 && (c & 0xc0) == 0x80) {
+ context->utf_char = (context->utf_char << 6) | (c & 0x3f);
+ context->utf_count--;
+ *(context->utf_buf_p) = c;
+ (context->utf_buf_p)++;
+ if (context->utf_count == 0) {
+ /*
+ ** We have all of the bytes, so terminate
+ ** the buffer and set 'clong' to the UCode_t
+ ** value. - FM
+ */
+ *(context->utf_buf_p) = '\0';
+ clong = context->utf_char;
+ if (clong < 256) {
+ c = ((char)(clong & 0xff));
+ }
+ goto top1;
+ } else {
+ /*
+ ** Wait for more. - KW
+ */
+ return;
+ }
+ } else {
+ /*
+ ** Start handling a new multibyte character. - FM
+ */
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = c;
+ (context->utf_buf_p)++;
+ if ((c & 0xe0) == 0xc0) {
+ context->utf_count = 1;
+ context->utf_char = (c & 0x1f);
+ } else if ((c & 0xf0) == 0xe0) {
+ context->utf_count = 2;
+ context->utf_char = (c & 0x0f);
+ } else if ((c & 0xf8) == 0xf0) {
+ context->utf_count = 3;
+ context->utf_char = (c & 0x07);
+ } else if ((c & 0xfc) == 0xf8) {
+ context->utf_count = 4;
+ context->utf_char = (c & 0x03);
+ } else if ((c & 0xfe) == 0xfc) {
+ context->utf_count = 5;
+ context->utf_char = (c & 0x01);
+ } else {
+ /*
+ ** Garbage. - KW
+ */
+ context->utf_count = 0;
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+ }
+ /*
+ ** Wait for more. - KW
+ */
+ return;
+ }
+ } else {
+ /*
+ ** Got an ASCII char. - KW
+ */
+ context->utf_count = 0;
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+ /* goto top; */
+ }
+ }
+
+#ifdef NOTDEFINED
+ /*
+ ** If we have a koi8-r input and do not have
+ ** koi8-r as the output, save the raw input
+ ** in saved_char_in before we potentially
+ ** convert it to Unicode. - FM
+ */
+ if (context->T.strip_raw_char_in)
+ saved_char_in = c;
+#endif /* NOTDEFINED */
+
+ /*
+ ** If we want the raw input converted
+ ** to Unicode, try that now. - FM
+ */
+ if (context->T.trans_to_uni &&
+ ((unsign_c >= 127) ||
+ (unsign_c < 32 && unsign_c != 0 &&
+ context->T.trans_C0_to_uni))) {
+ /*
+ ** Convert the octet to Unicode. - FM
+ */
+ clong = UCTransToUni(c, context->inUCLYhndl);
+ if (clong > 0) {
+ saved_char_in = c;
+ if (clong < 256) {
+ c = FROMASCII((char)clong);
+ }
+ }
+ goto top1;
+ } else if (unsign_c < 32 && unsign_c != 0 &&
+ context->T.trans_C0_to_uni) {
+ /*
+ ** This else if may be too ugly to keep. - KW
+ */
+ if (context->T.trans_from_uni &&
+ (((clong = UCTransToUni(c, context->inUCLYhndl)) >= 32) ||
+ (context->T.transp &&
+ (clong = UCTransToUni(c, context->inUCLYhndl)) > 0))) {
+ saved_char_in = c;
+ if (clong < 256) {
+ c = FROMASCII((char)clong);
+ }
+ goto top1;
+ } else {
+ uck = -1;
+ if (context->T.transp) {
+ uck = UCTransCharStr(replace_buf, 60, c,
+ context->inUCLYhndl,
+ context->inUCLYhndl, NO);
+ }
+ if (!context->T.transp || uck < 0) {
+ uck = UCTransCharStr(replace_buf, 60, c,
+ context->inUCLYhndl,
+ context->outUCLYhndl, YES);
+ }
+ if (uck == 0) {
+ return;
+ } else if (uck < 0) {
+ goto top0a;
+ }
+ c = replace_buf[0];
+ if (c && replace_buf[1]) {
+ if (context->state == S_text) {
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ return;
+ }
+ StrAllocCat(context->recover, replace_buf + 1);
+ }
+ goto top0a;
+ } /* Next line end of ugly stuff for C0. - KW */
+ } else {
+ goto top0a;
+ }
+
+ /*
+ ** At this point we have either unsign_c a.k.a. clong in
+ ** Unicode (and c in latin1 if clong is in the latin1 range),
+ ** or unsign_c and c will have to be passed raw. - KW
+ */
+/*
+** We jump up to here from below if we have
+** stuff in the recover, insert, or csi buffers
+** to process. We zero saved_char_in, in effect
+** as a flag that the octet in not that of the
+** actual call to this function. This may be OK
+** for now, for the stuff this function adds to
+** its recover buffer, but it might not be for
+** stuff other functions added to the insert or
+** csi buffer, so bear that in mind. - FM
+*/
+top:
+ saved_char_in = '\0';
+/*
+** We jump to here from above when we don't have
+** UTF-8 input, haven't converted to Unicode, and
+** want clong set to the input octet (unsigned)
+** without zeroing its saved_char_in copy (which
+** is signed). - FM
+*/
+top0a:
+ *(context->utf_buf) = '\0';
+ clong = (unsigned char)c;
+/*
+** We jump to here from above if we have converted
+** the input, or a multibyte sequence across calls,
+** to a Unicode value and loaded it into clong (to
+** which unsign_c has been defined), and from below
+** when we are recycling a character (e.g., because
+** it terminated an entity but is not the standard
+** semi-colon). The chararcter will already have
+** been put through the Unicode conversions. - FM
+*/
+top1:
+ /*
+ ** Ignore low ISO 646 7-bit control characters
+ ** if HTCJK is not set. - FM
+ */
+ if (unsign_c < 32 &&
+ c != 9 && c != 10 && c != 13 &&
+ HTCJK == NOCJK)
+ return;
+
+ /*
+ ** Ignore 127 if we don't have HTPassHighCtrlRaw
+ ** or HTCJK set. - FM
+ */
+#define PASSHICTRL (context->T.transp || \
+ unsign_c >= LYlowest_eightbit[context->inUCLYhndl])
+ if (c == 127 &&
+ !(PASSHICTRL || HTCJK != NOCJK))
+ return;
+
+ /*
+ ** Ignore 8-bit control characters 128 - 159 if
+ ** neither HTPassHighCtrlRaw nor HTCJK is set. - FM
+ */
+ if (unsign_c > 127 && unsign_c < 160 &&
+ !(PASSHICTRL || HTCJK != NOCJK))
+ return;
+
+ /*
+ ** Handle character based on context->state.
+ */
+ switch(context->state) {
+
+ case S_in_kanji:
+ /*
+ ** Note that if we don't have a CJK input, then this
+ ** is not the second byte of a CJK di-byte, and we're
+ ** trashing the input. That's why 8-bit characters
+ ** followed by, for example, '<' can cause the tag to
+ ** be treated as text, not markup. We could try to deal
+ ** with it by holding each first byte and then checking
+ ** byte pairs, but that doesn't seem worth the overhead
+ ** (see below). - FM
+ */
+ context->state = S_text;
+ PUTC(c);
+ break;
+
+ case S_text:
+ if (HTCJK != NOCJK && (c & 0200) != 0) {
+ /*
+ ** Setting up for Kanji multibyte handling (based on
+ ** Takuya ASADA's (asada@three-a.co.jp) CJK Lynx).
+ ** Note that if the input is not in fact CJK, the
+ ** next byte also will be mishandled, as explained
+ ** above. Toggle raw mode off in such cases, or
+ ** select the "7 bit approximations" display
+ ** character set, which is largely equivalent
+ ** to having raw mode off with CJK. - FM
+ */
+ context->state = S_in_kanji;
+ PUTC(c);
+ break;
+ } else if (HTCJK != NOCJK && c == '\033') {
+ /*
+ ** Setting up for CJK escape sequence handling (based on
+ ** Takuya ASADA's (asada@three-a.co.jp) CJK Lynx). - FM
+ */
+ context->state = S_esc;
+ PUTC(c);
+ break;
+ }
+ if (c == '&' && unsign_c < 127 &&
+ (!context->element_stack ||
+ (context->element_stack->tag &&
+ (context->element_stack->tag->contents == SGML_MIXED ||
+ context->element_stack->tag->contents == SGML_PCDATA ||
+ context->element_stack->tag->contents == SGML_RCDATA)))) {
+ /*
+ ** Setting up for possible entity, without the leading '&'. - FM
+ */
+ string->size = 0;
+ context->state = S_ero;
+ } else if (c == '<' && unsign_c < 127) {
+ /*
+ ** Setting up for possible tag. - FM
+ */
+ string->size = 0;
+ context->state = (context->element_stack &&
+ context->element_stack->tag &&
+ context->element_stack->tag->contents == SGML_LITTERAL)
+ ?
+ S_litteral : S_tag;
+#define PASS8859SPECL context->T.pass_160_173_raw
+ /*
+ ** Convert 160 (nbsp) to Lynx special character if
+ ** neither HTPassHighCtrlRaw nor HTCJK is set. - FM
+ */
+ } else if (unsign_c == 160 &&
+ !(PASS8859SPECL || HTCJK != NOCJK)) {
+ PUTC(HT_NON_BREAK_SPACE);
+ /*
+ ** Convert 173 (shy) to Lynx special character if
+ ** neither HTPassHighCtrlRaw nor HTCJK is set. - FM
+ */
+ } else if (unsign_c == 173 &&
+ !(PASS8859SPECL || HTCJK != NOCJK)) {
+ PUTC(LY_SOFT_HYPHEN);
+ /*
+ ** Handle the case in which we think we have a character
+ ** which doesn't need further processing (e.g., a koi8-r
+ ** input for a koi8-r output). - FM
+ */
+ } else if (context->T.use_raw_char_in && saved_char_in) {
+ /*
+ ** Only if the original character is still in saved_char_in,
+ ** otherwise we may be iterating from a goto top. - KW
+ */
+ PUTC(saved_char_in);
+ saved_char_in = '\0';
+/******************************************************************
+ * I. LATIN-1 OR UCS2 TO DISPLAY CHARSET
+ ******************************************************************/
+ } else if ((chk = (context->T.trans_from_uni && unsign_c >= 160)) &&
+ (uck = UCTransUniChar(unsign_c,
+ context->outUCLYhndl)) >= 32 &&
+ uck < 256) {
+ if (TRACE) {
+ fprintf(stderr,
+ "UCTransUniChar returned 0x%.2lX:'%c'.\n",
+ uck, FROMASCII((char)uck));
+ }
+ /*
+ ** We got one octet from the conversions, so use it. - FM
+ */
+ PUTC(FROMASCII((char)uck));
+ } else if ((chk &&
+ (uck == -4 ||
+ (context->T.repl_translated_C0 &&
+ uck > 0 && uck < 32))) &&
+ /*
+ ** Not found; look for replacement string. - KW
+ */
+ (uck = UCTransUniCharStr(replace_buf, 60, clong,
+ context->outUCLYhndl,
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string.
+ ** No further tests for valididy - assume that whoever
+ ** defined replacement strings knew what she was doing. - KW
+ */
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ /*
+ ** If we're displaying UTF-8, try that now. - FM
+ */
+ } else if (context->T.output_utf8 && PUTUTF8(clong)) {
+ ; /* do nothing more */
+ /*
+ ** If it's any other (> 160) 8-bit chararcter, and
+ ** we have not set HTPassEightBitRaw nor HTCJK, nor
+ ** have the "ISO Latin 1" character set selected,
+ ** back translate for our character set. - FM
+ */
+#define PASSHI8BIT (HTPassEightBitRaw || \
+ (context->T.do_8bitraw && !context->T.trans_from_uni))
+ } else if (unsign_c > 160 && unsign_c < 256 &&
+ !(PASSHI8BIT || HTCJK != NOCJK) &&
+ !IncludesLatin1Enc) {
+ int i;
+
+ string->size = 0;
+ EntityName = HTMLGetEntityName((int)(unsign_c - 160));
+ for (i = 0; EntityName[i]; i++)
+ HTChunkPutc(string, EntityName[i]);
+ HTChunkTerminate(string);
+ handle_entity(context, '\0');
+ string->size = 0;
+ if (!FoundEntity)
+ PUTC(';');
+ /*
+ ** If we get to here and have an ASCII char,
+ ** pass the character. - KW
+ */
+ } else if (unsign_c < 127 && unsign_c > 0) {
+ PUTC(c);
+ /*
+ ** If we get to here, and should have translated,
+ ** translation has failed so far. - KW
+ **
+ ** We should have sent UTF-8 output to the parser
+ ** already, but what the heck, try again. - FM
+ */
+ } else if (context->T.output_utf8 && *context->utf_buf) {
+ for (p = context->utf_buf; *p; p++)
+ PUTC(*p);
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+#ifdef NOTDEFINED
+ /*
+ ** Check for a strippable koi8-r 8-bit character. - FM
+ */
+ } else if (context->T.strip_raw_char_in && saved_char_in &&
+ ((unsigned char)saved_char_in >= 0xc0) &&
+ ((unsigned char)saved_char_in < 255)) {
+ /*
+ ** KOI8 special: strip high bit, gives (somewhat) readable
+ ** ASCII or KOI7 - it was constructed that way! - KW
+ */
+ PUTC(((char)(saved_char_in & 0x7f)));
+ saved_char_in = '\0';
+#endif /* NOTDEFINED */
+ /*
+ ** If we don't actually want the character,
+ ** make it safe and output that now. - FM
+ */
+ } else if ((unsigned char)c <
+ LYlowest_eightbit[context->outUCLYhndl] ||
+ (context->T.trans_from_uni && !HTPassEightBitRaw)) {
+#ifdef NOTUSED_FOTEMODS
+ /*
+ ** If we do not have the "7-bit approximations" as our
+ ** output character set (in which case we did it already)
+ ** seek a translation for that. Otherwise, or if the
+ ** translation fails, use UHHH notation. - FM
+ */
+ if ((chk = (context->outUCLYhndl !=
+ UCGetLYhndl_byMIME("us-ascii"))) &&
+ (uck = UCTransUniChar(unsign_c,
+ UCGetLYhndl_byMIME("us-ascii")))
+ >= 32 && uck < 127) {
+ /*
+ ** Got an ASCII character (yippey). - FM
+ */
+ PUTC(((char)(uck & 0xff)));
+ } else if ((chk && uck == -4) &&
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, clong,
+ UCGetLYhndl_byMIME("us-ascii"),
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string (yippey). - FM
+ */
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ } else {
+ /*
+ ** Out of luck, so use the UHHH notation (ugh). - FM
+ */
+#endif /* NOTUSED_FOTEMODS */
+ sprintf(replace_buf, "U%.2lX", unsign_c);
+ for (p = replace_buf; *p; p++) {
+ PUTC(*p);
+ }
+#ifdef NOTUSED_FOTEMODS
+ }
+#endif /* NOTUSED_FOTEMODS */
+ /*
+ ** If we get to here, pass the character. - FM
+ */
+ } else {
+ PUTC(c);
+ }
+ break;
+
+ /*
+ ** In litteral mode, waits only for specific end tag (for
+ ** compatibility with old servers, and for Lynx). - FM
+ */
+ case S_litteral:
+ HTChunkPutc(string, c);
+ if (TOUPPER(c) != ((string->size == 1) ?
+ '/' :
+ context->element_stack->tag->name[string->size-2])) {
+ int i;
+
+ /*
+ ** If complete match, end litteral.
+ */
+ if ((c == '>') &&
+ (!context->element_stack->tag->name[string->size-2])) {
+ end_element(context, context->element_stack->tag);
+ string->size = 0;
+ context->current_attribute_number = INVALID;
+ context->state = S_text;
+ break;
+ }
+ /*
+ ** If Mismatch: recover string.
+ */
+ PUTC('<');
+ for (i = 0; i < string->size; i++) /* recover */
+ PUTC(string->data[i]);
+ string->size = 0;
+ context->state = S_text;
+ }
+ break;
+
+ /*
+ ** Character reference (numeric entity) or named entity.
+ */
+ case S_ero:
+ if (c == '#') {
+ /*
+ ** Setting up for possible numeric entity.
+ */
+ context->state = S_cro; /* &# is Char Ref Open */
+ break;
+ }
+ context->state = S_entity; /* Fall through! */
+
+ /*
+ ** Handle possible named entity.
+ */
+ case S_entity:
+ if (unsign_c < 127 && (string->size ?
+ isalnum((unsigned char)c) : isalpha((unsigned char)c))) {
+ /*
+ ** Accept valid ASCII character. - FM
+ */
+ HTChunkPutc(string, c);
+ } else if (string->size == 0) {
+ /*
+ ** It was an ampersand that's just text, so output
+ ** the ampersand and recycle this character. - FM
+ */
+ PUTC('&');
+ context->state = S_text;
+ goto top1;
+ } else {
+ /*
+ ** Terminate entity name and try to handle it. - FM
+ */
+ HTChunkTerminate(string);
+ if (!strcmp(string->data, "zwnj") &&
+ (!context->element_stack ||
+ (context->element_stack->tag &&
+ context->element_stack->tag->contents == SGML_MIXED))) {
+ /*
+ ** Handle zwnj (8204) as <WBR>. - FM
+ */
+ char temp[8];
+
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML_character: Handling 'zwnj' entity as 'WBR' element.\n");
+ }
+ if (c != ';') {
+ sprintf(temp, "<WBR>%c", c);
+ } else {
+ sprintf(temp, "<WBR>");
+ }
+ if (context->recover == NULL) {
+ StrAllocCopy(context->recover, temp);
+ context->recover_index = 0;
+ } else {
+ StrAllocCat(context->recover, temp);
+ }
+ string->size = 0;
+ context->state = S_text;
+ break;
+ } else {
+ handle_entity(context, '\0');
+ }
+ string->size = 0;
+ context->state = S_text;
+ /*
+ ** Don't eat the terminator if we didn't find the
+ ** entity name and therefore sent the raw string
+ ** via handle_entity(), or if the terminator is
+ ** not the "standard" semi-colon for HTML. - FM
+ */
+ if (!FoundEntity || c != ';')
+ goto top1;
+ }
+ break;
+
+ /*
+ ** Check for a numeric entity.
+ */
+ case S_cro:
+ if (unsign_c < 127 && TOLOWER((unsigned char)c) == 'x') {
+ context->isHex = TRUE;
+ context->state = S_incro;
+ } else if (unsign_c < 127 && isdigit((unsigned char)c)) {
+ /*
+ ** Accept only valid ASCII digits. - FM
+ */
+ HTChunkPutc(string, c); /* accumulate a character NUMBER */
+ context->isHex = FALSE;
+ context->state = S_incro;
+ } else if (string->size == 0) {
+ /*
+ ** No 'x' or digit following the "&#" so recover
+ ** them and recycle the character. - FM
+ */
+ PUTC('&');
+ PUTC('#');
+ context->state = S_text;
+ goto top1;
+ }
+ break;
+
+ /*
+ ** Handle a numeric entity.
+ */
+ case S_incro:
+ if ((unsign_c < 127) &&
+ (context->isHex ? isxdigit((unsigned char)c) :
+ isdigit((unsigned char)c))) {
+ /*
+ ** Accept only valid hex or ASCII digits. - FM
+ */
+ HTChunkPutc(string, c); /* accumulate a character NUMBER */
+ } else if (string->size == 0) {
+ /*
+ ** No hex digit following the "&#x" so recover
+ ** them and recycle the character. - FM
+ */
+ PUTC('&');
+ PUTC('#');
+ PUTC('x');
+ context->isHex = FALSE;
+ context->state = S_text;
+ goto top1;
+ } else {
+ /*
+ ** Terminate the numeric entity and try to handle it. - FM
+ */
+ UCode_t code;
+ int i;
+ HTChunkTerminate(string);
+ if ((context->isHex ? sscanf(string->data, "%lx", &code) :
+ sscanf(string->data, "%ld", &code)) == 1) {
+ if ((code == 1) ||
+ (code > 129 && code < 156)) {
+ /*
+ ** Assume these are Microsoft code points,
+ ** inflicted on us by FrontPage. - FM
+ **
+ ** MS FrontPage uses syntax like &#153; in 128-159 range
+ ** and doesn't follow Unicode standards for this area.
+ ** Windows-1252 codepoints are assumed here.
+ */
+ switch (code) {
+ case 1:
+ /*
+ ** WHITE SMILING FACE
+ */
+ code = 0x263a;
+ break;
+ case 130:
+ /*
+ ** SINGLE LOW-9 QUOTATION MARK (sbquo)
+ */
+ code = 0x201a;
+ break;
+ case 132:
+ /*
+ ** DOUBLE LOW-9 QUOTATION MARK (bdquo)
+ */
+ code = 0x201e;
+ break;
+ case 133:
+ /*
+ ** HORIZONTAL ELLIPSIS (hellip)
+ */
+ code = 0x2026;
+ break;
+ case 134:
+ /*
+ ** DAGGER (dagger)
+ */
+ code = 0x2020;
+ break;
+ case 135:
+ /*
+ ** DOUBLE DAGGER (Dagger)
+ */
+ code = 0x2021;
+ break;
+ case 137:
+ /*
+ ** PER MILLE SIGN (permil)
+ */
+ code = 0x2030;
+ break;
+ case 139:
+ /*
+ ** SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+ ** (lsaquo)
+ */
+ code = 0x2039;
+ break;
+ case 145:
+ /*
+ ** LEFT SINGLE QUOTATION MARK (lsquo)
+ */
+ code = 0x2018;
+ break;
+ case 146:
+ /*
+ ** RIGHT SINGLE QUOTATION MARK (rsquo)
+ */
+ code = 0x2019;
+ break;
+ case 147:
+ /*
+ ** LEFT DOUBLE QUOTATION MARK (ldquo)
+ */
+ code = 0x201c;
+ break;
+ case 148:
+ /*
+ ** RIGHT DOUBLE QUOTATION MARK (rdquo)
+ */
+ code = 0x201d;
+ break;
+ case 149:
+ /*
+ ** BULLET (bull)
+ */
+ code = 0x2022;
+ break;
+ case 150:
+ /*
+ ** EN DASH (ndash)
+ */
+ code = 0x2013;
+ break;
+ case 151:
+ /*
+ ** EM DASH (mdash)
+ */
+ code = 0x2014;
+ break;
+ case 152:
+ /*
+ ** SMALL TILDE (tilde)
+ */
+ code = 0x02dc;
+ break;
+ case 153:
+ /*
+ ** TRADE MARK SIGN (trade)
+ */
+ code = 0x2122;
+ break;
+ case 155:
+ /*
+ ** SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+ ** (rsaquo)
+ */
+ code = 0x203a;
+ break;
+ default:
+ /*
+ ** Do not attempt a conversion
+ ** to valid Unicode values.
+ */
+ break;
+ }
+ }
+ /*
+ ** Check for special values. - FM
+ */
+ if ((code == 8204) &&
+ (!context->element_stack ||
+ (context->element_stack->tag &&
+ context->element_stack->tag->contents == SGML_MIXED))) {
+ /*
+ ** Handle zwnj (8204) as <WBR>. - FM
+ */
+ char temp[8];
+
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML_character: Handling '8204' (zwnj) reference as 'WBR' element.\n");
+ }
+ /*
+ ** Include the terminator if it is not
+ ** the standard semi-colon. - FM
+ */
+ if (c != ';') {
+ sprintf(temp, "<WBR>%c", c);
+ } else {
+ sprintf(temp, "<WBR>");
+ }
+ /*
+ ** Add the replacement string to the
+ ** recover buffer for processing. - FM
+ */
+ if (context->recover == NULL) {
+ StrAllocCopy(context->recover, temp);
+ context->recover_index = 0;
+ } else {
+ StrAllocCat(context->recover, temp);
+ }
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ break;
+ } else if (put_special_unicodes(context, code)) {
+ /*
+ ** We handled the value as a special character,
+ ** so recycle the terminator or break. - FM
+ */
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ if (c != ';')
+ goto top1;
+ break;
+ }
+ /*
+ ** Seek a translation from the chartrans tables.
+ */
+ if ((uck = UCTransUniChar(code,
+ context->outUCLYhndl)) >= 32 &&
+ uck < 256 &&
+ (uck < 127 ||
+ uck >= LYlowest_eightbit[context->outUCLYhndl])) {
+ PUTC(FROMASCII((char)uck));
+ } else if ((uck == -4 ||
+ (context->T.repl_translated_C0 &&
+ uck > 0 && uck < 32)) &&
+ /*
+ ** Not found; look for replacement string.
+ */
+ (uck = UCTransUniCharStr(replace_buf, 60, code,
+ context->outUCLYhndl,
+ 0) >= 0)) {
+ for (p = replace_buf; *p; p++) {
+ PUTC(*p);
+ }
+ /*
+ ** If we're displaying UTF-8, try that now. - FM
+ */
+ } else if (context->T.output_utf8 && PUTUTF8(code)) {
+ ; /* do nothing more */
+#ifdef NOTUSED_FOTEMODS
+ /*
+ ** If the value is greater than 255 and we do not
+ ** have the "7-bit approximations" as our output
+ ** character set (in which case we did it already)
+ ** seek a translation for that. - FM
+ */
+ } else if ((chk = ((code > 255) &&
+ context->outUCLYhndl !=
+ UCGetLYhndl_byMIME("us-ascii"))) &&
+ (uck = UCTransUniChar(code,
+ UCGetLYhndl_byMIME("us-ascii")))
+ >= 32 && uck < 127) {
+ /*
+ ** Got an ASCII character (yippey). - FM
+ */
+ PUTC(((char)(uck & 0xff)));
+ } else if ((chk && uck == -4) &&
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ UCGetLYhndl_byMIME("us-ascii"),
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string (yippey). - FM
+ */
+ for (p = replace_buf; *p; p++)
+ PUTC(*p);
+ /*
+ ** Ignore 8205 (zwj),
+ ** 8206 (lrm), and 8207 (rln), if we get to here. - FM
+ */
+ } else if (code == 8205 ||
+ code == 8206 ||
+ code == 8207) {
+ if (TRACE) {
+ string->size--;
+ LYstrncpy(replace_buf,
+ string->data,
+ (string->size < 64 ? string->size : 63));
+ fprintf(stderr,
+ "SGML_character: Ignoring '%s%s'.\n",
+ (context->isHex ? "&#x" : "&#"),
+ replace_buf);
+ }
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ if (c != ';')
+ goto top1;
+ break;
+#endif /* NOTUSED_FOTEMODS */
+ /*
+ ** Show the numeric entity if we get to here
+ ** and the value:
+ ** (1) Is greater than 255 (but use ASCII characters
+ ** for spaces or dashes).
+ ** (2) Is less than 32, and not valid or we don't
+ ** have HTCJK set.
+ ** (3) Is 127 and we don't have HTPassHighCtrlRaw or
+ ** HTCJK set.
+ ** (4) Is 128 - 159 and we don't have HTPassHighCtrlNum
+ ** set.
+ ** - FM
+ */
+ } else if ((code > 255) ||
+ (code < 32 &&
+ code != 9 && code != 10 && code != 13 &&
+ HTCJK == NOCJK) ||
+ (code == 127 &&
+ !(HTPassHighCtrlRaw || HTCJK != NOCJK)) ||
+ (code > 127 && code < 160 &&
+ !HTPassHighCtrlNum)) {
+ /*
+ ** Unhandled or illegal value. Recover the
+ ** "&#" or "&#x" and digit(s), and recycle
+ ** the terminator. - FM
+ */
+ PUTC('&');
+ PUTC('#');
+ if (context->isHex) {
+ PUTC('x');
+ context->isHex = FALSE;
+ }
+ string->size--;
+ for (i = 0; i < string->size; i++) /* recover */
+ PUTC(string->data[i]);
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ goto top1;
+ } else if (code < 161 ||
+ HTPassEightBitNum ||
+ IncludesLatin1Enc) {
+ /*
+ ** No conversion needed. - FM
+ */
+ PUTC(FROMASCII((char)code));
+ } else {
+ /*
+ ** Handle as named entity. - FM
+ */
+ code -= 160;
+ EntityName = HTMLGetEntityName(code);
+ if (EntityName && EntityName[0] != '\0') {
+ string->size = 0;
+ for (i = 0; EntityName[i]; i++)
+ HTChunkPutc(string, EntityName[i]);
+ HTChunkTerminate(string);
+ handle_entity(context, '\0');
+ /*
+ ** Add a semi-colon if something went wrong
+ ** and handle_entity() sent the string. - FM
+ */
+ if (!FoundEntity) {
+ PUTC(';');
+ }
+ } else {
+ /*
+ ** Our conversion failed, so recover the "&#"
+ ** and digit(s), and recycle the terminator. - FM
+ */
+ PUTC('&');
+ PUTC('#');
+ if (context->isHex) {
+ PUTC('x');
+ context->isHex = FALSE;
+ }
+ string->size--;
+ for (i = 0; i < string->size; i++) /* recover */
+ PUTC(string->data[i]);
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ goto top1;
+ }
+ }
+ /*
+ ** If we get to here, we succeeded. Hoorah!!! - FM
+ */
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ /*
+ ** Don't eat the terminator if it's not
+ ** the "standard" semi-colon for HTML. - FM
+ */
+ if (c != ';') {
+ goto top1;
+ }
+ } else {
+ /*
+ ** Not an entity, and don't know why not, so add
+ ** the terminator to the string, output the "&#"
+ ** or "&#x", and process the string via the recover
+ ** element. - FM
+ */
+ string->size--;
+ HTChunkPutc(string, c);
+ HTChunkTerminate(string);
+ PUTC('&');
+ PUTC('#');
+ if (context->isHex) {
+ PUTC('x');
+ context->isHex = FALSE;
+ }
+ if (context->recover == NULL) {
+ StrAllocCopy(context->recover, string->data);
+ context->recover_index = 0;
+ } else {
+ StrAllocCat(context->recover, string->data);
+ }
+ string->size = 0;
+ context->isHex = FALSE;
+ context->state = S_text;
+ break;
+ }
+ }
+ break;
+
+ /*
+ ** Tag
+ */
+ case S_tag: /* new tag */
+ if (unsign_c < 127 && (string->size ?
+ isalnum((unsigned char)c) : isalpha((unsigned char)c))) {
+ /*
+ ** Add valid ASCII character. - FM
+ */
+ HTChunkPutc(string, c);
+ } else if (c == '!' && !string->size) { /* <! */
+ /*
+ ** Terminate and set up for possible comment,
+ ** identifier, declaration, or marked section. - FM
+ */
+ context->state = S_exclamation;
+ context->lead_exclamation = TRUE;
+ context->doctype_bracket = FALSE;
+ context->first_bracket = FALSE;
+ HTChunkPutc(string, c);
+ break;
+ } else if (!string->size &&
+ (unsign_c <= 160 &&
+ (c != '/' && c != '?' && c != '_' && c != ':'))) {
+ /*
+ ** '<' must be followed by an ASCII letter to be a valid
+ ** start tag. Here it isn't, nor do we have a '/' for an
+ ** end tag, nor one of some other characters with a
+ ** special meaning for SGML or which are likely to be legal
+ ** Name Start characters in XML or some other extension.
+ ** So recover the '<' and following character as data. - FM & KW
+ */
+ context->state = S_text;
+ PUTC('<');
+ goto top1;
+ } else { /* End of tag name */
+ /*
+ ** Try to handle tag. - FM
+ */
+ HTTag * t;
+ if (c == '/') {
+ if (TRACE)
+ if (string->size!=0)
+ fprintf(stderr,"SGML: `<%s/' found!\n", string->data);
+ context->state = S_end;
+ break;
+ }
+ HTChunkTerminate(string) ;
+
+ t = SGMLFindTag(dtd, string->data);
+ if (t == context->unknown_tag && c == ':' &&
+ 0 == strcasecomp(string->data, "URL")) {
+ /*
+ ** Treat <URL: as text rather than a junk tag,
+ ** so we display it and the URL (Lynxism 8-). - FM
+ */
+ int i;
+ PUTC('<');
+ for (i = 0; i < 3; i++) /* recover */
+ PUTC(string->data[i]);
+ PUTC(c);
+ if (TRACE)
+ fprintf(stderr, "SGML: Treating <%s%c as text\n",
+ string->data, c);
+ string->size = 0;
+ context->state = S_text;
+ break;
+ } else if (!t) {
+ if (TRACE)
+ fprintf(stderr, "SGML: *** Invalid element %s\n",
+ string->data);
+ context->state = (c == '>') ? S_text : S_junk_tag;
+ break;
+ } else if (t == context->unknown_tag) {
+ if (TRACE)
+ fprintf(stderr, "SGML: *** Unknown element %s\n",
+ string->data);
+ /*
+ ** Fall through and treat like valid
+ ** tag for attribute parsing. - KW
+ */
+ }
+ context->current_tag = t;
+
+ /*
+ ** Clear out attributes.
+ */
+ {
+ int i;
+ for (i = 0; i < context->current_tag->number_of_attributes; i++)
+ context->present[i] = NO;
+ }
+ string->size = 0;
+ context->current_attribute_number = INVALID;
+
+ if (c == '>') {
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ } else {
+ context->state = S_tag_gap;
+ }
+ }
+ break;
+
+ case S_exclamation:
+ if (context->lead_exclamation && c == '-') {
+ /*
+ ** Set up for possible comment. - FM
+ */
+ context->lead_exclamation = FALSE;
+ context->first_dash = TRUE;
+ HTChunkPutc(string, c);
+ break;
+ }
+ if (context->lead_exclamation && c == '[') {
+ /*
+ ** Set up for possible marked section. - FM
+ */
+ context->lead_exclamation = FALSE;
+ context->first_bracket = TRUE;
+ context->second_bracket = FALSE;
+ HTChunkPutc(string, c);
+ context->state = S_marked;
+ break;
+ }
+ if (context->first_dash && c == '-') {
+ /*
+ ** Set up to handle comment. - FM
+ */
+ context->lead_exclamation = FALSE;
+ context->first_dash = FALSE;
+ context->end_comment = FALSE;
+ HTChunkPutc(string, c);
+ context->state = S_comment;
+ break;
+ }
+ context->lead_exclamation = FALSE;
+ context->first_dash = FALSE;
+ if (c == '>') {
+ /*
+ ** Try to handle identifier. - FM
+ */
+ HTChunkTerminate(string);
+ handle_identifier(context);
+ string->size = 0;
+ context->state = S_text;
+ break;
+ }
+ if (WHITE(c)) {
+ if (string->size == 8 &&
+ !strncasecomp(string->data, "!DOCTYPE", 8)) {
+ /*
+ ** Set up for DOCTYPE declaration. - FM
+ */
+ HTChunkPutc(string, c);
+ context->doctype_bracket = FALSE;
+ context->state = S_doctype;
+ break;
+ }
+ if (string->size == 7 &&
+ !strncasecomp(string->data, "!ENTITY", 7)) {
+ /*
+ ** Set up for ENTITY declaration. - FM
+ */
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ context->end_comment = TRUE;
+ context->state = S_sgmlent;
+ break;
+ }
+ if (string->size == 8 &&
+ !strncasecomp(string->data, "!ELEMENT", 8)) {
+ /*
+ ** Set up for ELEMENT declaration. - FM
+ */
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ context->end_comment = TRUE;
+ context->state = S_sgmlele;
+ break;
+ }
+ if (string->size == 8 &&
+ !strncasecomp(string->data, "!ATTLIST", 8)) {
+ /*
+ ** Set up for ATTLIST declaration. - FM
+ */
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ context->end_comment = TRUE;
+ context->state = S_sgmlatt;
+ break;
+ }
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_comment: /* Expecting comment. - FM */
+ if (historical_comments) {
+ /*
+ ** Any '>' terminates. - FM
+ */
+ if (c == '>') {
+ HTChunkTerminate(string);
+ handle_comment(context);
+ string->size = 0;
+ context->end_comment = FALSE;
+ context->first_dash = FALSE;
+ context->state = S_text;
+ break;
+ }
+ HTChunkPutc(string, c);
+ break;
+ }
+ if (!context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = TRUE;
+ break;
+ }
+ if (context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ if (!context->end_comment)
+ context->end_comment = TRUE;
+ else if (!minimal_comments)
+ /*
+ ** Validly treat '--' pairs as successive comments
+ ** (for minimal, any "--WHITE>" terminates). - FM
+ */
+ context->end_comment = FALSE;
+ break;
+ }
+ if (context->end_comment && c == '>') {
+ /*
+ ** Terminate and handle the comment. - FM
+ */
+ HTChunkTerminate(string);
+ handle_comment(context);
+ string->size = 0;
+ context->end_comment = FALSE;
+ context->first_dash = FALSE;
+ context->state = S_text;
+ break;
+ }
+ context->first_dash = FALSE;
+ if (context->end_comment && !isspace(c))
+ context->end_comment = FALSE;
+ HTChunkPutc(string, c);
+ break;
+
+ case S_doctype: /* Expecting DOCTYPE. - FM */
+ if (context->doctype_bracket) {
+ HTChunkPutc(string, c);
+ if (c == ']')
+ context->doctype_bracket = FALSE;
+ break;
+ }
+ if (c == '[' && WHITE(string->data[string->size - 1])) {
+ HTChunkPutc(string, c);
+ context->doctype_bracket = TRUE;
+ break;
+ }
+ if (c == '>') {
+ HTChunkTerminate(string);
+ handle_doctype(context);
+ string->size = 0;
+ context->state = S_text;
+ break;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_marked: /* Expecting marked section. - FM */
+ if (context->first_bracket && c == '[') {
+ HTChunkPutc(string, c);
+ context->first_bracket = FALSE;
+ context->second_bracket = TRUE;
+ break;
+ }
+ if (context->second_bracket && c == ']' &&
+ string->data[string->size - 1] == ']') {
+ HTChunkPutc(string, c);
+ context->second_bracket = FALSE;
+ break;
+ }
+ if (!context->second_bracket && c == '>') {
+ HTChunkTerminate(string);
+ handle_marked(context);
+ string->size = 0;
+ context->state = S_text;
+ break;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_sgmlent: /* Expecting ENTITY. - FM */
+ if (!context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = TRUE;
+ break;
+ }
+ if (context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ if (!context->end_comment)
+ context->end_comment = TRUE;
+ else
+ context->end_comment = FALSE;
+ break;
+ }
+ if (context->end_comment && c == '>') {
+ HTChunkTerminate(string);
+ handle_sgmlent(context);
+ string->size = 0;
+ context->end_comment = FALSE;
+ context->first_dash = FALSE;
+ context->state = S_text;
+ break;
+ }
+ context->first_dash = FALSE;
+ HTChunkPutc(string, c);
+ break;
+
+ case S_sgmlele: /* Expecting ELEMENT. - FM */
+ if (!context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = TRUE;
+ break;
+ }
+ if (context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ if (!context->end_comment)
+ context->end_comment = TRUE;
+ else
+ context->end_comment = FALSE;
+ break;
+ }
+ if (context->end_comment && c == '>') {
+ HTChunkTerminate(string);
+ handle_sgmlele(context);
+ string->size = 0;
+ context->end_comment = FALSE;
+ context->first_dash = FALSE;
+ context->state = S_text;
+ break;
+ }
+ context->first_dash = FALSE;
+ HTChunkPutc(string, c);
+ break;
+
+ case S_sgmlatt: /* Expecting ATTLIST. - FM */
+ if (!context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = TRUE;
+ break;
+ }
+ if (context->first_dash && c == '-') {
+ HTChunkPutc(string, c);
+ context->first_dash = FALSE;
+ if (!context->end_comment)
+ context->end_comment = TRUE;
+ else
+ context->end_comment = FALSE;
+ break;
+ }
+ if (context->end_comment && c == '>') {
+ HTChunkTerminate(string);
+ handle_sgmlatt(context);
+ string->size = 0;
+ context->end_comment = FALSE;
+ context->first_dash = FALSE;
+ context->state = S_text;
+ break;
+ }
+ context->first_dash = FALSE;
+ HTChunkPutc(string, c);
+ break;
+
+ case S_tag_gap: /* Expecting attribute or '>' */
+ if (WHITE(c))
+ break; /* Gap between attributes */
+ if (c == '>') { /* End of tag */
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ break;
+ }
+ HTChunkPutc(string, c);
+ context->state = S_attr; /* Get attribute */
+ break;
+
+ /* accumulating value */
+ case S_attr:
+ if (WHITE(c) || (c == '>') || (c == '=')) { /* End of word */
+ HTChunkTerminate(string);
+ handle_attribute_name(context, string->data);
+ string->size = 0;
+ if (c == '>') { /* End of tag */
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ break;
+ }
+ context->state = (c == '=' ? S_equals: S_attr_gap);
+ } else {
+ HTChunkPutc(string, c);
+ }
+ break;
+
+ case S_attr_gap: /* Expecting attribute or '=' or '>' */
+ if (WHITE(c))
+ break; /* Gap after attribute */
+ if (c == '>') { /* End of tag */
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ break;
+ } else if (c == '=') {
+ context->state = S_equals;
+ break;
+ }
+ HTChunkPutc(string, c);
+ context->state = S_attr; /* Get next attribute */
+ break;
+
+ case S_equals: /* After attr = */
+ if (WHITE(c))
+ break; /* Before attribute value */
+ if (c == '>') { /* End of tag */
+ if (TRACE)
+ fprintf(stderr, "SGML: found = but no value\n");
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ break;
+
+ } else if (c == '\'') {
+ context->state = S_squoted;
+ break;
+
+ } else if (c == '"') {
+ context->state = S_dquoted;
+ break;
+ }
+ HTChunkPutc(string, c);
+ context->state = S_value;
+ break;
+
+ case S_value:
+ if (WHITE(c) || (c == '>')) { /* End of word */
+ HTChunkTerminate(string) ;
+ handle_attribute_value(context, string->data);
+ string->size = 0;
+ if (c == '>') { /* End of tag */
+ if (context->current_tag->name)
+ start_element(context);
+ context->state = S_text;
+ break;
+ }
+ else context->state = S_tag_gap;
+ } else if (context->T.decode_utf8 &&
+ *context->utf_buf) {
+ HTChunkPuts(string, context->utf_buf);
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+ } else if (HTCJK == NOCJK &&
+ (context->T.output_utf8 ||
+ context->T.trans_from_uni)) {
+ if (clong == 0xfffd && saved_char_in &&
+ HTPassEightBitRaw &&
+ (unsigned char)saved_char_in >=
+ LYlowest_eightbit[context->outUCLYhndl]) {
+ HTChunkPutUtf8Char(string,
+ (0xf000 | (unsigned char)saved_char_in));
+ } else {
+ HTChunkPutUtf8Char(string, clong);
+ }
+ } else if (saved_char_in && context->T.use_raw_char_in) {
+ HTChunkPutc(string, saved_char_in);
+ } else {
+ HTChunkPutc(string, c);
+ }
+ break;
+
+ case S_squoted: /* Quoted attribute value */
+ if (c == '\'') { /* End of attribute value */
+ HTChunkTerminate(string) ;
+ handle_attribute_value(context, string->data);
+ string->size = 0;
+ context->state = S_tag_gap;
+ } else if (c == '\033') {
+ /*
+ ** Setting up for possible single quotes in CJK escape
+ ** sequences. - Takuya ASADA (asada@three-a.co.jp)
+ */
+ context->state = S_esc_sq;
+ HTChunkPutc(string, c);
+ } else if (context->T.decode_utf8 &&
+ *context->utf_buf) {
+ HTChunkPuts(string, context->utf_buf);
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+ } else if (HTCJK == NOCJK &&
+ (context->T.output_utf8 ||
+ context->T.trans_from_uni)) {
+ if (clong == 0xfffd && saved_char_in &&
+ HTPassEightBitRaw &&
+ (unsigned char)saved_char_in >=
+ LYlowest_eightbit[context->outUCLYhndl]) {
+ HTChunkPutUtf8Char(string,
+ (0xf000 | (unsigned char)saved_char_in));
+ } else {
+ HTChunkPutUtf8Char(string, clong);
+ }
+ } else if (saved_char_in && context->T.use_raw_char_in) {
+ HTChunkPutc(string, saved_char_in);
+ } else {
+ HTChunkPutc(string, c);
+ }
+ break;
+
+ case S_dquoted: /* Quoted attribute value */
+ if (c == '"' || /* Valid end of attribute value */
+ (soft_dquotes && /* If emulating old Netscape bug, treat '>' */
+ c == '>')) { /* as a co-terminator of dquoted and tag */
+ HTChunkTerminate(string) ;
+ handle_attribute_value(context, string->data);
+ string->size = 0;
+ context->state = S_tag_gap;
+ if (c == '>') /* We emulated the Netscape bug, so we go */
+ goto top1; /* back and treat it as the tag terminator */
+ } else if (c == '\033') {
+ /*
+ ** Setting up for possible double quotes in CJK escape
+ ** sequences. - Takuya ASADA (asada@three-a.co.jp)
+ */
+ context->state = S_esc_dq;
+ HTChunkPutc(string, c);
+ } else if (context->T.decode_utf8 &&
+ *context->utf_buf) {
+ HTChunkPuts(string, context->utf_buf);
+ context->utf_buf_p = context->utf_buf;
+ *(context->utf_buf_p) = '\0';
+ } else if (HTCJK == NOCJK &&
+ (context->T.output_utf8 ||
+ context->T.trans_from_uni)) {
+ if (clong == 0xfffd && saved_char_in &&
+ HTPassEightBitRaw &&
+ (unsigned char)saved_char_in >=
+ LYlowest_eightbit[context->outUCLYhndl]) {
+ HTChunkPutUtf8Char(string,
+ (0xf000 | (unsigned char)saved_char_in));
+ } else {
+ HTChunkPutUtf8Char(string, clong);
+ }
+ } else if (saved_char_in && context->T.use_raw_char_in) {
+ HTChunkPutc(string, saved_char_in);
+ } else {
+ HTChunkPutc(string, c);
+ }
+ break;
+
+ case S_end: /* </ */
+ if (unsign_c < 127 && isalnum((unsigned char)c)) {
+ HTChunkPutc(string, c);
+ } else { /* End of end tag name */
+ HTTag * t = 0;
+
+ HTChunkTerminate(string);
+ if (!*string->data) { /* Empty end tag */
+ if (context->element_stack)
+ t = context->element_stack->tag;
+ } else {
+ t = SGMLFindTag(dtd, string->data);
+ }
+ if (!t || t == context->unknown_tag) {
+ if (TRACE)
+ fprintf(stderr, "Unknown end tag </%s>\n", string->data);
+ } else {
+ BOOL tag_OK = (c == '>' || WHITE(c));
+ context->current_tag = t;
+#ifdef EXTENDED_HTMLDTD
+ /*
+ ** Just handle ALL end tags normally :-) - kw
+ */
+ if (New_DTD) {
+ end_element( context, context->current_tag);
+ } else
+#endif /* EXTENDED_HTMLDTD */
+ if (tag_OK &&
+ (!strcasecomp(string->data, "DD") ||
+ !strcasecomp(string->data, "DT") ||
+ !strcasecomp(string->data, "LI") ||
+ !strcasecomp(string->data, "LH") ||
+ !strcasecomp(string->data, "TD") ||
+ !strcasecomp(string->data, "TH") ||
+ !strcasecomp(string->data, "TR") ||
+ !strcasecomp(string->data, "THEAD") ||
+ !strcasecomp(string->data, "TFOOT") ||
+ !strcasecomp(string->data, "TBODY") ||
+ !strcasecomp(string->data, "COLGROUP"))) {
+ /*
+ ** Don't treat these end tags as invalid,
+ ** nor act on them. - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "SGML: `</%s%c' found! Ignoring it.\n",
+ string->data, c);
+ string->size = 0;
+ context->current_attribute_number = INVALID;
+ if (c != '>') {
+ context->state = S_junk_tag;
+ } else {
+ context->state = S_text;
+ }
+ break;
+ } else if (tag_OK &&
+ (!strcasecomp(string->data, "A") ||
+ !strcasecomp(string->data, "B") ||
+ !strcasecomp(string->data, "BLINK") ||
+ !strcasecomp(string->data, "CITE") ||
+ !strcasecomp(string->data, "EM") ||
+ !strcasecomp(string->data, "FONT") ||
+ !strcasecomp(string->data, "FORM") ||
+ !strcasecomp(string->data, "I") ||
+ !strcasecomp(string->data, "P") ||
+ !strcasecomp(string->data, "STRONG") ||
+ !strcasecomp(string->data, "TT") ||
+ !strcasecomp(string->data, "U"))) {
+ /*
+ ** Handle end tags for container elements declared
+ ** as SGML_EMPTY to prevent "expected tag substitution"
+ ** but still processed via HTML_end_element() in HTML.c
+ ** with checks there to avoid throwing the HTML.c stack
+ ** out of whack (Ugh, what a hack! 8-). - FM
+ */
+ if (context->inSELECT) {
+ /*
+ ** We are in a SELECT block. - FM
+ */
+ if (strcasecomp(string->data, "FORM")) {
+ /*
+ ** It is not at FORM end tag, so ignore it. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML: Ignoring end tag </%s> in SELECT block.\n",
+ string->data);
+ }
+ } else {
+ /*
+ ** End the SELECT block and then
+ ** handle the FORM end tag. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML: Faking SELECT end tag before </%s> end tag.\n",
+ string->data);
+ }
+ end_element(context,
+ SGMLFindTag(context->dtd, "SELECT"));
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML: End </%s>\n", string->data);
+ }
+ (*context->actions->end_element)
+ (context->target,
+ (context->current_tag - context->dtd->tags),
+ (char **)&context->include);
+ }
+ } else if (!strcasecomp(string->data, "P")) {
+ /*
+ ** Treat a P end tag like a P start tag (Ugh,
+ ** what a hack! 8-). - FM
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "SGML: `</%s%c' found! Treating as '<%s%c'.\n",
+ string->data, c, string->data, c);
+ {
+ int i;
+ for (i = 0;
+ i < context->current_tag->number_of_attributes;
+ i++) {
+ context->present[i] = NO;
+ }
+ }
+ if (context->current_tag->name)
+ start_element(context);
+ } else {
+ if (TRACE) {
+ fprintf(stderr,
+ "SGML: End </%s>\n", string->data);
+ }
+ (*context->actions->end_element)
+ (context->target,
+ (context->current_tag - context->dtd->tags),
+ (char **)&context->include);
+ }
+ string->size = 0;
+ context->current_attribute_number = INVALID;
+ if (c != '>') {
+ context->state = S_junk_tag;
+ } else {
+ context->state = S_text;
+ }
+ break;
+ } else {
+ /*
+ ** Handle all other end tags normally. - FM
+ */
+ end_element( context, context->current_tag);
+ }
+ }
+
+ string->size = 0;
+ context->current_attribute_number = INVALID;
+ if (c != '>') {
+ if (TRACE && !WHITE(c))
+ fprintf(stderr,"SGML: `</%s%c' found!\n", string->data, c);
+ context->state = S_junk_tag;
+ } else {
+ context->state = S_text;
+ }
+ }
+ break;
+
+
+ case S_esc: /* Expecting '$'or '(' following CJK ESC. */
+ if (c == '$') {
+ context->state = S_dollar;
+ } else if (c == '(') {
+ context->state = S_paren;
+ } else {
+ context->state = S_text;
+ }
+ PUTC(c);
+ break;
+
+ case S_dollar: /* Expecting '@', 'B', 'A' or '(' after CJK "ESC$". */
+ if (c == '@' || c == 'B' || c == 'A') {
+ context->state = S_nonascii_text;
+ } else if (c == '(') {
+ context->state = S_dollar_paren;
+ }
+ PUTC(c);
+ break;
+
+ case S_dollar_paren: /* Expecting 'C' after CJK "ESC$(". */
+ if (c == 'C') {
+ context->state = S_nonascii_text;
+ } else {
+ context->state = S_text;
+ }
+ PUTC(c);
+ break;
+
+ case S_paren: /* Expecting 'B', 'J', 'T' or 'I' after CJK "ESC(". */
+ if (c == 'B' || c == 'J' || c == 'T') {
+ context->state = S_text;
+ } else if (c == 'I') {
+ context->state = S_nonascii_text;
+ } else {
+ context->state = S_text;
+ }
+ PUTC(c);
+ break;
+
+ case S_nonascii_text: /* Expecting CJK ESC after non-ASCII text. */
+ if (c == '\033') {
+ context->state = S_esc;
+ }
+ PUTC(c);
+ break;
+
+ case S_esc_sq: /* Expecting '$'or '(' following CJK ESC. */
+ if (c == '$') {
+ context->state = S_dollar_sq;
+ } else if (c == '(') {
+ context->state = S_paren_sq;
+ } else {
+ context->state = S_squoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_dollar_sq: /* Expecting '@', 'B', 'A' or '(' after CJK "ESC$". */
+ if (c == '@' || c == 'B' || c == 'A') {
+ context->state = S_nonascii_text_sq;
+ } else if (c == '(') {
+ context->state = S_dollar_paren_sq;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_dollar_paren_sq: /* Expecting 'C' after CJK "ESC$(". */
+ if (c == 'C') {
+ context->state = S_nonascii_text_sq;
+ } else {
+ context->state = S_squoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_paren_sq: /* Expecting 'B', 'J', 'T' or 'I' after CJK "ESC(". */
+ if (c == 'B' || c == 'J' || c == 'T') {
+ context->state = S_squoted;
+ } else if (c == 'I') {
+ context->state = S_nonascii_text_sq;
+ } else {
+ context->state = S_squoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_nonascii_text_sq: /* Expecting CJK ESC after non-ASCII text. */
+ if (c == '\033') {
+ context->state = S_esc_sq;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_esc_dq: /* Expecting '$'or '(' following CJK ESC. */
+ if (c == '$') {
+ context->state = S_dollar_dq;
+ } else if (c == '(') {
+ context->state = S_paren_dq;
+ } else {
+ context->state = S_dquoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_dollar_dq: /* Expecting '@', 'B', 'A' or '(' after CJK "ESC$". */
+ if (c == '@' || c == 'B' || c == 'A') {
+ context->state = S_nonascii_text_dq;
+ } else if (c == '(') {
+ context->state = S_dollar_paren_dq;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_dollar_paren_dq: /* Expecting 'C' after CJK "ESC$(". */
+ if (c == 'C') {
+ context->state = S_nonascii_text_dq;
+ } else {
+ context->state = S_dquoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_paren_dq: /* Expecting 'B', 'J', 'T' or 'I' after CJK "ESC(". */
+ if (c == 'B' || c == 'J' || c == 'T') {
+ context->state = S_dquoted;
+ } else if (c == 'I') {
+ context->state = S_nonascii_text_dq;
+ } else {
+ context->state = S_dquoted;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_nonascii_text_dq: /* Expecting CJK ESC after non-ASCII text. */
+ if (c == '\033') {
+ context->state = S_esc_dq;
+ }
+ HTChunkPutc(string, c);
+ break;
+
+ case S_junk_tag:
+ if (c == '>') {
+ context->state = S_text;
+ }
+ } /* switch on context->state */
+
+ /*
+ ** Check whether we've added anything to the recover buffer. - FM
+ */
+ if (context->recover != NULL) {
+ if (context->recover[context->recover_index] == '\0') {
+ FREE(context->recover);
+ context->recover_index = 0;
+ } else {
+ c = context->recover[context->recover_index];
+ context->recover_index++;
+ goto top;
+ }
+ }
+
+ /*
+ ** Check whether an external function has added
+ ** anything to the include buffer. - FM
+ */
+ if (context->include != NULL) {
+ if (context->include[context->include_index] == '\0') {
+ FREE(context->include);
+ context->include_index = 0;
+ } else {
+ c = context->include[context->include_index];
+ context->include_index++;
+ goto top;
+ }
+ }
+
+ /*
+ ** Check whether an external function has added
+ ** anything to the csi buffer. - FM
+ */
+ if (context->csi != NULL) {
+ if (context->csi[context->csi_index] == '\0') {
+ FREE(context->csi);
+ context->csi_index = 0;
+ } else {
+ c = context->csi[context->csi_index];
+ context->csi_index++;
+ goto top;
+ }
+ }
+} /* SGML_character */
+
+
+PRIVATE void SGML_string ARGS2(
+ HTStream *, context,
+ CONST char*, str)
+{
+ CONST char *p;
+ for (p = str; *p; p++)
+ SGML_character(context, *p);
+}
+
+
+PRIVATE void SGML_write ARGS3(
+ HTStream *, context,
+ CONST char*, str,
+ int, l)
+{
+ CONST char *p;
+ CONST char *e = str+l;
+ for (p = str; p < e; p++)
+ SGML_character(context, *p);
+}
+
+/*_______________________________________________________________________
+*/
+
+/* Structured Object Class
+** -----------------------
+*/
+PUBLIC CONST HTStreamClass SGMLParser =
+{
+ "SGMLParser",
+ SGML_free,
+ SGML_abort,
+ SGML_character,
+ SGML_string,
+ SGML_write,
+};
+
+/* Create SGML Engine
+** ------------------
+**
+** On entry,
+** dtd represents the DTD, along with
+** actions is the sink for the data as a set of routines.
+**
+*/
+
+PUBLIC HTStream* SGML_new ARGS3(
+ CONST SGML_dtd *, dtd,
+ HTParentAnchor *, anchor,
+ HTStructured *, target)
+{
+ int i;
+ HTStream* context = (HTStream *) malloc(sizeof(*context));
+ if (!context)
+ outofmem(__FILE__, "SGML_begin");
+
+ context->isa = &SGMLParser;
+ context->string = HTChunkCreate(128); /* Grow by this much */
+ context->dtd = dtd;
+ context->target = target;
+ context->actions = (HTStructuredClass*)(((HTStream*)target)->isa);
+ /* Ugh: no OO */
+ context->unknown_tag = &HTTag_unrecognized;
+ context->state = S_text;
+ context->element_stack = 0; /* empty */
+ context->inSELECT = FALSE;
+#ifdef CALLERDATA
+ context->callerData = (void*) callerData;
+#endif /* CALLERDATA */
+ for (i = 0; i < MAX_ATTRIBUTES; i++)
+ context->value[i] = 0;
+
+ context->lead_exclamation = FALSE;
+ context->first_dash = FALSE;
+ context->end_comment = FALSE;
+ context->doctype_bracket = FALSE;
+ context->first_bracket = FALSE;
+ context->second_bracket = FALSE;
+ context->isHex = FALSE;
+
+ context->node_anchor = anchor; /* Could be NULL? */
+ context->utf_count = 0;
+ context->utf_char = 0;
+ context->utf_buf[0] = context->utf_buf[6] = '\0';
+ context->utf_buf_p = context->utf_buf;
+ UCTransParams_clear(&context->T);
+ context->inUCLYhndl = HTAnchor_getUCLYhndl(anchor,
+ UCT_STAGE_PARSER);
+ if (context->inUCLYhndl < 0) {
+ HTAnchor_copyUCInfoStage(anchor,
+ UCT_STAGE_PARSER,
+ UCT_STAGE_MIME,
+ -1);
+ context->inUCLYhndl = HTAnchor_getUCLYhndl(anchor,
+ UCT_STAGE_PARSER);
+ }
+ context->inUCI = HTAnchor_getUCInfoStage(anchor,
+ UCT_STAGE_PARSER);
+ set_chartrans_handling(context, anchor, -1);
+
+ context->recover = NULL;
+ context->recover_index = 0;
+ context->include = NULL;
+ context->include_index = 0;
+ context->url = NULL;
+ context->csi = NULL;
+ context->csi_index = 0;
+
+ return context;
+}
+
+/* Asian character conversion functions
+** ====================================
+**
+** Added 24-Mar-96 by FM, based on:
+**
+////////////////////////////////////////////////////////////////////////
+Copyright (c) 1993 Electrotechnical Laboratry (ETL)
+
+Permission to use, copy, modify, and distribute this material
+for any purpose and without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies, and that the name of ETL not be
+used in advertising or publicity pertaining to this
+material without the specific, prior written permission
+of an authorized representative of ETL.
+ETL MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
+OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
+WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+/////////////////////////////////////////////////////////////////////////
+Content-Type: program/C; charset=US-ASCII
+Program: SJIS.c
+Author: Yutaka Sato <ysato@etl.go.jp>
+Description:
+History:
+ 930923 extracted from codeconv.c of cosmos
+///////////////////////////////////////////////////////////////////////
+*/
+
+PUBLIC int TREAT_SJIS = 1;
+
+PUBLIC void JISx0201TO0208_EUC ARGS4(
+ register unsigned char, IHI,
+ register unsigned char, ILO,
+ register unsigned char *, OHI,
+ register unsigned char *, OLO)
+{
+ static char *table[] = {
+ "\xA1\xA3", "\xA1\xD6", "\xA1\xD7", "\xA1\xA2", "\xA1\xA6", "\xA5\xF2",
+ "\xA5\xA1", "\xA5\xA3", "\xA5\xA5", "\xA5\xA7", "\xA5\xA9",
+ "\xA5\xE3", "\xA5\xE5", "\xA5\xE7", "\xA5\xC3", "\xA1\xBC",
+ "\xA5\xA2", "\xA5\xA4", "\xA5\xA6", "\xA5\xA8", "\xA5\xAA",
+ "\xA5\xAB", "\xA5\xAD", "\xA5\xAF", "\xA5\xB1", "\xA5\xB3",
+ "\xA5\xB5", "\xA5\xB7", "\xA5\xB9", "\xA5\xBB", "\xA5\xBD",
+ "\xA5\xBF", "\xA5\xC1", "\xA5\xC4", "\xA5\xC6", "\xA5\xC8",
+ "\xA5\xCA", "\xA5\xCB", "\xA5\xCC", "\xA5\xCD", "\xA5\xCE",
+ "\xA5\xCF", "\xA5\xD2", "\xA5\xD5", "\xA5\xD8", "\xA5\xDB",
+ "\xA5\xDE", "\xA5\xDF", "\xA5\xE0", "\xA5\xE1", "\xA5\xE2",
+ "\xA5\xE4", "\xA5\xE6", "\xA5\xE8", "\xA5\xE9", "\xA5\xEA",
+ "\xA5\xEB", "\xA5\xEC", "\xA5\xED", "\xA5\xEF", "\xA5\xF3",
+ "\xA1\xAB", "\xA1\xAC"
+ };
+
+ if ((IHI == 0x8E) && (ILO >= 0xA1) && (ILO <= 0xDF)) {
+ *OHI = table[ILO - 0xA1][0];
+ *OLO = table[ILO - 0xA1][1];
+ } else {
+ *OHI = IHI;
+ *OLO = ILO;
+ }
+}
+
+PUBLIC unsigned char * SJIS_TO_JIS1 ARGS3(
+ register unsigned char, HI,
+ register unsigned char, LO,
+ register unsigned char *, JCODE)
+{
+ HI -= (HI <= 0x9F) ? 0x71 : 0xB1;
+ HI = (HI << 1) + 1;
+ if (0x7F < LO)
+ LO--;
+ if (0x9E <= LO) {
+ LO -= 0x7D;
+ HI++;
+ } else {
+ LO -= 0x1F;
+ }
+ JCODE[0] = HI;
+ JCODE[1] = LO;
+ return JCODE;
+}
+
+PUBLIC unsigned char * JIS_TO_SJIS1 ARGS3(
+ register unsigned char, HI,
+ register unsigned char, LO,
+ register unsigned char *, SJCODE)
+{
+ if (HI & 1)
+ LO += 0x1F;
+ else
+ LO += 0x7D;
+ if (0x7F <= LO)
+ LO++;
+
+ HI = ((HI - 0x21) >> 1) + 0x81;
+ if (0x9F < HI)
+ HI += 0x40;
+ SJCODE[0] = HI;
+ SJCODE[1] = LO;
+ return SJCODE;
+}
+
+PUBLIC unsigned char * EUC_TO_SJIS1 ARGS3(
+ unsigned char, HI,
+ unsigned char, LO,
+ register unsigned char *, SJCODE)
+{
+ if (HI == 0x8E) JISx0201TO0208_EUC(HI, LO, &HI, &LO);
+ JIS_TO_SJIS1(HI&0x7F, LO&0x7F, SJCODE);
+ return SJCODE;
+}
+
+PUBLIC void JISx0201TO0208_SJIS ARGS3(
+ register unsigned char, I,
+ register unsigned char *, OHI,
+ register unsigned char *, OLO)
+{
+ unsigned char SJCODE[2];
+
+ JISx0201TO0208_EUC('\x8E', I, OHI, OLO);
+ JIS_TO_SJIS1(*OHI&0x7F, *OLO&0x7F, SJCODE);
+ *OHI = SJCODE[0];
+ *OLO = SJCODE[1];
+}
+
+PUBLIC unsigned char * SJIS_TO_EUC1 ARGS3(
+ unsigned char, HI,
+ unsigned char, LO,
+ unsigned char *, data)
+{
+ SJIS_TO_JIS1(HI, LO, data);
+ data[0] |= 0x80;
+ data[1] |= 0x80;
+ return data;
+}
+
+PUBLIC unsigned char * SJIS_TO_EUC ARGS2(
+ unsigned char *, src,
+ unsigned char *, dst)
+{
+ register unsigned char hi, lo, *sp, *dp;
+ register int in_sjis = 0;
+
+ for (sp = src, dp = dst; (0 != (hi = sp[0]));) {
+ lo = sp[1];
+ if (TREAT_SJIS && IS_SJIS(hi, lo, in_sjis)) {
+ SJIS_TO_JIS1(hi,lo,dp);
+ dp[0] |= 0x80;
+ dp[1] |= 0x80;
+ dp += 2;
+ sp += 2;
+ } else {
+ *dp++ = *sp++;
+ }
+ }
+ *dp = 0;
+ return dst;
+}
+
+PUBLIC unsigned char * EUC_TO_SJIS ARGS2(
+ unsigned char *, src,
+ unsigned char *, dst)
+{
+ register unsigned char *sp, *dp;
+
+ for (sp = src, dp = dst; *sp;) {
+ if (*sp & 0x80) {
+ if (sp[1] && (sp[1] & 0x80)) {
+ JIS_TO_SJIS1(sp[0]&0x7F, sp[1]&0x7F, dp);
+ dp += 2;
+ sp += 2;
+ } else {
+ sp++;
+ }
+ } else {
+ *dp++ = *sp++;
+ }
+ }
+ *dp = 0;
+ return dst;
+}
+
+PUBLIC unsigned char * EUC_TO_JIS ARGS4(
+ unsigned char *, src,
+ unsigned char *, dst,
+ CONST char *, toK,
+ CONST char *, toA)
+{
+ register unsigned char kana_mode = 0;
+ register unsigned char cch;
+ register unsigned char *sp = src;
+ register unsigned char *dp = dst;
+ register int i;
+
+ while (0 != (cch = *sp++)) {
+ if (cch & 0x80) {
+ if (!kana_mode) {
+ kana_mode = ~kana_mode;
+ for (i = 0; toK[i]; i++) {
+ *dp++ = (unsigned char)toK[i];
+ }
+ }
+ if (*sp & 0x80) {
+ *dp++ = cch & ~0x80;
+ *dp++ = *sp++ & ~0x80;
+ }
+ } else {
+ if (kana_mode) {
+ kana_mode = ~kana_mode;
+ for (i = 0; toA[i]; i++) {
+ *dp++ = (unsigned char)toA[i];
+ *dp = '\0';
+ }
+ }
+ *dp++ = cch;
+ }
+ }
+ if (kana_mode) {
+ for (i = 0; toA[i]; i++) {
+ *dp++ = (unsigned char)toA[i];
+ }
+ }
+
+ if (dp)
+ *dp = 0;
+ return dst;
+}
+
+PUBLIC unsigned char * TO_EUC ARGS2(
+ unsigned char *, jis,
+ unsigned char *, euc)
+{
+ register unsigned char *s, *d, c, jis_stat;
+ register int to1B, to2B;
+ register int in_sjis = 0;
+
+ s = jis;
+ d = euc;
+ jis_stat = 0;
+ to2B = TO_2BCODE;
+ to1B = TO_1BCODE;
+
+ while (0 != (c = *s++)) {
+ if (c == ESC) {
+ if (*s == to2B) {
+ if ((s[1] == 'B') || (s[1] == '@') || (s[1] == 'A')) {
+ jis_stat = 0x80;
+ s += 2;
+ continue;
+ } else if ((s[1] == '(') && s[2] && (s[2] == 'C')) {
+ jis_stat = 0x80;
+ s += 3;
+ continue;
+ }
+ } else {
+ if (*s == to1B) {
+ if ((s[1]=='B') || (s[1]=='J') ||
+ (s[1]=='H') || (s[1]=='T')) {
+ jis_stat = 0;
+ s += 2;
+ continue;
+ }
+ }
+ }
+ }
+ if (IS_SJIS(c,*s,in_sjis)) {
+ SJIS_TO_EUC1(c, *s, d);
+ d += 2;
+ s++;
+ } else {
+ if (jis_stat && (0x20 < c)) {
+ *d++ = jis_stat | c;
+ } else {
+ *d++ = c;
+ }
+ }
+ }
+ *d = 0;
+ return euc;
+}
+
+PUBLIC void TO_SJIS ARGS2(
+ unsigned char *, any,
+ unsigned char *, sjis)
+{
+ unsigned char *euc;
+
+ if (!any || !sjis)
+ return;
+
+ euc = (unsigned char*)malloc(strlen((CONST char *)any)+1);
+ if (euc == NULL)
+ outofmem(__FILE__, "TO_SJIS");
+
+ TO_EUC(any, euc);
+ EUC_TO_SJIS(euc, sjis);
+ FREE(euc);
+}
+
+PUBLIC void TO_JIS ARGS2(
+ unsigned char *, any,
+ unsigned char *, jis)
+{
+ unsigned char *euc;
+
+ if (!any || !jis)
+ return;
+
+ euc = (unsigned char*)malloc(strlen((CONST char *)any)+1);
+ if (euc == NULL)
+ outofmem(__FILE__, "TO_JIS");
+
+ TO_EUC(any, euc);
+ EUC_TO_JIS(euc, jis, TO_KANJI, TO_ASCII);
+ FREE(euc);
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.h
new file mode 100644
index 00000000000..09ff6fe93a4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/SGML.h
@@ -0,0 +1,272 @@
+/* SGML parse and stream definition for libwww
+ SGML AND STRUCTURED STREAMS
+
+ The SGML parser is a state machine. It is called for every character
+
+ of the input stream. The DTD data structure contains pointers
+
+ to functions which are called to implement the actual effect of the
+
+ text read. When these functions are called, the attribute structures pointed to by the
+ DTD are valid, and the function is passed a pointer to the curent tag structure, and an
+ "element stack" which represents the state of nesting within SGML elements.
+
+ The following aspects are from Dan Connolly's suggestions: Binary search, Strcutured
+ object scheme basically, SGML content enum type.
+
+ (c) Copyright CERN 1991 - See Copyright.html
+
+ */
+#ifndef SGML_H
+#define SGML_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "HTStream.h"
+#include "HTAnchor.h"
+
+/*
+
+SGML content types
+
+ */
+typedef enum _SGMLContent {
+ SGML_EMPTY, /* No content. */
+ SGML_LITTERAL, /* Literal character data. Recognize exact close tag only.
+ Old www server compatibility only! Not SGML */
+ SGML_CDATA, /* Character data. Recognize </ only. */
+ SGML_RCDATA, /* Replaceable character data. Recognize </ and &ref; */
+ SGML_MIXED, /* Elements and parsed character data.
+ Recognize all markup. */
+ SGML_ELEMENT, /* Any data found will be returned as an error. */
+ SGML_PCDATA /* Added by KW. */
+} SGMLContent;
+
+
+typedef struct {
+ char * name; /* The (constant) name of the attribute */
+ /* Could put type info in here */
+} attr;
+
+typedef enum _TagClass {
+ /* textflow */
+ Tgc_FONTlike = 0x00001,/* S,STRIKE,I,B,TT,U,BIG,SMALL,STYLE,BLINK;BR,TAB */
+ Tgc_EMlike = 0x00002, /* EM,STRONG,DFN,CODE,SAMP,KBD,VAR,CITE,Q,INS,DEL,SPAN,.. */
+ Tgc_MATHlike = 0x00004, /* SUB,SUP,MATH,COMMENT */
+ Tgc_Alike = 0x00008, /* A */
+ Tgc_formula = 0x00010, /* not used until math is supported better... */
+ /* used for special structures: forms, tables,... */
+ Tgc_TRlike = 0x00020,/* TR and similar */
+ Tgc_SELECTlike = 0x00040,/* SELECT,INPUT,TEXTAREA(,...) */
+ /* structure */
+ Tgc_FORMlike = 0x00080,/* FORM itself */
+ Tgc_Plike = 0x00100, /* P,H1..H6,... structures containing text or
+ insertion but not other structures */
+ Tgc_DIVlike = 0x00200, /* ADDRESS,FIG,BDO,NOTE,FN,DIV,CENTER;FIG
+ structures which can contain other structures */
+ Tgc_LIlike = 0x00400, /* LH,LI,DT,DD;TH,TD structure-like, only valid
+ within certain other structures */
+ Tgc_ULlike = 0x00800, /* UL,OL,DL,DIR,MENU;TABLE;XMP,LISTING
+ special in some way, cannot contain (parsed)
+ text directly */
+ /* insertions */
+ Tgc_BRlike = 0x01000,/* BR,IMG,TAB allowed in any text */
+ Tgc_APPLETlike = 0x02000, /* APPLET,OBJECT,EMBED,SCRIPT */
+ Tgc_HRlike = 0x04000, /* HR,MARQUEE can contain all kinds of things
+ and/or are not allowed (?) in running text */
+ Tgc_MAPlike = 0x08000, /* MAP,AREA some specials that never contain
+ (directly or indirectly) other things than
+ special insertions */
+ Tgc_outer = 0x10000, /* HTML,FRAMESET,FRAME,PLAINTEXT; */
+ Tgc_BODYlike = 0x20000, /* BODY,BODYTEXT,NOFRAMES,TEXTFLOW; */
+ Tgc_HEADstuff = 0x40000, /* HEAD,BASE,STYLE,TITLE; */
+ /* special relations */
+ Tgc_same = 0x80000
+} TagClass;
+
+/* Some more properties of tags (or rather, elements) and rules how
+ to deal with them. - kw */
+typedef enum _TagFlags {
+ Tgf_endO = 0x00001, /* end tag can be Omitted */
+ Tgf_startO = 0x00002, /* start tag can be Omitted */
+ Tgf_mafse = 0x00004, /* Make Attribute-Free Start-tag End instead
+ (if found invalid) */
+ Tgf_strict = 0x00008 /* Ignore contained invalid elements,
+ don't pass them on */
+} TagFlags;
+
+/* A tag structure describes an SGML element.
+** -----------------------------------------
+**
+**
+** name is the string which comes after the tag opener "<".
+**
+** attributes points to a zero-terminated array
+** of attribute names.
+**
+** litteral determines how the SGML engine parses the charaters
+** within the element. If set, tag openers are ignored
+** except for that which opens a matching closing tag.
+**
+*/
+typedef struct _tag HTTag;
+struct _tag{
+ char * name; /* The name of the tag */
+ attr * attributes; /* The list of acceptable attributes */
+ int number_of_attributes; /* Number of possible attributes */
+ SGMLContent contents; /* End only on end tag @@ */
+ TagClass tagclass,
+ contains, /* which classes of elements this one can contain directly */
+ icontains, /* which classes of elements this one can contain indirectly */
+ contained, /* in which classes can this tag be contained ? */
+ icontained, /* in which classes can this tag be indirectly contained ? */
+ canclose; /* which classes of elements can this one close
+ if something looks wrong ? */
+ TagFlags flags;
+};
+
+
+/* DTD Information
+** ---------------
+**
+** Not the whole DTD, but all this parser uses of it.
+*/
+typedef struct {
+ char* name;
+ long code;
+} UC_entity_info;
+
+typedef struct {
+ HTTag * tags; /* Must be in strcmp order by name */
+ int number_of_tags;
+ CONST char ** entity_names; /* Must be in strcmp order by name */
+ size_t number_of_entities;
+ CONST UC_entity_info * unicode_entity_info; /* strcmp order by name */
+ size_t number_of_unicode_entities;
+ /*
+ ** All calls to unicode_entities table should be done
+ ** through HTMLGetEntityUCValue (LYCharSets.c) only.
+ ** unicode_entities table now holds *all*
+ ** old-style entities too.
+ */
+} SGML_dtd;
+
+
+/* SGML context passed to parsers
+*/
+typedef struct _HTSGMLContext *HTSGMLContext; /* Hidden */
+
+
+/*__________________________________________________________________________
+*/
+
+/*
+
+Structured Object definition
+
+ A structured object is something which can reasonably be represented
+ in SGML. I'll rephrase that. A structured object is am ordered
+ tree-structured arrangement of data which is representable as text.
+ The SGML parer outputs to a Structured object. A Structured object
+ can output its contents to another Structured Object. It's a kind of
+ typed stream. The architecure is largely Dan Conolly's. Elements and
+ entities are passed to the sob by number, implying a knowledge of the
+ DTD. Knowledge of the SGML syntax is not here, though.
+
+ Superclass: HTStream
+
+ The creation methods will vary on the type of Structured Object.
+ Maybe the callerData is enough info to pass along.
+
+ */
+typedef struct _HTStructured HTStructured;
+
+typedef struct _HTStructuredClass{
+
+ char* name; /* Just for diagnostics */
+
+ void (*_free) PARAMS((
+ HTStructured* me));
+
+ void (*_abort) PARAMS((
+ HTStructured* me,
+ HTError e));
+
+ void (*put_character) PARAMS((
+ HTStructured* me,
+ char ch));
+
+ void (*put_string) PARAMS((
+ HTStructured* me,
+ CONST char * str));
+
+ void (*_write) PARAMS((
+ HTStructured* me,
+ CONST char * str,
+ int len));
+
+ void (*start_element) PARAMS((
+ HTStructured* me,
+ int element_number,
+ CONST BOOL* attribute_present,
+ CONST char** attribute_value,
+ int charset,
+ char ** include));
+
+ void (*end_element) PARAMS((
+ HTStructured* me,
+ int element_number,
+ char ** include));
+
+ int (*put_entity) PARAMS((
+ HTStructured* me,
+ int entity_number));
+
+}HTStructuredClass;
+
+/*
+ Equivalents to the following functions possibly could be generalised
+ into additional HTStructuredClass members. FOr now they don't do
+ anything target-specific. - kw
+ */
+extern BOOLEAN LYCheckForCSI PARAMS((HTParentAnchor *anchor, char **url));
+extern void LYDoCSI PARAMS((char *url, CONST char *comment, char **csi));
+
+/*
+
+Find a Tag by Name
+
+ Returns a pointer to the tag within the DTD.
+
+ */
+extern HTTag * SGMLFindTag PARAMS((
+ CONST SGML_dtd * dtd,
+ CONST char * string));
+
+
+/*
+
+Create an SGML parser
+
+ */
+/*
+** On entry,
+** dtd must point to a DTD structure as defined above
+** callbacks must point to user routines.
+** callData is returned in callbacks transparently.
+** On exit,
+** The default tag starter has been processed.
+*/
+extern HTStream * SGML_new PARAMS((
+ CONST SGML_dtd * dtd,
+ HTParentAnchor * anchor,
+ HTStructured * target));
+
+extern CONST HTStreamClass SGMLParser;
+
+#endif /* SGML_H */
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/UCAux.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCAux.h
new file mode 100644
index 00000000000..b350e617e81
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCAux.h
@@ -0,0 +1,70 @@
+#ifndef UCAUX_H
+#define UCAUX_H
+
+extern BOOL UCCanUniTranslateFrom PARAMS((int from));
+extern BOOL UCCanTranslateUniTo PARAMS((int to));
+extern BOOL UCCanTranslateFromTo PARAMS((int from, int to));
+extern BOOL UCNeedNotTranslate PARAMS((
+ int from,
+ int to));
+
+struct _UCTransParams
+{
+ BOOL transp;
+ BOOL do_cjk;
+ BOOL decode_utf8;
+ BOOL output_utf8;
+ BOOL use_raw_char_in;
+ BOOL strip_raw_char_in;
+ BOOL pass_160_173_raw;
+ BOOL do_8bitraw;
+ BOOL trans_to_uni;
+ BOOL trans_C0_to_uni;
+ BOOL repl_translated_C0;
+ BOOL trans_from_uni;
+};
+typedef struct _UCTransParams UCTransParams;
+
+#ifndef UCDEFS_H
+#include "UCDefs.h"
+#endif /* UCDEFS_H */
+
+extern void UCSetTransParams PARAMS((
+ UCTransParams * pT,
+ int cs_in,
+ CONST LYUCcharset * p_in,
+ int cs_out,
+ CONST LYUCcharset * p_out));
+
+extern void UCTransParams_clear PARAMS((
+ UCTransParams * pT));
+
+extern void UCSetBoxChars PARAMS((
+ int cset,
+ int * pvert_out,
+ int * phori_out,
+ int vert_in,
+ int hori_in));
+
+#ifndef HTSTREAM_H
+#include "HTStream.h"
+#endif /* HTSTREAM_H */
+
+typedef void putc_func_t PARAMS((
+ HTStream * me,
+ char ch));
+
+#ifndef UCMAP_H
+#include "UCMap.h"
+#endif /* UCMAP_H */
+
+extern BOOL UCPutUtf8_charstring PARAMS((
+ HTStream * target,
+ putc_func_t * actions,
+ UCode_t code));
+
+extern BOOL UCConvertUniToUtf8 PARAMS((
+ UCode_t code,
+ char * buffer));
+
+#endif /* UCAUX_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/UCDefs.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCDefs.h
new file mode 100644
index 00000000000..ac2dc3bc2cb
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCDefs.h
@@ -0,0 +1,86 @@
+/* Definitions for Unicode character-translations */
+
+#ifndef UCDEFS_H
+#define UCDEFS_H
+
+typedef struct _LYUCcharset {
+ int UChndl;
+ CONST char * MIMEname;
+ int enc;
+ int repertoire;
+ int codepoints;
+ int cpranges; /* which ranges have valid displayable chars
+ (including nbsp and shy) */
+ int like8859; /* for which ranges is it like 8859-1 */
+} LYUCcharset;
+
+#define UCT_ENC_7BIT 0
+#define UCT_ENC_8BIT 1
+#define UCT_ENC_8859 2
+#define UCT_ENC_8BIT_C0 3 /* 8-bit some chars in C0 control area */
+#define UCT_ENC_MAYBE2022 4
+#define UCT_ENC_CJK 5
+#define UCT_ENC_16BIT 6
+#define UCT_ENC_UTF8 7
+
+
+#define UCT_REP_SUBSETOF_LAT1 0x01
+#define UCT_REP_SUPERSETOF_LAT1 0x02
+#define UCT_REP_IS_LAT1 UCT_REP_SUBSETOF_LAT1 | UCT_REP_SUPERSETOF_LAT1
+/*
+ * Assume everything we deal with is included in the UCS2 reperoire,
+ * so a flag for _REP_SUBSETOF_UCS2 would be redundant.
+ */
+
+/*
+ * More general description how the code points relate to 8859-1 and UCS:
+ */
+#define UCT_CP_SUBSETOF_LAT1 0x01 /* implies UCT_CP_SUBSETOF_UCS2 */
+#define UCT_CP_SUPERSETOF_LAT1 0x02
+#define UCT_CP_SUBSETOF_UCS2 0x04
+
+#define UCT_CP_IS_LAT1 UCT_CP_SUBSETOF_LAT1 | UCT_CP_SUPERSETOF_LAT1
+
+/*
+ * More specific bitflags for practically important code point ranges:
+ */
+#define UCT_R_LOWCTRL 0x08 /* 0x00-0x1F, for completeness */
+#define UCT_R_7BITINV 0x10 /* invariant, displayable 7bit chars */
+#define UCT_R_7BITNAT 0x20 /* displayable 7bit, national */
+#define UCT_R_HIGHCTRL 0x40
+#define UCT_R_8859SPECL 0x80 /* special chars in 8859-x sets: nbsp and shy*/
+#define UCT_R_HIGH8BIT 0x100 /* rest of 0xA0-0xFF range */
+
+#define UCT_R_ASCII UCT_R_7BITINV | UCT_R_7BITNAT /*displayable US-ASCII*/
+#define UCT_R_LAT1 UCT_R_ASCII | UCT_R_8859SPECL | UCT_R_HIGH8BIT
+#define UCT_R_8BIT UCT_R_LAT1 | UCT_R_HIGHCTRL /* full 8bit range */
+
+/*
+ * For the following some comments are in HTAnchor.c.
+ */
+#define UCT_STAGE_MIME 0
+#define UCT_STAGE_PARSER 1 /* What the parser (SGML.c) gets to see */
+#define UCT_STAGE_STRUCTURED 2 /* What the structured stream (HTML) gets fed*/
+#define UCT_STAGE_HTEXT 3 /* What gets fed to the HText_* functions */
+#define UCT_STAGEMAX 4
+
+#define UCT_SETBY_NONE 0
+#define UCT_SETBY_DEFAULT 1
+#define UCT_SETBY_LINK 2 /* set by A or LINK CHARSET= hint */
+#define UCT_SETBY_STRUCTURED 3 /* structured stream stage (HTML.c) */
+#define UCT_SETBY_PARSER 4 /* set by SGML parser or similar */
+#define UCT_SETBY_MIME 5 /* set explicitly by MIME charset parameter */
+
+typedef struct _UCStageInfo
+{
+ int lock; /* by what it has been set */
+ int LYhndl;
+ LYUCcharset C;
+} UCStageInfo;
+
+typedef struct _UCAnchorInfo
+{
+ struct _UCStageInfo s[UCT_STAGEMAX];
+} UCAnchorInfo;
+
+#endif /* UCDEFS_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/UCMap.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCMap.h
new file mode 100644
index 00000000000..e634f760ee0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/UCMap.h
@@ -0,0 +1,48 @@
+
+#ifndef UCMAP_H
+#define UCMAP_H
+
+typedef long UCode_t;
+
+extern int UCTransUniChar PARAMS((
+ UCode_t unicode,
+ int charset_out));
+extern int UCTransUniCharStr PARAMS((
+ char * outbuf,
+ int buflen,
+ UCode_t unicode,
+ int charset_out,
+ int chk_single_flag));
+extern int UCTransChar PARAMS((
+ char ch_in,
+ int charset_in,
+ int charset_out));
+extern int UCReverseTransChar PARAMS((
+ char ch_out,
+ int charset_in,
+ int charset_out));
+extern int UCTransCharStr PARAMS((
+ char * outbuf,
+ int buflen,
+ char ch_in,
+ int charset_in,
+ int charset_out,
+ int chk_single_flag));
+extern UCode_t UCTransToUni PARAMS((
+ char ch_in,
+ int charset_in));
+extern int UCGetLYhndl_byMIME PARAMS((
+ CONST char * p));
+extern int UCGetRawUniMode_byLYhndl PARAMS((
+ int i));
+
+extern int UCLYhndl_for_unspec;
+extern int UCLYhndl_for_unrec;
+extern int UCLYhndl_HTFile_for_unspec;
+extern int UCLYhndl_HTFile_for_unrec;
+
+#define UCTRANS_NOTFOUND (-4)
+
+#define HT_CANNOT_TRANSLATE -4 /* could go into HTUtils.h */
+
+#endif /* UCMAP_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/Version.make b/gnu/usr.bin/lynx/WWW/Library/Implementation/Version.make
new file mode 100644
index 00000000000..4b4b380f32b
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/Version.make
@@ -0,0 +1 @@
+VC = 2.14
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt.c
new file mode 100644
index 00000000000..ffc466c7126
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt.c
@@ -0,0 +1,129 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 1992, Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @(#)crypt.c 2.19 5/28/92
+ *
+ * Semiportable C version
+ *
+ */
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif
+
+#include "ufc-crypt.h"
+
+#include "LYLeaks.h"
+
+#ifdef _UFC_32_
+
+/*
+ * 32 bit version
+ */
+
+extern long32 _ufc_keytab[16][2];
+extern long32 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[];
+
+#define SBA(sb, v) (*(long32*)((char*)(sb)+(v)))
+
+static ufc_long ary[4];
+
+ufc_long *_ufc_doit(l1, l2, r1, r2, itr)
+ ufc_long l1, l2, r1, r2, itr;
+ { int i;
+ long32 s, *k;
+ register long32 *sb0 = _ufc_sb0;
+ register long32 *sb1 = _ufc_sb1;
+ register long32 *sb2 = _ufc_sb2;
+ register long32 *sb3 = _ufc_sb3;
+
+ while(itr--) {
+ k = &_ufc_keytab[0][0];
+ for(i=8; i--; ) {
+ s = *k++ ^ r1;
+ l1 ^= SBA(sb1, s & 0xffff); l2 ^= SBA(sb1, (s & 0xffff)+4);
+ l1 ^= SBA(sb0, s >>= 16); l2 ^= SBA(sb0, (s) +4);
+ s = *k++ ^ r2;
+ l1 ^= SBA(sb3, s & 0xffff); l2 ^= SBA(sb3, (s & 0xffff)+4);
+ l1 ^= SBA(sb2, s >>= 16); l2 ^= SBA(sb2, (s) +4);
+
+ s = *k++ ^ l1;
+ r1 ^= SBA(sb1, s & 0xffff); r2 ^= SBA(sb1, (s & 0xffff)+4);
+ r1 ^= SBA(sb0, s >>= 16); r2 ^= SBA(sb0, (s) +4);
+ s = *k++ ^ l2;
+ r1 ^= SBA(sb3, s & 0xffff); r2 ^= SBA(sb3, (s & 0xffff)+4);
+ r1 ^= SBA(sb2, s >>= 16); r2 ^= SBA(sb2, (s) +4);
+ }
+ s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s;
+ }
+ ary[0] = l1; ary[1] = l2; ary[2] = r1; ary[3] = r2;
+ return ary;
+ }
+
+#endif
+
+#ifdef _UFC_64_
+
+/*
+ * 64 bit version
+ */
+
+extern long64 _ufc_keytab[16];
+extern long64 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[];
+
+#define SBA(sb, v) (*(long64*)((char*)(sb)+(v)))
+
+static ufc_long ary[4];
+
+ufc_long *_ufc_doit(l1, l2, r1, r2, itr)
+ ufc_long l1, l2, r1, r2, itr;
+ { int i;
+ long64 l, r, s, *k;
+ register long64 *sb0 = _ufc_sb0;
+ register long64 *sb1 = _ufc_sb1;
+ register long64 *sb2 = _ufc_sb2;
+ register long64 *sb3 = _ufc_sb3;
+
+ l = (((long64)l1) << 32) | ((long64)l2);
+ r = (((long64)r1) << 32) | ((long64)r2);
+
+ while(itr--) {
+ k = &_ufc_keytab[0];
+ for(i=8; i--; ) {
+ s = *k++ ^ r;
+ l ^= SBA(sb3, (s >> 0) & 0xffff);
+ l ^= SBA(sb2, (s >> 16) & 0xffff);
+ l ^= SBA(sb1, (s >> 32) & 0xffff);
+ l ^= SBA(sb0, (s >> 48) & 0xffff);
+
+ s = *k++ ^ l;
+ r ^= SBA(sb3, (s >> 0) & 0xffff);
+ r ^= SBA(sb2, (s >> 16) & 0xffff);
+ r ^= SBA(sb1, (s >> 32) & 0xffff);
+ r ^= SBA(sb0, (s >> 48) & 0xffff);
+ }
+ s=l; l=r; r=s;
+ }
+
+ ary[0] = l >> 32; ary[1] = l & 0xffffffff;
+ ary[2] = r >> 32; ary[3] = r & 0xffffffff;
+ return ary;
+ }
+
+#endif
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt_util.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt_util.c
new file mode 100644
index 00000000000..9ed7e95d4da
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/crypt_util.c
@@ -0,0 +1,981 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 1992, Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @(#)crypt_util.c 2.40 09/21/92
+ *
+ * Support routines
+ *
+ */
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif
+
+#ifdef DEBUG
+/*#include <stdio.h> included by HTUTils.h - FM */
+#endif
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+#ifndef DOS
+#include "patchlevel.h"
+#include "ufc-crypt.h"
+#else
+/*
+ * Thanks to greg%wind@plains.NoDak.edu (Greg W. Wettstein)
+ * for DOS patches
+ */
+#include "pl.h"
+#include "ufc.h"
+#endif
+
+#include "LYLeaks.h"
+
+static char patchlevel_str[] = PATCHLEVEL;
+
+/*
+ * Permutation done once on the 56 bit
+ * key derived from the original 8 byte ASCII key.
+ */
+static int pc1[56] = {
+ 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
+};
+
+/*
+ * How much to rotate each 28 bit half of the pc1 permutated
+ * 56 bit key before using pc2 to give the i' key
+ */
+static int rots[16] = {
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+/*
+ * Permutation giving the key
+ * of the i' DES round
+ */
+static int pc2[48] = {
+ 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+/*
+ * The E expansion table which selects
+ * bits from the 32 bit intermediate result.
+ */
+static int esel[48] = {
+ 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
+};
+static int e_inverse[64];
+
+/*
+ * Permutation done on the
+ * result of sbox lookups
+ */
+static int perm32[32] = {
+ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
+ 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
+};
+
+/*
+ * The sboxes
+ */
+static int sbox[8][4][16]= {
+ { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
+ { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
+ { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
+ { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 }
+ },
+
+ { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
+ { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
+ { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
+ { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 }
+ },
+
+ { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
+ { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
+ { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
+ { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 }
+ },
+
+ { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
+ { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
+ { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
+ { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 }
+ },
+
+ { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
+ { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
+ { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
+ { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 }
+ },
+
+ { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
+ { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
+ { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
+ { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 }
+ },
+
+ { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
+ { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
+ { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
+ { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 }
+ },
+
+ { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
+ { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
+ { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
+ { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 }
+ }
+};
+
+/*
+ * This is the initial
+ * permutation matrix
+ */
+static int initial_perm[64] = {
+ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
+};
+
+/*
+ * This is the final
+ * permutation matrix
+ */
+static int final_perm[64] = {
+ 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
+};
+
+/*
+ * The 16 DES keys in BITMASK format
+ */
+#ifdef _UFC_32_
+long32 _ufc_keytab[16][2];
+#endif
+#ifdef _UFC_64_
+long64 _ufc_keytab[16];
+#endif
+
+#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.')
+#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
+
+/* Macro to set a bit (0..23) */
+#define BITMASK(i) ( (1L<<(11L-(i)%12L+3L)) << ((i)<12L?16L:0L) )
+
+/*
+ * sb arrays:
+ *
+ * Workhorses of the inner loop of the DES implementation.
+ * They do sbox lookup, shifting of this value, 32 bit
+ * permutation and E permutation for the next round.
+ *
+ * Kept in 'BITMASK' format.
+ */
+
+#ifdef _UFC_32_
+long32 _ufc_sb0[8192], _ufc_sb1[8192], _ufc_sb2[8192], _ufc_sb3[8192];
+static long32 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3};
+#endif
+
+#ifdef _UFC_64_
+long64 _ufc_sb0[4096], _ufc_sb1[4096], _ufc_sb2[4096], _ufc_sb3[4096];
+static long64 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3};
+#endif
+
+/*
+ * eperm32tab: do 32 bit permutation and E selection
+ *
+ * The first index is the byte number in the 32 bit value to be permuted
+ * - second - is the value of this byte
+ * - third - selects the two 32 bit values
+ *
+ * The table is used and generated internally in init_des to speed it up
+ */
+static ufc_long eperm32tab[4][256][2];
+
+/*
+ * do_pc1: permform pc1 permutation in the key schedule generation.
+ *
+ * The first index is the byte number in the 8 byte ASCII key
+ * - second - - the two 28 bits halfs of the result
+ * - third - selects the 7 bits actually used of each byte
+ *
+ * The result is kept with 28 bit per 32 bit with the 4 most significant
+ * bits zero.
+ */
+static ufc_long do_pc1[8][2][128];
+
+/*
+ * do_pc2: permform pc2 permutation in the key schedule generation.
+ *
+ * The first index is the septet number in the two 28 bit intermediate values
+ * - second - - - septet values
+ *
+ * Knowledge of the structure of the pc2 permutation is used.
+ *
+ * The result is kept with 28 bit per 32 bit with the 4 most significant
+ * bits zero.
+ */
+static ufc_long do_pc2[8][128];
+
+/*
+ * efp: undo an extra e selection and do final
+ * permutation giving the DES result.
+ *
+ * Invoked 6 bit a time on two 48 bit values
+ * giving two 32 bit longs.
+ */
+static ufc_long efp[16][64][2];
+
+/*
+ * revfinal: undo final permutation and do E expension.
+ *
+ * Invoked 6 bit a time on DES output
+ * giving 4 32 bit longs.
+ */
+static ufc_long revfinal[11][64][4];
+
+
+static unsigned char bytemask[8] = {
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+static ufc_long longmask[32] = {
+ 0x80000000, 0x40000000, 0x20000000, 0x10000000,
+ 0x08000000, 0x04000000, 0x02000000, 0x01000000,
+ 0x00800000, 0x00400000, 0x00200000, 0x00100000,
+ 0x00080000, 0x00040000, 0x00020000, 0x00010000,
+ 0x00008000, 0x00004000, 0x00002000, 0x00001000,
+ 0x00000800, 0x00000400, 0x00000200, 0x00000100,
+ 0x00000080, 0x00000040, 0x00000020, 0x00000010,
+ 0x00000008, 0x00000004, 0x00000002, 0x00000001
+};
+
+#ifdef DEBUG
+
+pr_bits(a, n)
+ ufc_long *a;
+ int n;
+ { ufc_long i, j, t, tmp;
+ n /= 8;
+ for(i = 0; i < n; i++) {
+ tmp=0;
+ for(j = 0; j < 8; j++) {
+ t=8*i+j;
+ tmp|=(a[t/24] & BITMASK(t % 24))?bytemask[j]:0;
+ }
+ (void)printf("%02x ",tmp);
+ }
+ printf(" ");
+ }
+
+static set_bits(v, b)
+ ufc_long v;
+ ufc_long *b;
+ { ufc_long i;
+ *b = 0;
+ for(i = 0; i < 24; i++) {
+ if(v & longmask[8 + i])
+ *b |= BITMASK(i);
+ }
+ }
+
+#endif
+
+/*
+ * Silly rewrite of 'bzero'. I do so
+ * because some machines don't have
+ * bzero and some don't have memset.
+ */
+
+STATIC void clearmem(start, cnt)
+ char *start;
+ int cnt;
+ { while(cnt--)
+ *start++ = '\0';
+ }
+
+static int initialized = 0;
+
+/* lookup a 6 bit value in sbox */
+
+#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf];
+
+/*
+ * Initialize unit - may be invoked directly
+ * by fcrypt users.
+ */
+
+void init_des()
+ { int comes_from_bit;
+ int bit, sg;
+ ufc_long j;
+ ufc_long mask1, mask2;
+
+ /*
+ * Create the do_pc1 table used
+ * to affect pc1 permutation
+ * when generating keys
+ */
+ for(bit = 0; bit < 56; bit++) {
+ comes_from_bit = pc1[bit] - 1;
+ mask1 = bytemask[comes_from_bit % 8 + 1];
+ mask2 = longmask[bit % 28 + 4];
+ for(j = 0; j < 128; j++) {
+ if(j & mask1)
+ do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2;
+ }
+ }
+
+ /*
+ * Create the do_pc2 table used
+ * to affect pc2 permutation when
+ * generating keys
+ */
+ for(bit = 0; bit < 48; bit++) {
+ comes_from_bit = pc2[bit] - 1;
+ mask1 = bytemask[comes_from_bit % 7 + 1];
+ mask2 = BITMASK(bit % 24);
+ for(j = 0; j < 128; j++) {
+ if(j & mask1)
+ do_pc2[comes_from_bit / 7][j] |= mask2;
+ }
+ }
+
+ /*
+ * Now generate the table used to do combined
+ * 32 bit permutation and e expansion
+ *
+ * We use it because we have to permute 16384 32 bit
+ * longs into 48 bit in order to initialize sb.
+ *
+ * Looping 48 rounds per permutation becomes
+ * just too slow...
+ *
+ */
+
+ clearmem((char*)eperm32tab, sizeof(eperm32tab));
+
+ for(bit = 0; bit < 48; bit++) {
+ ufc_long mask1,comes_from;
+
+ comes_from = perm32[esel[bit]-1]-1;
+ mask1 = bytemask[comes_from % 8];
+
+ for(j = 256; j--;) {
+ if(j & mask1)
+ eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK(bit % 24);
+ }
+ }
+
+ /*
+ * Create the sb tables:
+ *
+ * For each 12 bit segment of an 48 bit intermediate
+ * result, the sb table precomputes the two 4 bit
+ * values of the sbox lookups done with the two 6
+ * bit halves, shifts them to their proper place,
+ * sends them through perm32 and finally E expands
+ * them so that they are ready for the next
+ * DES round.
+ *
+ */
+ for(sg = 0; sg < 4; sg++) {
+ int j1, j2;
+ int s1, s2;
+
+ for(j1 = 0; j1 < 64; j1++) {
+ s1 = s_lookup(2 * sg, j1);
+ for(j2 = 0; j2 < 64; j2++) {
+ ufc_long to_permute, inx;
+
+ s2 = s_lookup(2 * sg + 1, j2);
+ to_permute = (((ufc_long)s1 << 4) |
+ (ufc_long)s2) << (24 - 8 * (ufc_long)sg);
+
+#ifdef _UFC_32_
+ inx = ((j1 << 6) | j2) << 1;
+ sb[sg][inx ] = eperm32tab[0][(to_permute >> 24) & 0xff][0];
+ sb[sg][inx+1] = eperm32tab[0][(to_permute >> 24) & 0xff][1];
+ sb[sg][inx ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0];
+ sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1];
+ sb[sg][inx ] |= eperm32tab[2][(to_permute >> 8) & 0xff][0];
+ sb[sg][inx+1] |= eperm32tab[2][(to_permute >> 8) & 0xff][1];
+ sb[sg][inx ] |= eperm32tab[3][(to_permute) & 0xff][0];
+ sb[sg][inx+1] |= eperm32tab[3][(to_permute) & 0xff][1];
+#endif
+#ifdef _UFC_64_
+ inx = ((j1 << 6) | j2);
+ sb[sg][inx] =
+ ((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) |
+ (long64)eperm32tab[0][(to_permute >> 24) & 0xff][1];
+ sb[sg][inx] |=
+ ((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) |
+ (long64)eperm32tab[1][(to_permute >> 16) & 0xff][1];
+ sb[sg][inx] |=
+ ((long64)eperm32tab[2][(to_permute >> 8) & 0xff][0] << 32) |
+ (long64)eperm32tab[2][(to_permute >> 8) & 0xff][1];
+ sb[sg][inx] |=
+ ((long64)eperm32tab[3][(to_permute) & 0xff][0] << 32) |
+ (long64)eperm32tab[3][(to_permute) & 0xff][1];
+#endif
+ }
+ }
+ }
+
+ /*
+ * Create an inverse matrix for esel telling
+ * where to plug out bits if undoing it
+ */
+ for(bit=48; bit--;) {
+ e_inverse[esel[bit] - 1 ] = bit;
+ e_inverse[esel[bit] - 1 + 32] = bit + 48;
+ }
+
+ /*
+ * create efp: the matrix used to
+ * undo the E expansion and effect final permutation
+ */
+ clearmem((char*)efp, sizeof efp);
+ for(bit = 0; bit < 64; bit++) {
+ int o_bit, o_long;
+ ufc_long word_value, mask1, mask2;
+ int comes_from_f_bit, comes_from_e_bit;
+ int comes_from_word, bit_within_word;
+
+ /* See where bit i belongs in the two 32 bit long's */
+ o_long = bit / 32; /* 0..1 */
+ o_bit = bit % 32; /* 0..31 */
+
+ /*
+ * And find a bit in the e permutated value setting this bit.
+ *
+ * Note: the e selection may have selected the same bit several
+ * times. By the initialization of e_inverse, we only look
+ * for one specific instance.
+ */
+ comes_from_f_bit = final_perm[bit] - 1; /* 0..63 */
+ comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */
+ comes_from_word = comes_from_e_bit / 6; /* 0..15 */
+ bit_within_word = comes_from_e_bit % 6; /* 0..5 */
+
+ mask1 = longmask[bit_within_word + 26];
+ mask2 = longmask[o_bit];
+
+ for(word_value = 64; word_value--;) {
+ if(word_value & mask1)
+ efp[comes_from_word][word_value][o_long] |= mask2;
+ }
+ }
+
+
+ /*
+ * Create revfinal: an array to undo final
+ * the effects of efp
+ */
+ clearmem((char*)revfinal, sizeof(revfinal));
+ for(bit = 0; bit < 96; bit++) {
+ int ibit = initial_perm[esel[bit % 48] - 1 + ((bit >= 48) ? 32 : 0)] - 1;
+ mask1 = bytemask[ibit % 6 + 2];
+ mask2 = BITMASK(bit % 24);
+ for(j = 64; j--;) {
+ if(j & mask1) {
+ revfinal[ibit / 6][j][bit / 24] |= mask2;
+ }
+ }
+ }
+
+ initialized++;
+ }
+
+/*
+ * Process the elements of the sb table permuting the
+ * bits swapped in the expansion by the current salt.
+ */
+
+#ifdef _UFC_32_
+STATIC void shuffle_sb(k, saltbits)
+ long32 *k;
+ ufc_long saltbits;
+ { ufc_long j;
+ long32 x;
+ for(j=4096; j--;) {
+ x = (k[0] ^ k[1]) & (long32)saltbits;
+ *k++ ^= x;
+ *k++ ^= x;
+ }
+ }
+#endif
+
+#ifdef _UFC_64_
+STATIC void shuffle_sb(k, saltbits)
+ long64 *k;
+ ufc_long saltbits;
+ { ufc_long j;
+ long64 x;
+ for(j=4096; j--;) {
+ x = ((*k >> 32) ^ *k) & (long64)saltbits;
+ *k++ ^= (x << 32) | x;
+ }
+ }
+#endif
+
+/*
+ * Setup the unit for a new salt
+ * Hopefully we'll not see a new salt in each crypt call.
+ */
+
+static unsigned char current_salt[3] = "&&"; /* invalid value */
+static ufc_long current_saltbits = 0;
+static int direction = 0;
+
+STATIC void setup_salt(s)
+ char *s;
+ { ufc_long i, j, saltbits;
+
+ if(!initialized)
+ init_des();
+
+ if(s[0] == current_salt[0] && s[1] == current_salt[1])
+ return;
+ current_salt[0] = s[0]; current_salt[1] = s[1];
+
+ /*
+ * This is the only crypt change to DES:
+ * entries are swapped in the expansion table
+ * according to the bits set in the salt.
+ */
+ saltbits = 0;
+ for(i = 0; i < 2; i++) {
+ long c=ascii_to_bin(s[i]);
+#ifdef notdef
+ /*
+ * Some applications do rely on illegal
+ * salts. It seems that UFC-crypt behaves
+ * identically to standard crypt
+ * implementations on illegal salts -- glad
+ */
+ if(c < 0 || c > 63)
+ c = 0;
+#endif
+ for(j = 0; j < 6; j++) {
+ if((c >> j) & 0x1)
+ saltbits |= BITMASK(6 * i + j);
+ }
+ }
+
+ /*
+ * Permute the sb table values
+ * to reflect the changed e
+ * selection table
+ */
+ shuffle_sb(_ufc_sb0, current_saltbits ^ saltbits);
+ shuffle_sb(_ufc_sb1, current_saltbits ^ saltbits);
+ shuffle_sb(_ufc_sb2, current_saltbits ^ saltbits);
+ shuffle_sb(_ufc_sb3, current_saltbits ^ saltbits);
+
+ current_saltbits = saltbits;
+ }
+
+STATIC void ufc_mk_keytab(key)
+ char *key;
+ { ufc_long v1, v2, *k1;
+ int i;
+#ifdef _UFC_32_
+ long32 v, *k2 = &_ufc_keytab[0][0];
+#endif
+#ifdef _UFC_64_
+ long64 v, *k2 = &_ufc_keytab[0];
+#endif
+
+ v1 = v2 = 0; k1 = &do_pc1[0][0][0];
+ for(i = 8; i--;) {
+ v1 |= k1[*key & 0x7f]; k1 += 128;
+ v2 |= k1[*key++ & 0x7f]; k1 += 128;
+ }
+
+ for(i = 0; i < 16; i++) {
+ k1 = &do_pc2[0][0];
+
+ v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i]));
+ v = k1[(v1 >> 21) & 0x7f]; k1 += 128;
+ v |= k1[(v1 >> 14) & 0x7f]; k1 += 128;
+ v |= k1[(v1 >> 7) & 0x7f]; k1 += 128;
+ v |= k1[(v1 ) & 0x7f]; k1 += 128;
+
+#ifdef _UFC_32_
+ *k2++ = v;
+ v = 0;
+#endif
+#ifdef _UFC_64_
+ v <<= 32;
+#endif
+
+ v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i]));
+ v |= k1[(v2 >> 21) & 0x7f]; k1 += 128;
+ v |= k1[(v2 >> 14) & 0x7f]; k1 += 128;
+ v |= k1[(v2 >> 7) & 0x7f]; k1 += 128;
+ v |= k1[(v2 ) & 0x7f];
+
+ *k2++ = v;
+ }
+
+ direction = 0;
+ }
+
+/*
+ * Undo an extra E selection and do final permutations
+ */
+
+ufc_long *_ufc_dofinalperm(l1, l2, r1, r2)
+ ufc_long l1,l2,r1,r2;
+ { ufc_long v1, v2, x;
+ static ufc_long ary[2];
+
+ x = (l1 ^ l2) & current_saltbits; l1 ^= x; l2 ^= x;
+ x = (r1 ^ r2) & current_saltbits; r1 ^= x; r2 ^= x;
+
+ v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3;
+
+ v1 |= efp[15][ r2 & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1];
+ v1 |= efp[14][(r2 >>= 6) & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1];
+ v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1];
+ v1 |= efp[12][(r2 >>= 6) & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1];
+
+ v1 |= efp[11][ r1 & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1];
+ v1 |= efp[10][(r1 >>= 6) & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1];
+ v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1];
+ v1 |= efp[ 8][(r1 >>= 6) & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1];
+
+ v1 |= efp[ 7][ l2 & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1];
+ v1 |= efp[ 6][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1];
+ v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1];
+ v1 |= efp[ 4][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1];
+
+ v1 |= efp[ 3][ l1 & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1];
+ v1 |= efp[ 2][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1];
+ v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1];
+ v1 |= efp[ 0][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1];
+
+ ary[0] = v1; ary[1] = v2;
+ return ary;
+ }
+
+/*
+ * crypt only: convert from 64 bit to 11 bit ASCII
+ * prefixing with the salt
+ */
+
+STATIC char *output_conversion(v1, v2, salt)
+ ufc_long v1, v2;
+ char *salt;
+ { static char outbuf[14];
+ int i, s, shf;
+
+ outbuf[0] = salt[0];
+ outbuf[1] = salt[1] ? salt[1] : salt[0];
+
+ for(i = 0; i < 5; i++) {
+ shf = (26 - 6 * i); /* to cope with MSC compiler bug */
+ outbuf[i + 2] = bin_to_ascii((v1 >> shf) & 0x3f);
+ }
+
+ s = (v2 & 0xf) << 2;
+ v2 = (v2 >> 2) | ((v1 & 0x3) << 30);
+
+ for(i = 5; i < 10; i++) {
+ shf = (56 - 6 * i);
+ outbuf[i + 2] = bin_to_ascii((v2 >> shf) & 0x3f);
+ }
+
+ outbuf[12] = bin_to_ascii(s);
+ outbuf[13] = 0;
+
+ return outbuf;
+ }
+
+ufc_long *_ufc_doit();
+
+/*
+ * UNIX crypt function
+ */
+
+char *crypt(key, salt)
+ char *key, *salt;
+ { ufc_long *s;
+ char ktab[9];
+
+ /*
+ * Hack DES tables according to salt
+ */
+ setup_salt(salt);
+
+ /*
+ * Setup key schedule
+ */
+ clearmem(ktab, sizeof ktab);
+ (void)strncpy(ktab, key, 8);
+ ufc_mk_keytab(ktab);
+
+ /*
+ * Go for the 25 DES encryptions
+ */
+ s = _ufc_doit((ufc_long)0, (ufc_long)0,
+ (ufc_long)0, (ufc_long)0, (ufc_long)25);
+ /*
+ * Do final permutations
+ */
+ s = _ufc_dofinalperm(s[0], s[1], s[2], s[3]);
+
+ /*
+ * And convert back to 6 bit ASCII
+ */
+ return output_conversion(s[0], s[1], salt);
+ }
+
+/*
+ * To make fcrypt users happy.
+ * They don't need to call init_des.
+ */
+
+char *fcrypt(key, salt)
+ char *key;
+ char *salt;
+ { return crypt(key, salt);
+ }
+
+/*
+ * UNIX encrypt function. Takes a bitvector
+ * represented by one byte per bit and
+ * encrypt/decrypt according to edflag
+ */
+
+void encrypt(block, edflag)
+ char *block;
+ int edflag;
+ { ufc_long l1, l2, r1, r2, *s;
+ int i;
+
+ /*
+ * Undo any salt changes to E expansion
+ */
+ setup_salt("..");
+
+ /*
+ * Reverse key table if
+ * changing operation (encrypt/decrypt)
+ */
+ if((edflag == 0) != (direction == 0)) {
+ for(i = 0; i < 8; i++) {
+#ifdef _UFC_32_
+ long32 x;
+ x = _ufc_keytab[15-i][0];
+ _ufc_keytab[15-i][0] = _ufc_keytab[i][0];
+ _ufc_keytab[i][0] = x;
+
+ x = _ufc_keytab[15-i][1];
+ _ufc_keytab[15-i][1] = _ufc_keytab[i][1];
+ _ufc_keytab[i][1] = x;
+#endif
+#ifdef _UFC_64_
+ long64 x;
+ x = _ufc_keytab[15-i];
+ _ufc_keytab[15-i] = _ufc_keytab[i];
+ _ufc_keytab[i] = x;
+#endif
+ }
+ direction = edflag;
+ }
+
+ /*
+ * Do initial permutation + E expansion
+ */
+ i = 0;
+ for(l1 = 0; i < 24; i++) {
+ if(block[initial_perm[esel[i]-1]-1])
+ l1 |= BITMASK(i);
+ }
+ for(l2 = 0; i < 48; i++) {
+ if(block[initial_perm[esel[i]-1]-1])
+ l2 |= BITMASK(i-24);
+ }
+
+ i = 0;
+ for(r1 = 0; i < 24; i++) {
+ if(block[initial_perm[esel[i]-1+32]-1])
+ r1 |= BITMASK(i);
+ }
+ for(r2 = 0; i < 48; i++) {
+ if(block[initial_perm[esel[i]-1+32]-1])
+ r2 |= BITMASK(i-24);
+ }
+
+ /*
+ * Do DES inner loops + final conversion
+ */
+ s = _ufc_doit(l1, l2, r1, r2, (ufc_long)1);
+ /*
+ * Do final permutations
+ */
+ s = _ufc_dofinalperm(s[0], s[1], s[2], s[3]);
+
+ /*
+ * And convert to bit array
+ */
+ l1 = s[0]; r1 = s[1];
+ for(i = 0; i < 32; i++) {
+ *block++ = (l1 & longmask[i]) != 0;
+ }
+ for(i = 0; i < 32; i++) {
+ *block++ = (r1 & longmask[i]) != 0;
+ }
+
+ }
+
+/*
+ * UNIX setkey function. Take a 64 bit DES
+ * key and setup the machinery.
+ */
+
+void setkey(key)
+ char *key;
+ { int i,j;
+ unsigned char c;
+ unsigned char ktab[8];
+
+ setup_salt(".."); /* be sure we're initialized */
+
+ for(i = 0; i < 8; i++) {
+ for(j = 0, c = 0; j < 8; j++)
+ c = c << 1 | *key++;
+ ktab[i] = c >> 1;
+ }
+
+ ufc_mk_keytab(ktab);
+ }
+
+/*
+ * Ultrix crypt16 function, thanks to pcl@convex.oxford.ac.uk (Paul Leyland)
+ */
+
+char *crypt16(key, salt)
+ char *key, *salt;
+ { ufc_long *s, *t;
+ char ktab[9], ttab[9];
+ static char q[14], res[25];
+ /*
+ * Hack DES tables according to salt
+ */
+ setup_salt(salt);
+
+ /*
+ * Setup key schedule
+ */
+ clearmem(ktab, sizeof ktab);
+ (void)strncpy(ktab, key, 8);
+ ufc_mk_keytab(ktab);
+
+ /*
+ * Go for first 20 DES encryptions
+ */
+ s = _ufc_doit((ufc_long)0, (ufc_long)0,
+ (ufc_long)0, (ufc_long)0, (ufc_long)20);
+
+ /*
+ * And convert back to 6 bit ASCII
+ */
+ strcpy (res, output_conversion(s[0], s[1], salt));
+
+ clearmem(ttab, sizeof ttab);
+ if (strlen (key) > 8) (void)strncpy(ttab, key+8, 8);
+ ufc_mk_keytab(ttab);
+
+ /*
+ * Go for second 5 DES encryptions
+ */
+ t = _ufc_doit((ufc_long)0, (ufc_long)0,
+ (ufc_long)0, (ufc_long)0, (ufc_long)5);
+ /*
+ * And convert back to 6 bit ASCII
+ */
+ strcpy (q, output_conversion(t[0], t[1], salt));
+ strcpy (res+13, q+2);
+
+ clearmem(ktab, sizeof ktab);
+ (void)strncpy(ktab, key, 8);
+ ufc_mk_keytab(ktab);
+
+ return res;
+ }
+
+/*
+ * Experimental -- not supported -- may choke your dog
+ */
+
+void ufc_setup_password(cookie, s)
+ long *cookie;
+ char *s;
+ { char c;
+ int i;
+ ufc_long x;
+ ufc_long dl1, dl2, dr1, dr2;
+
+ setup_salt(s);
+ dl1 = dl2 = dr1 = dr2 = 0;
+ for(i = 0, s += 2; c = *s++; i++) {
+ int x = ascii_to_bin(c);
+ dl1 |= revfinal[i][x][0];
+ dl2 |= revfinal[i][x][1];
+ dr1 |= revfinal[i][x][2];
+ dr2 |= revfinal[i][x][3];
+ }
+ x = (dl1 ^ dl2) & current_saltbits;
+ x = (dr1 ^ dr2) & current_saltbits;
+ cookie[0] = dl1 ^ x; cookie[1] = dl2 ^ x;
+ cookie[2] = dr1 ^ x; cookie[3] = dr2 ^ x;
+ }
+
+void ufc_do_pw(cookie, guess)
+ long *cookie;
+ char *guess;
+ { char ktab[9];
+ ufc_long *s;
+ clearmem(ktab, sizeof ktab);
+ (void)strncpy(ktab, guess, 8);
+ ufc_mk_keytab(ktab);
+ s = _ufc_doit((ufc_long)0, (ufc_long)0,
+ (ufc_long)0, (ufc_long)0, (ufc_long)25);
+ cookie[0] = s[0]; cookie[1] = s[1];
+ cookie[2] = s[2]; cookie[3] = s[3];
+ }
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/entities.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/entities.h
new file mode 100644
index 00000000000..55ce977b665
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/entities.h
@@ -0,0 +1,1084 @@
+/* Entity Names to Unicode table
+** -----------------------------
+**
+*
+* Whole entities[] thing (and much more) now present
+* in this kind of structure. The structured streams to which
+* the SGML modules sends its output could then easily have access
+* to both entity names and unicode values for each (special)
+* character. Probably the whole translation to display characters
+* should be done at that later stage (e.g. in HTML.c).
+* What's missing is a way for the later stage to return info
+* to SGML whether the entity could be displayed or not.
+* (like between SGML_character() and handle_entity() via FoundEntity.)
+* Well, trying to do that now.
+* Why keep two structures for entities? Backward compatibility..
+*/
+
+/* UC_entity_info structure is defined in SGML.h.
+ This has to be sorted alphabetically (case-sensitive),
+ bear this in mind when you add some more entities.. */
+
+/*
+
+This table available from ftp://ftp.unicode.org/
+original comment follows:
+
+
+# Author: John Cowan <cowan@ccil.org>
+# Date: 25 July 1997
+#
+# The following table maps SGML character entities from various
+# public sets (namely, ISOamsa, ISOamsb, ISOamsc, ISOamsn, ISOamso,
+# ISOamsr, ISObox, ISOcyr1, ISOcyr2, ISOdia, ISOgrk1, ISOgrk2,
+# ISOgrk3, ISOgrk4, ISOlat1, ISOlat2, ISOnum, ISOpub, ISOtech,
+# HTMLspecial, HTMLsymbol) to corresponding Unicode characters.
+#
+# The table has four tab-separated columns:
+# Column 1: SGML character entity name
+# Column 2: SGML public entity set
+# Column 3: Unicode 2.0 character code
+# Column 4: Unicode 2.0 character name (UPPER CASE)
+# Entries which don't have Unicode equivalents have "0x????"
+# in Column 3 and a lower case description (from the public entity
+# set DTD) in Column 4. The mapping is not reversible, because many
+# distinctions are unified away in Unicode, particularly between
+# mathematical symbols.
+#
+# The table is sorted case-blind by SGML character entity name.
+#
+# The contents of this table are drawn from various sources, and
+# are in the public domain.
+#
+########################
+
+ We just sort it and move column 2 away (line too long, sorry;
+ look at sgml.html in test/ directory for details).
+ Also we add a few (obsolete) synonyms:
+ "brkbar" for "brvbar" 0x00A6
+ "emdash" for "mdash" 0x2014
+ "endash" for "ndash" 0x2013
+ "hibar" for "macr" 0x00AF
+ for exact compatibility with entities[] and previous bevavior.
+ BTW, lots of synonyms found in this table, we shouldn't worry about...
+*/
+
+static CONST UC_entity_info unicode_entities[] = {
+ {"AElig", 0x00C6}, /* LATIN CAPITAL LETTER AE */
+ {"Aacgr", 0x0386}, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */
+ {"Aacute", 0x00C1}, /* LATIN CAPITAL LETTER A WITH ACUTE */
+ {"Abreve", 0x0102}, /* LATIN CAPITAL LETTER A WITH BREVE */
+ {"Acirc", 0x00C2}, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+ {"Acy", 0x0410}, /* CYRILLIC CAPITAL LETTER A */
+ {"Agr", 0x0391}, /* GREEK CAPITAL LETTER ALPHA */
+ {"Agrave", 0x00C0}, /* LATIN CAPITAL LETTER A WITH GRAVE */
+ {"Alpha", 0x0391}, /* GREEK CAPITAL LETTER ALPHA */
+ {"Amacr", 0x0100}, /* LATIN CAPITAL LETTER A WITH MACRON */
+ {"Aogon", 0x0104}, /* LATIN CAPITAL LETTER A WITH OGONEK */
+ {"Aring", 0x00C5}, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
+ {"Atilde", 0x00C3}, /* LATIN CAPITAL LETTER A WITH TILDE */
+ {"Auml", 0x00C4}, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
+ {"Barwed", 0x2306}, /* PERSPECTIVE */
+ {"Bcy", 0x0411}, /* CYRILLIC CAPITAL LETTER BE */
+ {"Beta", 0x0392}, /* GREEK CAPITAL LETTER BETA */
+ {"Bgr", 0x0392}, /* GREEK CAPITAL LETTER BETA */
+ {"CHcy", 0x0427}, /* CYRILLIC CAPITAL LETTER CHE */
+ {"Cacute", 0x0106}, /* LATIN CAPITAL LETTER C WITH ACUTE */
+ {"Cap", 0x22D2}, /* DOUBLE INTERSECTION */
+ {"Ccaron", 0x010C}, /* LATIN CAPITAL LETTER C WITH CARON */
+ {"Ccedil", 0x00C7}, /* LATIN CAPITAL LETTER C WITH CEDILLA */
+ {"Ccirc", 0x0108}, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+ {"Cdot", 0x010A}, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */
+ {"Chi", 0x03A7}, /* GREEK CAPITAL LETTER CHI */
+ {"Cup", 0x22D3}, /* DOUBLE UNION */
+ {"DJcy", 0x0402}, /* CYRILLIC CAPITAL LETTER DJE */
+ {"DScy", 0x0405}, /* CYRILLIC CAPITAL LETTER DZE */
+ {"DZcy", 0x040F}, /* CYRILLIC CAPITAL LETTER DZHE */
+ {"Dagger", 0x2021}, /* DOUBLE DAGGER */
+ {"Dcaron", 0x010E}, /* LATIN CAPITAL LETTER D WITH CARON */
+ {"Dcy", 0x0414}, /* CYRILLIC CAPITAL LETTER DE */
+ {"Delta", 0x0394}, /* GREEK CAPITAL LETTER DELTA */
+ {"Dgr", 0x0394}, /* GREEK CAPITAL LETTER DELTA */
+ {"Dot", 0x00A8}, /* DIAERESIS */
+ {"DotDot", 0x20DC}, /* COMBINING FOUR DOTS ABOVE */
+ {"Dstrok", 0x0110}, /* LATIN CAPITAL LETTER D WITH STROKE */
+ {"EEacgr", 0x0389}, /* GREEK CAPITAL LETTER ETA WITH TONOS */
+ {"EEgr", 0x0397}, /* GREEK CAPITAL LETTER ETA */
+ {"ENG", 0x014A}, /* LATIN CAPITAL LETTER ENG */
+ {"ETH", 0x00D0}, /* LATIN CAPITAL LETTER ETH */
+ {"Eacgr", 0x0388}, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */
+ {"Eacute", 0x00C9}, /* LATIN CAPITAL LETTER E WITH ACUTE */
+ {"Ecaron", 0x011A}, /* LATIN CAPITAL LETTER E WITH CARON */
+ {"Ecirc", 0x00CA}, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+ {"Ecy", 0x042D}, /* CYRILLIC CAPITAL LETTER E */
+ {"Edot", 0x0116}, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */
+ {"Egr", 0x0395}, /* GREEK CAPITAL LETTER EPSILON */
+ {"Egrave", 0x00C8}, /* LATIN CAPITAL LETTER E WITH GRAVE */
+ {"Emacr", 0x0112}, /* LATIN CAPITAL LETTER E WITH MACRON */
+ {"Eogon", 0x0118}, /* LATIN CAPITAL LETTER E WITH OGONEK */
+ {"Epsilon", 0x0395}, /* GREEK CAPITAL LETTER EPSILON */
+ {"Eta", 0x0397}, /* GREEK CAPITAL LETTER ETA */
+ {"Euml", 0x00CB}, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
+ {"Fcy", 0x0424}, /* CYRILLIC CAPITAL LETTER EF */
+ {"GJcy", 0x0403}, /* CYRILLIC CAPITAL LETTER GJE */
+ {"Gamma", 0x0393}, /* GREEK CAPITAL LETTER GAMMA */
+ {"Gbreve", 0x011E}, /* LATIN CAPITAL LETTER G WITH BREVE */
+ {"Gcedil", 0x0122}, /* LATIN CAPITAL LETTER G WITH CEDILLA */
+ {"Gcirc", 0x011C}, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+ {"Gcy", 0x0413}, /* CYRILLIC CAPITAL LETTER GHE */
+ {"Gdot", 0x0120}, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */
+ {"Gg", 0x22D9}, /* VERY MUCH GREATER-THAN */
+ {"Ggr", 0x0393}, /* GREEK CAPITAL LETTER GAMMA */
+ {"Gt", 0x226B}, /* MUCH GREATER-THAN */
+ {"HARDcy", 0x042A}, /* CYRILLIC CAPITAL LETTER HARD SIGN */
+ {"Hcirc", 0x0124}, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+ {"Hstrok", 0x0126}, /* LATIN CAPITAL LETTER H WITH STROKE */
+ {"IEcy", 0x0415}, /* CYRILLIC CAPITAL LETTER IE */
+ {"IJlig", 0x0132}, /* LATIN CAPITAL LIGATURE IJ */
+ {"IOcy", 0x0401}, /* CYRILLIC CAPITAL LETTER IO */
+ {"Iacgr", 0x038A}, /* GREEK CAPITAL LETTER IOTA WITH TONOS */
+ {"Iacute", 0x00CD}, /* LATIN CAPITAL LETTER I WITH ACUTE */
+ {"Icirc", 0x00CE}, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+ {"Icy", 0x0418}, /* CYRILLIC CAPITAL LETTER I */
+ {"Idigr", 0x03AA}, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+ {"Idot", 0x0130}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
+ {"Igr", 0x0399}, /* GREEK CAPITAL LETTER IOTA */
+ {"Igrave", 0x00CC}, /* LATIN CAPITAL LETTER I WITH GRAVE */
+ {"Imacr", 0x012A}, /* LATIN CAPITAL LETTER I WITH MACRON */
+ {"Iogon", 0x012E}, /* LATIN CAPITAL LETTER I WITH OGONEK */
+ {"Iota", 0x0399}, /* GREEK CAPITAL LETTER IOTA */
+ {"Itilde", 0x0128}, /* LATIN CAPITAL LETTER I WITH TILDE */
+ {"Iukcy", 0x0406}, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN*/
+ {"Iuml", 0x00CF}, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
+ {"Jcirc", 0x0134}, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+ {"Jcy", 0x0419}, /* CYRILLIC CAPITAL LETTER SHORT I */
+ {"Jsercy", 0x0408}, /* CYRILLIC CAPITAL LETTER JE */
+ {"Jukcy", 0x0404}, /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+ {"KHcy", 0x0425}, /* CYRILLIC CAPITAL LETTER HA */
+ {"KHgr", 0x03A7}, /* GREEK CAPITAL LETTER CHI */
+ {"KJcy", 0x040C}, /* CYRILLIC CAPITAL LETTER KJE */
+ {"Kappa", 0x039A}, /* GREEK CAPITAL LETTER KAPPA */
+ {"Kcedil", 0x0136}, /* LATIN CAPITAL LETTER K WITH CEDILLA */
+ {"Kcy", 0x041A}, /* CYRILLIC CAPITAL LETTER KA */
+ {"Kgr", 0x039A}, /* GREEK CAPITAL LETTER KAPPA */
+ {"LJcy", 0x0409}, /* CYRILLIC CAPITAL LETTER LJE */
+ {"Lacute", 0x0139}, /* LATIN CAPITAL LETTER L WITH ACUTE */
+ {"Lambda", 0x039B}, /* GREEK CAPITAL LETTER LAMDA */
+ {"Larr", 0x219E}, /* LEFTWARDS TWO HEADED ARROW */
+ {"Lcaron", 0x013D}, /* LATIN CAPITAL LETTER L WITH CARON */
+ {"Lcedil", 0x013B}, /* LATIN CAPITAL LETTER L WITH CEDILLA */
+ {"Lcy", 0x041B}, /* CYRILLIC CAPITAL LETTER EL */
+ {"Lgr", 0x039B}, /* GREEK CAPITAL LETTER LAMDA */
+ {"Ll", 0x22D8}, /* VERY MUCH LESS-THAN */
+ {"Lmidot", 0x013F}, /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */
+ {"Lstrok", 0x0141}, /* LATIN CAPITAL LETTER L WITH STROKE */
+ {"Lt", 0x226A}, /* MUCH LESS-THAN */
+ {"Mcy", 0x041C}, /* CYRILLIC CAPITAL LETTER EM */
+ {"Mgr", 0x039C}, /* GREEK CAPITAL LETTER MU */
+ {"Mu", 0x039C}, /* GREEK CAPITAL LETTER MU */
+ {"NJcy", 0x040A}, /* CYRILLIC CAPITAL LETTER NJE */
+ {"Nacute", 0x0143}, /* LATIN CAPITAL LETTER N WITH ACUTE */
+ {"Ncaron", 0x0147}, /* LATIN CAPITAL LETTER N WITH CARON */
+ {"Ncedil", 0x0145}, /* LATIN CAPITAL LETTER N WITH CEDILLA */
+ {"Ncy", 0x041D}, /* CYRILLIC CAPITAL LETTER EN */
+ {"Ngr", 0x039D}, /* GREEK CAPITAL LETTER NU */
+ {"Ntilde", 0x00D1}, /* LATIN CAPITAL LETTER N WITH TILDE */
+ {"Nu", 0x039D}, /* GREEK CAPITAL LETTER NU */
+ {"OElig", 0x0152}, /* LATIN CAPITAL LIGATURE OE */
+ {"OHacgr", 0x038F}, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */
+ {"OHgr", 0x03A9}, /* GREEK CAPITAL LETTER OMEGA */
+ {"Oacgr", 0x038C}, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */
+ {"Oacute", 0x00D3}, /* LATIN CAPITAL LETTER O WITH ACUTE */
+ {"Ocirc", 0x00D4}, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+ {"Ocy", 0x041E}, /* CYRILLIC CAPITAL LETTER O */
+ {"Odblac", 0x0150}, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+ {"Ogr", 0x039F}, /* GREEK CAPITAL LETTER OMICRON */
+ {"Ograve", 0x00D2}, /* LATIN CAPITAL LETTER O WITH GRAVE */
+ {"Omacr", 0x014C}, /* LATIN CAPITAL LETTER O WITH MACRON */
+ {"Omega", 0x03A9}, /* GREEK CAPITAL LETTER OMEGA */
+ {"Omicron", 0x039F}, /* GREEK CAPITAL LETTER OMICRON */
+ {"Oslash", 0x00D8}, /* LATIN CAPITAL LETTER O WITH STROKE */
+ {"Otilde", 0x00D5}, /* LATIN CAPITAL LETTER O WITH TILDE */
+ {"Ouml", 0x00D6}, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
+ {"PHgr", 0x03A6}, /* GREEK CAPITAL LETTER PHI */
+ {"PSgr", 0x03A8}, /* GREEK CAPITAL LETTER PSI */
+ {"Pcy", 0x041F}, /* CYRILLIC CAPITAL LETTER PE */
+ {"Pgr", 0x03A0}, /* GREEK CAPITAL LETTER PI */
+ {"Phi", 0x03A6}, /* GREEK CAPITAL LETTER PHI */
+ {"Pi", 0x03A0}, /* GREEK CAPITAL LETTER PI */
+ {"Prime", 0x2033}, /* DOUBLE PRIME */
+ {"Psi", 0x03A8}, /* GREEK CAPITAL LETTER PSI */
+ {"Racute", 0x0154}, /* LATIN CAPITAL LETTER R WITH ACUTE */
+ {"Rarr", 0x21A0}, /* RIGHTWARDS TWO HEADED ARROW */
+ {"Rcaron", 0x0158}, /* LATIN CAPITAL LETTER R WITH CARON */
+ {"Rcedil", 0x0156}, /* LATIN CAPITAL LETTER R WITH CEDILLA */
+ {"Rcy", 0x0420}, /* CYRILLIC CAPITAL LETTER ER */
+ {"Rgr", 0x03A1}, /* GREEK CAPITAL LETTER RHO */
+ {"Rho", 0x03A1}, /* GREEK CAPITAL LETTER RHO */
+ {"SHCHcy", 0x0429}, /* CYRILLIC CAPITAL LETTER SHCHA */
+ {"SHcy", 0x0428}, /* CYRILLIC CAPITAL LETTER SHA */
+ {"SOFTcy", 0x042C}, /* CYRILLIC CAPITAL LETTER SOFT SIGN */
+ {"Sacute", 0x015A}, /* LATIN CAPITAL LETTER S WITH ACUTE */
+ {"Scaron", 0x0160}, /* LATIN CAPITAL LETTER S WITH CARON */
+ {"Scedil", 0x015E}, /* LATIN CAPITAL LETTER S WITH CEDILLA */
+ {"Scirc", 0x015C}, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+ {"Scy", 0x0421}, /* CYRILLIC CAPITAL LETTER ES */
+ {"Sgr", 0x03A3}, /* GREEK CAPITAL LETTER SIGMA */
+ {"Sigma", 0x03A3}, /* GREEK CAPITAL LETTER SIGMA */
+ {"Sub", 0x22D0}, /* DOUBLE SUBSET */
+ {"Sup", 0x22D1}, /* DOUBLE SUPERSET */
+ {"THORN", 0x00DE}, /* LATIN CAPITAL LETTER THORN */
+ {"THgr", 0x0398}, /* GREEK CAPITAL LETTER THETA */
+ {"TSHcy", 0x040B}, /* CYRILLIC CAPITAL LETTER TSHE */
+ {"TScy", 0x0426}, /* CYRILLIC CAPITAL LETTER TSE */
+ {"Tau", 0x03A4}, /* GREEK CAPITAL LETTER TAU */
+ {"Tcaron", 0x0164}, /* LATIN CAPITAL LETTER T WITH CARON */
+ {"Tcedil", 0x0162}, /* LATIN CAPITAL LETTER T WITH CEDILLA */
+ {"Tcy", 0x0422}, /* CYRILLIC CAPITAL LETTER TE */
+ {"Tgr", 0x03A4}, /* GREEK CAPITAL LETTER TAU */
+ {"Theta", 0x0398}, /* GREEK CAPITAL LETTER THETA */
+ {"Tstrok", 0x0166}, /* LATIN CAPITAL LETTER T WITH STROKE */
+ {"Uacgr", 0x038E}, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */
+ {"Uacute", 0x00DA}, /* LATIN CAPITAL LETTER U WITH ACUTE */
+ {"Ubrcy", 0x040E}, /* CYRILLIC CAPITAL LETTER SHORT U */
+ {"Ubreve", 0x016C}, /* LATIN CAPITAL LETTER U WITH BREVE */
+ {"Ucirc", 0x00DB}, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+ {"Ucy", 0x0423}, /* CYRILLIC CAPITAL LETTER U */
+ {"Udblac", 0x0170}, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+ {"Udigr", 0x03AB}, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+ {"Ugr", 0x03A5}, /* GREEK CAPITAL LETTER UPSILON */
+ {"Ugrave", 0x00D9}, /* LATIN CAPITAL LETTER U WITH GRAVE */
+ {"Umacr", 0x016A}, /* LATIN CAPITAL LETTER U WITH MACRON */
+ {"Uogon", 0x0172}, /* LATIN CAPITAL LETTER U WITH OGONEK */
+ {"Upsi", 0x03A5}, /* GREEK CAPITAL LETTER UPSILON */
+ {"Upsilon", 0x03A5}, /* GREEK CAPITAL LETTER UPSILON */
+ {"Uring", 0x016E}, /* LATIN CAPITAL LETTER U WITH RING ABOVE */
+ {"Utilde", 0x0168}, /* LATIN CAPITAL LETTER U WITH TILDE */
+ {"Uuml", 0x00DC}, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
+ {"Vcy", 0x0412}, /* CYRILLIC CAPITAL LETTER VE */
+ {"Vdash", 0x22A9}, /* FORCES */
+ {"Verbar", 0x2016}, /* DOUBLE VERTICAL LINE */
+ {"Vvdash", 0x22AA}, /* TRIPLE VERTICAL BAR RIGHT TURNSTILE */
+ {"Wcirc", 0x0174}, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */
+ {"Xgr", 0x039E}, /* GREEK CAPITAL LETTER XI */
+ {"Xi", 0x039E}, /* GREEK CAPITAL LETTER XI */
+ {"YAcy", 0x042F}, /* CYRILLIC CAPITAL LETTER YA */
+ {"YIcy", 0x0407}, /* CYRILLIC CAPITAL LETTER YI */
+ {"YUcy", 0x042E}, /* CYRILLIC CAPITAL LETTER YU */
+ {"Yacute", 0x00DD}, /* LATIN CAPITAL LETTER Y WITH ACUTE */
+ {"Ycirc", 0x0176}, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */
+ {"Ycy", 0x042B}, /* CYRILLIC CAPITAL LETTER YERU */
+ {"Yuml", 0x0178}, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+ {"ZHcy", 0x0416}, /* CYRILLIC CAPITAL LETTER ZHE */
+ {"Zacute", 0x0179}, /* LATIN CAPITAL LETTER Z WITH ACUTE */
+ {"Zcaron", 0x017D}, /* LATIN CAPITAL LETTER Z WITH CARON */
+ {"Zcy", 0x0417}, /* CYRILLIC CAPITAL LETTER ZE */
+ {"Zdot", 0x017B}, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+ {"Zeta", 0x0396}, /* GREEK CAPITAL LETTER ZETA */
+ {"Zgr", 0x0396}, /* GREEK CAPITAL LETTER ZETA */
+ {"aacgr", 0x03AC}, /* GREEK SMALL LETTER ALPHA WITH TONOS */
+ {"aacute", 0x00E1}, /* LATIN SMALL LETTER A WITH ACUTE */
+ {"abreve", 0x0103}, /* LATIN SMALL LETTER A WITH BREVE */
+ {"acirc", 0x00E2}, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+ {"acute", 0x00B4}, /* ACUTE ACCENT */
+ {"acy", 0x0430}, /* CYRILLIC SMALL LETTER A */
+ {"aelig", 0x00E6}, /* LATIN SMALL LETTER AE */
+ {"agr", 0x03B1}, /* GREEK SMALL LETTER ALPHA */
+ {"agrave", 0x00E0}, /* LATIN SMALL LETTER A WITH GRAVE */
+ {"alefsym", 0x2135}, /* ALEF SYMBOL */
+ {"aleph", 0x2135}, /* ALEF SYMBOL */
+ {"alpha", 0x03B1}, /* GREEK SMALL LETTER ALPHA */
+ {"amacr", 0x0101}, /* LATIN SMALL LETTER A WITH MACRON */
+ {"amalg", 0x2210}, /* N-ARY COPRODUCT */
+ {"amp", 0x0026}, /* AMPERSAND */
+ {"and", 0x2227}, /* LOGICAL AND */
+ {"ang", 0x2220}, /* ANGLE */
+ {"ang90", 0x221F}, /* RIGHT ANGLE */
+ {"angmsd", 0x2221}, /* MEASURED ANGLE */
+ {"angsph", 0x2222}, /* SPHERICAL ANGLE */
+ {"angst", 0x212B}, /* ANGSTROM SIGN */
+ {"aogon", 0x0105}, /* LATIN SMALL LETTER A WITH OGONEK */
+ {"ap", 0x2248}, /* ALMOST EQUAL TO */
+ {"ape", 0x224A}, /* ALMOST EQUAL OR EQUAL TO */
+ {"apos", 0x02BC}, /* MODIFIER LETTER APOSTROPHE */
+ {"aring", 0x00E5}, /* LATIN SMALL LETTER A WITH RING ABOVE */
+ {"ast", 0x002A}, /* ASTERISK */
+ {"asymp", 0x2248}, /* ALMOST EQUAL TO */
+ {"atilde", 0x00E3}, /* LATIN SMALL LETTER A WITH TILDE */
+ {"auml", 0x00E4}, /* LATIN SMALL LETTER A WITH DIAERESIS */
+ {"b.Delta", 0x0394}, /* GREEK CAPITAL LETTER DELTA */
+ {"b.Gamma", 0x0393}, /* GREEK CAPITAL LETTER GAMMA */
+ {"b.Lambda", 0x039B}, /* GREEK CAPITAL LETTER LAMDA */
+ {"b.Omega", 0x03A9}, /* GREEK CAPITAL LETTER OMEGA */
+ {"b.Phi", 0x03A6}, /* GREEK CAPITAL LETTER PHI */
+ {"b.Pi", 0x03A0}, /* GREEK CAPITAL LETTER PI */
+ {"b.Psi", 0x03A8}, /* GREEK CAPITAL LETTER PSI */
+ {"b.Sigma", 0x03A3}, /* GREEK CAPITAL LETTER SIGMA */
+ {"b.Theta", 0x0398}, /* GREEK CAPITAL LETTER THETA */
+ {"b.Upsi", 0x03A5}, /* GREEK CAPITAL LETTER UPSILON */
+ {"b.Xi", 0x039E}, /* GREEK CAPITAL LETTER XI */
+ {"b.alpha", 0x03B1}, /* GREEK SMALL LETTER ALPHA */
+ {"b.beta", 0x03B2}, /* GREEK SMALL LETTER BETA */
+ {"b.chi", 0x03C7}, /* GREEK SMALL LETTER CHI */
+ {"b.delta", 0x03B3}, /* GREEK SMALL LETTER GAMMA */
+ {"b.epsi", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"b.epsis", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"b.epsiv", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"b.eta", 0x03B7}, /* GREEK SMALL LETTER ETA */
+ {"b.gamma", 0x03B3}, /* GREEK SMALL LETTER GAMMA */
+ {"b.gammad", 0x03DC}, /* GREEK LETTER DIGAMMA */
+ {"b.iota", 0x03B9}, /* GREEK SMALL LETTER IOTA */
+ {"b.kappa", 0x03BA}, /* GREEK SMALL LETTER KAPPA */
+ {"b.kappav", 0x03F0}, /* GREEK KAPPA SYMBOL */
+ {"b.lambda", 0x03BB}, /* GREEK SMALL LETTER LAMDA */
+ {"b.mu", 0x03BC}, /* GREEK SMALL LETTER MU */
+ {"b.nu", 0x03BD}, /* GREEK SMALL LETTER NU */
+ {"b.omega", 0x03CE}, /* GREEK SMALL LETTER OMEGA WITH TONOS */
+ {"b.phis", 0x03C6}, /* GREEK SMALL LETTER PHI */
+ {"b.phiv", 0x03D5}, /* GREEK PHI SYMBOL */
+ {"b.pi", 0x03C0}, /* GREEK SMALL LETTER PI */
+ {"b.piv", 0x03D6}, /* GREEK PI SYMBOL */
+ {"b.psi", 0x03C8}, /* GREEK SMALL LETTER PSI */
+ {"b.rho", 0x03C1}, /* GREEK SMALL LETTER RHO */
+ {"b.rhov", 0x03F1}, /* GREEK RHO SYMBOL */
+ {"b.sigma", 0x03C3}, /* GREEK SMALL LETTER SIGMA */
+ {"b.sigmav", 0x03C2}, /* GREEK SMALL LETTER FINAL SIGMA */
+ {"b.tau", 0x03C4}, /* GREEK SMALL LETTER TAU */
+ {"b.thetas", 0x03B8}, /* GREEK SMALL LETTER THETA */
+ {"b.thetav", 0x03D1}, /* GREEK THETA SYMBOL */
+ {"b.upsi", 0x03C5}, /* GREEK SMALL LETTER UPSILON */
+ {"b.xi", 0x03BE}, /* GREEK SMALL LETTER XI */
+ {"b.zeta", 0x03B6}, /* GREEK SMALL LETTER ZETA */
+ {"barwed", 0x22BC}, /* NAND */
+ {"bcong", 0x224C}, /* ALL EQUAL TO */
+ {"bcy", 0x0431}, /* CYRILLIC SMALL LETTER BE */
+ {"bdquo", 0x201E}, /* DOUBLE LOW-9 QUOTATION MARK */
+ {"becaus", 0x2235}, /* BECAUSE */
+ {"bepsi", 0x220D}, /* SMALL CONTAINS AS MEMBER */
+ {"bernou", 0x212C}, /* SCRIPT CAPITAL B */
+ {"beta", 0x03B2}, /* GREEK SMALL LETTER BETA */
+ {"beth", 0x2136}, /* BET SYMBOL */
+ {"bgr", 0x03B2}, /* GREEK SMALL LETTER BETA */
+ {"blank", 0x2423}, /* OPEN BOX */
+ {"blk12", 0x2592}, /* MEDIUM SHADE */
+ {"blk14", 0x2591}, /* LIGHT SHADE */
+ {"blk34", 0x2593}, /* DARK SHADE */
+ {"block", 0x2588}, /* FULL BLOCK */
+ {"bottom", 0x22A5}, /* UP TACK */
+ {"bowtie", 0x22C8}, /* BOWTIE */
+ {"boxDL", 0x2557}, /* BOX DRAWINGS DOUBLE DOWN AND LEFT */
+ {"boxDR", 0x2554}, /* BOX DRAWINGS DOUBLE DOWN AND RIGHT */
+ {"boxDl", 0x2556}, /* BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE */
+ {"boxDr", 0x2553}, /* BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE */
+ {"boxH", 0x2550}, /* BOX DRAWINGS DOUBLE HORIZONTAL */
+ {"boxHD", 0x2566}, /* BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL */
+ {"boxHU", 0x2569}, /* BOX DRAWINGS DOUBLE UP AND HORIZONTAL */
+ {"boxHd", 0x2564}, /* BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE*/
+ {"boxHu", 0x2567}, /* BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE */
+ {"boxUL", 0x255D}, /* BOX DRAWINGS DOUBLE UP AND LEFT */
+ {"boxUR", 0x255A}, /* BOX DRAWINGS DOUBLE UP AND RIGHT */
+ {"boxUl", 0x255C}, /* BOX DRAWINGS UP DOUBLE AND LEFT SINGLE */
+ {"boxUr", 0x2559}, /* BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE */
+ {"boxV", 0x2551}, /* BOX DRAWINGS DOUBLE VERTICAL */
+ {"boxVH", 0x256C}, /* BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL */
+ {"boxVL", 0x2563}, /* BOX DRAWINGS DOUBLE VERTICAL AND LEFT */
+ {"boxVR", 0x2560}, /* BOX DRAWINGS DOUBLE VERTICAL AND RIGHT */
+ {"boxVh", 0x256B}, /* BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SI*/
+ {"boxVl", 0x2562}, /* BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE */
+ {"boxVr", 0x255F}, /* BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE */
+ {"boxdL", 0x2555}, /* BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE */
+ {"boxdR", 0x2552}, /* BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE */
+ {"boxdl", 0x2510}, /* BOX DRAWINGS LIGHT DOWN AND LEFT */
+ {"boxdr", 0x250C}, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */
+ {"boxh", 0x2500}, /* BOX DRAWINGS LIGHT HORIZONTAL */
+ {"boxhD", 0x2565}, /* BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE*/
+ {"boxhU", 0x2568}, /* BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE */
+ {"boxhd", 0x252C}, /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+ {"boxhu", 0x2534}, /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+ {"boxuL", 0x255B}, /* BOX DRAWINGS UP SINGLE AND LEFT DOUBLE */
+ {"boxuR", 0x2558}, /* BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE */
+ {"boxul", 0x2518}, /* BOX DRAWINGS LIGHT UP AND LEFT */
+ {"boxur", 0x2514}, /* BOX DRAWINGS LIGHT UP AND RIGHT */
+ {"boxv", 0x2502}, /* BOX DRAWINGS LIGHT VERTICAL */
+ {"boxvH", 0x256A}, /* BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DO*/
+ {"boxvL", 0x2561}, /* BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE */
+ {"boxvR", 0x255E}, /* BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE */
+ {"boxvh", 0x253C}, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+ {"boxvl", 0x2524}, /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+ {"boxvr", 0x251C}, /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+ {"bprime", 0x2035}, /* REVERSED PRIME */
+ {"breve", 0x02D8}, /* BREVE */
+ {"brkbar", 0x00A6}, /* obsolete synonym for "brvbar" 0x00A6 */
+ {"brvbar", 0x00A6}, /* BROKEN BAR */
+ {"bsim", 0x223D}, /* REVERSED TILDE */
+ {"bsime", 0x22CD}, /* REVERSED TILDE EQUALS */
+ {"bsol", 0x005C}, /* REVERSE SOLIDUS */
+ {"bull", 0x2022}, /* BULLET */
+ {"bump", 0x224E}, /* GEOMETRICALLY EQUIVALENT TO */
+ {"bumpe", 0x224F}, /* DIFFERENCE BETWEEN */
+ {"cacute", 0x0107}, /* LATIN SMALL LETTER C WITH ACUTE */
+ {"cap", 0x2229}, /* INTERSECTION */
+ {"caret", 0x2041}, /* CARET INSERTION POINT */
+ {"caron", 0x02C7}, /* CARON */
+ {"ccaron", 0x010D}, /* LATIN SMALL LETTER C WITH CARON */
+ {"ccedil", 0x00E7}, /* LATIN SMALL LETTER C WITH CEDILLA */
+ {"ccirc", 0x0109}, /* LATIN SMALL LETTER C WITH CIRCUMFLEX */
+ {"cdot", 0x010B}, /* LATIN SMALL LETTER C WITH DOT ABOVE */
+ {"cedil", 0x00B8}, /* CEDILLA */
+ {"cent", 0x00A2}, /* CENT SIGN */
+ {"chcy", 0x0447}, /* CYRILLIC SMALL LETTER CHE */
+ {"check", 0x2713}, /* CHECK MARK */
+ {"chi", 0x03C7}, /* GREEK SMALL LETTER CHI */
+ {"cir", 0x25CB}, /* WHITE CIRCLE */
+ {"circ", 0x02C6}, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+ {"cire", 0x2257}, /* RING EQUAL TO */
+ {"clubs", 0x2663}, /* BLACK CLUB SUIT */
+ {"colon", 0x003A}, /* COLON */
+ {"colone", 0x2254}, /* COLON EQUALS */
+ {"comma", 0x002C}, /* COMMA */
+ {"commat", 0x0040}, /* COMMERCIAL AT */
+ {"comp", 0x2201}, /* COMPLEMENT */
+ {"compfn", 0x2218}, /* RING OPERATOR */
+ {"cong", 0x2245}, /* APPROXIMATELY EQUAL TO */
+ {"conint", 0x222E}, /* CONTOUR INTEGRAL */
+ {"coprod", 0x2210}, /* N-ARY COPRODUCT */
+ {"copy", 0x00A9}, /* COPYRIGHT SIGN */
+ {"copysr", 0x2117}, /* SOUND RECORDING COPYRIGHT */
+ {"crarr", 0x21B5}, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS */
+ {"cross", 0x2717}, /* BALLOT X */
+ {"cuepr", 0x22DE}, /* EQUAL TO OR PRECEDES */
+ {"cuesc", 0x22DF}, /* EQUAL TO OR SUCCEEDS */
+ {"cularr", 0x21B6}, /* ANTICLOCKWISE TOP SEMICIRCLE ARROW */
+ {"cup", 0x222A}, /* UNION */
+ {"cupre", 0x227C}, /* PRECEDES OR EQUAL TO */
+ {"curarr", 0x21B7}, /* CLOCKWISE TOP SEMICIRCLE ARROW */
+ {"curren", 0x00A4}, /* CURRENCY SIGN */
+ {"cuvee", 0x22CE}, /* CURLY LOGICAL OR */
+ {"cuwed", 0x22CF}, /* CURLY LOGICAL AND */
+ {"dArr", 0x21D3}, /* DOWNWARDS DOUBLE ARROW */
+ {"dagger", 0x2020}, /* DAGGER */
+ {"daleth", 0x2138}, /* DALET SYMBOL */
+ {"darr", 0x2193}, /* DOWNWARDS ARROW */
+ {"darr2", 0x21CA}, /* DOWNWARDS PAIRED ARROWS */
+ {"dash", 0x2010}, /* HYPHEN */
+ {"dashv", 0x22A3}, /* LEFT TACK */
+ {"dblac", 0x02DD}, /* DOUBLE ACUTE ACCENT */
+ {"dcaron", 0x010F}, /* LATIN SMALL LETTER D WITH CARON */
+ {"dcy", 0x0434}, /* CYRILLIC SMALL LETTER DE */
+ {"deg", 0x00B0}, /* DEGREE SIGN */
+ {"delta", 0x03B4}, /* GREEK SMALL LETTER DELTA */
+ {"dgr", 0x03B4}, /* GREEK SMALL LETTER DELTA */
+ {"dharl", 0x21C3}, /* DOWNWARDS HARPOON WITH BARB LEFTWARDS */
+ {"dharr", 0x21C2}, /* DOWNWARDS HARPOON WITH BARB RIGHTWARDS */
+ {"diam", 0x22C4}, /* DIAMOND OPERATOR */
+ {"diams", 0x2666}, /* BLACK DIAMOND SUIT */
+ {"die", 0x00A8}, /* DIAERESIS */
+ {"divide", 0x00F7}, /* DIVISION SIGN */
+ {"divonx", 0x22C7}, /* DIVISION TIMES */
+ {"djcy", 0x0452}, /* CYRILLIC SMALL LETTER DJE */
+ {"dlarr", 0x2199}, /* SOUTH WEST ARROW */
+ {"dlcorn", 0x231E}, /* BOTTOM LEFT CORNER */
+ {"dlcrop", 0x230D}, /* BOTTOM LEFT CROP */
+ {"dollar", 0x0024}, /* DOLLAR SIGN */
+ {"dot", 0x02D9}, /* DOT ABOVE */
+ {"drarr", 0x2198}, /* SOUTH EAST ARROW */
+ {"drcorn", 0x231F}, /* BOTTOM RIGHT CORNER */
+ {"drcrop", 0x230C}, /* BOTTOM RIGHT CROP */
+ {"dscy", 0x0455}, /* CYRILLIC SMALL LETTER DZE */
+ {"dstrok", 0x0111}, /* LATIN SMALL LETTER D WITH STROKE */
+ {"dtri", 0x25BF}, /* WHITE DOWN-POINTING SMALL TRIANGLE */
+ {"dtrif", 0x25BE}, /* BLACK DOWN-POINTING SMALL TRIANGLE */
+ {"dzcy", 0x045F}, /* CYRILLIC SMALL LETTER DZHE */
+ {"eDot", 0x2251}, /* GEOMETRICALLY EQUAL TO */
+ {"eacgr", 0x03AD}, /* GREEK SMALL LETTER EPSILON WITH TONOS */
+ {"eacute", 0x00E9}, /* LATIN SMALL LETTER E WITH ACUTE */
+ {"ecaron", 0x011B}, /* LATIN SMALL LETTER E WITH CARON */
+ {"ecir", 0x2256}, /* RING IN EQUAL TO */
+ {"ecirc", 0x00EA}, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+ {"ecolon", 0x2255}, /* EQUALS COLON */
+ {"ecy", 0x044D}, /* CYRILLIC SMALL LETTER E */
+ {"edot", 0x0117}, /* LATIN SMALL LETTER E WITH DOT ABOVE */
+ {"eeacgr", 0x03AE}, /* GREEK SMALL LETTER ETA WITH TONOS */
+ {"eegr", 0x03B7}, /* GREEK SMALL LETTER ETA */
+ {"efDot", 0x2252}, /* APPROXIMATELY EQUAL TO OR THE IMAGE OF */
+ {"egr", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"egrave", 0x00E8}, /* LATIN SMALL LETTER E WITH GRAVE */
+ {"egs", 0x22DD}, /* EQUAL TO OR GREATER-THAN */
+ {"ell", 0x2113}, /* SCRIPT SMALL L */
+ {"els", 0x22DC}, /* EQUAL TO OR LESS-THAN */
+ {"emacr", 0x0113}, /* LATIN SMALL LETTER E WITH MACRON */
+ {"emdash", 0x2014}, /* obsolete synonym for "mdash" 0x2014 */
+ {"empty", 0x2205}, /* EMPTY SET */
+ {"emsp", 0x2003}, /* EM SPACE */
+ {"emsp13", 0x2004}, /* THREE-PER-EM SPACE */
+ {"emsp14", 0x2005}, /* FOUR-PER-EM SPACE */
+ {"endash", 0x2013}, /* obsolete synonym for "ndash" 0x2013 */
+ {"eng", 0x014B}, /* LATIN SMALL LETTER ENG */
+ {"ensp", 0x2002}, /* EN SPACE */
+ {"eogon", 0x0119}, /* LATIN SMALL LETTER E WITH OGONEK */
+ {"epsi", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"epsilon", 0x03B5}, /* GREEK SMALL LETTER EPSILON */
+ {"epsis", 0x220A}, /* SMALL ELEMENT OF */
+ {"equals", 0x003D}, /* EQUALS SIGN */
+ {"equiv", 0x2261}, /* IDENTICAL TO */
+ {"erDot", 0x2253}, /* IMAGE OF OR APPROXIMATELY EQUAL TO */
+ {"esdot", 0x2250}, /* APPROACHES THE LIMIT */
+ {"eta", 0x03B7}, /* GREEK SMALL LETTER ETA */
+ {"eth", 0x00F0}, /* LATIN SMALL LETTER ETH */
+ {"euml", 0x00EB}, /* LATIN SMALL LETTER E WITH DIAERESIS */
+ {"excl", 0x0021}, /* EXCLAMATION MARK */
+ {"exist", 0x2203}, /* THERE EXISTS */
+ {"fcy", 0x0444}, /* CYRILLIC SMALL LETTER EF */
+ {"female", 0x2640}, /* FEMALE SIGN */
+ {"ffilig", 0xFB03}, /* LATIN SMALL LIGATURE FFI */
+ {"fflig", 0xFB00}, /* LATIN SMALL LIGATURE FF */
+ {"ffllig", 0xFB04}, /* LATIN SMALL LIGATURE FFL */
+ {"filig", 0xFB01}, /* LATIN SMALL LIGATURE FI */
+ {"flat", 0x266D}, /* MUSIC FLAT SIGN */
+ {"fllig", 0xFB02}, /* LATIN SMALL LIGATURE FL */
+ {"fnof", 0x0192}, /* LATIN SMALL LETTER F WITH HOOK */
+ {"forall", 0x2200}, /* FOR ALL */
+ {"fork", 0x22D4}, /* PITCHFORK */
+ {"frac12", 0x00BD}, /* VULGAR FRACTION ONE HALF */
+ {"frac13", 0x2153}, /* VULGAR FRACTION ONE THIRD */
+ {"frac14", 0x00BC}, /* VULGAR FRACTION ONE QUARTER */
+ {"frac15", 0x2155}, /* VULGAR FRACTION ONE FIFTH */
+ {"frac16", 0x2159}, /* VULGAR FRACTION ONE SIXTH */
+ {"frac18", 0x215B}, /* VULGAR FRACTION ONE EIGHTH */
+ {"frac23", 0x2154}, /* VULGAR FRACTION TWO THIRDS */
+ {"frac25", 0x2156}, /* VULGAR FRACTION TWO FIFTHS */
+ {"frac34", 0x00BE}, /* VULGAR FRACTION THREE QUARTERS */
+ {"frac35", 0x2157}, /* VULGAR FRACTION THREE FIFTHS */
+ {"frac38", 0x215C}, /* VULGAR FRACTION THREE EIGHTHS */
+ {"frac45", 0x2158}, /* VULGAR FRACTION FOUR FIFTHS */
+ {"frac56", 0x215A}, /* VULGAR FRACTION FIVE SIXTHS */
+ {"frac58", 0x215D}, /* VULGAR FRACTION FIVE EIGHTHS */
+ {"frac78", 0x215E}, /* VULGAR FRACTION SEVEN EIGHTHS */
+ {"frasl", 0x2044}, /* FRACTION SLASH */
+ {"frown", 0x2322}, /* FROWN */
+ {"gE", 0x2267}, /* GREATER-THAN OVER EQUAL TO */
+ {"gacute", 0x01F5}, /* LATIN SMALL LETTER G WITH ACUTE */
+ {"gamma", 0x03B3}, /* GREEK SMALL LETTER GAMMA */
+ {"gammad", 0x03DC}, /* GREEK LETTER DIGAMMA */
+ {"gbreve", 0x011F}, /* LATIN SMALL LETTER G WITH BREVE */
+ {"gcedil", 0x0123}, /* LATIN SMALL LETTER G WITH CEDILLA */
+ {"gcirc", 0x011D}, /* LATIN SMALL LETTER G WITH CIRCUMFLEX */
+ {"gcy", 0x0433}, /* CYRILLIC SMALL LETTER GHE */
+ {"gdot", 0x0121}, /* LATIN SMALL LETTER G WITH DOT ABOVE */
+ {"ge", 0x2265}, /* GREATER-THAN OR EQUAL TO */
+ {"gel", 0x22DB}, /* GREATER-THAN EQUAL TO OR LESS-THAN */
+ {"ges", 0x2265}, /* GREATER-THAN OR EQUAL TO */
+ {"ggr", 0x03B3}, /* GREEK SMALL LETTER GAMMA */
+ {"gimel", 0x2137}, /* GIMEL SYMBOL */
+ {"gjcy", 0x0453}, /* CYRILLIC SMALL LETTER GJE */
+ {"gl", 0x2277}, /* GREATER-THAN OR LESS-THAN */
+ {"gnE", 0x2269}, /* GREATER-THAN BUT NOT EQUAL TO */
+ {"gne", 0x2269}, /* GREATER-THAN BUT NOT EQUAL TO */
+ {"gnsim", 0x22E7}, /* GREATER-THAN BUT NOT EQUIVALENT TO */
+ {"grave", 0x0060}, /* GRAVE ACCENT */
+ {"gsdot", 0x22D7}, /* GREATER-THAN WITH DOT */
+ {"gsim", 0x2273}, /* GREATER-THAN OR EQUIVALENT TO */
+ {"gt", 0x003E}, /* GREATER-THAN SIGN */
+ {"gvnE", 0x2269}, /* GREATER-THAN BUT NOT EQUAL TO */
+ {"hArr", 0x21D4}, /* LEFT RIGHT DOUBLE ARROW */
+ {"hairsp", 0x200A}, /* HAIR SPACE */
+ {"half", 0x00BD}, /* VULGAR FRACTION ONE HALF */
+ {"hamilt", 0x210B}, /* SCRIPT CAPITAL H */
+ {"hardcy", 0x044A}, /* CYRILLIC SMALL LETTER HARD SIGN */
+ {"harr", 0x2194}, /* LEFT RIGHT ARROW */
+ {"harrw", 0x21AD}, /* LEFT RIGHT WAVE ARROW */
+ {"hcirc", 0x0125}, /* LATIN SMALL LETTER H WITH CIRCUMFLEX */
+ {"hearts", 0x2665}, /* BLACK HEART SUIT */
+ {"hellip", 0x2026}, /* HORIZONTAL ELLIPSIS */
+ {"hibar", 0x00AF}, /* obsolete synonym for "macr" 0x00AF */
+ {"horbar", 0x2015}, /* HORIZONTAL BAR */
+ {"hstrok", 0x0127}, /* LATIN SMALL LETTER H WITH STROKE */
+ {"hybull", 0x2043}, /* HYPHEN BULLET */
+ {"hyphen", 0x002D}, /* HYPHEN-MINUS */
+ {"iacgr", 0x03AF}, /* GREEK SMALL LETTER IOTA WITH TONOS */
+ {"iacute", 0x00ED}, /* LATIN SMALL LETTER I WITH ACUTE */
+ {"icirc", 0x00EE}, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+ {"icy", 0x0438}, /* CYRILLIC SMALL LETTER I */
+ {"idiagr", 0x0390}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TON*/
+ {"idigr", 0x03CA}, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+ {"iecy", 0x0435}, /* CYRILLIC SMALL LETTER IE */
+ {"iexcl", 0x00A1}, /* INVERTED EXCLAMATION MARK */
+ {"iff", 0x21D4}, /* LEFT RIGHT DOUBLE ARROW */
+ {"igr", 0x03B9}, /* GREEK SMALL LETTER IOTA */
+ {"igrave", 0x00EC}, /* LATIN SMALL LETTER I WITH GRAVE */
+ {"ijlig", 0x0133}, /* LATIN SMALL LIGATURE IJ */
+ {"imacr", 0x012B}, /* LATIN SMALL LETTER I WITH MACRON */
+ {"image", 0x2111}, /* BLACK-LETTER CAPITAL I */
+ {"incare", 0x2105}, /* CARE OF */
+ {"infin", 0x221E}, /* INFINITY */
+ {"inodot", 0x0131}, /* LATIN SMALL LETTER DOTLESS I */
+ {"int", 0x222B}, /* INTEGRAL */
+ {"intcal", 0x22BA}, /* INTERCALATE */
+ {"iocy", 0x0451}, /* CYRILLIC SMALL LETTER IO */
+ {"iogon", 0x012F}, /* LATIN SMALL LETTER I WITH OGONEK */
+ {"iota", 0x03B9}, /* GREEK SMALL LETTER IOTA */
+ {"iquest", 0x00BF}, /* INVERTED QUESTION MARK */
+ {"isin", 0x2208}, /* ELEMENT OF */
+ {"itilde", 0x0129}, /* LATIN SMALL LETTER I WITH TILDE */
+ {"iukcy", 0x0456}, /* CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I*/
+ {"iuml", 0x00EF}, /* LATIN SMALL LETTER I WITH DIAERESIS */
+ {"jcirc", 0x0135}, /* LATIN SMALL LETTER J WITH CIRCUMFLEX */
+ {"jcy", 0x0439}, /* CYRILLIC SMALL LETTER SHORT I */
+ {"jsercy", 0x0458}, /* CYRILLIC SMALL LETTER JE */
+ {"jukcy", 0x0454}, /* CYRILLIC SMALL LETTER UKRAINIAN IE */
+ {"kappa", 0x03BA}, /* GREEK SMALL LETTER KAPPA */
+ {"kappav", 0x03F0}, /* GREEK KAPPA SYMBOL */
+ {"kcedil", 0x0137}, /* LATIN SMALL LETTER K WITH CEDILLA */
+ {"kcy", 0x043A}, /* CYRILLIC SMALL LETTER KA */
+ {"kgr", 0x03BA}, /* GREEK SMALL LETTER KAPPA */
+ {"kgreen", 0x0138}, /* LATIN SMALL LETTER KRA */
+ {"khcy", 0x0445}, /* CYRILLIC SMALL LETTER HA */
+ {"khgr", 0x03C7}, /* GREEK SMALL LETTER CHI */
+ {"kjcy", 0x045C}, /* CYRILLIC SMALL LETTER KJE */
+ {"lAarr", 0x21DA}, /* LEFTWARDS TRIPLE ARROW */
+ {"lArr", 0x21D0}, /* LEFTWARDS DOUBLE ARROW */
+ {"lE", 0x2266}, /* LESS-THAN OVER EQUAL TO */
+ {"lacute", 0x013A}, /* LATIN SMALL LETTER L WITH ACUTE */
+ {"lagran", 0x2112}, /* SCRIPT CAPITAL L */
+ {"lambda", 0x03BB}, /* GREEK SMALL LETTER LAMDA */
+ {"lang", 0x2329}, /* LEFT-POINTING ANGLE BRACKET */
+ {"laquo", 0x00AB}, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ {"larr", 0x2190}, /* LEFTWARDS ARROW */
+ {"larr2", 0x21C7}, /* LEFTWARDS PAIRED ARROWS */
+ {"larrhk", 0x21A9}, /* LEFTWARDS ARROW WITH HOOK */
+ {"larrlp", 0x21AB}, /* LEFTWARDS ARROW WITH LOOP */
+ {"larrtl", 0x21A2}, /* LEFTWARDS ARROW WITH TAIL */
+ {"lcaron", 0x013E}, /* LATIN SMALL LETTER L WITH CARON */
+ {"lcedil", 0x013C}, /* LATIN SMALL LETTER L WITH CEDILLA */
+ {"lceil", 0x2308}, /* LEFT CEILING */
+ {"lcub", 0x007B}, /* LEFT CURLY BRACKET */
+ {"lcy", 0x043B}, /* CYRILLIC SMALL LETTER EL */
+ {"ldot", 0x22D6}, /* LESS-THAN WITH DOT */
+ {"ldquo", 0x201C}, /* LEFT DOUBLE QUOTATION MARK */
+ {"ldquor", 0x201E}, /* DOUBLE LOW-9 QUOTATION MARK */
+ {"le", 0x2264}, /* LESS-THAN OR EQUAL TO */
+ {"leg", 0x22DA}, /* LESS-THAN EQUAL TO OR GREATER-THAN */
+ {"les", 0x2264}, /* LESS-THAN OR EQUAL TO */
+ {"lfloor", 0x230A}, /* LEFT FLOOR */
+ {"lg", 0x2276}, /* LESS-THAN OR GREATER-THAN */
+ {"lgr", 0x03BB}, /* GREEK SMALL LETTER LAMDA */
+ {"lhard", 0x21BD}, /* LEFTWARDS HARPOON WITH BARB DOWNWARDS */
+ {"lharu", 0x21BC}, /* LEFTWARDS HARPOON WITH BARB UPWARDS */
+ {"lhblk", 0x2584}, /* LOWER HALF BLOCK */
+ {"ljcy", 0x0459}, /* CYRILLIC SMALL LETTER LJE */
+ {"lmidot", 0x0140}, /* LATIN SMALL LETTER L WITH MIDDLE DOT */
+ {"lnE", 0x2268}, /* LESS-THAN BUT NOT EQUAL TO */
+ {"lne", 0x2268}, /* LESS-THAN BUT NOT EQUAL TO */
+ {"lnsim", 0x22E6}, /* LESS-THAN BUT NOT EQUIVALENT TO */
+ {"lowast", 0x2217}, /* ASTERISK OPERATOR */
+ {"lowbar", 0x005F}, /* LOW LINE */
+ {"loz", 0x25CA}, /* LOZENGE */
+ {"loz", 0x2727}, /* WHITE FOUR POINTED STAR */
+ {"lozf", 0x2726}, /* BLACK FOUR POINTED STAR */
+ {"lpar", 0x0028}, /* LEFT PARENTHESIS */
+ {"lrarr2", 0x21C6}, /* LEFTWARDS ARROW OVER RIGHTWARDS ARROW */
+ {"lrhar2", 0x21CB}, /* LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON */
+ {"lrm", 0x200E}, /* LEFT-TO-RIGHT MARK */
+ {"lsaquo", 0x2039}, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ {"lsh", 0x21B0}, /* UPWARDS ARROW WITH TIP LEFTWARDS */
+ {"lsim", 0x2272}, /* LESS-THAN OR EQUIVALENT TO */
+ {"lsqb", 0x005B}, /* LEFT SQUARE BRACKET */
+ {"lsquo", 0x2018}, /* LEFT SINGLE QUOTATION MARK */
+ {"lsquor", 0x201A}, /* SINGLE LOW-9 QUOTATION MARK */
+ {"lstrok", 0x0142}, /* LATIN SMALL LETTER L WITH STROKE */
+ {"lt", 0x003C}, /* LESS-THAN SIGN */
+ {"lthree", 0x22CB}, /* LEFT SEMIDIRECT PRODUCT */
+ {"ltimes", 0x22C9}, /* LEFT NORMAL FACTOR SEMIDIRECT PRODUCT */
+ {"ltri", 0x25C3}, /* WHITE LEFT-POINTING SMALL TRIANGLE */
+ {"ltrie", 0x22B4}, /* NORMAL SUBGROUP OF OR EQUAL TO */
+ {"ltrif", 0x25C2}, /* BLACK LEFT-POINTING SMALL TRIANGLE */
+ {"lvnE", 0x2268}, /* LESS-THAN BUT NOT EQUAL TO */
+ {"macr", 0x00AF}, /* MACRON */
+ {"male", 0x2642}, /* MALE SIGN */
+ {"malt", 0x2720}, /* MALTESE CROSS */
+ {"map", 0x21A6}, /* RIGHTWARDS ARROW FROM BAR */
+ {"marker", 0x25AE}, /* BLACK VERTICAL RECTANGLE */
+ {"mcy", 0x043C}, /* CYRILLIC SMALL LETTER EM */
+ {"mdash", 0x2014}, /* EM DASH */
+ {"mgr", 0x03BC}, /* GREEK SMALL LETTER MU */
+ {"micro", 0x00B5}, /* MICRO SIGN */
+ {"mid", 0x2223}, /* DIVIDES */
+ {"middot", 0x00B7}, /* MIDDLE DOT */
+ {"minus", 0x2212}, /* MINUS SIGN */
+ {"minusb", 0x229F}, /* SQUARED MINUS */
+ {"mldr", 0x2026}, /* HORIZONTAL ELLIPSIS */
+ {"mnplus", 0x2213}, /* MINUS-OR-PLUS SIGN */
+ {"models", 0x22A7}, /* MODELS */
+ {"mu", 0x03BC}, /* GREEK SMALL LETTER MU */
+ {"mumap", 0x22B8}, /* MULTIMAP */
+ {"nVDash", 0x22AF}, /* NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNS*/
+ {"nVdash", 0x22AE}, /* DOES NOT FORCE */
+ {"nabla", 0x2207}, /* NABLA */
+ {"nacute", 0x0144}, /* LATIN SMALL LETTER N WITH ACUTE */
+ {"nap", 0x2249}, /* NOT ALMOST EQUAL TO */
+ {"napos", 0x0149}, /* LATIN SMALL LETTER N PRECEDED BY APOSTROPHE */
+ {"natur", 0x266E}, /* MUSIC NATURAL SIGN */
+ {"nbsp", 0x00A0}, /* NO-BREAK SPACE */
+ {"ncaron", 0x0148}, /* LATIN SMALL LETTER N WITH CARON */
+ {"ncedil", 0x0146}, /* LATIN SMALL LETTER N WITH CEDILLA */
+ {"ncong", 0x2247}, /* NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO */
+ {"ncy", 0x043D}, /* CYRILLIC SMALL LETTER EN */
+ {"ndash", 0x2013}, /* EN DASH */
+ {"ne", 0x2260}, /* NOT EQUAL TO */
+ {"nearr", 0x2197}, /* NORTH EAST ARROW */
+ {"nequiv", 0x2262}, /* NOT IDENTICAL TO */
+ {"nexist", 0x2204}, /* THERE DOES NOT EXIST */
+ {"nge", 0x2271}, /* NEITHER GREATER-THAN NOR EQUAL TO */
+ {"nges", 0x2271}, /* NEITHER GREATER-THAN NOR EQUAL TO */
+ {"ngr", 0x03BD}, /* GREEK SMALL LETTER NU */
+ {"ngt", 0x226F}, /* NOT GREATER-THAN */
+ {"nhArr", 0x21CE}, /* LEFT RIGHT DOUBLE ARROW WITH STROKE */
+ {"nharr", 0x21AE}, /* LEFT RIGHT ARROW WITH STROKE */
+ {"ni", 0x220B}, /* CONTAINS AS MEMBER */
+ {"njcy", 0x045A}, /* CYRILLIC SMALL LETTER NJE */
+ {"nlArr", 0x21CD}, /* LEFTWARDS DOUBLE ARROW WITH STROKE */
+ {"nlarr", 0x219A}, /* LEFTWARDS ARROW WITH STROKE */
+ {"nldr", 0x2025}, /* TWO DOT LEADER */
+ {"nle", 0x2270}, /* NEITHER LESS-THAN NOR EQUAL TO */
+ {"nles", 0x2270}, /* NEITHER LESS-THAN NOR EQUAL TO */
+ {"nlt", 0x226E}, /* NOT LESS-THAN */
+ {"nltri", 0x22EA}, /* NOT NORMAL SUBGROUP OF */
+ {"nltrie", 0x22EC}, /* NOT NORMAL SUBGROUP OF OR EQUAL TO */
+ {"nmid", 0x2224}, /* DOES NOT DIVIDE */
+ {"not", 0x00AC}, /* NOT SIGN */
+ {"notin", 0x2209}, /* NOT AN ELEMENT OF */
+ {"npar", 0x2226}, /* NOT PARALLEL TO */
+ {"npr", 0x2280}, /* DOES NOT PRECEDE */
+ {"npre", 0x22E0}, /* DOES NOT PRECEDE OR EQUAL */
+ {"nrArr", 0x21CF}, /* RIGHTWARDS DOUBLE ARROW WITH STROKE */
+ {"nrarr", 0x219B}, /* RIGHTWARDS ARROW WITH STROKE */
+ {"nrtri", 0x22EB}, /* DOES NOT CONTAIN AS NORMAL SUBGROUP */
+ {"nrtrie", 0x22ED}, /* DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL */
+ {"nsc", 0x2281}, /* DOES NOT SUCCEED */
+ {"nsce", 0x22E1}, /* DOES NOT SUCCEED OR EQUAL */
+ {"nsim", 0x2241}, /* NOT TILDE */
+ {"nsime", 0x2244}, /* NOT ASYMPTOTICALLY EQUAL TO */
+ {"nspar", 0x2226}, /* NOT PARALLEL TO */
+ {"nsub", 0x2284}, /* NOT A SUBSET OF */
+ {"nsubE", 0x2288}, /* NEITHER A SUBSET OF NOR EQUAL TO */
+ {"nsube", 0x2288}, /* NEITHER A SUBSET OF NOR EQUAL TO */
+ {"nsup", 0x2285}, /* NOT A SUPERSET OF */
+ {"nsupE", 0x2289}, /* NEITHER A SUPERSET OF NOR EQUAL TO */
+ {"nsupe", 0x2289}, /* NEITHER A SUPERSET OF NOR EQUAL TO */
+ {"ntilde", 0x00F1}, /* LATIN SMALL LETTER N WITH TILDE */
+ {"nu", 0x03BD}, /* GREEK SMALL LETTER NU */
+ {"num", 0x0023}, /* NUMBER SIGN */
+ {"numero", 0x2116}, /* NUMERO SIGN */
+ {"numsp", 0x2007}, /* FIGURE SPACE */
+ {"nvDash", 0x22AD}, /* NOT TRUE */
+ {"nvdash", 0x22AC}, /* DOES NOT PROVE */
+ {"nwarr", 0x2196}, /* NORTH WEST ARROW */
+ {"oS", 0x24C8}, /* CIRCLED LATIN CAPITAL LETTER S */
+ {"oacgr", 0x03CC}, /* GREEK SMALL LETTER OMICRON WITH TONOS */
+ {"oacute", 0x00F3}, /* LATIN SMALL LETTER O WITH ACUTE */
+ {"oast", 0x229B}, /* CIRCLED ASTERISK OPERATOR */
+ {"ocir", 0x229A}, /* CIRCLED RING OPERATOR */
+ {"ocirc", 0x00F4}, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+ {"ocy", 0x043E}, /* CYRILLIC SMALL LETTER O */
+ {"odash", 0x229D}, /* CIRCLED DASH */
+ {"odblac", 0x0151}, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+ {"odot", 0x2299}, /* CIRCLED DOT OPERATOR */
+ {"oelig", 0x0153}, /* LATIN SMALL LIGATURE OE */
+ {"ogon", 0x02DB}, /* OGONEK */
+ {"ogr", 0x03BF}, /* GREEK SMALL LETTER OMICRON */
+ {"ograve", 0x00F2}, /* LATIN SMALL LETTER O WITH GRAVE */
+ {"ohacgr", 0x03CE}, /* GREEK SMALL LETTER OMEGA WITH TONOS */
+ {"ohgr", 0x03C9}, /* GREEK SMALL LETTER OMEGA */
+ {"ohm", 0x2126}, /* OHM SIGN */
+ {"olarr", 0x21BA}, /* ANTICLOCKWISE OPEN CIRCLE ARROW */
+ {"oline", 0x203E}, /* OVERLINE */
+ {"omacr", 0x014D}, /* LATIN SMALL LETTER O WITH MACRON */
+ {"omega", 0x03C9}, /* GREEK SMALL LETTER OMEGA */
+ {"omicron", 0x03BF}, /* GREEK SMALL LETTER OMICRON */
+ {"ominus", 0x2296}, /* CIRCLED MINUS */
+ {"oplus", 0x2295}, /* CIRCLED PLUS */
+ {"or", 0x2228}, /* LOGICAL OR */
+ {"orarr", 0x21BB}, /* CLOCKWISE OPEN CIRCLE ARROW */
+ {"order", 0x2134}, /* SCRIPT SMALL O */
+ {"ordf", 0x00AA}, /* FEMININE ORDINAL INDICATOR */
+ {"ordm", 0x00BA}, /* MASCULINE ORDINAL INDICATOR */
+ {"oslash", 0x00F8}, /* LATIN SMALL LETTER O WITH STROKE */
+ {"osol", 0x2298}, /* CIRCLED DIVISION SLASH */
+ {"otilde", 0x00F5}, /* LATIN SMALL LETTER O WITH TILDE */
+ {"otimes", 0x2297}, /* CIRCLED TIMES */
+ {"ouml", 0x00F6}, /* LATIN SMALL LETTER O WITH DIAERESIS */
+ {"par", 0x2225}, /* PARALLEL TO */
+ {"para", 0x00B6}, /* PILCROW SIGN */
+ {"part", 0x2202}, /* PARTIAL DIFFERENTIAL */
+ {"pcy", 0x043F}, /* CYRILLIC SMALL LETTER PE */
+ {"percnt", 0x0025}, /* PERCENT SIGN */
+ {"period", 0x002E}, /* FULL STOP */
+ {"permil", 0x2030}, /* PER MILLE SIGN */
+ {"perp", 0x22A5}, /* UP TACK */
+ {"pgr", 0x03C0}, /* GREEK SMALL LETTER PI */
+ {"phgr", 0x03C6}, /* GREEK SMALL LETTER PHI */
+ {"phi", 0x03C6}, /* GREEK SMALL LETTER PHI */
+ {"phis", 0x03C6}, /* GREEK SMALL LETTER PHI */
+ {"phiv", 0x03D5}, /* GREEK PHI SYMBOL */
+ {"phmmat", 0x2133}, /* SCRIPT CAPITAL M */
+ {"phone", 0x260E}, /* BLACK TELEPHONE */
+ {"pi", 0x03C0}, /* GREEK SMALL LETTER PI */
+ {"piv", 0x03D6}, /* GREEK PI SYMBOL */
+ {"planck", 0x210F}, /* PLANCK CONSTANT OVER TWO PI */
+ {"plus", 0x002B}, /* PLUS SIGN */
+ {"plusb", 0x229E}, /* SQUARED PLUS */
+ {"plusdo", 0x2214}, /* DOT PLUS */
+ {"plusmn", 0x00B1}, /* PLUS-MINUS SIGN */
+ {"pound", 0x00A3}, /* POUND SIGN */
+ {"pr", 0x227A}, /* PRECEDES */
+ {"pre", 0x227C}, /* PRECEDES OR EQUAL TO */
+ {"prime", 0x2032}, /* PRIME */
+ {"prnsim", 0x22E8}, /* PRECEDES BUT NOT EQUIVALENT TO */
+ {"prod", 0x220F}, /* N-ARY PRODUCT */
+ {"prop", 0x221D}, /* PROPORTIONAL TO */
+ {"prsim", 0x227E}, /* PRECEDES OR EQUIVALENT TO */
+ {"psgr", 0x03C8}, /* GREEK SMALL LETTER PSI */
+ {"psi", 0x03C8}, /* GREEK SMALL LETTER PSI */
+ {"puncsp", 0x2008}, /* PUNCTUATION SPACE */
+ {"quest", 0x003F}, /* QUESTION MARK */
+ {"quot", 0x0022}, /* QUOTATION MARK */
+ {"rAarr", 0x21DB}, /* RIGHTWARDS TRIPLE ARROW */
+ {"rArr", 0x21D2}, /* RIGHTWARDS DOUBLE ARROW */
+ {"racute", 0x0155}, /* LATIN SMALL LETTER R WITH ACUTE */
+ {"radic", 0x221A}, /* SQUARE ROOT */
+ {"rang", 0x232A}, /* RIGHT-POINTING ANGLE BRACKET */
+ {"raquo", 0x00BB}, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ {"rarr", 0x2192}, /* RIGHTWARDS ARROW */
+ {"rarr2", 0x21C9}, /* RIGHTWARDS PAIRED ARROWS */
+ {"rarrhk", 0x21AA}, /* RIGHTWARDS ARROW WITH HOOK */
+ {"rarrlp", 0x21AC}, /* RIGHTWARDS ARROW WITH LOOP */
+ {"rarrtl", 0x21A3}, /* RIGHTWARDS ARROW WITH TAIL */
+ {"rarrw", 0x219D}, /* RIGHTWARDS WAVE ARROW */
+ {"rcaron", 0x0159}, /* LATIN SMALL LETTER R WITH CARON */
+ {"rcedil", 0x0157}, /* LATIN SMALL LETTER R WITH CEDILLA */
+ {"rceil", 0x2309}, /* RIGHT CEILING */
+ {"rcub", 0x007D}, /* RIGHT CURLY BRACKET */
+ {"rcy", 0x0440}, /* CYRILLIC SMALL LETTER ER */
+ {"rdquo", 0x201D}, /* RIGHT DOUBLE QUOTATION MARK */
+ {"rdquor", 0x201C}, /* LEFT DOUBLE QUOTATION MARK */
+ {"real", 0x211C}, /* BLACK-LETTER CAPITAL R */
+ {"rect", 0x25AD}, /* WHITE RECTANGLE */
+ {"reg", 0x00AE}, /* REGISTERED SIGN */
+ {"rfloor", 0x230B}, /* RIGHT FLOOR */
+ {"rgr", 0x03C1}, /* GREEK SMALL LETTER RHO */
+ {"rhard", 0x21C1}, /* RIGHTWARDS HARPOON WITH BARB DOWNWARDS */
+ {"rharu", 0x21C0}, /* RIGHTWARDS HARPOON WITH BARB UPWARDS */
+ {"rho", 0x03C1}, /* GREEK SMALL LETTER RHO */
+ {"rhov", 0x03F1}, /* GREEK RHO SYMBOL */
+ {"ring", 0x02DA}, /* RING ABOVE */
+ {"rlarr2", 0x21C4}, /* RIGHTWARDS ARROW OVER LEFTWARDS ARROW */
+ {"rlhar2", 0x21CC}, /* RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON */
+ {"rlm", 0x200F}, /* RIGHT-TO-LEFT MARK */
+ {"rpar", 0x0029}, /* RIGHT PARENTHESIS */
+ {"rsaquo", 0x203A}, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ {"rsh", 0x21B1}, /* UPWARDS ARROW WITH TIP RIGHTWARDS */
+ {"rsqb", 0x005D}, /* RIGHT SQUARE BRACKET */
+ {"rsquo", 0x2019}, /* RIGHT SINGLE QUOTATION MARK */
+ {"rsquor", 0x2018}, /* LEFT SINGLE QUOTATION MARK */
+ {"rthree", 0x22CC}, /* RIGHT SEMIDIRECT PRODUCT */
+ {"rtimes", 0x22CA}, /* RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT */
+ {"rtri", 0x25B9}, /* WHITE RIGHT-POINTING SMALL TRIANGLE */
+ {"rtrie", 0x22B5}, /* CONTAINS AS NORMAL SUBGROUP OR EQUAL TO */
+ {"rtrif", 0x25B8}, /* BLACK RIGHT-POINTING SMALL TRIANGLE */
+ {"rx", 0x211E}, /* PRESCRIPTION TAKE */
+ {"sacute", 0x015B}, /* LATIN SMALL LETTER S WITH ACUTE */
+ {"samalg", 0x2210}, /* N-ARY COPRODUCT */
+ {"sbquo", 0x201A}, /* SINGLE LOW-9 QUOTATION MARK */
+ {"sbsol", 0x005C}, /* REVERSE SOLIDUS */
+ {"sc", 0x227B}, /* SUCCEEDS */
+ {"scaron", 0x0161}, /* LATIN SMALL LETTER S WITH CARON */
+ {"sccue", 0x227D}, /* SUCCEEDS OR EQUAL TO */
+ {"sce", 0x227D}, /* SUCCEEDS OR EQUAL TO */
+ {"scedil", 0x015F}, /* LATIN SMALL LETTER S WITH CEDILLA */
+ {"scirc", 0x015D}, /* LATIN SMALL LETTER S WITH CIRCUMFLEX */
+ {"scnsim", 0x22E9}, /* SUCCEEDS BUT NOT EQUIVALENT TO */
+ {"scsim", 0x227F}, /* SUCCEEDS OR EQUIVALENT TO */
+ {"scy", 0x0441}, /* CYRILLIC SMALL LETTER ES */
+ {"sdot", 0x22C5}, /* DOT OPERATOR */
+ {"sdotb", 0x22A1}, /* SQUARED DOT OPERATOR */
+ {"sect", 0x00A7}, /* SECTION SIGN */
+ {"semi", 0x003B}, /* SEMICOLON */
+ {"setmn", 0x2216}, /* SET MINUS */
+ {"sext", 0x2736}, /* SIX POINTED BLACK STAR */
+ {"sfgr", 0x03C2}, /* GREEK SMALL LETTER FINAL SIGMA */
+ {"sfrown", 0x2322}, /* FROWN */
+ {"sgr", 0x03C3}, /* GREEK SMALL LETTER SIGMA */
+ {"sharp", 0x266F}, /* MUSIC SHARP SIGN */
+ {"shchcy", 0x0449}, /* CYRILLIC SMALL LETTER SHCHA */
+ {"shcy", 0x0448}, /* CYRILLIC SMALL LETTER SHA */
+ {"shy", 0x00AD}, /* SOFT HYPHEN */
+ {"sigma", 0x03C3}, /* GREEK SMALL LETTER SIGMA */
+ {"sigmaf", 0x03C2}, /* GREEK SMALL LETTER FINAL SIGMA */
+ {"sigmav", 0x03C2}, /* GREEK SMALL LETTER FINAL SIGMA */
+ {"sim", 0x223C}, /* TILDE OPERATOR */
+ {"sime", 0x2243}, /* ASYMPTOTICALLY EQUAL TO */
+ {"smile", 0x2323}, /* SMILE */
+ {"softcy", 0x044C}, /* CYRILLIC SMALL LETTER SOFT SIGN */
+ {"sol", 0x002F}, /* SOLIDUS */
+ {"spades", 0x2660}, /* BLACK SPADE SUIT */
+ {"spar", 0x2225}, /* PARALLEL TO */
+ {"sqcap", 0x2293}, /* SQUARE CAP */
+ {"sqcup", 0x2294}, /* SQUARE CUP */
+ {"sqsub", 0x228F}, /* SQUARE IMAGE OF */
+ {"sqsube", 0x2291}, /* SQUARE IMAGE OF OR EQUAL TO */
+ {"sqsup", 0x2290}, /* SQUARE ORIGINAL OF */
+ {"sqsupe", 0x2292}, /* SQUARE ORIGINAL OF OR EQUAL TO */
+ {"squ", 0x25A1}, /* WHITE SQUARE */
+ {"square", 0x25A1}, /* WHITE SQUARE */
+ {"squf", 0x25AA}, /* BLACK SMALL SQUARE */
+ {"ssetmn", 0x2216}, /* SET MINUS */
+ {"ssmile", 0x2323}, /* SMILE */
+ {"sstarf", 0x22C6}, /* STAR OPERATOR */
+ {"star", 0x2606}, /* WHITE STAR */
+ {"starf", 0x2605}, /* BLACK STAR */
+ {"sub", 0x2282}, /* SUBSET OF */
+ {"subE", 0x2286}, /* SUBSET OF OR EQUAL TO */
+ {"sube", 0x2286}, /* SUBSET OF OR EQUAL TO */
+ {"subnE", 0x228A}, /* SUBSET OF WITH NOT EQUAL TO */
+ {"subne", 0x228A}, /* SUBSET OF WITH NOT EQUAL TO */
+ {"sum", 0x2211}, /* N-ARY SUMMATION */
+ {"sung", 0x266A}, /* EIGHTH NOTE */
+ {"sup", 0x2283}, /* SUPERSET OF */
+ {"sup1", 0x00B9}, /* SUPERSCRIPT ONE */
+ {"sup2", 0x00B2}, /* SUPERSCRIPT TWO */
+ {"sup3", 0x00B3}, /* SUPERSCRIPT THREE */
+ {"supE", 0x2287}, /* SUPERSET OF OR EQUAL TO */
+ {"supe", 0x2287}, /* SUPERSET OF OR EQUAL TO */
+ {"supnE", 0x228B}, /* SUPERSET OF WITH NOT EQUAL TO */
+ {"supne", 0x228B}, /* SUPERSET OF WITH NOT EQUAL TO */
+ {"szlig", 0x00DF}, /* LATIN SMALL LETTER SHARP S */
+ {"target", 0x2316}, /* POSITION INDICATOR */
+ {"tau", 0x03C4}, /* GREEK SMALL LETTER TAU */
+ {"tcaron", 0x0165}, /* LATIN SMALL LETTER T WITH CARON */
+ {"tcedil", 0x0163}, /* LATIN SMALL LETTER T WITH CEDILLA */
+ {"tcy", 0x0442}, /* CYRILLIC SMALL LETTER TE */
+ {"tdot", 0x20DB}, /* COMBINING THREE DOTS ABOVE */
+ {"telrec", 0x2315}, /* TELEPHONE RECORDER */
+ {"tgr", 0x03C4}, /* GREEK SMALL LETTER TAU */
+ {"there4", 0x2234}, /* THEREFORE */
+ {"theta", 0x03B8}, /* GREEK SMALL LETTER THETA */
+ {"thetas", 0x03B8}, /* GREEK SMALL LETTER THETA */
+ {"thetasym", 0x03D1}, /* GREEK THETA SYMBOL */
+ {"thetav", 0x03D1}, /* GREEK THETA SYMBOL */
+ {"thgr", 0x03B8}, /* GREEK SMALL LETTER THETA */
+ {"thinsp", 0x2009}, /* THIN SPACE */
+ {"thkap", 0x2248}, /* ALMOST EQUAL TO */
+ {"thksim", 0x223C}, /* TILDE OPERATOR */
+ {"thorn", 0x00FE}, /* LATIN SMALL LETTER THORN */
+ {"tilde", 0x02DC}, /* SMALL TILDE */
+ {"times", 0x00D7}, /* MULTIPLICATION SIGN */
+ {"timesb", 0x22A0}, /* SQUARED TIMES */
+ {"top", 0x22A4}, /* DOWN TACK */
+ {"tprime", 0x2034}, /* TRIPLE PRIME */
+ {"trade", 0x2122}, /* TRADE MARK SIGN */
+ {"trie", 0x225C}, /* DELTA EQUAL TO */
+ {"tscy", 0x0446}, /* CYRILLIC SMALL LETTER TSE */
+ {"tshcy", 0x045B}, /* CYRILLIC SMALL LETTER TSHE */
+ {"tstrok", 0x0167}, /* LATIN SMALL LETTER T WITH STROKE */
+ {"twixt", 0x226C}, /* BETWEEN */
+ {"uArr", 0x21D1}, /* UPWARDS DOUBLE ARROW */
+ {"uacgr", 0x03CD}, /* GREEK SMALL LETTER UPSILON WITH TONOS */
+ {"uacute", 0x00FA}, /* LATIN SMALL LETTER U WITH ACUTE */
+ {"uarr", 0x2191}, /* UPWARDS ARROW */
+ {"uarr2", 0x21C8}, /* UPWARDS PAIRED ARROWS */
+ {"ubrcy", 0x045E}, /* CYRILLIC SMALL LETTER SHORT U */
+ {"ubreve", 0x016D}, /* LATIN SMALL LETTER U WITH BREVE */
+ {"ucirc", 0x00FB}, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+ {"ucy", 0x0443}, /* CYRILLIC SMALL LETTER U */
+ {"udblac", 0x0171}, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+ {"udiagr", 0x03B0}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND */
+ {"udigr", 0x03CB}, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+ {"ugr", 0x03C5}, /* GREEK SMALL LETTER UPSILON */
+ {"ugrave", 0x00F9}, /* LATIN SMALL LETTER U WITH GRAVE */
+ {"uharl", 0x21BF}, /* UPWARDS HARPOON WITH BARB LEFTWARDS */
+ {"uharr", 0x21BE}, /* UPWARDS HARPOON WITH BARB RIGHTWARDS */
+ {"uhblk", 0x2580}, /* UPPER HALF BLOCK */
+ {"ulcorn", 0x231C}, /* TOP LEFT CORNER */
+ {"ulcrop", 0x230F}, /* TOP LEFT CROP */
+ {"umacr", 0x016B}, /* LATIN SMALL LETTER U WITH MACRON */
+ {"uml", 0x00A8}, /* DIAERESIS */
+ {"uogon", 0x0173}, /* LATIN SMALL LETTER U WITH OGONEK */
+ {"uplus", 0x228E}, /* MULTISET UNION */
+ {"upsi", 0x03C5}, /* GREEK SMALL LETTER UPSILON */
+ {"upsih", 0x03D2}, /* GREEK UPSILON WITH HOOK SYMBOL */
+ {"upsilon", 0x03C5}, /* GREEK SMALL LETTER UPSILON */
+ {"urcorn", 0x231D}, /* TOP RIGHT CORNER */
+ {"urcrop", 0x230E}, /* TOP RIGHT CROP */
+ {"uring", 0x016F}, /* LATIN SMALL LETTER U WITH RING ABOVE */
+ {"utilde", 0x0169}, /* LATIN SMALL LETTER U WITH TILDE */
+ {"utri", 0x25B5}, /* WHITE UP-POINTING SMALL TRIANGLE */
+ {"utrif", 0x25B4}, /* BLACK UP-POINTING SMALL TRIANGLE */
+ {"uuml", 0x00FC}, /* LATIN SMALL LETTER U WITH DIAERESIS */
+ {"vArr", 0x21D5}, /* UP DOWN DOUBLE ARROW */
+ {"vDash", 0x22A8}, /* TRUE */
+ {"varr", 0x2195}, /* UP DOWN ARROW */
+ {"vcy", 0x0432}, /* CYRILLIC SMALL LETTER VE */
+ {"vdash", 0x22A2}, /* RIGHT TACK */
+ {"veebar", 0x22BB}, /* XOR */
+ {"vellip", 0x22EE}, /* VERTICAL ELLIPSIS */
+ {"verbar", 0x007C}, /* VERTICAL LINE */
+ {"vltri", 0x22B2}, /* NORMAL SUBGROUP OF */
+ {"vprime", 0x2032}, /* PRIME */
+ {"vprop", 0x221D}, /* PROPORTIONAL TO */
+ {"vrtri", 0x22B3}, /* CONTAINS AS NORMAL SUBGROUP */
+ {"vsubnE", 0x228A}, /* SUBSET OF WITH NOT EQUAL TO */
+ {"vsubne", 0x228A}, /* SUBSET OF WITH NOT EQUAL TO */
+ {"vsupnE", 0x228B}, /* SUPERSET OF WITH NOT EQUAL TO */
+ {"vsupne", 0x228B}, /* SUPERSET OF WITH NOT EQUAL TO */
+ {"wcirc", 0x0175}, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */
+ {"wedgeq", 0x2259}, /* ESTIMATES */
+ {"weierp", 0x2118}, /* SCRIPT CAPITAL P */
+ {"wreath", 0x2240}, /* WREATH PRODUCT */
+ {"xcirc", 0x25CB}, /* WHITE CIRCLE */
+ {"xdtri", 0x25BD}, /* WHITE DOWN-POINTING TRIANGLE */
+ {"xgr", 0x03BE}, /* GREEK SMALL LETTER XI */
+ {"xhArr", 0x2194}, /* LEFT RIGHT ARROW */
+ {"xharr", 0x2194}, /* LEFT RIGHT ARROW */
+ {"xi", 0x03BE}, /* GREEK SMALL LETTER XI */
+ {"xlArr", 0x21D0}, /* LEFTWARDS DOUBLE ARROW */
+ {"xrArr", 0x21D2}, /* RIGHTWARDS DOUBLE ARROW */
+ {"xutri", 0x25B3}, /* WHITE UP-POINTING TRIANGLE */
+ {"yacute", 0x00FD}, /* LATIN SMALL LETTER Y WITH ACUTE */
+ {"yacy", 0x044F}, /* CYRILLIC SMALL LETTER YA */
+ {"ycirc", 0x0177}, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */
+ {"ycy", 0x044B}, /* CYRILLIC SMALL LETTER YERU */
+ {"yen", 0x00A5}, /* YEN SIGN */
+ {"yicy", 0x0457}, /* CYRILLIC SMALL LETTER YI */
+ {"yucy", 0x044E}, /* CYRILLIC SMALL LETTER YU */
+ {"yuml", 0x00FF}, /* LATIN SMALL LETTER Y WITH DIAERESIS */
+ {"zacute", 0x017A}, /* LATIN SMALL LETTER Z WITH ACUTE */
+ {"zcaron", 0x017E}, /* LATIN SMALL LETTER Z WITH CARON */
+ {"zcy", 0x0437}, /* CYRILLIC SMALL LETTER ZE */
+ {"zdot", 0x017C}, /* LATIN SMALL LETTER Z WITH DOT ABOVE */
+ {"zeta", 0x03B6}, /* GREEK SMALL LETTER ZETA */
+ {"zgr", 0x03B6}, /* GREEK SMALL LETTER ZETA */
+ {"zhcy", 0x0436}, /* CYRILLIC SMALL LETTER ZHE */
+ {"zwj", 0x200D}, /* ZERO WIDTH JOINER */
+ {"zwnj", 0x200C}, /* ZERO WIDTH NON-JOINER */
+/* {"epsiv", 0x????}, variant epsilon # ISOgrk3 */
+/* {"fjlig", 0x????}, fj ligature # ISOpub */
+/* {"gEl", 0x????}, greater-than, double equals, less-than # ISOamsr */
+/* {"gap", 0x????}, greater-than, approximately equal to # ISOamsr */
+/* {"gnap", 0x????}, greater-than, not approximately equal t# ISOamsn */
+/* {"jnodot", 0x????}, latin small letter dotless j # ISOamso */
+/* {"lEg", 0x????}, less-than, double equals, greater-than # ISOamsr */
+/* {"lap", 0x????}, less-than, approximately equal to # ISOamsr */
+/* {"lnap", 0x????}, less-than, not approximately equal to # ISOamsn */
+/* {"lpargt", 0x????}, left parenthesis, greater-than # ISOamsc */
+/* {"ngE", 0x????}, not greater-than, double equals # ISOamsn */
+/* {"nlE", 0x????}, not less-than, double equals # ISOamsn */
+/* {"nsmid", 0x????}, nshortmid # ISOamsn */
+/* {"prap", 0x????}, precedes, approximately equal to # ISOamsr */
+/* {"prnE", 0x????}, precedes, not double equal # ISOamsn */
+/* {"prnap", 0x????}, precedes, not approximately equal to # ISOamsn */
+/* {"rpargt", 0x????}, right parenthesis, greater-than # ISOamsc */
+/* {"scap", 0x????}, succeeds, approximately equal to # ISOamsr */
+/* {"scnE", 0x????}, succeeds, not double equals # ISOamsn */
+/* {"scnap", 0x????}, succeeds, not approximately equal to # ISOamsn */
+/* {"smid", 0x????}, shortmid # ISOamsr */
+};
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/getline.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/getline.c
new file mode 100644
index 00000000000..7f6ff038ceb
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/getline.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* CHANGED FOR VMS */
+
+/*
+ * <getline.c>
+ */
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include <stddef.h>
+
+#include "LYLeaks.h"
+
+/* Read up to (and including) a newline from STREAM into *LINEPTR
+ (and null-terminate it). *LINEPTR is a pointer returned from malloc (or
+ NULL), pointing to *N characters of space. It is realloc'd as
+ necessary. Returns the number of characters read (not including the
+ null terminator), or -1 on error or EOF. */
+
+int getline(char **lineptr, size_t *n, FILE *stream)
+{
+static char line[256];
+char *ptr;
+unsigned int len;
+
+ if (lineptr == NULL || n == NULL)
+ {
+ SOCKET_ERRNO = EINVAL;
+ return -1;
+ }
+
+ if (ferror (stream))
+ return -1;
+
+ if (feof(stream))
+ return -1;
+
+ fgets(line,256,stream);
+
+ ptr = strchr(line,'\n');
+ if (ptr)
+ *ptr = '\0';
+
+ len = strlen(line);
+
+ if ((len+1) < 256)
+ {
+ ptr = realloc(*lineptr, 256);
+ if (ptr == NULL)
+ return(-1);
+ *lineptr = ptr;
+ *n = 256;
+ }
+
+ strcpy(*lineptr,line);
+ return(len);
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/getpass.c b/gnu/usr.bin/lynx/WWW/Library/Implementation/getpass.c
new file mode 100644
index 00000000000..a7f0de7b247
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/getpass.c
@@ -0,0 +1,64 @@
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* CHANGED FOR VMS */
+
+/*
+ * <getpass.c>
+ */
+
+#include "HTUtils.h"
+/*#include <stdio.h> included by HTUtils.h -- FM */
+#include <descrip.h>
+#include <psldef.h>
+#include <iodef.h>
+#include <starlet.h>
+
+#include "LYLeaks.h"
+
+PUBLIC char * getpass ARGS1(CONST char *, prompt)
+{
+ static char *buf;
+
+ int result;
+ $DESCRIPTOR(devnam,"SYS$INPUT");
+ int chan;
+ int promptlen;
+ struct {
+ short result;
+ short count;
+ int info;
+ } iosb;
+
+ promptlen = strlen(prompt);
+
+ buf = (char *)malloc(256);
+ if (buf == NULL)
+ return(NULL);
+
+ result = sys$assign(&devnam, &chan, PSL$C_USER, 0, 0);
+
+ result = sys$qiow(0, chan, IO$_READPROMPT | IO$M_PURGE |IO$M_NOECHO, &iosb, 0, 0,
+ buf, 255, 0, 0, prompt, promptlen);
+
+ buf[iosb.count] = '\0';
+
+ result = sys$dassgn(chan);
+
+ return buf;
+}
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/patchlevel.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/patchlevel.h
new file mode 100644
index 00000000000..c37c8654d32
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/patchlevel.h
@@ -0,0 +1,24 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 1992, Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @(#)patchlevel.h 1.11 7/15/92
+ *
+ */
+
+#define PATCHLEVEL "UFC-crypt, patchlevel 1e, @(#)patchlevel.h 1.11 7/15/92"
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/tcp.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/tcp.h
new file mode 100644
index 00000000000..7dde5f34b16
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/tcp.h
@@ -0,0 +1,681 @@
+/* System dependencies in the W3 library
+ SYSTEM DEPENDENCIES
+
+ System-system differences for TCP include files and macros. This
+ file includes for each system the files necessary for network and
+ file I/O. It should be used in conjunction with HTUtils.h to help
+ ensure portability across as many platforms and flavors of platforms
+ as possible.
+
+ AUTHORS
+
+ TBL Tim Berners-Lee, W3 project, CERN, <timbl@info.cern.ch>
+ EvA Eelco van Asperen <evas@cs.few.eur.nl>
+ MA Marc Andreessen NCSA
+ AT Aleksandar Totic <atotic@ncsa.uiuc.edu>
+ SCW Susan C. Weber <sweber@kyle.eitech.com>
+
+ HISTORY:
+ 22 Feb 91 Written (TBL) as part of the WWW library.
+ 16 Jan 92 PC code from EvA
+ 22 Apr 93 Merged diffs bits from xmosaic release
+ 29 Apr 93 Windows/NT code from SCW
+ 20 May 94 A.Harper Add support for VMS CMU TCP/IP transport
+ 3 Oct 94 A.Harper Add support for VMS SOCKETSHR/NETLIB
+ 15 Jul 95 S. Bjorndahl Gnu C for VMS Globaldef/ref support
+
+*/
+
+#ifndef TCP_H
+#define TCP_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* !HTUTILS_H */
+
+/*
+
+Default values
+
+ These values may be reset and altered by system-specific sections
+ later on. there are also a bunch of defaults at the end .
+
+ */
+/* Default values of those: */
+#define NETCLOSE close /* Routine to close a TCP-IP socket */
+#define NETREAD HTDoRead /* Routine to read from a TCP-IP socket */
+#define NETWRITE write /* Routine to write to a TCP-IP socket */
+#define SOCKET_READ read /* normal socket read routine */
+#define IOCTL ioctl /* normal ioctl routine for sockets */
+#define SOCKET_ERRNO errno /* normal socket errno */
+
+/* Unless stated otherwise, */
+#define SELECT /* Can handle >1 channel. */
+#define GOT_SYSTEM /* Can call shell with string */
+
+#ifdef unix
+#define GOT_PIPE
+#endif /* unix */
+
+typedef struct sockaddr_in SockA; /* See netinet/in.h */
+
+
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif /* !STDIO_H */
+
+#ifndef VMS
+#include <sys/types.h>
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define D_NAMLEN(dirent) strlen((dirent)->d_name)
+# define STRUCT_DIRENT struct dirent
+#else
+# define D_NAMLEN(dirent) (dirent)->d_namlen
+# define STRUCT_DIRENT struct direct
+# define direct dirent /* FIXME */
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+#endif /* !VMS */
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#ifdef _AIX
+#define AIX
+#endif /* _AIX */
+#ifdef AIX
+#define unix
+#endif /* AIX */
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif
+
+#if HAVE_STRING_H
+#include <string.h> /* For bzero etc */
+#endif /* HAVE_STRING_H */
+
+/*
+
+ M ACROS FOR CONVERTING CHARACTERS
+
+ */
+#ifndef TOASCII
+#define TOASCII(c) (c)
+#define FROMASCII(c) (c)
+#endif /* !TOASCII */
+
+
+/*
+IBM-PC running Windows NT
+
+ These parameters providede by Susan C. Weber <sweber@kyle.eitech.com>.
+*/
+
+#ifdef _WINDOWS
+#include "fcntl.h" /* For HTFile.c */
+#include "sys\types.h" /* For HTFile.c */
+#include "sys\stat.h" /* For HTFile.c */
+#undef NETREAD
+#undef NETWRITE
+#undef NETCLOSE
+#undef IOCTL
+#define NETREAD(s,b,l) recv((s),(b),(l),0)
+#define NETWRITE(s,b,l) send((s),(b),(l),0)
+#define NETCLOSE(s) closesocket(s)
+#define IOCTL ioctlsocket
+#include <io.h>
+#include <string.h>
+#include <process.h>
+#include <time.h>
+#include <errno.h>
+#include <direct.h>
+#include <stdio.h>
+#include <winsock.h>
+typedef struct sockaddr_in SockA; /* See netinet/in.h */
+#define EINPROGRESS (WSABASEERR+36)
+#define EALREADY (WSABASEERR+37)
+#define EISCONN (WSABASEERR+56)
+#define EINTR (WSABASEERR+4)
+#define EAGAIN (WSABASEERR+1002)
+#define ENOTCONN (WSABASEERR+57)
+#define ECONNRESET (WSABASEERR+54)
+#define EINVAL 22
+#define INCLUDES_DONE
+#define TCP_INCLUDES_DONE
+#endif /* WINDOWS */
+
+
+
+/*
+
+VAX/VMS
+
+ Under VMS, there are many versions of TCP-IP. Define one if you do
+ not use Digital's UCX product:
+
+ UCX DEC's "Ultrix connection" (default)
+ CMU_TCP Available via FTP from sacusr.mp.usbr.gov
+ SOCKETSHR Eckhart Meyer's interface to NETLIB
+ WIN_TCP From Wollongong, now GEC software.
+ MULTINET From SRI, became TGV, then Cisco.
+ DECNET Cern's TCP socket emulation over DECnet
+
+ The last three do not interfere with the
+ unix i/o library, and so they need special calls to read, write and
+ close sockets. In these cases the socket number is a VMS channel
+ number, so we make the @@@ HORRIBLE @@@ assumption that a channel
+ number will be greater than 10 but a unix file descriptor less than
+ 10. It works.
+
+ */
+#ifdef VMS
+
+#ifdef UCX
+#undef IOCTL
+#define IOCTL HTioctl
+#endif /* UCX */
+
+#ifdef WIN_TCP
+#undef SOCKET_READ
+#undef NETWRITE
+#undef NETCLOSE
+#define SOCKET_READ(s,b,l) ((s)>10 ? netread((s),(b),(l)) : read((s),(b),(l)))
+#define NETWRITE(s,b,l) ((s)>10 ? netwrite((s),(b),(l)) : write((s),(b),(l)))
+#define NETCLOSE(s) ((s)>10 ? netclose(s) : close(s))
+#undef IOCTL
+#define IOCTL(a,b,c) -1 /* disables ioctl function */
+#define NO_IOCTL /* flag to check if ioctl is disabled */
+#endif /* WIN_TCP */
+
+#ifdef CMU_TCP
+#undef SOCKET_READ
+#undef NETREAD
+#undef NETWRITE
+#undef NETCLOSE
+#define SOCKET_READ(s,b,l) (cmu_get_sdc((s)) != 0 ? cmu_read((s),(b),(l)) : read((s),(b),(l)))
+#define NETREAD(s,b,l) (cmu_get_sdc((s)) != 0 ? HTDoRead((s),(b),(l)) : read((s),(b),(l)))
+#define NETWRITE(s,b,l) (cmu_get_sdc((s)) != 0 ? cmu_write((s),(b),(l)) : write((s),(b),(l)))
+#define NETCLOSE(s) (cmu_get_sdc((s)) != 0 ? cmu_close((s)) : close((s)))
+#endif /* CMU_TCP */
+
+#ifdef MULTINET
+#undef NETCLOSE
+#undef SOCKET_READ
+#undef NETWRITE
+#undef IOCTL
+#undef SOCKET_ERRNO
+/*
+** Delete these socket_foo() prototypes as MultiNet adds them
+** to it's socket library headers. Compiler warnings due to
+** the absence of arguments in the generic prototypes here will
+** include the names of those which can be deleted. - FM
+*/
+extern int socket_read();
+extern int socket_write();
+extern int socket_close();
+extern int socket_ioctl();
+
+#define SOCKET_READ(s,b,l) ((s)>10 ? socket_read((s),(b),(l)) : \
+ read((s),(b),(l)))
+#define NETWRITE(s,b,l) ((s)>10 ? socket_write((s),(b),(l)) : \
+ write((s),(b),(l)))
+#define NETCLOSE(s) ((s)>10 ? socket_close(s) : close(s))
+#define IOCTL socket_ioctl
+#define SOCKET_ERRNO socket_errno
+#endif /* MULTINET */
+
+#ifdef SOCKETSHR_TCP
+#undef SOCKET_READ
+#undef NETREAD
+#undef NETWRITE
+#undef NETCLOSE
+#undef IOCTL
+#define SOCKET_READ(s,b,l) (si_get_sdc((s)) != 0 ? si_read((s),(b),(l)) : \
+ read((s),(b),(l)))
+#define NETREAD(s,b,l) (si_get_sdc((s)) != 0 ? HTDoRead((s),(b),(l)) : \
+ read((s),(b),(l)))
+#define NETWRITE(s,b,l) (si_get_sdc((s)) != 0 ? si_write((s),(b),(l)) : \
+ write((s),(b),(l)))
+#define NETCLOSE(s) (si_get_sdc((s)) != 0 ? si_close((s)) : close((s)))
+#define IOCTL si_ioctl
+#endif /* SOCKETSHR_TCP */
+
+#include <string.h>
+
+#ifndef STDIO_H
+#include <stdio.h>
+#define STDIO_H
+#endif /* !STDIO_H */
+
+#include <file.h>
+#include <stat.h>
+#include <unixio.h>
+#include <unixlib.h>
+
+#define INCLUDES_DONE
+
+#ifdef MULTINET /* Include from standard Multinet directories */
+/*
+** Delete any of these multinet_foo() and associated prototypes
+** as MultiNet adds them to its socket library headers. You'll
+** get compiler warnings about them, due the absence of arguments
+** in the generic prototyping here, and the warnings will include
+** the names of the functions whose prototype entries can be
+** deleted here. - FM
+*/
+extern int multinet_accept();
+extern int multinet_bind();
+extern int bzero();
+extern int multinet_connect();
+extern int multinet_gethostname();
+extern int multinet_getsockname();
+extern unsigned short multinet_htons(unsigned short __val);
+extern unsigned short multinet_ntohs(unsigned short __val);
+extern int multinet_listen();
+extern int multinet_select();
+extern int multinet_socket();
+extern char *vms_errno_string();
+
+#ifndef __SOCKET_TYPEDEFS
+#define __SOCKET_TYPEDEFS 1
+#endif /* !__SOCKET_TYPEDEFS */
+#include <time.h>
+#include <types.h>
+#ifdef __TIME_T
+#define __TYPES 1
+#define __TYPES_LOADED 1
+#endif /* __TIME_T */
+#ifdef __SOCKET_TYPEDEFS
+#undef __SOCKET_TYPEDEFS
+#endif /* __SOCKET_TYPEDEFS */
+#include "multinet_root:[multinet.include.sys]types.h"
+#ifndef __SOCKET_TYPEDEFS
+#define __SOCKET_TYPEDEFS 1
+#endif /* !__SOCKET_TYPEDEFS */
+#include "multinet_root:[multinet.include]errno.h"
+#ifdef __TYPES
+#define __TIME_T 1
+#endif /* __TYPE */
+#ifdef __TIME_LOADED
+#define __TIME 1 /* to avoid double definitions in in.h */
+#endif /* __TIME_LOADED */
+#include "multinet_root:[multinet.include.sys]time.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.arpa]inet.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include.sys]ioctl.h"
+#define TCP_INCLUDES_DONE
+/*
+** Uncomment this if you get compiler messages
+** about struct timeval having no linkage. - FM
+*/
+/*#define NO_TIMEVAL*/
+#ifdef NO_TIMEVAL
+struct timeval {
+ long tv_sec; /* seconds since Jan. 1, 1970 */
+ long tv_usec; /* microseconds */
+};
+#endif /* NO_TIMEVAL */
+#endif /* MULTINET */
+
+
+#ifdef DECNET
+#include <types.h>
+#include <errno.h>
+#include <time.h>
+#include "types.h" /* for socket.h */
+#include "socket.h"
+#include "dn"
+#include "dnetdb"
+/* #include "vms.h" */
+#define TCP_INCLUDES_DONE
+#endif /* DECNET */
+
+
+#ifdef UCX
+#include <types.h>
+#include <errno.h>
+#include <time.h>
+#include <socket.h>
+#include <in.h>
+#include <inet.h>
+#if defined(TCPWARE) && !defined(__DECC)
+#include "tcpware_include:netdb.h"
+#include "tcpware_include:ucx$inetdef.h"
+#else
+#include <netdb.h>
+#include <ucx$inetdef.h>
+#endif /* TCPWARE */
+#define TCP_INCLUDES_DONE
+#endif /* UCX */
+
+
+#ifdef CMU_TCP
+#include <types.h>
+#include <errno.h>
+#include "cmuip_root:[syslib]time.h"
+#include "cmuip_root:[syslib]socket.h"
+#include <in.h>
+#include <inet.h>
+#include <netdb.h>
+#include "cmuip_root:[syslib]ioctl.h"
+#define TCP_INCLUDES_DONE
+#endif /* CMU_TCP */
+
+
+#ifdef SOCKETSHR_TCP
+#include <types.h>
+#include <errno.h>
+#include <time.h>
+#include <socket.h>
+#include <in.h>
+#include <inet.h>
+#include <netdb.h>
+#include "socketshr_library:socketshr.h"
+#include "socketshr_library:ioctl.h"
+#define TCP_INCLUDES_DONE
+#endif /* SOCKETSHR_TCP */
+
+#ifdef WIN_TCP
+#include <types.h>
+#include <errno.h>
+#include <time.h>
+#include <socket.h>
+#include <in.h>
+#include <inet.h>
+#include <netdb.h>
+#ifndef NO_IOCTL
+#include <ioctl.h>
+#endif /* !NO_IOCTL */
+#define TCP_INCLUDES_DONE
+#endif /* WIN_TCP */
+
+#ifndef TCP_INCLUDES_DONE
+#include <types.h>
+#include <errno.h>
+#include <time.h>
+#ifdef VMS_SOCKET_HEADERS
+/*
+** Not all versions of VMS have the full set of headers
+** for socket library functions, because the TCP/IP
+** packages were layered products. If we want these
+** specifically, instead of those for the above packages,
+** the module should be compiled with VMS_SOCKET_HEADERS
+** defined instead of layered product definitions, above.
+** If the module is not using socket library functions,
+** none of the definitions need be used, and we include
+** only the above three headers. - FM
+*/
+#include <socket.h>
+#include <in.h>
+#include <inet.h>
+#include <netdb.h>
+#include <ioctl.h>
+#endif /* VMS_SOCKET_HEADERS */
+#define TCP_INCLUDES_DONE
+#endif /* !TCP_INCLUDES_DONE */
+
+/*
+
+ On VMS machines, the linker needs to be told to put global data sections into
+ a data
+ segment using these storage classes. (MarkDonszelmann)
+
+ */
+#if defined(VAXC) && !defined(__DECC)
+#define GLOBALDEF globaldef
+#define GLOBALREF globalref
+#else
+#ifdef __GNUC__ /* this added by Sterling Bjorndahl */
+#define GLOBALREF_IS_MACRO 1
+#define GLOBALDEF_IS_MACRO 1
+#include <gnu_hacks.h> /* defines GLOBALREF and GLOBALDEF for GNUC on VMS */
+#endif /* __GNUC__ */
+#endif /* VAXC && !DECC */
+
+#endif /* VMS */
+
+/*
+ * On non-VMS machines and for DECC on VMS, the GLOBALDEF and GLOBALREF
+ * storage types default to normal C storage types.
+ */
+#ifndef GLOBALREF
+#define GLOBALDEF
+#define GLOBALREF extern
+#endif /* !GLOBALREF */
+
+#ifdef DJGPP
+#undef SELECT
+#define TCP_INCLUDES_DONE
+#define NO_IOCTL
+#include <errno.h>
+#include <sys/types.h>
+#include <socket.h>
+
+#undef NETWRITE
+#define NETWRITE write_s
+#undef NETREAD
+#define NETREAD read_s
+#undef NETCLOSE
+#define NETCLOSE close_s
+#endif
+
+/*
+SCO ODT unix version
+ */
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif /* HAVE_SYS_FILIO_H */
+
+/*
+MIPS unix
+ */
+/* Mips hack (bsd4.3/sysV mixture...) */
+#ifdef mips
+extern int errno;
+#endif /* mips */
+
+/*
+Regular BSD unix versions
+=========================
+ These are a default unix where not already defined specifically.
+ */
+#ifndef INCLUDES_DONE
+#include <sys/types.h>
+/* #include <streams/streams.h> not ultrix */
+#if HAVE_STRING_H
+#include <string.h>
+#endif /* HAVE_STRING_H */
+#include <errno.h> /* independent */
+#ifdef SCO
+#include <sys/timeb.h>
+#include <time.h>
+#endif /* SCO */
+#if defined(AIX) || defined(SVR4)
+#include <time.h>
+#endif /* AIX || SVR4 */
+#include <sys/time.h> /* independent */
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/file.h> /* For open() etc */
+#if defined(NeXT) || defined(sony_news)
+#ifndef mode_t
+typedef unsigned short mode_t;
+#endif /* !mode_t */
+#ifndef pid_t
+typedef int pid_t;
+#endif /* !pid_t */
+#ifndef S_ISREG
+#define S_ISREG(m) (((m) & 0170000) == 0100000)
+#endif /* S_ISREG */
+#ifndef WEXITSTATUS
+#ifdef sony_news
+#define WEXITSTATUS(s) WIFEXITED(s)
+#else
+#define WEXITSTATUS(s) (((s).w_status >> 8) & 0377)
+#endif /* sony_news */
+#endif /* !WEXITSTATUS */
+#ifndef WTERMSIG
+#ifdef sony_news
+#define WTERMSIG(s) (s).w_termsig
+#else
+#define WTERMSIG(s) (((s).w_status >> 8) & 0177)
+#endif /* sony_news */
+#endif /* !WTERMSIG */
+#endif /* NeXT || sony_news */
+#define INCLUDES_DONE
+#endif /* Normal includes */
+
+/* FIXME: this should be autoconf'd */
+/* Interactive UNIX for i386 and i486 -- Thanks to jeffrey@itm.itm.org */
+#ifdef ISC
+#include <net/errno.h>
+#include <sys/types.h>
+#include <sys/tty.h>
+#include <sys/sioctl.h>
+#include <sys/bsdtypes.h>
+#ifndef MERGE
+#define MERGE
+#include <sys/pty.h>
+#undef MERGE
+#else
+#include <sys/pty.h>
+#endif /* !MERGE */
+#ifndef USE_DIRENT
+#define USE_DIRENT /* sys V style directory open */
+#endif /* USE_DIRENT */
+#include <sys/dirent.h>
+#endif /* ISC */
+
+/* Directory reading stuff - BSD or SYS V
+*/
+#if defined(UNIX) && !defined(unix)
+#define unix
+#endif /* UNIX && !unix */
+
+#ifdef HAVE_CONFIG_H
+
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# endif /* HAVE_LIMITS_H */
+# if !defined(MAXINT) && defined(INT_MAX)
+# define MAXINT INT_MAX
+# endif /* !MAXINT && INT_MAX */
+
+#else
+
+/* FIXME: remove after completing configure-script */
+#ifdef unix /* if this is to compile on a UNIX machine */
+#define HAVE_READDIR 1 /* if directory reading functions are available */
+#ifdef USE_DIRENT /* sys v version */
+#include <dirent.h>
+#define direct dirent
+#else
+#include <sys/dir.h>
+#endif /* USE_DIRENT */
+#if defined(sun) && defined(__svr4__)
+#include <sys/fcntl.h>
+#include <limits.h>
+#else
+#if defined(__hpux) || defined(LINUX) || defined (__FreeBSD__)
+#include <limits.h>
+#endif /* __hpux || LINUX || __FreeBSD__ */
+#endif /* sun && __svr4__ */
+#if !defined(MAXINT) && defined(INT_MAX)
+#define MAXINT INT_MAX
+#endif /* !MAXINT && INT_MAX */
+#endif /* unix */
+
+#ifndef VM
+#ifndef VMS
+#ifndef THINK_C
+#define DECL_SYS_ERRLIST 1
+#endif /* !THINK_C */
+#endif /* !VMS */
+#endif /* !VM */
+
+#endif /* !HAVE_CONFIG_H */
+
+/*
+Defaults
+========
+ INCLUDE FILES FOR TCP
+ */
+#ifndef TCP_INCLUDES_DONE
+#ifndef NO_IOCTL
+#include <sys/ioctl.h> /* EJB */
+#endif /* !NO_IOCTL */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifndef __hpux /* this may or may not be good -marc */
+#include <arpa/inet.h> /* Must be after netinet/in.h */
+#endif /* !__hpux */
+#include <netdb.h>
+#endif /* TCP includes */
+
+/*
+
+ROUGH ESTIMATE OF MAX PATH LENGTH
+
+*/
+#ifndef HT_MAX_PATH
+#ifdef MAXPATHLEN
+#define HT_MAX_PATH MAXPATHLEN
+#else
+#ifdef PATH_MAX
+#define HT_MAX_PATH PATH_MAX
+#else
+#define HT_MAX_PATH 1024 /* Any better ideas? */
+#endif
+#endif
+#endif /* HT_MAX_PATH */
+
+#if HT_MAX_PATH < 256
+#undef HT_MAX_PATH
+#define HT_MAX_PATH 256
+#endif
+
+/*
+ MACROS FOR MANIPULATING MASKS FOR SELECT()
+ */
+#ifdef SELECT
+#ifndef FD_SET
+typedef unsigned int fd_set;
+#define FD_SET(fd,pmask) (*(pmask)) |= (1<<(fd))
+#define FD_CLR(fd,pmask) (*(pmask)) &= ~(1<<(fd))
+#define FD_ZERO(pmask) (*(pmask))=0
+#define FD_ISSET(fd,pmask) (*(pmask) & (1<<(fd)))
+#endif /* !FD_SET */
+#endif /* SELECT */
+
+
+#endif /* TCP_H */
diff --git a/gnu/usr.bin/lynx/WWW/Library/Implementation/ufc-crypt.h b/gnu/usr.bin/lynx/WWW/Library/Implementation/ufc-crypt.h
new file mode 100644
index 00000000000..13da8b4737d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/Implementation/ufc-crypt.h
@@ -0,0 +1,108 @@
+/*
+ * UFC-crypt: ultra fast crypt(3) implementation
+ *
+ * Copyright (C) 1991, 1992, Free Software Foundation, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * @(#)ufc-crypt.h 1.16 09/21/92
+ *
+ * Definitions of datatypes
+ *
+ */
+
+/*
+ * Requirements for datatypes:
+ *
+ * A datatype 'ufc_long' of at least 32 bit
+ * *and*
+ * A type 'long32' of exactly 32 bits (_UFC_32_)
+ * *or*
+ * A type 'long64' of exactly 64 bits (_UFC_64_)
+ *
+ * 'int' is assumed to be at least 8 bit
+ */
+
+/*
+ * #ifdef's for various architectures
+ */
+
+#ifdef cray
+/* thanks to <hutton@opus.sdsc.edu> (Tom Hutton) for testing */
+typedef unsigned long ufc_long;
+typedef unsigned long long64;
+#define _UFC_64_
+#endif
+
+#ifdef convex
+/* thanks to pcl@convex.oxford.ac.uk (Paul Leyland) for testing */
+typedef unsigned long ufc_long;
+typedef long long long64;
+#define _UFC_64_
+#endif
+
+#ifdef ksr
+/*
+ * Note - the KSR machine does not define a unique symbol
+ * which we can check. So you MUST add '-Dksr' to your Makefile.
+ * Thanks to lijewski@theory.tc.cornell.edu (Mike Lijewski) for
+ * the patch.
+ */
+typedef unsigned long ufc_long;
+typedef unsigned long long64;
+#define _UFC_64_
+#endif
+
+/*
+ * For debugging 64 bit code etc with 'gcc'
+ */
+
+#ifdef GCC3232
+typedef unsigned long ufc_long;
+typedef unsigned long long32;
+#define _UFC_32_
+#endif
+
+#ifdef GCC3264
+typedef unsigned long ufc_long;
+typedef long long long64;
+#define _UFC_64_
+#endif
+
+#ifdef GCC6432
+typedef long long ufc_long;
+typedef unsigned long long32;
+#define _UFC_32_
+#endif
+
+#ifdef GCC6464
+typedef long long ufc_long;
+typedef long long long64;
+#define _UFC_64_
+#endif
+
+/*
+ * Catch all for 99.95% of all UNIX machines
+ */
+
+#ifndef _UFC_64_
+#ifndef _UFC_32_
+#define _UFC_32_
+typedef unsigned long ufc_long;
+typedef unsigned long long32;
+#endif
+#endif
+
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/apollo_m68k/Makefile b/gnu/usr.bin/lynx/WWW/Library/apollo_m68k/Makefile
new file mode 100644
index 00000000000..20aa9ac8cd4
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/apollo_m68k/Makefile
@@ -0,0 +1,38 @@
+# Make WWW for apollo NOTE WWW macro changed for unwritable source tree **
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = apollo_m68k
+
+# For ASIS installation, the ASIS code for the machine/os
+ASIS_MACH = apollo-68k/sr-10.3
+
+
+CFLAGS = -O -DDEBUG
+LFLAGS =
+CC = cc
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+#WWW = /user/timbl/hypertext/WWW
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+# LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+LIBDIR = /tmp/WWWLibrary_Build
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
+
+
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/clix/Makefile b/gnu/usr.bin/lynx/WWW/Library/clix/Makefile
new file mode 100644
index 00000000000..e1996d27019
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/clix/Makefile
@@ -0,0 +1,30 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = clix
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+
+CFLAGS = -O -DDEBUG -DUSG -DUNIX -DCLIX
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/convex/Makefile b/gnu/usr.bin/lynx/WWW/Library/convex/Makefile
new file mode 100644
index 00000000000..fcd28786696
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/convex/Makefile
@@ -0,0 +1,32 @@
+# Make WWW under ConvexOS
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = convex
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+
+CFLAGS = -O -DDEBUG -Dunix
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+# HTWAIS = $(LOB)/HTWAIS.o
+# WAIS = YES
+# WAISINC = -I/tmp/freeWAIS-0.202/ir
+# WAISCFLAGS = -DDIRECT_WAIS
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/decstation/Makefile b/gnu/usr.bin/lynx/WWW/Library/decstation/Makefile
new file mode 100644
index 00000000000..b35d278cd38
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/decstation/Makefile
@@ -0,0 +1,23 @@
+# Platform-specific Makefile for W3 Library (decstation)
+# -----------------------------------------
+#
+
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+#CFLAGS =
+CFLAGS = -O
+CC = cc
+#LFLAGS = -lresolv
+LFLAGS =
+
+ASIS_MACH = dec-station/ultrix-4.2
+WWW_MACH = decstation
+
+# Directory for installed binary:
+LIBDIR = /usr/local/lib
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/djgpp/CommonMakefile b/gnu/usr.bin/lynx/WWW/Library/djgpp/CommonMakefile
new file mode 100644
index 00000000000..1fdaf314799
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/djgpp/CommonMakefile
@@ -0,0 +1,371 @@
+# Common Makefile for W3 Library Code
+# -----------------------------------
+#
+# (c) CERN 1990, 1991 -- see Copyright.html for conditions
+#
+# This file should be invariant between systems.
+# DEPENDENCIES NOT COMPLETE @@
+#
+# make Compile and link the software (private version)
+# make install Copy it into the system (implies make)
+# make update Copy installed version into installed version
+# make uninstall Unlink installed version from the system
+# make clean Remove intermediate files
+# make cleanall Remove intremediate files and products
+#
+# Macros required to be defined already for make:
+#
+# CC The C compiler
+# CFLAGS Flags for $(CC) -- except the -I which are below
+# LFLAGS Flags for ld
+# LYFLAGS Flags for Lynx
+#
+# WWW The WWW source tree directory
+#
+# Macros needed for make install:
+#
+# LIBDIR Directory for installed library
+#______________________________________________________________________
+
+# If this env var is set to something else Some makes will use that instead
+SHELL = /bin/sh
+
+# .h files are distributed but originally are made from the
+# self-documenting hypertext files.
+
+.SUFFIXES: .h .html .htm
+.html.h:
+# - chmod +w $*.h
+# www -w90 -na -to text/x-c $*.html > $*.h
+# chmod -w $*.h
+
+# If this is actually run in a subdirectory,
+#
+WWW = ../..
+# WWW = ../.. For [cernlib] build in this directory
+
+WC = $(WWW)/Library
+CMN = $(WWW)/Library/Implementation/
+VMS = $(CMN)vms
+# Where shall we put the objects and built library?
+
+LOB = $(WTMP)/Library/$(WWW_MACH)
+
+# Only needed if HTWAIS.c is to be compiled. Put into your Makefile.include
+# uncomment these and fill in WAISINC for adding direct wais access
+# to Lynx.
+#HTWAIS = $(LOB)/HTWAIS.o
+#WAIS = YES
+#WAISINC = -I../../../../freeWAIS-0.202/ir
+#WAISCFLAGS = -DDIRECT_WAIS
+#
+
+# This path, if relative, is taken relative to the directory
+# in which this makefile is, not the pwd. This screws up the
+# recursive invocation
+# include $(CMN)Version.make
+include $(ABS)$(WWW)/Library/Implementation/Version.make
+
+# XMOsAIC hack is only for server to cope with xmosaic kludge for mmedia
+#
+# add -DNEW_GATEWAY here for the new gateway config stuff
+CFLAGS2 = $(CFLAGS) $(LYFLAGS) $(WAISCFLAGS) -I$(CMN) -DXMOSAIC_HACK -DACCESS_AUTH
+
+CERNLIBBIN = $(WWW)/bin
+
+COMMON = $(LOB)/HTParse.o $(LOB)/HTAccess.o $(LOB)/HTTP.o \
+ $(LOB)/HTFile.o $(LOB)/HTBTree.o $(LOB)/HTFTP.o $(LOB)/HTTCP.o \
+ $(LOB)/SGML.o $(LOB)/HTMLDTD.o $(LOB)/HTChunk.o \
+ $(LOB)/HTPlain.o $(LOB)/HTWriter.o \
+ $(LOB)/HTMLGen.o \
+ $(LOB)/HTAtom.o $(LOB)/HTAnchor.o $(LOB)/HTStyle.o \
+ $(LOB)/HTList.o $(LOB)/HTString.o $(LOB)/HTDOS.o \
+ $(LOB)/HTRules.o $(LOB)/HTFormat.o $(LOB)/HTMIME.o \
+ $(LOB)/HTHistory.o $(LOB)/HTNews.o $(LOB)/HTGopher.o \
+ $(LOB)/HTTelnet.o $(LOB)/HTFinger.o $(LOB)/HTWSRC.o $(HTWAIS) \
+ $(LOB)/HTAAUtil.o $(LOB)/HTAAServ.o $(LOB)/HTAABrow.o \
+ $(LOB)/HTAAFile.o $(LOB)/HTPasswd.o $(LOB)/HTGroup.o \
+ $(LOB)/HTACL.o $(LOB)/HTAuth.o $(LOB)/HTAAProt.o \
+ $(LOB)/HTAssoc.o $(LOB)/HTLex.o $(LOB)/HTUU.o
+
+CFILES = $(CMN)HTParse.c $(CMN)HTAccess.c $(CMN)HTTP.c $(CMN)HTFile.c \
+ $(CMN)HTBTree.c \
+ $(CMN)HTFTP.c $(CMN)HTTCP.c $(CMN)SGML.c \
+ $(CMN)HTMLDTD.c \
+ $(CMN)HTPlain.c $(CMN)HTWriter.c \
+ $(CMN)HTDOS.c $(CMN)HTMLGen.c \
+ $(CMN)HTChunk.c $(CMN)HTAtom.c $(CMN)HTAnchor.c $(CMN)HTStyle.c \
+ $(CMN)HTList.c $(CMN)HTString.c $(CMN)HTRules.c \
+ $(CMN)HTFormat.c $(CMN)HTMIME.c $(CMN)HTHistory.c \
+ $(CMN)HTNews.c $(CMN)HTGopher.c $(CMN)HTTelnet.c \
+ $(CMN)HTFinger.c $(CMN)HTWAIS.c $(CMN)HTWSRC.c \
+ $(CMN)HTAAUtil.c $(CMN)HTAAServ.c $(CMN)HTAABrow.c \
+ $(CMN)HTAAFile.c $(CMN)HTPasswd.c $(CMN)HTGroup.c \
+ $(CMN)HTACL.c $(CMN)HTAuth.c $(CMN)HTAAProt.c \
+ $(CMN)HTAssoc.c $(CMN)HTLex.c $(CMN)HTUU.c
+
+HFILES = $(CMN)HTParse.h $(CMN)HTAccess.h $(CMN)HTTP.h $(CMN)HTFile.h \
+ $(CMN)HTBTree.h $(CMN)HTFTP.h $(CMN)HTTCP.h \
+ $(CMN)SGML.h $(CMN)HTML.h $(CMN)HTMLDTD.h $(CMN)HTChunk.h \
+ $(CMN)HTPlain.h $(CMN)HTWriter.h \
+ $(CMN)HTFWriter.h $(CMN)HTMLGen.h $(CMN)HTDOS.h \
+ $(CMN)HTStream.h \
+ $(CMN)HTAtom.h $(CMN)HTAnchor.h $(CMN)HTStyle.h \
+ $(CMN)HTList.h \
+ $(CMN)HTString.h $(CMN)HTAlert.h $(CMN)HTRules.h \
+ $(CMN)HTFormat.h $(CMN)HTInit.h \
+ $(CMN)HTMIME.h $(CMN)HTHistory.h $(CMN)HTNews.h \
+ $(CMN)HTGopher.h \
+ $(CMN)HTUtils.h $(CMN)tcp.h $(CMN)HText.h \
+ $(CMN)HTTelnet.h $(CMN)HTFinger.h \
+ $(CMN)HTWAIS.h $(CMN)HTWSRC.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAServ.h $(CMN)HTAABrow.h \
+ $(CMN)HTAAFile.h $(CMN)HTPasswd.h $(CMN)HTGroup.h \
+ $(CMN)HTACL.h $(CMN)HTAuth.h $(CMN)HTAAProt.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h $(CMN)HTUU.h
+
+SOURCES = $(CFILES) $(HFILES) $(CMN)Version.make \
+ $(CMN)CommonMakefile $(CMN)Makefile \
+ $(WWW)/README.txt $(WWW)/Copyright.txt $(WWW)/BUILD $(WWW)/Makefile
+SPECIFIC = $(WWW)/All/*/Makefile.include $(WWW)/All/Implementation/Makefile* \
+ $(VMS)/descrip.mms $(VMS)/build_multinet.com \
+ $(VMS)/COPYING.LIB $(VMS)/setup.com $(VMS)/multinet.opt \
+ $(VMS)/patchlevel.h $(VMS)/ufc-crypt.h \
+ $(VMS)/crypt.c $(VMS)/crypt_util.c \
+ $(VMS)/getline.c $(VMS)/getpass.c \
+ $(VMS)/HTVMSUtils.h $(VMS)/HTVMSUtils.c
+
+
+# Library
+#
+# On SGI, ranlib is unnecessary and does not exist so we ignore errors
+# for that step
+$(LOB)/libwww.a : $(COMMON)
+ ar r $(LOB)/libwww.a $(COMMON)
+ -ranlib $(LOB)/libwww.a
+
+# Clean up everything generatable except final products
+clean :
+ rm $(LOB)/*.o
+ -rmdir $(LOB)
+
+# Clean up everything generatable including final products
+
+cleanall : clean
+ rm $(LOB)/libwww.a
+
+# Install W3 library into system space (not normally necessary)
+
+install : libwww.a
+ if [ ! -r $(LIBDIR) ] mkdir $(LIBDIR)
+ cp libwww.a $(LIBDIR)/libwww.a
+
+uninstall :
+ rm $(LIBDIR)/libwww.a
+
+# Distribution use only:
+# ----------------------
+
+# Needs www version 2.4 or later to do this
+inc : $(HFILES)
+ echo Include files generated from hypertext.
+
+binary : /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+ echo FTP archive binary Libray $(VC) for $(WWW_MACH) up to date.
+
+
+/pub/www/bin/$(WWW_MACH)/libwww_$(VC).a : libwww.a
+ -mkdir /pub/www/bin/$(WWW_MACH)
+ cp libwww.a /pub/www/bin/$(WWW_MACH)/libwww_$(VC).a
+
+# Source Distribution:
+
+distribute : /pub/www/README.txt /pub/www/Copyright.txt
+ (cd $(WWW)/..; WWW=WWW ABS=`pwd`/ make $(MFLAGS) \
+ -f WWW/Library/Implementation/CommonMakefile \
+ /pub/www/src/WWWLibrary_$(VC).tar.Z)
+ (cd ../Implementation; cvs tag \
+ `sed -e 's/VC = /v/' Version.make | sed -e 's?\.?/?'` )
+ echo Distribution of Library version $(VC) up to date.
+
+/pub/www/src/WWWLibrary_$(VC).tar.Z : $(SOURCES)
+ tar cf /pub/www/src/WWWLibrary_$(VC).tar \
+ $(SOURCES) $(SPECIFIC) $(WC)/*/Makefile
+ compress /pub/www/src/WWWLibrary_$(VC).tar
+
+
+# Hypertext supplied in text format
+# ---------------------------------
+
+$(WWW)/README.txt : $(WWW)/../README.html
+ www -n -p66 http://www.w3.org/hypertext/README.html \
+ > $(WWW)/README.txt
+/pub/www/README.txt : $(WWW)/README.txt
+ cp $(WWW)/README.txt /pub/www/README.txt
+
+$(WWW)/Copyright.txt : $(WWW)/../Copyright.html
+ www -n -p66 http://www.w3.org/hypertext/Copyright.html \
+ > $(WWW)/Copyright.txt
+/pub/www/Copyright.txt : $(WWW)/Copyright.txt
+ cp $(WWW)/Copyright.txt /pub/www/Copyright.txt
+
+# Common code
+# -----------
+
+# Directory for object files
+
+$(LOB)/HTList.o : $(OE) $(CMN)HTList.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTList.c
+
+$(LOB)/HTAnchor.o : $(OE) $(CMN)HTAnchor.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAnchor.c
+
+$(LOB)/HTFormat.o : $(OE) $(CMN)HTFormat.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFormat.c
+
+$(LOB)/HTMIME.o : $(OE) $(CMN)HTMIME.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMIME.c
+
+$(LOB)/HTHistory.o : $(OE) $(CMN)HTHistory.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTHistory.c
+
+$(LOB)/HTDOS.o : $(OE) $(CMN)HTDOS.c $(CMN)HTUtils.h $(CMN)../../../userdefs.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTDOS.c
+
+$(LOB)/HTNews.o : $(OE) $(CMN)HTNews.c $(CMN)HTUtils.h $(CMN)HTList.h\
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTNews.c
+
+$(LOB)/HTGopher.o : $(OE) $(CMN)HTGopher.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGopher.c
+
+$(LOB)/HTTelnet.o : $(OE) $(CMN)HTTelnet.c $(CMN)HTUtils.h $(CMN)HTTelnet.h $(CMN)../../../userdefs.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTelnet.c
+
+$(LOB)/HTFinger.o : $(OE) $(CMN)HTFinger.c $(CMN)HTUtils.h $(CMN)HTList.h \
+ $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFinger.c
+
+$(LOB)/HTStyle.o : $(OE) $(CMN)HTStyle.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTStyle.c
+
+$(LOB)/HTAtom.o : $(OE) $(CMN)HTAtom.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAtom.c
+
+$(LOB)/HTChunk.o : $(OE) $(CMN)HTChunk.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTChunk.c
+
+$(LOB)/HTString.o : $(OE) $(CMN)HTString.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTString.c
+
+$(LOB)/HTRules.o : $(OE) $(CMN)HTRules.c $(CMN)HTUtils.h $(CMN)Version.make \
+ $(CMN)HTAAServ.h $(CMN)HTAAProt.h
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTRules.c
+
+$(LOB)/SGML.o : $(OE) $(CMN)SGML.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)SGML.c
+
+$(LOB)/HTMLGen.o : $(OE) $(CMN)HTMLGen.c $(CMN)HTUtils.h $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLGen.c
+
+$(LOB)/HTMLDTD.o : $(OE) $(CMN)HTMLDTD.c $(CMN)SGML.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLDTD.c
+
+$(LOB)/HTPlain.o : $(OE) $(CMN)HTPlain.c $(CMN)HTPlain.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPlain.c
+
+$(LOB)/HTWAIS.o : $(OE) $(CMN)HTWAIS.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(WAISINC) $(CMN)HTWAIS.c
+
+$(LOB)/HTWSRC.o : $(OE) $(CMN)HTWSRC.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWSRC.c
+
+$(LOB)/HTWriter.o : $(OE) $(CMN)HTWriter.c $(CMN)HTWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWriter.c
+
+
+# Access Authorization
+
+$(LOB)/HTAAUtil.o : $(OE) $(CMN)HTAAUtil.c $(CMN)HTAAUtil.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAUtil.c
+
+$(LOB)/HTAAFile.o : $(OE) $(CMN)HTAAFile.c $(CMN)HTAAFile.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAFile.c
+
+$(LOB)/HTPasswd.o : $(OE) $(CMN)HTPasswd.c $(CMN)HTPasswd.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPasswd.c
+
+$(LOB)/HTGroup.o : $(OE) $(CMN)HTGroup.c $(CMN)HTGroup.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGroup.c
+
+$(LOB)/HTACL.o : $(OE) $(CMN)HTACL.c $(CMN)HTACL.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTGroup.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTACL.c
+
+$(LOB)/HTAuth.o : $(OE) $(CMN)HTAuth.c $(CMN)HTAuth.h \
+ $(CMN)HTAAUtil.h $(CMN)HTPasswd.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAuth.c
+
+$(LOB)/HTAAServ.o : $(OE) $(CMN)HTAAServ.c $(CMN)HTAAServ.h \
+ $(CMN)HTAAUtil.h $(CMN)HTAAFile.h $(CMN)HTPasswd.h \
+ $(CMN)HTGroup.h $(CMN)HTACL.h $(CMN)HTAuth.h \
+ $(CMN)HTUU.h $(CMN)HTParse.h $(CMN)HTList.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTRules.h \
+ $(CMN)HTAAProt.h $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAServ.c
+
+$(LOB)/HTAABrow.o : $(OE) $(CMN)HTAABrow.c $(CMN)HTAABrow.h \
+ $(CMN)HTAAUtil.h $(CMN)HTUU.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h \
+ $(CMN)HTParse.h $(CMN)HTList.h $(CMN)HTAlert.h \
+ $(CMN)HTAssoc.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAABrow.c
+
+$(LOB)/HTAAProt.o : $(OE) $(CMN)HTAAProt.c $(CMN)HTAAProt.h \
+ $(CMN)HTUtils.h $(CMN)HTAAUtil.h $(CMN)HTAAFile.h \
+ $(CMN)HTAssoc.h $(CMN)HTLex.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAAProt.c
+
+$(LOB)/HTAssoc.o : $(OE) $(CMN)HTAssoc.c $(CMN)HTAssoc.h \
+ $(CMN)HTUtils.h $(CMN)HTString.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAssoc.c
+
+$(LOB)/HTLex.o : $(OE) $(CMN)HTLex.c $(CMN)HTLex.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTLex.c
+
+$(LOB)/HTUU.o : $(OE) $(CMN)HTUU.c $(CMN)HTUU.h $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTUU.c
+
+
+# Communications & Files
+
+$(LOB)/HTTP.o : $(OE) $(CMN)HTTP.c $(CMN)HTUtils.h $(CMN)HTAABrow.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTP.c
+
+$(LOB)/HTTCP.o : $(OE) $(CMN)HTTCP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTCP.c
+
+$(LOB)/HTFile.o : $(OE) $(CMN)HTFile.c $(CMN)HTUtils.h \
+ $(CMN)HTMLDTD.h $(CMN)HTAAServ.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFile.c
+
+$(LOB)/HTBTree.o : $(OE) $(CMN)HTBTree.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTBTree.c
+
+$(LOB)/HTFTP.o : $(OE) $(CMN)HTFTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFTP.c
+
+$(LOB)/HTAccess.o : $(OE) $(CMN)HTAccess.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAccess.c
+
+$(LOB)/HTParse.o : $(OE) $(CMN)HTParse.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTParse.c
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/djgpp/makefile b/gnu/usr.bin/lynx/WWW/Library/djgpp/makefile
new file mode 100644
index 00000000000..d7272e45eca
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/djgpp/makefile
@@ -0,0 +1,30 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = djgpp
+
+# The ASIS repository's name for the machine we are on
+#ASIS_MACH = hardware/os
+
+CFLAGS = -O3 -DUSE_ZLIB -DDOSPATH -DNOUSERS -DDEBUG -I../../../djgpp/tcplib/include -I../../../djgpp/tcplib/include/tcp \
+-I../../../src -I../../..
+LFLAGS =
+CC = gcc
+
+# Directory for installed binary:
+!BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+include $(WWW)/Library/Implementation/Version.make
+#include $(WWW)/Library/Implementation/CommonMakefile
+include ./CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/duns/Makefile b/gnu/usr.bin/lynx/WWW/Library/duns/Makefile
new file mode 100644
index 00000000000..4852817e856
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/duns/Makefile
@@ -0,0 +1,489 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space. Imake tries to compensate
+# for this, but is not always successful.
+#
+
+###########################################################################
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a00214>
+# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
+#
+# Platform-specific parameters may be set in the appropriate .cf
+# configuration files. Site-wide parameters may be set in the file
+# site.def. Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor doesn't define any unique symbols, you'll need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make Makefile", "make Makefiles", or "make World").
+#
+# If you absolutely can't get imake to work, you'll need to set the
+# variables at the top of each Makefile as well as the dependencies at the
+# bottom (makedepend will do this automatically).
+#
+
+###########################################################################
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform: $XConsortium: sun.cf,v 1.38 89/12/23 16:10:10 jim Exp $
+# operating system: SunOS 4.0.3
+
+###########################################################################
+# site-specific configuration parameters - edit site.def to change
+
+ SHELL = /bin/sh
+
+ TOP = .
+ CURRENT_DIR = .
+
+ AR = ar clq
+ BOOTSTRAPCFLAGS =
+ CC = cc
+
+ COMPRESS = compress
+ CPP = /lib/cpp $(STD_CPP_DEFINES)
+ PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
+ INSTALL = install
+ LD = ld
+ LINT = lint
+ LINTLIBFLAG = -C
+ LINTOPTS = -axz
+ LN = ln -s
+ MAKE = make
+ MV = mv
+ CP = cp
+ RANLIB = ranlib
+ RANLIBINSTFLAGS =
+ RM = rm -f
+ STD_INCLUDES =
+ STD_CPP_DEFINES =
+ STD_DEFINES =
+ EXTRA_LOAD_FLAGS =
+ EXTRA_LIBRARIES =
+ TAGS = ctags
+
+ SHAREDCODEDEF = -DSHAREDCODE
+ SHLIBDEF = -DSUNSHLIB
+
+ PROTO_DEFINES =
+
+ INSTPGMFLAGS =
+
+ INSTBINFLAGS = -m 0755
+ INSTUIDFLAGS = -m 4755
+ INSTLIBFLAGS = -m 0664
+ INSTINCFLAGS = -m 0444
+ INSTMANFLAGS = -m 0444
+ INSTDATFLAGS = -m 0444
+ INSTKMEMFLAGS = -m 4755
+
+ DESTDIR =
+
+ TOP_INCLUDES = -I$(INCROOT)
+
+ CDEBUGFLAGS = -O
+ CCOPTIONS =
+ COMPATFLAGS =
+
+ ALLINCLUDES = $(STD_INCLUDES) $(TOP_INCLUDES) $(INCLUDES) $(EXTRA_INCLUDES)
+ ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
+ CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+ LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+ LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+ LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS)
+ LDCOMBINEFLAGS = -X -r
+
+ MACROFILE = sun.cf
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+ IMAKE_DEFINES =
+
+ IRULESRC = $(CONFIGDIR)
+ IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+###########################################################################
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
+
+###########################################################################
+# X Window System make variables; this need to be coordinated with rules
+# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
+
+ PATHSEP = /
+ USRLIBDIR = $(DESTDIR)/usr/lib
+ BINDIR = $(DESTDIR)/usr/bin/X11
+ INCROOT = $(DESTDIR)/usr/include
+ BUILDINCROOT = $(TOP)
+ BUILDINCDIR = $(BUILDINCROOT)/X11
+ BUILDINCTOP = ..
+ INCDIR = $(INCROOT)/X11
+ ADMDIR = $(DESTDIR)/usr/adm
+ LIBDIR = $(USRLIBDIR)/X11
+ CONFIGDIR = $(LIBDIR)/config
+ LINTLIBDIR = $(USRLIBDIR)/lint
+
+ FONTDIR = $(LIBDIR)/fonts
+ XINITDIR = $(LIBDIR)/xinit
+ XDMDIR = $(LIBDIR)/xdm
+ AWMDIR = $(LIBDIR)/awm
+ TWMDIR = $(LIBDIR)/twm
+ GWMDIR = $(LIBDIR)/gwm
+ MANPATH = $(DESTDIR)/usr/man
+ MANSOURCEPATH = $(MANPATH)/man
+ MANDIR = $(MANSOURCEPATH)n
+ LIBMANDIR = $(MANSOURCEPATH)3
+ XAPPLOADDIR = $(LIBDIR)/app-defaults
+
+ SOXLIBREV = 4.2
+ SOXTREV = 4.0
+ SOXAWREV = 4.0
+ SOOLDXREV = 4.0
+ SOXMUREV = 4.0
+ SOXEXTREV = 4.0
+
+ FONTCFLAGS = -t
+
+ INSTAPPFLAGS = $(INSTDATFLAGS)
+
+ IMAKE = imake
+ DEPEND = makedepend
+ RGB = rgb
+ FONTC = bdftosnf
+ MKFONTDIR = mkfontdir
+ MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier.sh
+
+ CONFIGSRC = $(TOP)/config
+ CLIENTSRC = $(TOP)/clients
+ DEMOSRC = $(TOP)/demos
+ LIBSRC = $(TOP)/lib
+ FONTSRC = $(TOP)/fonts
+ INCLUDESRC = $(TOP)/X11
+ SERVERSRC = $(TOP)/server
+ UTILSRC = $(TOP)/util
+ SCRIPTSRC = $(UTILSRC)/scripts
+ EXAMPLESRC = $(TOP)/examples
+ CONTRIBSRC = $(TOP)/../contrib
+ DOCSRC = $(TOP)/doc
+ RGBSRC = $(TOP)/rgb
+ DEPENDSRC = $(UTILSRC)/makedepend
+ IMAKESRC = $(CONFIGSRC)
+ XAUTHSRC = $(LIBSRC)/Xau
+ XLIBSRC = $(LIBSRC)/X
+ XMUSRC = $(LIBSRC)/Xmu
+ TOOLKITSRC = $(LIBSRC)/Xt
+ AWIDGETSRC = $(LIBSRC)/Xaw
+ OLDXLIBSRC = $(LIBSRC)/oldX
+ XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+ BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+ MKFONTDIRSRC = $(FONTSRC)/mkfontdir
+ EXTENSIONSRC = $(TOP)/extensions
+
+ DEPEXTENSIONLIB =
+ EXTENSIONLIB = -lXext
+
+ DEPXLIB = $(DEPEXTENSIONLIB)
+ XLIB = $(EXTENSIONLIB) -lX11
+
+ DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+ XAUTHLIB = -lXau
+
+ DEPXMULIB =
+ XMULIB = -lXmu
+
+ DEPOLDXLIB =
+ OLDXLIB = -loldX
+
+ DEPXTOOLLIB =
+ XTOOLLIB = -lXt
+
+ DEPXAWLIB =
+ XAWLIB = -lXaw
+
+ LINTEXTENSIONLIB = $(USRLIBDIR)/llib-lXext.ln
+ LINTXLIB = $(USRLIBDIR)/llib-lX11.ln
+ LINTXMU = $(USRLIBDIR)/llib-lXmu.ln
+ LINTXTOOL = $(USRLIBDIR)/llib-lXt.ln
+ LINTXAW = $(USRLIBDIR)/llib-lXaw.ln
+
+ DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+ DEPLIBS1 = $(DEPLIBS)
+ DEPLIBS2 = $(DEPLIBS)
+ DEPLIBS3 = $(DEPLIBS)
+
+###########################################################################
+# Imake rules for building libraries, programs, scripts, and data files
+# rules: $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
+
+###########################################################################
+# start of Imakefile
+
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+TK_WWW_SOURCE_PATH=/a/dxcern/userd/tbl/hypertext/WWW/TkWWW/Tcl
+
+TK_WWW_INSTALL_PATH=/a/dxcern/userd/tbl/hypertext/WWW/TkWWW/$(WWW_MACH)
+
+TK_WWW_HOME_PAGE=http://www.w3.org/default.html
+TK_WWW_START_PAGE=$(TK_WWW_HOME_PAGE)
+
+CC = gcc -fno-builtin -Wall
+
+CDEBUGFLAGS = -O3 -pipe
+
+COMPATFLAGS = -I/afs/athena.mit.edu/course/other/cdsdev/www-compat
+CCOPTIONS =
+
+BINDIR = $(TK_WWW_INSTALL_PATH)
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = unix.x
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = /tmp
+
+# Common Makefile for W3 Library Code
+# -----------------------------------
+#
+# (c) CERN 1990, 1991 -- see Copyright.html for conditions
+#
+# This file should be invariant between systems.
+# DEPENDENCIES NOT COMPLETE
+
+#
+# make Compile and link the software (private version)
+# make clean Remove intermediate files
+
+WC = $(WWW)/Library
+CMN = $(WWW)/Library/Implementation/
+
+# Where shall we put the objects and built library?
+
+LOB = $(WTMP)/Library/$(WWW_MACH)
+
+# Bug: This path, if relative, is taken relative to the directory
+# in which this makefile is, not the pwd. This screws up the
+# recursive invocation
+
+VC = 2.14
+
+CFLAGS2 = $(CFLAGS) -I$(CMN)
+
+CERNLIBBIN = $(WWW)/bin
+
+COMMON = $(LOB)/HTParse.o $(LOB)/HTAccess.o $(LOB)/HTTP.o \
+ $(LOB)/HTFile.o $(LOB)/HTFTP.o $(LOB)/HTTCP.o \
+ $(LOB)/SGML.o $(LOB)/HTMLDTD.o $(LOB)/HTChunk.o \
+ $(LOB)/HTPlain.o $(LOB)/HTWriter.o $(LOB)/HTFWriter.o \
+ $(LOB)/HTMLGen.o \
+ $(LOB)/HTAtom.o $(LOB)/HTAnchor.o $(LOB)/HTStyle.o \
+ $(LOB)/HTList.o $(LOB)/HTString.o $(LOB)/HTAlert.o \
+ $(LOB)/HTRules.o $(LOB)/HTFormat.o $(LOB)/HTInit.o $(LOB)/HTMIME.o \
+ $(LOB)/HTHistory.o $(LOB)/HTNews.o $(LOB)/HTGopher.o \
+ $(LOB)/HTTelnet.o $(LOB)/HTWSRC.o $(HTWAIS)
+
+CFILES = $(CMN)HTParse.c $(CMN)HTAccess.c $(CMN)HTTP.c $(CMN)HTFile.c \
+ $(CMN)HTFTP.c $(CMN)HTTCP.c $(CMN)SGML.c \
+ $(CMN)HTMLDTD.c \
+ $(CMN)HTPlain.c $(CMN)HTWriter.c $(CMN)HTFWriter.c $(CMN)HTMLGen.c \
+ $(CMN)HTChunk.c $(CMN)HTAtom.c $(CMN)HTAnchor.c $(CMN)HTStyle.c \
+ $(CMN)HTList.c $(CMN)HTString.c $(CMN)HTAlert.c $(CMN)HTRules.c \
+ $(CMN)HTFormat.c $(CMN)HTInit.c $(CMN)HTMIME.c $(CMN)HTHistory.c \
+ $(CMN)HTNews.c $(CMN)HTGopher.c $(CMN)HTTelnet.c \
+ $(CMN)HTWAIS.c $(CMN)HTWSRC.c
+
+HFILES = $(CMN)HTParse.h $(CMN)HTAccess.h $(CMN)HTTP.h $(CMN)HTFile.h \
+ $(CMN)HTFTP.h $(CMN)HTTCP.h \
+ $(CMN)SGML.h $(CMN)HTML.h $(CMN)HTMLDTD.h $(CMN)HTChunk.h \
+ $(CMN)HTPlain.h $(CMN)HTWriter.h \
+ $(CMN)HTFWriter.h $(CMN)HTMLGen.h \
+ $(CMN)HTStream.h \
+ $(CMN)HTAtom.h $(CMN)HTAnchor.h $(CMN)HTStyle.h \
+ $(CMN)HTList.h \
+ $(CMN)HTString.h $(CMN)HTAlert.h $(CMN)HTRules.h \
+ $(CMN)HTFormat.h $(CMN)HTInit.h \
+ $(CMN)HTMIME.h $(CMN)HTHistory.h $(CMN)HTNews.h \
+ $(CMN)HTGopher.h \
+ $(CMN)HTUtils.h $(CMN)tcp.h $(CMN)WWW.h $(CMN)HText.h \
+ $(CMN)HTTelnet.h \
+ $(CMN)HTWAIS.h $(CMN)HTWSRC.h
+
+SOURCES = $(CFILES) $(HFILES) $(CMN)Version.make $(CMN)CommonMakefile \
+ $(WWW)/README.txt $(WWW)/Copyright.txt $(WWW)/BUILD
+SPECIFIC = $(WWW)/All
+
+# Library
+#
+# On SGI, ranlib is unnecessary and does not exist so we ignore errors
+# for that step
+all: $(LOB)/libwww.a
+ $(MV) $(LOB)/libwww.a $(WC)/$(WWW_MACH)
+
+$(LOB)/libwww.a : $(COMMON)
+ ar r $(LOB)/libwww.a $(COMMON)
+ -ranlib $(LOB)/libwww.a
+
+# Clean up everything generatable except final products
+clean ::
+ $(RM) $(LOB)
+
+# Clean up everything generatable including final products
+
+cleanall :: clean
+ $(RM) $(LOB)/libwww.a
+
+# Common code
+# -----------
+
+# Directory for object files - .created checks it exists
+
+OE = $(LOB)/.created
+$(OE) :
+ -mkdir $(WTMP)
+ -mkdir $(WTMP)/Library
+ -mkdir $(WTMP)/Library/$(WWW_MACH)
+ touch $@
+
+$(LOB)/HTList.o : $(OE) $(CMN)HTList.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTList.c
+
+$(LOB)/HTAnchor.o : $(OE) $(CMN)HTAnchor.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAnchor.c
+
+$(LOB)/HTFormat.o : $(OE) $(CMN)HTFormat.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFormat.c
+
+$(LOB)/HTInit.o : $(OE) $(CMN)HTInit.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTInit.c
+
+$(LOB)/HTMIME.o : $(OE) $(CMN)HTMIME.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMIME.c
+
+$(LOB)/HTHistory.o : $(OE) $(CMN)HTHistory.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTHistory.c
+
+$(LOB)/HTNews.o : $(OE) $(CMN)HTNews.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTNews.c
+
+$(LOB)/HTGopher.o : $(OE) $(CMN)HTGopher.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGopher.c
+
+$(LOB)/HTTelnet.o : $(OE) $(CMN)HTTelnet.c $(CMN)HTUtils.h $(CMN)HTTelnet.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTelnet.c
+
+$(LOB)/HTStyle.o : $(OE) $(CMN)HTStyle.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTStyle.c
+
+$(LOB)/HTAtom.o : $(OE) $(CMN)HTAtom.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAtom.c
+
+$(LOB)/HTChunk.o : $(OE) $(CMN)HTChunk.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTChunk.c
+
+$(LOB)/HTString.o : $(OE) $(CMN)HTString.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTString.c
+
+$(LOB)/HTAlert.o : $(OE) $(CMN)HTAlert.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTAlert.c
+
+$(LOB)/HTRules.o : $(OE) $(CMN)HTRules.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTRules.c
+
+$(LOB)/SGML.o : $(OE) $(CMN)SGML.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)SGML.c
+
+$(LOB)/HTMLGen.o : $(OE) $(CMN)HTMLGen.c $(CMN)HTUtils.h $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLGen.c
+
+$(LOB)/HTMLDTD.o : $(OE) $(CMN)HTMLDTD.c $(CMN)SGML.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLDTD.c
+
+$(LOB)/HTPlain.o : $(OE) $(CMN)HTPlain.c $(CMN)HTPlain.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPlain.c
+
+$(LOB)/HTWAIS.o : $(OE) $(CMN)HTWAIS.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(WAISINC) $(CMN)HTWAIS.c
+
+$(LOB)/HTWSRC.o : $(OE) $(CMN)HTWSRC.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWSRC.c
+
+$(LOB)/HTWriter.o : $(OE) $(CMN)HTWriter.c $(CMN)HTWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWriter.c
+
+$(LOB)/HTFWriter.o : $(OE) $(CMN)HTFWriter.c $(CMN)HTFWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFWriter.c
+
+# Communications & Files
+
+$(LOB)/HTTP.o : $(OE) $(CMN)HTTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTP.c
+
+$(LOB)/HTTCP.o : $(OE) $(CMN)HTTCP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTCP.c
+
+$(LOB)/HTFile.o : $(OE) $(CMN)HTFile.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFile.c
+
+$(LOB)/HTFTP.o : $(OE) $(CMN)HTFTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFTP.c
+
+$(LOB)/HTAccess.o : $(OE) $(CMN)HTAccess.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAccess.c
+
+$(LOB)/HTParse.o : $(OE) $(CMN)HTParse.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTParse.c
+
+###########################################################################
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+ $(RM_CMD) \#*
+
+Makefile::
+ -@if [ -f Makefile ]; then \
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+ $(TAGS) -w *.[ch]
+ $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+ #load $(ALLDEFINES) $(SRCS)
+
+osaber:
+ #load $(ALLDEFINES) $(OBJS)
+
+###########################################################################
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+ @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+###########################################################################
+# dependencies generated by makedepend
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/freebsd/Makefile b/gnu/usr.bin/lynx/WWW/Library/freebsd/Makefile
new file mode 100644
index 00000000000..a82f13b8757
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/freebsd/Makefile
@@ -0,0 +1,27 @@
+# Make WWW under FreeBSD
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = freebsd
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = i386/FreeBSD
+
+
+CFLAGS += -DDEBUG
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/isc/Makefile b/gnu/usr.bin/lynx/WWW/Library/isc/Makefile
new file mode 100644
index 00000000000..29de6885626
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/isc/Makefile
@@ -0,0 +1,30 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = isc
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = intel/isc
+
+
+CFLAGS = -DDEBUG -O -DISC -Dvfork=fork
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/mips/Makefile b/gnu/usr.bin/lynx/WWW/Library/mips/Makefile
new file mode 100644
index 00000000000..1c84cbe089c
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/mips/Makefile
@@ -0,0 +1,29 @@
+# Makefile for WWW under svr4
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = mips
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = mips/mips
+
+
+#CFLAGS = -DDEBUG -systype svr3 -DMIPS -DNO_BCOPY
+CFLAGS = -O -DDEBUG -systype svr3 -I/svr3/usr/include/bsd
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/netbsd/Makefile b/gnu/usr.bin/lynx/WWW/Library/netbsd/Makefile
new file mode 100644
index 00000000000..ae92760a5b8
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/netbsd/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under NetBSD
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = netbsd
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = i386/NetBSD
+
+
+CFLAGS = -O -DUSE_DIRENT
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/next/Makefile b/gnu/usr.bin/lynx/WWW/Library/next/Makefile
new file mode 100644
index 00000000000..bd35c89a9d0
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/next/Makefile
@@ -0,0 +1,40 @@
+# Platform-specific Makefile for W3 Library (NeXT)
+# -----------------------------------------
+#
+# Library compiled with fudge to alow XMOSAIC to
+# pick up binary files... for now.
+
+WWW = ../..
+
+# Where should temporary (object) files go? Normally, WTMP = $(WWW)
+#WTMP = /tmp
+WTMP = $(WWW)
+
+# For MACH 3.0 it seems -bsd is needed to order to define errno
+# in /usr/include/bsd/sys/errno.h. But __STRICT_BSD__ is needed for
+# errno.
+
+CFLAGS = -Wall -O -DXMOSAIC_HACK
+
+# Yes please, I want direct WAIS access
+#
+#WAIS = ../../../freeWAIS
+#WAISINC = -I$(WAIS)/ir
+#WAISCFLAGS = -DDIRECT_WAIS
+#WAISLIB = $(WAIS)/bin/client.a $(WAIS)/bin/wais.a
+# $(WAIS)/bin/inv.a $(WAIS)/bin/wais.a
+#HTWAIS = $(WTMP)/Library/$(WWW_MACH)/HTWAIS.o
+
+CC = cc
+# For testing memory leaks only! Use /NextDeveloper/MallocDebug app
+LFLAGS = -lMallocDebug
+#LFLAGS =
+
+WWW_MACH = next
+ASIS_MACH = next/2.0
+
+
+# Directory for installed binary:
+LIBDIR = /usr/local/lib
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/osf/Makefile b/gnu/usr.bin/lynx/WWW/Library/osf/Makefile
new file mode 100644
index 00000000000..a81457a60e9
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/osf/Makefile
@@ -0,0 +1,23 @@
+# Platform-specific Makefile for W3 Library (decstation)
+# -----------------------------------------
+#
+
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+#CFLAGS =
+CFLAGS = -DSYS5
+CC = cc -O
+#LFLAGS =
+LFLAGS =
+
+ASIS_MACH = alpha/osf1
+WWW_MACH = osf
+
+# Directory for installed binary:
+LIBDIR = /usr/local/lib
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/ptx/Makefile b/gnu/usr.bin/lynx/WWW/Library/ptx/Makefile
new file mode 100644
index 00000000000..772d6c6a038
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/ptx/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under Sequent's DYNIX/ptx
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = ptx
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = Sequent/ptx
+
+
+CFLAGS = -O -DDEBUG -DUSE_DIRENT -DSVR4 -DNO_IOCTL -DUSE_FCNTL
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/rs6000/Makefile b/gnu/usr.bin/lynx/WWW/Library/rs6000/Makefile
new file mode 100644
index 00000000000..334a5a4afbd
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/rs6000/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under unix for rs6000 with no gcc
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = rs6000
+
+# For ASIS
+ASIS_MACH = ibm-rs6000/aix-3.2
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# The AIX compiler does not define unix... AIX will do it and avoid realloc bug
+
+CFLAGS = -O -DDEBUG
+CC = cc
+LFLAGS =
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = $(WWW)
+
+# Where is the W3 object library?
+LIBDIR = /usr/local/lib
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/sco/Makefile b/gnu/usr.bin/lynx/WWW/Library/sco/Makefile
new file mode 100644
index 00000000000..a00a948b069
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/sco/Makefile
@@ -0,0 +1,33 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = sco
+
+# The ASIS repository's name for the machine we are on
+# SCO does not presently have ranlib. Ignore the error
+# message about that when the CommonMakefile tries to
+# invoke it.
+ASIS_MACH = intel/sco
+
+
+CFLAGS = -O -DDEBUG -DSVR4
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/sgi/Makefile b/gnu/usr.bin/lynx/WWW/Library/sgi/Makefile
new file mode 100644
index 00000000000..24530722fb7
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/sgi/Makefile
@@ -0,0 +1,30 @@
+# Make WWW for Silicon Graphics
+#
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = sgi
+
+# Architecutre in ASIS scheme
+# SGI does not presently have ranlib. Ignore the error
+# message about that when the CommonMakefile tries to
+# invoke it.
+ASIS_MACH = sgi/iris-3.5
+
+CFLAGS = -DDEBUG -O -cckr
+CC = cc
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/snake/Makefile b/gnu/usr.bin/lynx/WWW/Library/snake/Makefile
new file mode 100644
index 00000000000..06db3012bf1
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/snake/Makefile
@@ -0,0 +1,33 @@
+# Make WWW under unix for HP 700 or 800 (Snake) using cc
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = snake
+
+# Distribution point for ASIS repository
+ASIS_MACH = hp-700/hpux-8.0
+
+CFLAGS = -O -DDEBUG
+
+# Link with BSD library for getwd()
+LFLAGS = -lBSD
+
+#CC = cc
+#CC = gcc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/solaris2/Makefile b/gnu/usr.bin/lynx/WWW/Library/solaris2/Makefile
new file mode 100644
index 00000000000..a390cae9d0e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/solaris2/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under unix for sun 4
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = solaris2
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = sun-4/sunos-5.2
+
+
+CFLAGS = -O -DDEBUG -DNGROUPS=16 -Dd_namlen=d_reclen -DNO_BCOPY -DSOLARIS2 -DSVR4 -DUSE_DIRENT
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/sun3/Makefile b/gnu/usr.bin/lynx/WWW/Library/sun3/Makefile
new file mode 100644
index 00000000000..ee9c6288e13
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/sun3/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under unix for sun 3
+#
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = sun3
+
+# For ASIS installation, the ASIS code for the machine/os
+ASIS_MACH = sun-3/sunos-4.1.1
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+CFLAGS = -DDEBUG -O
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/sun4/Makefile b/gnu/usr.bin/lynx/WWW/Library/sun4/Makefile
new file mode 100644
index 00000000000..cf14decbcbf
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/sun4/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under unix for sun 4
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = sun4
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = sun-4/sunos-4.1.1
+
+
+CFLAGS = -DDEBUG -O
+LFLAGS =
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/svr4/Makefile b/gnu/usr.bin/lynx/WWW/Library/svr4/Makefile
new file mode 100644
index 00000000000..a97e6656555
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/svr4/Makefile
@@ -0,0 +1,29 @@
+# Make WWW under svr4
+#
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = svr4
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = generic/svr4
+
+
+CFLAGS = -O -DDEBUG -DUSE_DIRENT -DSVR4
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/umaxv-m88k/Makefile b/gnu/usr.bin/lynx/WWW/Library/umaxv-m88k/Makefile
new file mode 100644
index 00000000000..79c323c0d59
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/umaxv-m88k/Makefile
@@ -0,0 +1,30 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = umaxv-m88k
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+
+CFLAGS = -O -DDEBUG -D_SYSV3
+LFLAGS =
+CC = cc
+
+# Directory for installed binary:
+BINDIR = /usr/local/bin
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+
+include $(WWW)/Library/Implementation/CommonMakefile
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/unix/makefile.in b/gnu/usr.bin/lynx/WWW/Library/unix/makefile.in
new file mode 100644
index 00000000000..94918497d7f
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/unix/makefile.in
@@ -0,0 +1,62 @@
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = unix
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+LFLAGS =
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = $(srcdir)
+
+LYFLAGS = # FIXME: set in parent makefile
+
+CC = @CC@
+DEFS = @DEFS@
+CPPFLAGS = @CPPFLAGS@
+CPPOPTS = $(DEFS) $(CPPFLAGS) $(LYFLAGS) -I../../.. -I../../../src -I$(top_srcdir) -I$(top_srcdir)/src
+LY_CFLAGS = @CFLAGS@
+CFLAGS = $(CPPOPTS) $(LY_CFLAGS)
+
+# Directory for installed binary:
+BINDIR = @bindir@
+
+# Where is the W3 object library to be installed (not normally done)?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = $(top_srcdir)/WWW
+
+# Where should temporary (object) files go?
+WTMP = ../..
+
+@make_include_left@$(WWW)/Library/Implementation/Version.make@make_include_right@
+@make_include_left@$(WWW)/Library/Implementation/CommonMakefile@make_include_right@
+
+# Override values set in CommonMakefile
+
+RANLIB = @RANLIB@
+
+all : $(LOB)/libwww.a
+
+.SUFFIXES: .i .h .html
+
+.c.o:
+@RULE_CC@
+ @ECHO_CC@$(CC) $(CPPOPTS) $(CFLAGS) -c $(srcdir)/$*.c
+
+.c.i:
+@RULE_CC@
+ @ECHO_CC@$(CPP) -C $(CPPOPTS) $*.c >$@
+
+depend :
+ makedepend -fmakefile -- $(CFLAGS) -- $(CFILES)
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/gnu/usr.bin/lynx/WWW/Library/unix_x/Makefile b/gnu/usr.bin/lynx/WWW/Library/unix_x/Makefile
new file mode 100644
index 00000000000..23c12453cf7
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/unix_x/Makefile
@@ -0,0 +1,491 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.51 89/12/12 12:37:30 jim Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space. Imake tries to compensate
+# for this, but is not always successful.
+#
+
+###########################################################################
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a02602>
+# $XConsortium: Imake.tmpl,v 1.77 89/12/18 17:01:37 jim Exp $
+#
+# Platform-specific parameters may be set in the appropriate .cf
+# configuration files. Site-wide parameters may be set in the file
+# site.def. Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor doesn't define any unique symbols, you'll need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make Makefile", "make Makefiles", or "make World").
+#
+# If you absolutely can't get imake to work, you'll need to set the
+# variables at the top of each Makefile as well as the dependencies at the
+# bottom (makedepend will do this automatically).
+#
+
+###########################################################################
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform: $XConsortium: sun.cf,v 1.38 89/12/23 16:10:10 jim Exp $
+# operating system: SunOS 4.1.1
+
+###########################################################################
+# site-specific configuration parameters - edit site.def to change
+
+# site: $XConsortium: site.def,v 1.21 89/12/06 11:46:50 jim Exp $
+
+ SHELL = /bin/sh
+
+ TOP = ../../../.
+ CURRENT_DIR = ./../Library/unix_x
+
+ AR = ar cq
+ BOOTSTRAPCFLAGS =
+ CC = gcc -DNOSTDHDRS -fstrength-reduce -fpcc-struct-return -fwritable-strings -traditional
+
+ COMPRESS = compress
+ CPP = /lib/cpp $(STD_CPP_DEFINES)
+ PREPROCESSCMD = gcc -DNOSTDHDRS -fstrength-reduce -fpcc-struct-return -fwritable-strings -traditional -E $(STD_CPP_DEFINES)
+ INSTALL = install
+ LD = ld
+ LINT = lint
+ LINTLIBFLAG = -C
+ LINTOPTS = -axz
+ LN = ln -s
+ MAKE = make
+ MV = mv
+ CP = cp
+ RANLIB = ranlib
+ RANLIBINSTFLAGS =
+ RM = rm -f
+ STD_INCLUDES =
+ STD_CPP_DEFINES =
+ STD_DEFINES =
+ EXTRA_LOAD_FLAGS =
+ EXTRA_LIBRARIES =
+ TAGS = ctags
+
+ SHAREDCODEDEF = -DSHAREDCODE
+ SHLIBDEF = -DSUNSHLIB
+
+ PROTO_DEFINES =
+
+ INSTPGMFLAGS =
+
+ INSTBINFLAGS = -m 0755
+ INSTUIDFLAGS = -m 4755
+ INSTLIBFLAGS = -m 0664
+ INSTINCFLAGS = -m 0444
+ INSTMANFLAGS = -m 0444
+ INSTDATFLAGS = -m 0444
+ INSTKMEMFLAGS = -m 4755
+
+ DESTDIR =
+
+ TOP_INCLUDES = -I$(INCROOT)
+
+ CDEBUGFLAGS = -O
+ CCOPTIONS =
+ COMPATFLAGS =
+
+ ALLINCLUDES = $(STD_INCLUDES) $(TOP_INCLUDES) $(INCLUDES) $(EXTRA_INCLUDES)
+ ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(PROTO_DEFINES) $(DEFINES) $(COMPATFLAGS)
+ CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+ LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+ LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+ LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS)
+ LDCOMBINEFLAGS = -X -r
+
+ MACROFILE = sun.cf
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+ IMAKE_DEFINES =
+
+ IRULESRC = $(CONFIGDIR)
+ IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+###########################################################################
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
+
+###########################################################################
+# X Window System make variables; this need to be coordinated with rules
+# $XConsortium: Project.tmpl,v 1.63 89/12/18 16:46:44 jim Exp $
+
+ PATHSEP = /
+ USRLIBDIR = $(DESTDIR)/usr/lib
+ BINDIR = $(DESTDIR)/usr/bin/X11
+ INCROOT = $(DESTDIR)/usr/include
+ BUILDINCROOT = $(TOP)
+ BUILDINCDIR = $(BUILDINCROOT)/X11
+ BUILDINCTOP = ..
+ INCDIR = $(INCROOT)/X11
+ ADMDIR = $(DESTDIR)/usr/adm
+ LIBDIR = $(USRLIBDIR)/X11
+ CONFIGDIR = $(LIBDIR)/config
+ LINTLIBDIR = $(USRLIBDIR)/lint
+
+ FONTDIR = $(LIBDIR)/fonts
+ XINITDIR = $(LIBDIR)/xinit
+ XDMDIR = $(LIBDIR)/xdm
+ AWMDIR = $(LIBDIR)/awm
+ TWMDIR = $(LIBDIR)/twm
+ GWMDIR = $(LIBDIR)/gwm
+ MANPATH = $(DESTDIR)/usr/man
+ MANSOURCEPATH = $(MANPATH)/man
+ MANDIR = $(MANSOURCEPATH)n
+ LIBMANDIR = $(MANSOURCEPATH)3
+ XAPPLOADDIR = $(LIBDIR)/app-defaults
+
+ SOXLIBREV = 4.2
+ SOXTREV = 4.0
+ SOXAWREV = 4.0
+ SOOLDXREV = 4.0
+ SOXMUREV = 4.0
+ SOXEXTREV = 4.0
+
+ FONTCFLAGS = -t
+
+ INSTAPPFLAGS = $(INSTDATFLAGS)
+
+ IMAKE = imake
+ DEPEND = makedepend
+ RGB = rgb
+ FONTC = bdftosnf
+ MKFONTDIR = mkfontdir
+ MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier.sh
+
+ CONFIGSRC = $(TOP)/config
+ CLIENTSRC = $(TOP)/clients
+ DEMOSRC = $(TOP)/demos
+ LIBSRC = $(TOP)/lib
+ FONTSRC = $(TOP)/fonts
+ INCLUDESRC = $(TOP)/X11
+ SERVERSRC = $(TOP)/server
+ UTILSRC = $(TOP)/util
+ SCRIPTSRC = $(UTILSRC)/scripts
+ EXAMPLESRC = $(TOP)/examples
+ CONTRIBSRC = $(TOP)/../contrib
+ DOCSRC = $(TOP)/doc
+ RGBSRC = $(TOP)/rgb
+ DEPENDSRC = $(UTILSRC)/makedepend
+ IMAKESRC = $(CONFIGSRC)
+ XAUTHSRC = $(LIBSRC)/Xau
+ XLIBSRC = $(LIBSRC)/X
+ XMUSRC = $(LIBSRC)/Xmu
+ TOOLKITSRC = $(LIBSRC)/Xt
+ AWIDGETSRC = $(LIBSRC)/Xaw
+ OLDXLIBSRC = $(LIBSRC)/oldX
+ XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+ BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+ MKFONTDIRSRC = $(FONTSRC)/mkfontdir
+ EXTENSIONSRC = $(TOP)/extensions
+
+ DEPEXTENSIONLIB = $(USRLIBDIR)/libXext.a
+ EXTENSIONLIB = -lXext
+
+ DEPXLIB = $(DEPEXTENSIONLIB)
+ XLIB = $(EXTENSIONLIB) -lX11
+
+ DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+ XAUTHLIB = -lXau
+
+ DEPXMULIB =
+ XMULIB = -lXmu
+
+ DEPOLDXLIB =
+ OLDXLIB = -loldX
+
+ DEPXTOOLLIB =
+ XTOOLLIB = -lXt
+
+ DEPXAWLIB =
+ XAWLIB = -lXaw
+
+ LINTEXTENSIONLIB = $(USRLIBDIR)/llib-lXext.ln
+ LINTXLIB = $(USRLIBDIR)/llib-lX11.ln
+ LINTXMU = $(USRLIBDIR)/llib-lXmu.ln
+ LINTXTOOL = $(USRLIBDIR)/llib-lXt.ln
+ LINTXAW = $(USRLIBDIR)/llib-lXaw.ln
+
+ DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+ DEPLIBS1 = $(DEPLIBS)
+ DEPLIBS2 = $(DEPLIBS)
+ DEPLIBS3 = $(DEPLIBS)
+
+###########################################################################
+# Imake rules for building libraries, programs, scripts, and data files
+# rules: $XConsortium: Imake.rules,v 1.67 89/12/18 17:14:15 jim Exp $
+
+###########################################################################
+# start of Imakefile
+
+# Make WWW under unix for a.n.other unix system (bsd)
+# Use this as a template
+
+TK_WWW_SOURCE_PATH=/a/dxcern/userd/tbl/hypertext/WWW/TkWWW/Tcl
+
+TK_WWW_INSTALL_PATH=/a/dxcern/userd/tbl/hypertext/WWW/TkWWW/$WWW_MACH
+
+TK_WWW_HOME_PAGE=http://www.w3.org/default.html
+TK_WWW_START_PAGE=$(TK_WWW_HOME_PAGE)
+
+CC = gcc -fno-builtin -Wall
+
+CDEBUGFLAGS = -O3 -pipe
+
+COMPATFLAGS = -I/afs/athena.mit.edu/course/other/cdsdev/www-compat
+CCOPTIONS =
+
+BINDIR = $(TK_WWW_INSTALL_PATH)
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = unix_x
+
+# The ASIS repository's name for the machine we are on
+ASIS_MACH = hardware/os
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = /tmp
+
+# Common Makefile for W3 Library Code
+# -----------------------------------
+#
+# (c) CERN 1990, 1991 -- see Copyright.html for conditions
+#
+# This file should be invariant between systems.
+# DEPENDENCIES NOT COMPLETE
+
+#
+# make Compile and link the software (private version)
+# make clean Remove intermediate files
+
+WC = $(WWW)/Library
+CMN = $(WWW)/Library/Implementation/
+
+# Where shall we put the objects and built library?
+
+LOB = $(WTMP)/Library/$(WWW_MACH)
+
+# Bug: This path, if relative, is taken relative to the directory
+# in which this makefile is, not the pwd. This screws up the
+# recursive invocation
+
+VC = 2.14
+
+CFLAGS2 = $(CFLAGS) -I$(CMN)
+
+CERNLIBBIN = $(WWW)/bin
+
+COMMON = $(LOB)/HTParse.o $(LOB)/HTAccess.o $(LOB)/HTTP.o \
+ $(LOB)/HTBTree.o \
+ $(LOB)/HTFile.o $(LOB)/HTFTP.o $(LOB)/HTTCP.o \
+ $(LOB)/SGML.o $(LOB)/HTMLDTD.o $(LOB)/HTChunk.o \
+ $(LOB)/HTPlain.o $(LOB)/HTWriter.o $(LOB)/HTFWriter.o \
+ $(LOB)/HTMLGen.o \
+ $(LOB)/HTAtom.o $(LOB)/HTAnchor.o $(LOB)/HTStyle.o \
+ $(LOB)/HTList.o $(LOB)/HTString.o $(LOB)/HTAlert.o \
+ $(LOB)/HTRules.o $(LOB)/HTFormat.o $(LOB)/HTInit.o $(LOB)/HTMIME.o \
+ $(LOB)/HTHistory.o $(LOB)/HTNews.o $(LOB)/HTGopher.o \
+ $(LOB)/HTTelnet.o $(LOB)/HTWSRC.o $(HTWAIS)
+
+CFILES = $(CMN)HTParse.c $(CMN)HTAccess.c $(CMN)HTTP.c $(CMN)HTBTree.c \
+ $(CMN)HTFile.c \
+ $(CMN)HTFTP.c $(CMN)HTTCP.c $(CMN)SGML.c \
+ $(CMN)HTMLDTD.c \
+ $(CMN)HTPlain.c $(CMN)HTWriter.c $(CMN)HTFWriter.c $(CMN)HTMLGen.c \
+ $(CMN)HTChunk.c $(CMN)HTAtom.c $(CMN)HTAnchor.c $(CMN)HTStyle.c \
+ $(CMN)HTList.c $(CMN)HTString.c $(CMN)HTAlert.c $(CMN)HTRules.c \
+ $(CMN)HTFormat.c $(CMN)HTInit.c $(CMN)HTMIME.c $(CMN)HTHistory.c \
+ $(CMN)HTNews.c $(CMN)HTGopher.c $(CMN)HTTelnet.c \
+ $(CMN)HTWAIS.c $(CMN)HTWSRC.c
+
+HFILES = $(CMN)HTParse.h $(CMN)HTAccess.h $(CMN)HTTP.h $(CMN)HTBTree.h \
+ $(CMN)HTFile.h \
+ $(CMN)HTFTP.h $(CMN)HTTCP.h \
+ $(CMN)SGML.h $(CMN)HTML.h $(CMN)HTMLDTD.h $(CMN)HTChunk.h \
+ $(CMN)HTPlain.h $(CMN)HTWriter.h \
+ $(CMN)HTFWriter.h $(CMN)HTMLGen.h \
+ $(CMN)HTStream.h \
+ $(CMN)HTAtom.h $(CMN)HTAnchor.h $(CMN)HTStyle.h \
+ $(CMN)HTList.h \
+ $(CMN)HTString.h $(CMN)HTAlert.h $(CMN)HTRules.h \
+ $(CMN)HTFormat.h $(CMN)HTInit.h \
+ $(CMN)HTMIME.h $(CMN)HTHistory.h $(CMN)HTNews.h \
+ $(CMN)HTGopher.h \
+ $(CMN)HTUtils.h $(CMN)tcp.h $(CMN)WWW.h $(CMN)HText.h \
+ $(CMN)HTTelnet.h \
+ $(CMN)HTWAIS.h $(CMN)HTWSRC.h
+
+SOURCES = $(CFILES) $(HFILES) $(CMN)Version.make $(CMN)CommonMakefile \
+ $(WWW)/README.txt $(WWW)/Copyright.txt $(WWW)/BUILD
+SPECIFIC = $(WWW)/All
+
+# Library
+#
+# On SGI, ranlib is unnecessary and does not exist so we ignore errors
+# for that step
+all: $(LOB)/libwww.a
+ $(MV) $(LOB)/libwww.a $(WC)/$(WWW_MACH)
+
+$(LOB)/libwww.a : $(COMMON)
+ ar r $(LOB)/libwww.a $(COMMON)
+ -ranlib $(LOB)/libwww.a
+
+# Clean up everything generatable except final products
+clean ::
+ $(RM) $(LOB)
+
+# Clean up everything generatable including final products
+
+cleanall :: clean
+ $(RM) $(LOB)/libwww.a
+
+# Common code
+# -----------
+
+# Directory for object files - .created checks it exists
+
+OE = $(LOB)/.created
+$(OE) :
+ -mkdir $(WTMP)
+ -mkdir $(WTMP)/Library
+ -mkdir $(WTMP)/Library/$(WWW_MACH)
+ touch $@
+
+$(LOB)/HTList.o : $(OE) $(CMN)HTList.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTList.c
+
+$(LOB)/HTAnchor.o : $(OE) $(CMN)HTAnchor.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAnchor.c
+
+$(LOB)/HTFormat.o : $(OE) $(CMN)HTFormat.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFormat.c
+
+$(LOB)/HTInit.o : $(OE) $(CMN)HTInit.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTInit.c
+
+$(LOB)/HTMIME.o : $(OE) $(CMN)HTMIME.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMIME.c
+
+$(LOB)/HTHistory.o : $(OE) $(CMN)HTHistory.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTHistory.c
+
+$(LOB)/HTNews.o : $(OE) $(CMN)HTNews.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTNews.c
+
+$(LOB)/HTGopher.o : $(OE) $(CMN)HTGopher.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTGopher.c
+
+$(LOB)/HTTelnet.o : $(OE) $(CMN)HTTelnet.c $(CMN)HTUtils.h $(CMN)HTTelnet.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTelnet.c
+
+$(LOB)/HTStyle.o : $(OE) $(CMN)HTStyle.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTStyle.c
+
+$(LOB)/HTAtom.o : $(OE) $(CMN)HTAtom.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAtom.c
+
+$(LOB)/HTChunk.o : $(OE) $(CMN)HTChunk.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTChunk.c
+
+$(LOB)/HTString.o : $(OE) $(CMN)HTString.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTString.c
+
+$(LOB)/HTAlert.o : $(OE) $(CMN)HTAlert.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTAlert.c
+
+$(LOB)/HTRules.o : $(OE) $(CMN)HTRules.c $(CMN)HTUtils.h $(CMN)Version.make
+ $(CC) -c -o $@ $(CFLAGS2) -DVC=\"$(VC)\" $(CMN)HTRules.c
+
+$(LOB)/SGML.o : $(OE) $(CMN)SGML.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)SGML.c
+
+$(LOB)/HTMLGen.o : $(OE) $(CMN)HTMLGen.c $(CMN)HTUtils.h $(CMN)HTMLDTD.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLGen.c
+
+$(LOB)/HTMLDTD.o : $(OE) $(CMN)HTMLDTD.c $(CMN)SGML.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTMLDTD.c
+
+$(LOB)/HTPlain.o : $(OE) $(CMN)HTPlain.c $(CMN)HTPlain.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTPlain.c
+
+$(LOB)/HTWAIS.o : $(OE) $(CMN)HTWAIS.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(WAISINC) $(CMN)HTWAIS.c
+
+$(LOB)/HTWSRC.o : $(OE) $(CMN)HTWSRC.c $(CMN)HTUtils.h $(CMN)HTList.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWSRC.c
+
+$(LOB)/HTWriter.o : $(OE) $(CMN)HTWriter.c $(CMN)HTWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTWriter.c
+
+$(LOB)/HTFWriter.o : $(OE) $(CMN)HTFWriter.c $(CMN)HTFWriter.h $(CMN)HTStream.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFWriter.c
+
+# Communications & Files
+
+$(LOB)/HTTP.o : $(OE) $(CMN)HTTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTP.c
+
+$(LOB)/HTTCP.o : $(OE) $(CMN)HTTCP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTTCP.c
+
+$(LOB)/HTBTree.o : $(OE) $(CMN)HTBTree.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTBTree.c
+
+$(LOB)/HTFile.o : $(OE) $(CMN)HTFile.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFile.c
+
+$(LOB)/HTFTP.o : $(OE) $(CMN)HTFTP.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTFTP.c
+
+$(LOB)/HTAccess.o : $(OE) $(CMN)HTAccess.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTAccess.c
+
+$(LOB)/HTParse.o : $(OE) $(CMN)HTParse.c $(CMN)HTUtils.h
+ $(CC) -c -o $@ $(CFLAGS2) $(CMN)HTParse.c
+
+###########################################################################
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+ $(RM_CMD) \#*
+
+Makefile::
+ -@if [ -f Makefile ]; then \
+ echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+ $(TAGS) -w *.[ch]
+ $(TAGS) -xw *.[ch] > TAGS
+
+###########################################################################
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+ @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+###########################################################################
+# dependencies generated by makedepend
+
diff --git a/gnu/usr.bin/lynx/WWW/Library/vax_ultrix/Makefile b/gnu/usr.bin/lynx/WWW/Library/vax_ultrix/Makefile
new file mode 100644
index 00000000000..2caf766cc0e
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/vax_ultrix/Makefile
@@ -0,0 +1,33 @@
+# Make WWW under ultrix with gcc
+#
+
+
+# For W3 distribution, machine type for subdirectories
+WWW_MACH = vax_ultrix
+
+# For ASIS installation, the ASIS code for the machine/os
+ASIS_MACH = none
+
+CC = gcc
+CFLAGS = -O -DDEBUG -Wall
+LFLAGS = -O
+
+# This is bug fix for out-of-date ultrix on cernvax
+# LFLAGS = -O pfcode.o -lresolv
+
+# Directory for installed binary:
+BINDIR = /usr/local/unix
+
+
+#_________________ OK if normal W3 distribution
+# Where is the WWW source root?
+WWW = ../..
+
+# Where should temporary (object) files go?
+WTMP = /tmp
+
+
+# Where is the W3 object library?
+LIBDIR = $(WWW)/Library/Implementation/$(WWW_MACH)
+
+include $(WWW)/Library/Implementation/CommonMakefile
diff --git a/gnu/usr.bin/lynx/WWW/Library/vms/COPYING.LIB b/gnu/usr.bin/lynx/WWW/Library/vms/COPYING.LIB
new file mode 100644
index 00000000000..eb685a5ec98
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/vms/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/gnu/usr.bin/lynx/WWW/Library/vms/descrip.mms b/gnu/usr.bin/lynx/WWW/Library/vms/descrip.mms
new file mode 100644
index 00000000000..216e6aee654
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/vms/descrip.mms
@@ -0,0 +1,255 @@
+! Make WorldWideWeb LIBRARY under VMS
+! =======================================================
+!
+! History:
+! 14 Aug 91 (TBL) Reconstituted
+! 25 Jun 92 (JFG) Added TCP socket emulation over DECnet
+! 07 Sep 93 (MD) Remade for version 2.09a
+! 10 Dec 93 (FM) Upgrade for version 2.14 with Lynx v2.1
+! 13 Dec 93 (FM) Added conditional compilations for VAXC vs. DECC
+! (MMS can't handle a MODULE list as large as the
+! WWWLibrary has become, so this just illustrates
+! how you'd set it up if it could 8-).
+! 26 Oct 94 (RLD) Updated to work with VAX/VMS v5.5-1 and AXP/VMS v6.1
+! 31 Oct 94 (RLD) Updated for Lynx v2.3.4, supporting OpenCMU and
+! TCPWare
+! 18 Nov 94 (FM) Updated for SOCKETSHR/NETLIB
+! 07 Dec 94 (FM) Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+! 03 May 95 (FM) Include /NoMember for DECC (not the default on AXP,
+! and the code assumes byte alignment).
+! 07 Jul 95 (FM) Added GNUC support.
+!
+! Bugs:
+! The dependencies are anything but complete - they were
+! just enough to allow the files to be compiled.
+!
+! Instructions:
+! Copy [WWW.LIBRARY.VMS]DESCRIP.MMS into [WWW.LIBRARY.IMPLEMENTATION]
+! Use the correct command line for your TCP/IP implementation,
+! inside the IMPLEMENTATION directory:
+!
+! $ MMS/MACRO=(MULTINET=1) for VAXC - MultiNet
+! $ MMS/MACRO=(WIN_TCP=1) for VAXC - Wollongong TCP/IP
+! $ MMS/MACRO=(UCX=1) for VAXC - UCX
+! $ MMS/MACRO=(CMU_TCP=1) for VAXC - OpenCMU TCP/IP
+! $ MMS/MACRO=(SOCKETSHR_TCP=1) for VAXC - SOCKETSHR/NETLIB
+! $ MMS/MACRO=(TCPWARE=1) for VAXC - TCPWare TCP/IP
+! $ MMS/MACRO=(DECNET=1) for VAXC - socket emulation over DECnet
+!
+! $ MMS/MACRO=(MULTINET=1,DEC_C=1) for DECC - MultiNet
+! $ MMS/MACRO=(WIN_TCP=1,DEC_C=1) for DECC - Wollongong TCP/IP
+! $ MMS/MACRO=(UCX=1,DEC_C=1) for DECC - UCX
+! $ MMS/MACRO=(CMU_TCP=1,DEC_C=1) for DECC - OpenCMU TCP/IP
+! $ MMS/MACRO=(SOCKETSHR_TCP=1,DEC_C=1) for DECC - SOCKETSHR/NETLIB
+! $ MMS/MACRO=(TCPWARE=1,DEC_C=1) for DECC - TCPWare TCP/IP
+! $ MMS/MACRO=(DECNET=1,DEC_C=1) for DECC - socket emulation over DECnet
+!
+! $ MMS/MACRO=(MULTINET=1,GNU_C=1) for GNUC - MultiNet
+! $ MMS/MACRO=(WIN_TCP=1,GNU_C=1) for GNUC - Wollongong TCP/IP
+! $ MMS/MACRO=(UCX=1,GNU_C=1) for GNUC - UCX
+! $ MMS/MACRO=(CMU_TCP=1,GNU_C=1) for GNUC - OpenCMU TCP/IP
+! $ MMS/MACRO=(SOCKETSHR_TCP=1,GNU_C=1) for GNUC - SOCKETSHR/NETLIB
+! $ MMS/MACRO=(TCPWARE=1,GNU_C=1) for GNUC - TCPWare TCP/IP
+! $ MMS/MACRO=(DECNET=1,GNU_C=1) for GNUC - socket emulation over DECnet
+!
+! To compile with debug mode:
+!
+! $ MMS/MACRO=(MULTINET=1, DEBUG=1) for Multinet
+!
+!
+! If you are on HEP net and want to build using the really latest sources on
+! PRIAM:: then define an extra macro U=PRIAM::, e.g.
+!
+! $ MMS/MACRO=(MULTINET=1, U=PRIAM::) for Multinet
+!
+! This will copy the sources from PRIAM as necessary. You can also try
+!
+! $ MMS/MACRO=(U=PRIAM::) descrip.mms
+!
+! to update this file.
+
+
+.include Version.make
+
+! debug flags
+.ifdef DEBUG
+DEBUGFLAGS = /Debug /NoOptimize
+.endif
+
+! defines valid for all compilations
+EXTRADEFINES = DEBUG, ACCESS_AUTH, VC="""$(VC)"""
+
+! DECC flags for all compilations
+.ifdef DEC_C
+DCFLAGS = /NoMember /Warning=(disable=implicitfunc)
+.endif
+
+.ifdef UCX
+TCP = UCX
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=All $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), UCX)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define=($(EXTRADEFINES), UCX)
+.endif
+.endif
+
+.ifdef TCPWARE
+TCP = TCPWARE
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=All $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), UCX, TCPWARE)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), UCX, TCPWARE)
+.endif
+.endif
+
+.ifdef MULTINET
+TCP = MULTINET
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=ANSI $(DEBUGFLAGS) $(DCFLAGS) /Define=(_DECC_V4_SOURCE, __SOCKET_TYPEDEFS, $(EXTRADEFINES), MULTINET)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), MULTINET)
+.endif
+.endif
+
+.ifdef WIN_TCP
+TCP = WIN_TCP
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=ANSI $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), WIN_TCP)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), WIN_TCP)
+.endif
+.endif
+
+.ifdef CMU_TCP
+TCP = CMU_TCP
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=ANSI $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), CMU_TCP)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), CMU_TCP)
+.endif
+.endif
+
+.ifdef SOCKETSHR_TCP
+TCP = SOCKETSHR_TCP
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=ANSI $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), SOCKETSHR_TCP)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), SOCKETSHR_TCP)
+.endif
+.endif
+
+.ifdef DECNET
+TCP = DECNET
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=All $(DEBUGFLAGS) $(DCFLAGS) /Define=($(EXTRADEFINES), DECNET)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), DECNET)
+.endif
+.endif
+
+.ifdef TCP
+.else
+TCP = MULTINET ! (Default to MULTINET)
+.ifdef DEC_C
+CFLAGS = /decc/Prefix=ANSI $(DEBUGFLAGS) $(DCFLAGS) /Define=(_DECC_V4_SOURCE, __SOCKET_TYPEDEFS, $(EXTRADEFINES), MULTINET)
+.else
+CFLAGS = $(DEBUGFLAGS) /Define = ($(EXTRADEFINES), MULTINET)
+.endif
+.endif
+
+.ifdef GNU_C
+CC = gcc
+.endif
+
+!HEADERS = HTUtils.h, HTStream.h, tcp.h, HText.h -
+! HTParse.h, HTAccess.h, HTTP.h, HTFile.h, -
+! HTBTree.h, HTTCP.h, SGML.h, -
+! HTML.h, HTMLDTD.h, HTChunk.h, HTPlain.h, -
+! HTWriter.h, HTFwriter.h, HTMLGen.h, -
+! HTAtom.h, HTAnchor.h, HTStyle.h, -
+! HTList.h, HTString.h, HTAlert.h, -
+! HTRules.h, HTFormat.h, HTInit.h, -
+! HTMIME.h, HTHistory.h, HTTelnet.h, -
+! HTFinger.h, HTAABrow.h, HTAAFile.h, -
+! HTAAProt.h, HTAAServ.h, HTAAUtil.h, -
+! HTAssoc.h, HTPasswd.h, HTAuth.h, HTUU.h, -
+! HTVMSUtils.h, ufc-crypt.h, patchlevel.h
+
+MODULES = HTParse, HTAccess, HTTP, HTFile, HTBTree, HTFTP, HTTCP, HTString, -
+ SGML, HTMLDTD, HTChunk, HTPlain, HTWriter, HTMLGen, -
+ HTAtom, HTAnchor, HTStyle, HTList, HTRules, HTFormat, -
+ HTMIME, HTHistory, HTNews, HTGopher, HTTelnet, HTFinger, -
+ HTWSRC, HTAAUtil, HTAABrow, HTAAServ, HTAAFile, HTPasswd, HTGroup, -
+ HTACL, HTAuth, HTAAProt, HTAssoc, HTLex, HTUU, HTVMSUtils, getpass, -
+ getline, crypt, crypt_util, HTWAIS, HTVMS_WaisUI, HTVMS_WaisProt
+
+!.ifdef DECNET ! Strip FTP, Gopher, News, WAIS
+!HEADERS = $(COMMON_HEADERS)
+!MODULES = $(COMMON_MODULES)
+!.else
+!HEADERS = $(COMMON_HEADERS), $(EXTRA_HEADERS), $(WAIS_HEADER)
+!MODULES = $(COMMON_MODULES), $(EXTRA_MODULES), $(WAIS_MODULE)
+!.endif
+
+!___________________________________________________________________
+! WWW Library
+
+!library : $(HEADERS) wwwlib_$(TCP)($(MODULES))
+library : wwwlib_$(TCP)($(MODULES))
+ @ Continue
+
+build_$(TCP).com : descrip.mms
+ $(MMS) /NoAction /From_Sources /Output = Build_$(TCP).com /Macro = ($(TCP)=1)
+
+clean :
+ - Set Protection = (Owner:RWED) *.*;-1
+ - Purge /NoLog /NoConfirm
+ - Delete /NoLog /NoConfirm *.obj;,*.olb;
+
+!___________________________________________________________________
+! Simple Dependencies
+
+
+!HTString.obj : HTString.c HTString.h tcp.h Version.make HTUtils.h
+!HTAtom.obj : HTAtom.c HTAtom.h HTUtils.h HTString.h
+!HTChunk.obj : HTChunk.c HTChunk.h HTUtils.h
+!HTList.obj : HTList.c HTList.h HTUtils.h
+!HTBTree.obj : HTBTree.c HTBTree.h HTUtils.h
+!HTMLDTD.obj : HTMLDTD.c HTMLDTD.h SGML.h
+!HTPlain.obj : HTPlain.c HTPlain.h HTStream.h
+!HTWriter.obj : HTWriter.c HTWriter.h HTStream.h
+!HTMLGen.obj : HTMLGen.c HTMLGen.h HTUtils.h HTMLDTD.h
+!HTRules.obj : HTRules.c HTRules.h HTUtils.h Version.make
+!HTMIME.obj : HTMIME.c HTMIME.h HTUtils.h HTList.h
+!HTTelnet.obj : HTTelnet.c HTTelnet.h HTUtils.h
+!HTWAIS.obj : HTWAIS.c HTWAIS.h HTUtils.h HTList.h
+!HTWSRC.obj : HTWSRC.c HTWSRC.h HTUtils.h HTList.h
+!HTAccess.obj : HTAccess.c HTAccess.h HTUtils.h
+!HTAnchor.obj : HTAnchor.c HTAnchor.h HTUtils.h HTList.h
+!HTFile.obj : HTFile.c HTFile.h HTUtils.h HTVMSUtils.h
+!HTFormat.obj : HTFormat.c HTFormat.h HTUtils.h HTML.h SGML.h HTPlain.h HTMLGen.h HTList.h
+!HTFTP.obj : HTFTP.c HTFTP.h HTUtils.h
+!HTGopher.obj : HTGopher.c HTGopher.h HTUtils.h HTList.h
+!HTFinger.obj : HTFinger.c HTFinger.h HTUtils.h HTList.h
+!HTHistory.obj : HTHistory.c HTHistory.h HTUtils.h HTList.h
+!HTNews.obj : HTNews.c HTNews.h HTUtils.h HTList.h
+!HTParse.obj : HTParse.c HTParse.h HTUtils.h
+!HTStyle.obj : HTStyle.c HTStyle.h HTUtils.h
+!HTTCP.obj : HTTCP.c HTTCP.h HTUtils.h tcp.h
+!HTTP.obj : HTTP.c HTTP.h HTUtils.h
+!SGML.obj : SGML.c SGML.h HTUtils.h
+!HTAABrow.obj : HTAABrow.c HTUtils.h
+!HTAAFile.obj : HTAAFile.c HTUtils.h
+!HTAAProt.obj : HTAAProt.c HTUtils.h
+!HTAAServ.obj : HTAAServ.c HTUtils.h
+!HTAAUtil.obj : HTAAUtil.c HTUtils.h
+!HTACL.obj : HTACL.c HTUtils.h
+!HTGroup.obj : HTGroup.c HTUtils.h
+!HTLex.obj : HTLex.c HTUtils.h
+!HTAssoc.obj : HTAssoc.c HTAssoc.h HTAAUtil.h HTString.h
+!HTPasswd.obj : HTPasswd.c HTPasswd.h HTUtils.h HTAAUtil.h HTFile.h tcp.h
+!HTAuth.obj : HTAuth.c HTAuth.h HTUtils.h HTPasswd.h HTAssoc.h HTUU.h
+!HTUU.obj : HTUU.c HTUU.h HTUtils.h
+!crypt.obj : crypt.c ufc-crypt.h
+!HTVMSUtils.obj : HTVMSUtils.c HTVMSUtils.h HTUtils.h
+!crypt_util.obj : crypt_util.c ufc-crypt.h patchlevel.h
diff --git a/gnu/usr.bin/lynx/WWW/Library/vms/libmake.com b/gnu/usr.bin/lynx/WWW/Library/vms/libmake.com
new file mode 100644
index 00000000000..96223f00407
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Library/vms/libmake.com
@@ -0,0 +1,201 @@
+$ v = 'f$verify(0)'
+$! LIBMAKE.COM
+$!
+$! Command file to build the WWWLibrary on VMS systems.
+$!
+$! 08-Oct-1997 F.Macrides macrides@sci.wfeb.edu
+$! Added comments and minor tweaks for convenient addition of
+$! compiler definitions and compiler and linker options.
+$! 26-Jul-1995 F.Macrides macrides@sci.wfeb.edu
+$! Adding support for GNUC.
+$! 03-May-1995 F.Macrides macrides@sci.wfeb.edu
+$! Include /nomember for compilations with DECC. It's not the
+$! default on AXP and the code assumes byte alignment.
+$! 07-Dec-1994 F.Macrides macrides@sci.wfeb.edu
+$! Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+$! 03-NOV-1994 A.Harper A.Harper@kcl.ac.uk
+$! Mods to support SOCKETSHR/NETLIB and add a /DEBUG/NOOPT option
+$! 02-Jun-1994 F.Macrides macrides@sci.wfeb.edu
+$! Mods to support TCPWare (To use non-blocking connects, you need
+$! the DRIVERS_V405B.INC patch from FTP.PROCESS.COM for TCPware for
+$! OpenVMS Version 4.0-5, or a higher version of TCPWare, which will
+$! have that bug in the TCPDRIVER fixed. Otherwise, add NO_IOCTL to
+$! the /define=(...) list.)
+$! 20-May-1994 Andy Harper A.Harper@bay.cc.kcl.ac.uk
+$! Added support for the CMU TCP/IP transport
+$! 13-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Mods for conditional compilations with VAXC versus DECC
+$! 10-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for WWWLibrary v2.14 with Lynx v2.1
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$!
+$! Compiler definitions can be added here as a comma separated
+$! list with a lead comma, e.g., ",HAVE_FOO_H,DO_BLAH". They
+$! will apply only to the libwww-FM modules. - FM
+$!
+$ extra = ""
+$!
+$! If no TCP/IP agent is specified (as the first argument),
+$! prompt for a number from the list. Note that the agent
+$! must be the first argument if the debugger mode is to be
+$! set via a second argument (see below). - FM
+$!
+$ agent = 0
+$ IF P1 .EQS. ""
+$ THEN
+$ write sys$output "Acceptable TCP/IP agents are"
+$ write sys$output " [1] MultiNet (default)"
+$ write sys$output " [2] UCX"
+$ write sys$output " [3] WIN_TCP"
+$ write sys$output " [4] CMU_TCP"
+$ write sys$output " [5] SOCKETSHR_TCP"
+$ write sys$output " [6] TCPWARE"
+$ write sys$output " [7] DECNET"
+$ read sys$command/prompt="Agent [1,2,3,4,5,6,7] (RETURN = [1]) " agent
+$ ENDIF
+$ if agent .eq. 1 .or. agent .eqs. "" .or. p1 .eqs. "MULTINET" then -
+ transport = "MULTINET"
+$ if agent .eq. 2 .or. p1 .eqs. "UCX" then transport = "UCX"
+$ if agent .eq. 3 .or. p1 .eqs. "WIN_TCP" then transport = "WIN_TCP"
+$ if agent .eq. 4 .or. p1 .eqs. "CMU_TCP" then transport = "CMU_TCP"
+$ if agent .eq. 5 .or. p1 .eqs. "SOCKETSHR_TCP" then transport = "SOCKETSHR_TCP"
+$ if agent .eq. 6 .or. p1 .eqs. "TCPWARE" then transport = "TCPWARE"
+$ if agent .eq. 7 .or. p1 .eqs. "DECNET" then transport = "DECNET"
+$!
+$ if transport .eqs. "TCPWARE" then extra = extra + ",UCX"
+$!
+$! Compiler options can be specified here. If there was
+$! a second argument (with any value), then debugger mode
+$! with no optimization will be specified as well. - FM
+$!
+$ cc_opts = ""
+$ if p2 .nes. "" then cc_opts = cc_opts + "/DEBUG/NOOPT"
+$!
+$ IF f$trnlnm("VAXCMSG") .eqs. "DECC$MSG" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/DECC" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/VAXC"
+$ THEN
+$ v1 = f$verify(1)
+$! DECC:
+$ v1 = 'f$verify(0)'
+$ If transport .eqs. "UCX" .or. transport .eqs. "TCPWARE"
+$ Then
+$ v1 = f$verify(1)
+$!
+$ cc/decc/prefix=all /nomember 'cc_opts'-
+ /warning=(disable=implicitfunc)-
+ /DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra',VC="""2.14""")-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---]) -
+ [-.Implementation]HTString.c
+$!
+$ cc := cc/decc/prefix=all /nomember 'cc_opts'-
+ /warning=(disable=implicitfunc)-
+ /DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra')-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---])
+$!
+$ v1 = 'f$verify(0)'
+$ Else
+$ if transport .eqs. "MULTINET" then -
+ extra = extra + ",_DECC_V4_SOURCE,__SOCKET_TYPEDEFS"
+$ v1 = f$verify(1)
+$!
+$ cc/decc/prefix=ansi /nomember 'cc_opts'-
+ /warning=(disable=implicitfunc)-
+ /DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra',VC="""2.14""")-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---]) -
+ [-.Implementation]HTString.c
+$!
+$ cc := cc/decc/prefix=ansi /nomember 'cc_opts'-
+ /warning=(disable=implicitfunc)-
+ /DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra')-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---])
+$!
+$ v1 = 'f$verify(0)'
+$ EndIf
+$ ELSE
+$ IF f$search("gnu_cc:[000000]gcclib.olb") .nes. ""
+$ THEN
+$ v1 = f$verify(1)
+$! GNUC:
+$!
+$ gcc/DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra',VC="""2.14""") 'cc_opts'-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---]) -
+ [-.Implementation]HTString.c
+$!
+$ cc := gcc/DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra') 'cc_opts'-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---])
+$!
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ v1 = f$verify(1)
+$! VAXC:
+$!
+$ cc/DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra',VC="""2.14""") 'cc_opts'-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---]) -
+ [-.Implementation]HTString.c
+$!
+$ cc := cc/DEFINE=(DEBUG,ACCESS_AUTH,'transport''extra') 'cc_opts'-
+ /INCLUDE=([-.Implementation],[---.src],[---.src.chrtrans],[---])
+$!
+$ v1 = 'f$verify(0)'
+$ ENDIF
+$ ENDIF
+$ v1 = f$verify(1)
+$ cc [-.Implementation]HTParse.c
+$ cc [-.Implementation]HTAccess.c
+$ cc [-.Implementation]HTTP.c
+$ cc [-.Implementation]HTFile.c
+$ cc [-.Implementation]HTBTree.c
+$ cc [-.Implementation]HTFTP.c
+$ cc [-.Implementation]HTTCP.c
+$ cc [-.Implementation]SGML.c
+$ cc [-.Implementation]HTMLDTD.c
+$ cc [-.Implementation]HTChunk.c
+$ cc [-.Implementation]HTPlain.c
+$ cc [-.Implementation]HTWriter.c
+$ cc [-.Implementation]HTMLGen.c
+$ cc [-.Implementation]HTAtom.c
+$ cc [-.Implementation]HTAnchor.c
+$ cc [-.Implementation]HTStyle.c
+$ cc [-.Implementation]HTList.c
+$ cc [-.Implementation]HTRules.c
+$ cc [-.Implementation]HTFormat.c
+$ cc [-.Implementation]HTMIME.c
+$ cc [-.Implementation]HTHistory.c
+$ cc [-.Implementation]HTNews.c
+$ cc [-.Implementation]HTGopher.c
+$ cc [-.Implementation]HTTelnet.c
+$ cc [-.Implementation]HTFinger.c
+$ cc [-.Implementation]HTWSRC.c
+$ cc [-.Implementation]HTAAUtil.c
+$ cc [-.Implementation]HTAABrow.c
+$ cc [-.Implementation]HTAAServ.c
+$ cc [-.Implementation]HTAAFile.c
+$ cc [-.Implementation]HTPasswd.c
+$ cc [-.Implementation]HTGroup.c
+$ cc [-.Implementation]HTACL.c
+$ cc [-.Implementation]HTAuth.c
+$ cc [-.Implementation]HTAAProt.c
+$ cc [-.Implementation]HTAssoc.c
+$ cc [-.Implementation]HTLex.c
+$ cc [-.Implementation]HTUU.c
+$ cc [-.Implementation]HTVMSUtils.c
+$ cc [-.Implementation]getpass.c
+$ cc [-.Implementation]getline.c
+$ cc [-.Implementation]crypt.c
+$ cc [-.Implementation]crypt_util.c
+$ cc [-.Implementation]HTWAIS.c
+$ cc [-.Implementation]HTVMS_WaisUI.c
+$ cc [-.Implementation]HTVMS_WaisProt.c
+$!
+$ If f$search("[-.Implementation]WWWLib_''transport'.olb") .eqs. "" Then -
+ LIBRARY/Create [-.Implementation]WWWLib_'transport'.olb
+$ LIBRARY/Replace [-.Implementation]WWWLib_'transport'.olb *.obj
+$ Delete/nolog/noconf *.obj;*
+$!
+$ v1 = 'f$verify(0)'
+$ CLEANUP:
+$ v1 = f$verify(v)
+$exit
diff --git a/gnu/usr.bin/lynx/WWW/Makefile b/gnu/usr.bin/lynx/WWW/Makefile
new file mode 100644
index 00000000000..41a90056fb3
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/Makefile
@@ -0,0 +1,9 @@
+# Make basic WWW distribution
+#
+# See the README and the documentation on the web.
+# When you have done BUILD you will have www so you will be able to
+# read the documentation online.
+#
+all :
+ BUILD
+
diff --git a/gnu/usr.bin/lynx/WWW/README.txt b/gnu/usr.bin/lynx/WWW/README.txt
new file mode 100644
index 00000000000..ad5d8bee56d
--- /dev/null
+++ b/gnu/usr.bin/lynx/WWW/README.txt
@@ -0,0 +1,208 @@
+ Read Me
+ WORLDWIDEWEB CERN-DISTRIBUTED CODE
+
+ See the CERN copyright[1] . This is the README file which you get when you
+ unwrap one of our tar files. These files contain information about
+ hypertext, hypertext systems, and the WorldWideWeb project. If you have
+ taken this with a .tar file, you will have only a subset of the files.
+
+ THIS FILE IS A VERY ABRIDGED VERSION OF THE INFORMATION AVAILABLE ON THE
+ WEB. IF IN DOUBT, READ THE WEB DIRECTLY. If you have not got ANY browser
+ installed yet, do this by telnet to info.cern.ch (no username or password).
+
+ Files from info.cern.ch are also mirrored on ftp.ripe.net.
+
+Archive Directory structure
+
+ Under /pub/www[2] , besides this README file, you'll find bin[3] , src[4]
+ and doc[5] directories. The main archives are as follows:
+
+ bin/xxx/bbbb Executable binaries of program bbbb for system xxx.
+ Check what's there before you bother compiling. (Note
+ HP700/8800 series is "snake")
+
+ bin/next/WorldWideWeb_v.vv.tar.Z
+ The Hypertext Browser/editor for the NeXT -- binary.
+
+ src/WWWLibrary_v.vv.tar.Z
+ The W3 Library. All source, and Makefiles for
+ selected systems.
+
+ src/WWWLineMode_v.vv.tar.Z
+ The Line mode browser - all source, and Makefiles for
+ selected systems. Requires the Library[6] .
+
+ src/WWWDaemon_v.vv.tar.Z
+ The HTTP daemon, and WWW-WAIS gateway programs.
+ Source. Requires the Library.
+
+ src/WWWMailRobot_v.vv.tar.Z
+ The Mail Robot.
+
+ doc/WWWBook.tar.Z A snapshot of our internal documentation - we prefer
+ you to access this on line -- see warnings below.
+
+Basic WWW software installation from source
+
+ This applies to the line mode client and the server. Below, $prod means
+ LineMode or Daemon depending on which you are building.
+
+ GENERATED DIRECTORY STRUCTURE
+
+ The tar files are all designed to be unwrapped in the same (this) directory.
+ They create different parts of a common directory tree under that directory.
+ There may be some duplication. They also generate a few files in this
+ directory: README.*, Copyright.*, and some installation instructions (.txt).
+
+ The directory structure is, for product $prod and machine $WWW_MACH
+
+ WWW/$prod/Implementation
+ Source files for a given product
+
+ WWW/$prod/Implementation/CommonMakefile
+ The machine-independent parts of the Makefile for this
+ product
+
+
+ Read Me (65/66)
+ WWW/$prod/$WWW_MACH/ Area for compiling for a given system
+
+ WWW/All/$WWW_MACH/Makefile.include
+ The machine-dependent parts of the makefile for any
+ product
+
+ WWW/All/Implementation/Makefile.product
+ A makefile which includes both parts above and so can
+ be used from any product, any machine.
+
+ COMPILATION ON ALREADY SUPPORTED PLATFORMS
+
+ You must get the WWWLibrary tar file as well as the products you want and
+ unwrap them all from the same directory.
+
+ You must define the environmant variable WWW_MACH to be the architecure of
+ your machine (sun4, decstation, rs6000, sgi, snake, etc)
+
+ In directory WWW, type BUILD.
+
+ COMPILATION ON NEW PLATFORMS
+
+ If your machine is not on the list:
+
+ Make up a new subdirectory of that name under WWW/$prod and WWW/All,
+ copying the contents of a basically similar architecture's directory.
+
+ Check the WWW/All/$WWW_MACH/Makefile.include for suitable directory and
+ flag definitions.
+
+ Check the file tcp.h for the system-specific include file coordinates,
+ etc.
+
+ Send any changes you have to make back to www-request@info.cern.ch for
+ inclusion into future releases.
+
+ Once you have this set up, type BUILD.
+
+NeXTStep Browser/Editor
+
+ The browser for the NeXT is those files contained in the application
+ directory WWW/Next/Implementation/WorldWideWeb.app and is compiled. When you
+ install the app, you may want to configure the default page,
+ WorldWideWeb.app/default.html. These must point to some useful information!
+ You should keep it up to date with pointers to info on your site and
+ elsewhere. If you use the CERN home page note there is a link at the bottom
+ to the master copy on our server. You should set up the address of your
+ local news server with
+
+ dwrite WorldWideWeb NewsHost news
+
+ replacing the last word with the actual address of your news host. See
+ Installation instructions[7] .
+
+Line Mode browser
+
+ Binaries of this for some systems are available in /pub/www/bin/ . The
+ binaries can be picked up, set executable, and run immediately.
+
+ If there is no binary, see "Installation from source" above.
+
+ (See Installation notes[8] ). Do the same thing (in the same directory) to
+ the WWWLibrary_v.cc.tar.Z file to get the common library.
+
+
+ Read Me (65/130)
+ You will have an ASCII printable manual in the file
+ WWW/LineMode/Defaults/line-mode-guide.txt which you can print out at this
+ stage. This is a frozen copy of some of the online documentation.
+
+ Whe you install the browser, you may configure a default page. This is
+ /usr/local/lib/WWW/default.html for the line mode browser. This must point
+ to some useful information! You should keep it up to date with pointers to
+ info on your site and elsewhere. If you use the CERN home page note there is
+ a link at the bottom to the master copy on our server.
+
+ Some basic documentation on the browser is delivered with the home page in
+ the directory WWW/LineMode/Defaults. A separate tar file of that directory
+ (WWWLineModeDefaults.tar.Z) is available if you just want to update that.
+
+ The rest of the documentation is in hypertext, and so wil be readable most
+ easily with a browser. We suggest that after installing the browser, you
+ browse through the basic documentation so that you are aware of the options
+ and customisation possibilities for example.
+
+Server
+
+ The server can be run very simply under the internet daemon, to export a
+ file directory tree as a browsable hypertext tree. Binaries are avilable
+ for some platofrms, otherwise follow instructions above for compiling and
+ then go on to " Installing the basic W3 server[9] ".
+
+XMosaic
+
+ XMosaic is an X11/Motif W3 browser.
+
+ The sources and binaries are distributed separately from
+ FTP.NCSA.UIUC.EDU[10] , in /Web/xmosaic[11] . Binaries are available for
+ some platforms. If you have to build from source, check the README in the
+ distribution.
+
+ The binaries can be picked up, uncompressed, set "executable" and run
+ immediately.
+
+Viola browser for X11
+
+ Viola is an X11 application for reading global hypertext. If a binary is
+ available from your machine, in /pub/www/bin/.../viola*, then take that and
+ also the Viola "apps" tar file which contains the scripts you will need.
+
+ To generate this from source, you will need both the W3 library and the
+ Viola source files. There is an Imakefile with the viola source directory.
+ You will need to generate the XPA and XPM libraries and the W3 library
+ befere you make viola itself.
+
+Documentation
+
+ In the /pub/www/doc[12] directory are a number articles, preprints and
+ guides on the web.
+
+ See the online WWW bibliography[13] for a list of these and other articles,
+ books, etc. and also the list of WWW Manuals[14] available in text and
+ postscript form.
+
+General
+
+ Your comments will of course be most appreciated, on code, or information on
+ the web which is out of date or misleading. If you write your own hypertext
+ and make it available by anonymous ftp or using a server, tell us and we'll
+ put some pointers to it in ours. Thus spreads the web...
+
+ Read Me (66/195)
+ Tim Berners-Lee
+
+ WorldWideWeb project
+
+ CERN, 1211 Geneva 23, Switzerland
+
+ Tel: +41 22 767 3755; Fax: +41 22 767 7155; email: timbl@info.cern.ch
+
+
diff --git a/gnu/usr.bin/lynx/aclocal.m4 b/gnu/usr.bin/lynx/aclocal.m4
new file mode 100644
index 00000000000..fe75e1c20f1
--- /dev/null
+++ b/gnu/usr.bin/lynx/aclocal.m4
@@ -0,0 +1,1513 @@
+dnl Macros for auto-configure script.
+dnl by T.E.Dickey <dickey@clark.net>
+dnl and Jim Spath <jspath@mail.bcpl.lib.md.us>
+dnl and Philippe De Muyter <phdm@macqel.be>
+dnl
+dnl Created: 1997/1/28
+dnl Updated: 1997/12/23
+dnl
+dnl ---------------------------------------------------------------------------
+dnl ---------------------------------------------------------------------------
+dnl Add an include-directory to $CPPFLAGS. Don't add /usr/include, since it's
+dnl redundant. We don't normally need to add -I/usr/local/include for gcc,
+dnl but old versions (and some misinstalled ones) need that.
+AC_DEFUN([CF_ADD_INCDIR],
+[
+for cf_add_incdir in $1
+do
+ while true
+ do
+ case $cf_add_incdir in
+ /usr/include) # (vi
+ ;;
+ *) # (vi
+ CPPFLAGS="$CPPFLAGS -I$cf_add_incdir"
+ ;;
+ esac
+ cf_top_incdir=`echo $cf_add_incdir | sed -e 's:/include/.*$:/include:'`
+ test "$cf_top_incdir" = "$cf_add_incdir" && break
+ cf_add_incdir="$cf_top_incdir"
+ done
+done
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for existence of alternate-character-set support in curses, so we
+dnl can decide to use it for box characters.
+dnl
+AC_DEFUN([CF_ALT_CHAR_SET],
+[
+AC_MSG_CHECKING([if curses supports alternate-character set])
+AC_CACHE_VAL(cf_cv_alt_char_set,[
+ AC_TRY_LINK([
+#include <$cf_cv_ncurses_header>
+ ],[chtype x = acs_map['l']; acs_map['m'] = 0],
+ [cf_cv_alt_char_set=yes],
+ [cf_cv_alt_char_set=no])])
+AC_MSG_RESULT($cf_cv_alt_char_set)
+test $cf_cv_alt_char_set = yes && AC_DEFINE(ALT_CHAR_SET)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl This is adapted from the macros 'fp_PROG_CC_STDC' and 'fp_C_PROTOTYPES'
+dnl in the sharutils 4.2 distribution.
+AC_DEFUN([CF_ANSI_CC_CHECK],
+[
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(cf_cv_ansi_cc,[
+cf_cv_ansi_cc=no
+cf_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc
+# UnixWare 1.2 (cannot use -Xc, since ANSI/POSIX clashes)
+for cf_arg in "-DCC_HAS_PROTOS" "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+ CFLAGS="$cf_save_CFLAGS $cf_arg"
+ AC_TRY_COMPILE(
+[
+#ifndef CC_HAS_PROTOS
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+#endif
+],[
+ int test (int i, double x);
+ struct s1 {int (*f) (int a);};
+ struct s2 {int (*f) (double a);};],
+ [cf_cv_ansi_cc="$cf_arg"; break])
+done
+CFLAGS="$cf_save_CFLAGS"
+])
+AC_MSG_RESULT($cf_cv_ansi_cc)
+
+if test "$cf_cv_ansi_cc" != "no"; then
+if test ".$cf_cv_ansi_cc" != ".-DCC_HAS_PROTOS"; then
+ CFLAGS="$CFLAGS $cf_cv_ansi_cc"
+else
+ AC_DEFINE(CC_HAS_PROTOS)
+fi
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Allow user to disable a normally-on option.
+AC_DEFUN([CF_ARG_DISABLE],
+[CF_ARG_OPTION($1,[$2 (default: on)],[$3],[$4],yes)])dnl
+dnl ---------------------------------------------------------------------------
+dnl Allow user to enable a normally-off option.
+AC_DEFUN([CF_ARG_ENABLE],
+[CF_ARG_OPTION($1,[$2 (default: off)],[$3],[$4],no)])dnl
+dnl ---------------------------------------------------------------------------
+dnl Restricted form of AC_ARG_ENABLE that ensures user doesn't give bogus
+dnl values.
+dnl
+dnl Parameters:
+dnl $1 = option name
+dnl $2 = help-string
+dnl $3 = action to perform if option is not default
+dnl $4 = action if perform if option is default
+dnl $5 = default option value (either 'yes' or 'no')
+AC_DEFUN([CF_ARG_OPTION],
+[AC_ARG_ENABLE($1,[$2],[test "$enableval" != ifelse($5,no,yes,no) && enableval=ifelse($5,no,no,yes)
+ if test "$enableval" != "$5" ; then
+ifelse($3,,[ :]dnl
+,[ $3]) ifelse($4,,,[
+ else
+ $4])
+ fi],[enableval=$5 ifelse($4,,,[
+ $4
+])dnl
+ ])])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if curses.h defines TRUE/FALSE (it does under SVr4).
+AC_DEFUN([CF_BOOL_DEFS],
+[
+AC_MSG_CHECKING(if TRUE/FALSE are defined)
+AC_CACHE_VAL(cf_cv_bool_defs,[
+AC_TRY_COMPILE([
+#include <$cf_cv_ncurses_header>
+#include <stdio.h>],[int x = TRUE, y = FALSE],
+ [cf_cv_bool_defs=yes],
+ [cf_cv_bool_defs=no])])
+AC_MSG_RESULT($cf_cv_bool_defs)
+if test "$cf_cv_bool_defs" = no ; then
+ AC_DEFINE(TRUE,(1))
+ AC_DEFINE(FALSE,(0))
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for data that is usually declared in <stdio.h> or <errno.h>
+dnl $1 = the name to check
+AC_DEFUN([CF_CHECK_ERRNO],
+[
+AC_MSG_CHECKING([declaration of $1])
+AC_CACHE_VAL(cf_cv_dcl_$1,[
+ AC_TRY_COMPILE([
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h> ],
+ [long x = (long) $1],
+ [eval 'cf_cv_dcl_'$1'=yes'],
+ [eval 'cf_cv_dcl_'$1'=no]')])
+eval 'cf_result=$cf_cv_dcl_'$1
+AC_MSG_RESULT($cf_result)
+
+# It's possible (for near-UNIX clones) that the data doesn't exist
+AC_CACHE_VAL(cf_cv_have_$1,[
+if test $cf_result = no ; then
+ eval 'cf_result=DECL_'$1
+ CF_UPPER(cf_result,$cf_result)
+ AC_DEFINE_UNQUOTED($cf_result)
+ AC_MSG_CHECKING([existence of $1])
+ AC_TRY_LINK([
+#undef $1
+extern long $1;
+],
+ [$1 = 2],
+ [eval 'cf_cv_have_'$1'=yes'],
+ [eval 'cf_cv_have_'$1'=no'])
+ eval 'cf_result=$cf_cv_have_'$1
+ AC_MSG_RESULT($cf_result)
+else
+ eval 'cf_cv_have_'$1'=yes'
+fi
+])
+eval 'cf_result=HAVE_'$1
+CF_UPPER(cf_result,$cf_result)
+eval 'test $cf_cv_have_'$1' = yes && AC_DEFINE_UNQUOTED($cf_result)'
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if a function is declared by including a set of include files.
+dnl Invoke the corresponding actions according to whether it is found or not.
+dnl
+dnl Gcc (unlike other compilers) will only warn about the miscast assignment
+dnl in the first test, but most compilers will oblige with an error in the
+dnl second test.
+dnl
+dnl CF_CHECK_FUNCDECL(INCLUDES, FUNCTION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+AC_DEFUN(CF_CHECK_FUNCDECL,
+[
+AC_MSG_CHECKING([for $2 declaration])
+AC_CACHE_VAL(ac_cv_func_decl_$2,
+[AC_TRY_COMPILE([$1],
+[#ifndef ${ac_func}
+extern int ${ac_func}();
+#endif],[
+AC_TRY_COMPILE([$1],
+[#ifndef ${ac_func}
+int (*p)() = ${ac_func};
+#endif],[
+eval "ac_cv_func_decl_$2=yes"],[
+eval "ac_cv_func_decl_$2=no"])],[
+eval "ac_cv_func_decl_$2=yes"])])
+if eval "test \"`echo '$ac_cv_func_'decl_$2`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], , :, [$3])
+else
+ AC_MSG_RESULT(no)
+ifelse([$4], , , [$4
+])dnl
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if functions are declared by including a set of include files.
+dnl and define DECL_XXX if not.
+dnl
+dnl CF_CHECK_FUNCDECLS(INCLUDES, FUNCTION... [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+AC_DEFUN(CF_CHECK_FUNCDECLS,
+[for ac_func in $2
+do
+CF_CHECK_FUNCDECL([$1], $ac_func,
+[$3],
+[
+ CF_UPPER(ac_tr_func,DECL_$ac_func)
+ AC_DEFINE_UNQUOTED($ac_tr_func) $4])dnl
+done
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if curses supports color. (Note that while SVr3 curses supports
+dnl color, it does this differently from SVr4 curses; more work would be needed
+dnl to accommodate SVr3).
+dnl
+AC_DEFUN([CF_COLOR_CURSES],
+[
+AC_MSG_CHECKING(if curses supports color attributes)
+AC_CACHE_VAL(cf_cv_color_curses,[
+ AC_TRY_LINK([
+#include <${cf_cv_ncurses_header-curses.h}>
+],
+ [chtype x = COLOR_BLUE;
+ has_colors();
+ start_color();
+#ifndef NCURSES_BROKEN
+ wbkgd(curscr, getbkgd(stdscr)); /* X/Open XPG4 aka SVr4 Curses */
+#endif
+ ],
+ [cf_cv_color_curses=yes],
+ [cf_cv_color_curses=no])
+ ])
+AC_MSG_RESULT($cf_cv_color_curses)
+if test $cf_cv_color_curses = yes ; then
+ AC_DEFINE(COLOR_CURSES)
+ test ".$cf_cv_ncurses_broken" != .yes && AC_DEFINE(HAVE_GETBKGD)
+fi
+])
+dnl ---------------------------------------------------------------------------
+dnl Look for the curses libraries. Older curses implementations may require
+dnl termcap/termlib to be linked as well.
+AC_DEFUN([CF_CURSES_LIBS],[
+AC_CHECK_FUNC(initscr,,[
+case $host_os in #(vi
+freebsd*) #(vi
+ AC_CHECK_LIB(mytinfo,tgoto,[LIBS="-lmytinfo $LIBS"])
+ ;;
+hpux10.*)
+ AC_CHECK_LIB(cur_colr,initscr,[
+ LIBS="-lcur_colr $LIBS"
+ CFLAGS="-I/usr/include/curses_colr $CFLAGS"
+ ac_cv_func_initscr=yes
+ ],[
+ AC_CHECK_LIB(Hcurses,initscr,[
+ # HP's header uses __HP_CURSES, but user claims _HP_CURSES.
+ LIBS="-lHcurses $LIBS"
+ CFLAGS="-D__HP_CURSES -D_HP_CURSES $CFLAGS"
+ ac_cv_func_initscr=yes
+ ])])
+ ;;
+esac
+
+if test ".$With5lib" != ".no" ; then
+if test -d /usr/5lib ; then
+ # SunOS 3.x or 4.x
+ CPPFLAGS="$CPPFLAGS -I/usr/5include"
+ LIBS="$LIBS -L/usr/5lib"
+fi
+fi
+
+if test ".$ac_cv_func_initscr" != .yes ; then
+ cf_save_LIBS="$LIBS"
+ cf_term_lib=""
+ cf_curs_lib=""
+
+ # Check for library containing tgoto. Do this before curses library
+ # because it may be needed to link the test-case for initscr.
+ AC_CHECK_FUNC(tgoto,[cf_term_lib=predefined],[
+ for cf_term_lib in termcap termlib unknown
+ do
+ AC_CHECK_LIB($cf_term_lib,tgoto,[break])
+ done
+ ])
+
+ # Check for library containing initscr
+ test "$cf_term_lib" != predefined && test "$cf_term_lib" != unknown && LIBS="-l$cf_term_lib $cf_save_LIBS"
+ for cf_curs_lib in curses ncurses xcurses cursesX jcurses unknown
+ do
+ AC_CHECK_LIB($cf_curs_lib,initscr,[break])
+ done
+ test $cf_curs_lib = unknown && AC_ERROR(no curses library found)
+
+ LIBS="-l$cf_curs_lib $cf_save_LIBS"
+ if test "$cf_term_lib" = unknown ; then
+ AC_MSG_CHECKING(if we can link with $cf_curs_lib library)
+ AC_TRY_LINK([#include <${cf_cv_ncurses_header-curses.h}>],
+ [initscr()],
+ [cf_result=yes],
+ [cf_result=no])
+ AC_MSG_RESULT($cf_result)
+ test $cf_result = no && AC_ERROR(Cannot link curses library)
+ elif test "$cf_term_lib" != predefined ; then
+ AC_MSG_CHECKING(if we need both $cf_curs_lib and $cf_term_lib libraries)
+ AC_TRY_LINK([#include <${cf_cv_ncurses_header-curses.h}>],
+ [initscr(); tgoto((char *)0, 0, 0);],
+ [cf_result=no],
+ [
+ LIBS="-l$cf_curs_lib -l$cf_term_lib $cf_save_LIBS"
+ AC_TRY_LINK([#include <${cf_cv_ncurses_header-curses.h}>],
+ [initscr()],
+ [cf_result=yes],
+ [cf_result=error])
+ ])
+ AC_MSG_RESULT($cf_result)
+ fi
+fi
+
+])])
+dnl ---------------------------------------------------------------------------
+dnl Solaris 2.x curses provides a "performance" tradeoff according to whether
+dnl CURS_PERFORMANCE is defined. If defined, the implementation defines macros
+dnl that access the WINDOW structure. Otherwise, function calls are used.
+AC_DEFUN([CF_CURS_PERFORMANCE],
+[
+AC_MSG_CHECKING([for curses performance tradeoff])
+AC_CACHE_VAL(cf_cv_curs_performance,[
+ cf_cv_curs_performance=no
+ AC_TRY_COMPILE([
+#include <$cf_cv_ncurses_header>],[
+#if defined(wbkgdset) && defined(clearok) && defined(getbkgd)
+ int x = ERR;
+#else
+ int x = ; /* force an error */
+#endif
+ ],[
+ AC_TRY_COMPILE([
+#define CURS_PERFORMANCE
+#include <$cf_cv_ncurses_header>],[
+#if defined(wbkgdset) && defined(clearok) && defined(getbkgd)
+ int x = ; /* force an error */
+#else
+ int x = ERR;
+#endif
+ ],[cf_cv_curs_performance=yes])])])
+AC_MSG_RESULT($cf_cv_curs_performance)
+test $cf_cv_curs_performance = yes && AC_DEFINE(CURS_PERFORMANCE)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for a program in the given list $3, defining the corresponding
+dnl program variable $2.
+dnl
+AC_DEFUN([CF_DEFINE_PROG],[
+AC_MSG_CHECKING(for $1)
+AC_CACHE_VAL(cf_cv_$2,[
+ cf_cv_$2=unknown
+ for cv_path in $3
+ do
+ if test -f $cv_path ; then
+ cf_cv_$2=$cv_path
+ break
+ fi
+ done
+ ])
+AC_MSG_RESULT($cf_cv_$2)
+AC_DEFINE_UNQUOTED($2,"$cf_cv_$2")
+])
+dnl ---------------------------------------------------------------------------
+dnl You can always use "make -n" to see the actual options, but it's hard to
+dnl pick out/analyze warning messages when the compile-line is long.
+dnl
+dnl Sets:
+dnl ECHO_LD - symbol to prefix "cc -o" lines
+dnl RULE_CC - symbol to put before implicit "cc -c" lines (e.g., .c.o)
+dnl SHOW_CC - symbol to put before explicit "cc -c" lines
+dnl ECHO_CC - symbol to put before any "cc" line
+dnl
+AC_DEFUN([CF_DISABLE_ECHO],[
+AC_MSG_CHECKING(if you want to see long compiling messages)
+CF_ARG_DISABLE(echo,
+ [ --disable-echo test: display "compiling" commands],
+ [
+ ECHO_LD='@echo linking [$]@;'
+ RULE_CC=' @echo compiling [$]<'
+ SHOW_CC=' @echo compiling [$]@'
+ ECHO_CC='@'
+],[
+ ECHO_LD=''
+ RULE_CC='# compiling'
+ SHOW_CC='# compiling'
+ ECHO_CC=''
+])
+AC_MSG_RESULT($enableval)
+AC_SUBST(ECHO_LD)
+AC_SUBST(RULE_CC)
+AC_SUBST(SHOW_CC)
+AC_SUBST(ECHO_CC)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if 'errno' is declared in <errno.h>
+AC_DEFUN([CF_ERRNO],
+[
+CF_CHECK_ERRNO(errno)
+])dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([CF_FANCY_CURSES],
+[
+AC_MSG_CHECKING(if curses supports fancy attributes)
+AC_CACHE_VAL(cf_cv_fancy_curses,[
+ AC_TRY_LINK([
+#include <$cf_cv_ncurses_header>
+],
+ [attrset(A_UNDERLINE|A_BOLD|A_REVERSE);
+ wattrset(stdscr, A_BLINK|A_DIM);
+ attroff(A_BOLD);
+ keypad(stdscr,TRUE);
+ ],
+ [cf_cv_fancy_curses=yes],
+ [cf_cv_fancy_curses=no])
+ ])
+AC_MSG_RESULT($cf_cv_fancy_curses)
+test $cf_cv_fancy_curses = yes && AC_DEFINE(FANCY_CURSES)
+])
+dnl ---------------------------------------------------------------------------
+dnl Look for a non-standard library, given parameters for AC_TRY_LINK. We
+dnl prefer a standard location, and use -L options only if we do not find the
+dnl library in the standard library location(s).
+dnl $1 = library name
+dnl $2 = includes
+dnl $3 = code fragment to compile/link
+dnl $4 = corresponding function-name
+dnl
+dnl Sets the variable "$cf_libdir" as a side-effect, so we can see if we had
+dnl to use a -L option.
+AC_DEFUN([CF_FIND_LIBRARY],
+[
+ cf_cv_have_lib_$1=no
+ cf_libdir=""
+ AC_CHECK_FUNC($4,cf_cv_have_lib_$1=yes,[
+ cf_save_LIBS="$LIBS"
+ AC_MSG_CHECKING(for $4 in -l$1)
+ LIBS="-l$1 $LIBS"
+ AC_TRY_LINK([$2],[$3],
+ [AC_MSG_RESULT(yes)
+ cf_cv_have_lib_$1=yes
+ ],
+ [AC_MSG_RESULT(no)
+ CF_LIBRARY_PATH(cf_search,$1)
+ for cf_libdir in $cf_search
+ do
+ AC_MSG_CHECKING(for -l$1 in $cf_libdir)
+ LIBS="-L$cf_libdir -l$1 $cf_save_LIBS"
+ AC_TRY_LINK([$2],[$3],
+ [AC_MSG_RESULT(yes)
+ cf_cv_have_lib_$1=yes
+ break],
+ [AC_MSG_RESULT(no)
+ LIBS="$cf_save_LIBS"])
+ done
+ ])
+ ])
+if test $cf_cv_have_lib_$1 = no ; then
+ AC_ERROR(Cannot link $1 library)
+fi
+case $host_os in #(vi
+linux*) # Suse Linux does not follow /usr/lib convention
+ $1="[$]$1 /lib"
+ ;;
+esac
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for availability of fcntl versus ioctl(,FIONBIO,). Lynx uses this
+dnl for Sequent (ptx), and it is needed for OS/2 EMX.
+AC_DEFUN([CF_FIONBIO],
+[
+AC_CACHE_CHECK(if we should use fcntl or ioctl,cf_cv_fionbio,[
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/ioctl.h>
+],[
+ int ret = ioctl(0, FIONBIO, (char *)0);
+ ],[cf_cv_fionbio=ioctl],[
+AC_TRY_LINK([
+#include <sys/types.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif],[
+ int ret = fcntl(0, F_SETFL, O_NONBLOCK);
+ ],
+ [cf_cv_fionbio=fcntl],
+ [cf_cv_fionbio=unknown])])
+])
+test "$cf_cv_fionbio" = "fcntl" && AC_DEFINE(USE_FCNTL)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl A conventional existence-check for 'lstat' won't work with the Linux
+dnl version of gcc 2.7.0, since the symbol is defined only within <sys/stat.h>
+dnl as an inline function.
+dnl
+dnl So much for portability.
+AC_DEFUN([CF_FUNC_LSTAT],
+[
+AC_MSG_CHECKING(for lstat)
+AC_CACHE_VAL(ac_cv_func_lstat,[
+AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/stat.h>],
+ [lstat(".", (struct stat *)0)],
+ [ac_cv_func_lstat=yes],
+ [ac_cv_func_lstat=no])
+ ])
+AC_MSG_RESULT($ac_cv_func_lstat )
+if test $ac_cv_func_lstat = yes; then
+ AC_DEFINE(HAVE_LSTAT)
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Test for the presence of <sys/wait.h>, 'union wait', arg-type of 'wait()'
+dnl and/or 'waitpid()'.
+dnl
+dnl Note that we cannot simply grep for 'union wait' in the wait.h file,
+dnl because some Posix systems turn this on only when a BSD variable is
+dnl defined.
+dnl
+dnl I don't use AC_HEADER_SYS_WAIT, because it defines HAVE_SYS_WAIT_H, which
+dnl would conflict with an attempt to test that header directly.
+dnl
+AC_DEFUN([CF_FUNC_WAIT],
+[
+AC_REQUIRE([CF_UNION_WAIT])
+if test $cf_cv_type_unionwait = yes; then
+
+ AC_MSG_CHECKING(if union wait can be used as wait-arg)
+ AC_CACHE_VAL(cf_cv_arg_union_wait,[
+ AC_TRY_COMPILE($cf_wait_headers,
+ [union wait x; wait(&x)],
+ [cf_cv_arg_union_wait=yes],
+ [cf_cv_arg_union_wait=no])
+ ])
+ AC_MSG_RESULT($cf_cv_arg_union_wait)
+ test $cf_cv_arg_union_wait = yes && AC_DEFINE(WAIT_USES_UNION)
+
+ AC_MSG_CHECKING(if union wait can be used as waitpid-arg)
+ AC_CACHE_VAL(cf_cv_arg_union_waitpid,[
+ AC_TRY_COMPILE($cf_wait_headers,
+ [union wait x; waitpid(0, &x, 0)],
+ [cf_cv_arg_union_waitpid=yes],
+ [cf_cv_arg_union_waitpid=no])
+ ])
+ AC_MSG_RESULT($cf_cv_arg_union_waitpid)
+ test $cf_cv_arg_union_waitpid = yes && AC_DEFINE(WAITPID_USES_UNION)
+
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Test for availability of useful gcc __attribute__ directives to quiet
+dnl compiler warnings. Though useful, not all are supported -- and contrary
+dnl to documentation, unrecognized directives cause older compilers to barf.
+AC_DEFUN([CF_GCC_ATTRIBUTES],
+[
+if test -n "$GCC"
+then
+cat > conftest.i <<EOF
+#ifndef GCC_PRINTF
+#define GCC_PRINTF 0
+#endif
+#ifndef GCC_SCANF
+#define GCC_SCANF 0
+#endif
+#ifndef GCC_NORETURN
+#define GCC_NORETURN /* nothing */
+#endif
+#ifndef GCC_UNUSED
+#define GCC_UNUSED /* nothing */
+#endif
+EOF
+if test -n "$GCC"
+then
+ AC_CHECKING([for gcc __attribute__ directives])
+ changequote(,)dnl
+cat > conftest.$ac_ext <<EOF
+#line __oline__ "configure"
+#include "confdefs.h"
+#include "conftest.h"
+#include "conftest.i"
+#if GCC_PRINTF
+#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
+#else
+#define GCC_PRINTFLIKE(fmt,var) /*nothing*/
+#endif
+#if GCC_SCANF
+#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var)))
+#else
+#define GCC_SCANFLIKE(fmt,var) /*nothing*/
+#endif
+extern void wow(char *,...) GCC_SCANFLIKE(1,2);
+extern void oops(char *,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN;
+extern void foo(void) GCC_NORETURN;
+int main(int argc GCC_UNUSED, char *argv[] GCC_UNUSED) { return 0; }
+EOF
+ changequote([,])dnl
+ for cf_attribute in scanf printf unused noreturn
+ do
+ CF_UPPER(CF_ATTRIBUTE,$cf_attribute)
+ cf_directive="__attribute__(($cf_attribute))"
+ echo "checking for gcc $cf_directive" 1>&AC_FD_CC
+ case $cf_attribute in
+ scanf|printf)
+ cat >conftest.h <<EOF
+#define GCC_$CF_ATTRIBUTE 1
+EOF
+ ;;
+ *)
+ cat >conftest.h <<EOF
+#define GCC_$CF_ATTRIBUTE $cf_directive
+EOF
+ ;;
+ esac
+ if AC_TRY_EVAL(ac_compile); then
+ test -n "$verbose" && AC_MSG_RESULT(... $cf_attribute)
+ cat conftest.h >>confdefs.h
+# else
+# sed -e 's/__attr.*/\/*nothing*\//' conftest.h >>confdefs.h
+ fi
+ done
+else
+ fgrep define conftest.i >>confdefs.h
+fi
+rm -rf conftest*
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if the compiler supports useful warning options. There's a few that
+dnl we don't use, simply because they're too noisy:
+dnl
+dnl -Wconversion (useful in older versions of gcc, but not in gcc 2.7.x)
+dnl -Wredundant-decls (system headers make this too noisy)
+dnl -Wtraditional (combines too many unrelated messages, only a few useful)
+dnl -Wwrite-strings (too noisy, but should review occasionally)
+dnl -pedantic
+dnl
+AC_DEFUN([CF_GCC_WARNINGS],
+[
+if test -n "$GCC"
+then
+ changequote(,)dnl
+ cat > conftest.$ac_ext <<EOF
+#line __oline__ "configure"
+int main(int argc, char *argv[]) { return argv[argc-1] == 0; }
+EOF
+ changequote([,])dnl
+ AC_CHECKING([for gcc warning options])
+ cf_save_CFLAGS="$CFLAGS"
+ EXTRA_CFLAGS="-W -Wall"
+ cf_warn_CONST=""
+ test "$with_ext_const" = yes && cf_warn_CONST="Wwrite-strings"
+ for cf_opt in \
+ Wbad-function-cast \
+ Wcast-align \
+ Wcast-qual \
+ Winline \
+ Wmissing-declarations \
+ Wmissing-prototypes \
+ Wnested-externs \
+ Wpointer-arith \
+ Wshadow \
+ Wstrict-prototypes $cf_warn_CONST
+ do
+ CFLAGS="$cf_save_CFLAGS $EXTRA_CFLAGS -$cf_opt"
+ if AC_TRY_EVAL(ac_compile); then
+ test -n "$verbose" && AC_MSG_RESULT(... -$cf_opt)
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -$cf_opt"
+ test "$cf_opt" = Wcast-qual && EXTRA_CFLAGS="$EXTRA_CFLAGS -DXTSTRINGDEFINES"
+ fi
+ done
+ rm -f conftest*
+ CFLAGS="$cf_save_CFLAGS"
+fi
+AC_SUBST(EXTRA_CFLAGS)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Construct a search-list for a nonstandard header-file
+AC_DEFUN([CF_HEADER_PATH],
+[$1=""
+if test -d "$includedir" ; then
+test "$includedir" != NONE && $1="[$]$1 $includedir $includedir/$2"
+fi
+if test -d "$oldincludedir" ; then
+test "$oldincludedir" != NONE && $1="[$]$1 $oldincludedir $oldincludedir/$2"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && $1="[$]$1 $prefix/include $prefix/include/$2"
+fi
+test "$prefix" != /usr/local && $1="[$]$1 /usr/local/include /usr/local/include/$2"
+test "$prefix" != /usr && $1="[$]$1 /usr/include /usr/include/$2"
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Insert text into the help-message, for readability, from AC_ARG_WITH.
+AC_DEFUN([CF_HELP_MESSAGE],
+[AC_DIVERT_HELP([$1])dnl
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Construct a search-list for a nonstandard library-file
+AC_DEFUN([CF_LIBRARY_PATH],
+[$1=""
+if test -d "$libdir" ; then
+test "$libdir" != NONE && $1="[$]$1 $libdir $libdir/$2"
+fi
+if test -d "$exec_prefix"; then
+test "$exec_prefix" != NONE && $1="[$]$1 $exec_prefix/lib $exec_prefix/lib/$2"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && \
+test "$prefix" != "$exec_prefix" && $1="[$]$1 $prefix/lib $prefix/lib/$2"
+fi
+test "$prefix" != /usr/local && $1="[$]$1 /usr/local/lib /usr/local/lib/$2"
+test "$prefix" != /usr && $1="[$]$1 /usr/lib /usr/lib/$2"
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if we've got setlocale() and its header, <locale.h>
+AC_DEFUN([CF_LOCALE],
+[
+AC_MSG_CHECKING(for setlocale())
+AC_CACHE_VAL(cf_cv_locale,[
+AC_TRY_LINK([#include <locale.h>],
+ [setlocale(LC_ALL, "")],
+ [cf_cv_locale=yes],
+ [cf_cv_locale=no])
+ ])
+AC_MSG_RESULT($cf_cv_locale)
+test $cf_cv_locale = yes && AC_DEFINE(LOCALE)
+])
+dnl ---------------------------------------------------------------------------
+dnl Check for the use of 'include' in 'make' (BSDI is a special case)
+dnl The symbol $ac_make is set in AC_MAKE_SET, as a side-effect.
+AC_DEFUN([CF_MAKE_INCLUDE],
+[
+AC_MSG_CHECKING(for style of include in makefiles)
+
+make_include_left=""
+make_include_right=""
+make_include_quote="unknown"
+
+cf_inc=head$$
+cf_dir=subd$$
+echo 'RESULT=OK' >$cf_inc
+mkdir $cf_dir
+
+for cf_include in "include" ".include" "!include"
+do
+ for cf_quote in '' '"'
+ do
+ cat >$cf_dir/makefile <<CF_EOF
+SHELL=/bin/sh
+${cf_include} ${cf_quote}../$cf_inc${cf_quote}
+all :
+ @echo 'cf_make_include=\$(RESULT)'
+CF_EOF
+ cf_make_include=""
+ eval `cd $cf_dir && ${MAKE-make} 2>&AC_FD_CC | grep cf_make_include=OK`
+ if test -n "$cf_make_include"; then
+ make_include_left="$cf_include"
+ make_include_quote="$cf_quote"
+ break
+ else
+ echo Tried 1>&AC_FD_CC
+ cat $cf_dir/makefile 1>&AC_FD_CC
+ fi
+ done
+ test -n "$cf_make_include" && break
+done
+
+rm -rf $cf_inc $cf_dir
+
+if test -z "$make_include_left" ; then
+ AC_ERROR(Your $ac_make program does not support includes)
+fi
+if test ".$make_include_quote" != .unknown ; then
+ make_include_left="$make_include_left $make_include_quote"
+ make_include_right="$make_include_quote"
+fi
+
+AC_MSG_RESULT(${make_include_left}file${make_include_right})
+
+AC_SUBST(make_include_left)
+AC_SUBST(make_include_right)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for pre-1.9.9g ncurses (among other problems, the most obvious is
+dnl that color combinations don't work).
+AC_DEFUN([CF_NCURSES_BROKEN],
+[
+AC_REQUIRE([CF_NCURSES_VERSION])
+if test "$cf_cv_ncurses_version" != no ; then
+AC_MSG_CHECKING(for obsolete/broken version of ncurses)
+AC_CACHE_VAL(cf_cv_ncurses_broken,[
+AC_TRY_COMPILE([
+#include <$cf_cv_ncurses_header>],[
+#if defined(NCURSES_VERSION) && defined(wgetbkgd)
+ make an error
+#else
+ int x = 1
+#endif
+],
+ [cf_cv_ncurses_broken=no],
+ [cf_cv_ncurses_broken=yes])
+])
+AC_MSG_RESULT($cf_cv_ncurses_broken)
+if test "$cf_cv_ncurses_broken" = yes ; then
+ AC_MSG_WARN(hmm... you should get an up-to-date version of ncurses)
+ AC_DEFINE(NCURSES_BROKEN)
+fi
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Look for the SVr4 curses clone 'ncurses' in the standard places, adjusting
+dnl the CPPFLAGS variable.
+dnl
+dnl The header files may be installed as either curses.h, or ncurses.h
+dnl (obsolete). If not installed for overwrite, the curses.h file would be
+dnl in an ncurses subdirectory (e.g., /usr/include/ncurses), but someone may
+dnl have installed overwriting the vendor's curses. Only very old versions
+dnl (pre-1.9.2d, the first autoconf'd version) of ncurses don't define
+dnl either __NCURSES_H or NCURSES_VERSION in the header.
+dnl
+dnl If the installer has set $CFLAGS or $CPPFLAGS so that the ncurses header
+dnl is already in the include-path, don't even bother with this, since we cannot
+dnl easily determine which file it is. In this case, it has to be <curses.h>.
+dnl
+AC_DEFUN([CF_NCURSES_CPPFLAGS],
+[
+AC_MSG_CHECKING(for ncurses header file)
+AC_CACHE_VAL(cf_cv_ncurses_header,[
+ AC_TRY_COMPILE([#include <curses.h>],[
+#ifdef NCURSES_VERSION
+printf("%s\n", NCURSES_VERSION);
+#else
+#ifdef __NCURSES_H
+printf("old\n");
+#else
+make an error
+#endif
+#endif
+ ],
+ [cf_cv_ncurses_header=predefined],[
+ CF_HEADER_PATH(cf_search,ncurses)
+ test -n "$verbose" && echo
+ for cf_incdir in $cf_search
+ do
+ for cf_header in \
+ curses.h \
+ ncurses.h
+ do
+changequote(,)dnl
+ if egrep "NCURSES_[VH]" $cf_incdir/$cf_header 1>&AC_FD_CC 2>&1; then
+changequote([,])dnl
+ cf_cv_ncurses_header=$cf_incdir/$cf_header
+ test -n "$verbose" && echo $ac_n " ... found $ac_c" 1>&AC_FD_MSG
+ break
+ fi
+ test -n "$verbose" && echo " ... tested $cf_incdir/$cf_header" 1>&AC_FD_MSG
+ done
+ test -n "$cf_cv_ncurses_header" && break
+ done
+ test -z "$cf_cv_ncurses_header" && AC_ERROR(not found)
+ ])])
+AC_MSG_RESULT($cf_cv_ncurses_header)
+AC_DEFINE(NCURSES)
+
+changequote(,)dnl
+cf_incdir=`echo $cf_cv_ncurses_header | sed -e 's:/[^/]*$::'`
+changequote([,])dnl
+
+case $cf_cv_ncurses_header in # (vi
+*/ncurses.h)
+ AC_DEFINE(HAVE_NCURSES_H)
+ ;;
+esac
+
+case $cf_cv_ncurses_header in # (vi
+predefined) # (vi
+ cf_cv_ncurses_header=curses.h
+ ;;
+*)
+ CF_ADD_INCDIR($cf_incdir)
+ ;;
+esac
+CF_NCURSES_VERSION
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Look for the ncurses library. This is a little complicated on Linux,
+dnl because it may be linked with the gpm (general purpose mouse) library.
+dnl Some distributions have gpm linked with (bsd) curses, which makes it
+dnl unusable with ncurses. However, we don't want to link with gpm unless
+dnl ncurses has a dependency, since gpm is normally set up as a shared library,
+dnl and the linker will record a dependency.
+AC_DEFUN([CF_NCURSES_LIBS],
+[AC_REQUIRE([CF_NCURSES_CPPFLAGS])
+
+ # This works, except for the special case where we find gpm, but
+ # ncurses is in a nonstandard location via $LIBS, and we really want
+ # to link gpm.
+cf_ncurses_LIBS=""
+cf_ncurses_SAVE="$LIBS"
+AC_CHECK_LIB(gpm,Gpm_Open,
+ [AC_CHECK_LIB(gpm,initscr,
+ [LIBS="$cf_ncurses_SAVE"],
+ [cf_ncurses_LIBS="-lgpm"])])
+
+case $host_os in #(vi
+freebsd*)
+ # This is only necessary if you are linking against an obsolete
+ # version of ncurses (but it should do no harm, since it's static).
+ AC_CHECK_LIB(mytinfo,tgoto,[cf_ncurses_LIBS="-lmytinfo $cf_ncurses_LIBS"])
+ ;;
+esac
+
+LIBS="$cf_ncurses_LIBS $LIBS"
+CF_FIND_LIBRARY(ncurses,
+ [#include <${cf_cv_ncurses_header-curses.h}>],
+ [initscr()],
+ initscr)
+
+if test -n "$cf_ncurses_LIBS" ; then
+ AC_MSG_CHECKING(if we can link ncurses without $cf_ncurses_LIBS)
+ cf_ncurses_SAVE="$LIBS"
+ for p in $cf_ncurses_LIBS ; do
+ q=`echo $LIBS | sed -e 's/'$p' //' -e 's/'$p'$//'`
+ if test "$q" != "$LIBS" ; then
+ LIBS="$q"
+ fi
+ done
+ AC_TRY_LINK([#include <${cf_cv_ncurses_header-curses.h}>],
+ [initscr(); mousemask(0,0); tgoto((char *)0, 0, 0);],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_RESULT(no)
+ LIBS="$cf_ncurses_SAVE"])
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for the version of ncurses, to aid in reporting bugs, etc.
+AC_DEFUN([CF_NCURSES_VERSION],
+[AC_MSG_CHECKING(for ncurses version)
+AC_CACHE_VAL(cf_cv_ncurses_version,[
+ cf_cv_ncurses_version=no
+ cf_tempfile=out$$
+ AC_TRY_RUN([
+#include <${cf_cv_ncurses_header-curses.h}>
+int main()
+{
+ FILE *fp = fopen("$cf_tempfile", "w");
+#ifdef NCURSES_VERSION
+# ifdef NCURSES_VERSION_PATCH
+ fprintf(fp, "%s.%d\n", NCURSES_VERSION, NCURSES_VERSION_PATCH);
+# else
+ fprintf(fp, "%s\n", NCURSES_VERSION);
+# endif
+#else
+# ifdef __NCURSES_H
+ fprintf(fp, "old\n");
+# else
+ make an error
+# endif
+#endif
+ exit(0);
+}],[
+ cf_cv_ncurses_version=`cat $cf_tempfile`
+ rm -f $cf_tempfile],,[
+
+ # This will not work if the preprocessor splits the line after the
+ # Autoconf token. The 'unproto' program does that.
+ cat > conftest.$ac_ext <<EOF
+#include <${cf_cv_ncurses_header-curses.h}>
+#undef Autoconf
+#ifdef NCURSES_VERSION
+Autoconf NCURSES_VERSION
+#else
+#ifdef __NCURSES_H
+Autoconf "old"
+#endif
+;
+#endif
+EOF
+ cf_try="$ac_cpp conftest.$ac_ext 2>&AC_FD_CC | grep '^Autoconf ' >conftest.out"
+ AC_TRY_EVAL(cf_try)
+ if test -f conftest.out ; then
+changequote(,)dnl
+ cf_out=`cat conftest.out | sed -e 's@^Autoconf @@' -e 's@^[^"]*"@@' -e 's@".*@@'`
+changequote([,])dnl
+ test -n "$cf_out" && cf_cv_ncurses_version="$cf_out"
+ rm -f conftest.out
+ fi
+])])
+AC_MSG_RESULT($cf_cv_ncurses_version)
+])
+dnl ---------------------------------------------------------------------------
+dnl After checking for functions in the default $LIBS, make a further check
+dnl for the functions that are netlib-related (these aren't always in the
+dnl libc, etc., and have to be handled specially because there are conflicting
+dnl and broken implementations.
+dnl Common library requirements (in order):
+dnl -lresolv -lsocket -lnsl
+dnl -lnsl -lsocket
+dnl -lsocket
+dnl -lbsd
+AC_DEFUN([CF_NETLIBS],[
+cf_test_netlibs=no
+AC_MSG_CHECKING(for network libraries)
+AC_CACHE_VAL(cf_cv_netlibs,[
+AC_MSG_RESULT(working...)
+cf_cv_netlibs=""
+cf_test_netlibs=yes
+AC_CHECK_FUNCS(gethostname,,[
+ CF_RECHECK_FUNC(gethostname,nsl,cf_cv_netlibs,[
+ CF_RECHECK_FUNC(gethostname,socket,cf_cv_netlibs)])])
+#
+# FIXME: sequent needs this library (i.e., -lsocket -linet -lnsl), but
+# I don't know the entrypoints - 97/7/22 TD
+AC_HAVE_LIBRARY(inet,cf_cv_netlibs="-linet $cf_cv_netlibs")
+#
+if test "$ac_cv_func_lsocket" != no ; then
+AC_CHECK_FUNCS(socket,,[
+ CF_RECHECK_FUNC(socket,socket,cf_cv_netlibs,[
+ CF_RECHECK_FUNC(socket,bsd,cf_cv_netlibs)])])
+fi
+#
+AC_CHECK_FUNCS(gethostbyname,,[
+ CF_RECHECK_FUNC(gethostbyname,nsl,cf_cv_netlibs)])
+#
+AC_CHECK_FUNCS(strcasecmp,,[
+ CF_RECHECK_FUNC(strcasecmp,resolv,cf_cv_netlibs)])
+])
+LIBS="$LIBS $cf_cv_netlibs"
+test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&AC_FD_MSG
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for the symbol NGROUPS
+AC_DEFUN([CF_NGROUPS],
+[
+AC_MSG_CHECKING(if NGROUPS is defined)
+AC_CACHE_VAL(cf_cv_ngroups,[
+AC_TRY_COMPILE([
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+],[int x = NGROUPS],
+ [cf_cv_ngroups=yes],
+ [AC_TRY_COMPILE([
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+],[int x = NGROUPS_MAX],
+ [cf_cv_ngroups=NGROUPS_MAX],
+ [cf_cv_ngroups=no])
+ ])
+AC_MSG_RESULT($cf_cv_ngroups)
+if test "$cf_cv_ngroups" = no ; then
+ AC_DEFINE(NGROUPS,16)
+elif test "$cf_cv_ngroups" = NGROUPS_MAX ; then
+ AC_DEFINE(NGROUPS,NGROUPS_MAX)
+fi
+])
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for a given program, defining corresponding symbol.
+dnl $1 = environment variable, which is suffixed by "_PATH" in the #define.
+dnl $2 = program name to find.
+dnl
+dnl If there is more than one token in the result, #define the remaining tokens
+dnl to $1_ARGS. We need this for 'install' in particular.
+dnl
+dnl FIXME: we should allow this to be overridden by environment variables
+dnl
+AC_DEFUN([CF_PATH_PROG],[
+test -z "[$]$1" && $1=$2
+if test "$with_full_paths" = yes ; then
+ AC_PATH_PROG($1,$2,[$]$1)
+else
+ AC_MSG_CHECKING(for $2)
+ AC_MSG_RESULT([$]$1)
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_$1
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+AC_DEFINE_UNQUOTED($1_PATH,"$cf_path_prog")
+test -n "$cf_path_args" && AC_DEFINE_UNQUOTED($1_ARGS,"$cf_path_args")
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Re-check on a function to see if we can pick it up by adding a library.
+dnl $1 = function to check
+dnl $2 = library to check in
+dnl $3 = environment to update (e.g., $LIBS)
+dnl $4 = what to do if this fails
+dnl
+dnl This uses 'unset' if the shell happens to support it, but leaves the
+dnl configuration variable set to 'unknown' if not. This is a little better
+dnl than the normal autoconf test, which gives misleading results if a test
+dnl for the function is made (e.g., with AC_CHECK_FUNC) after this macro is
+dnl used (autoconf does not distinguish between a null token and one that is
+dnl set to 'no').
+AC_DEFUN([CF_RECHECK_FUNC],[
+AC_CHECK_LIB($2,$1,[
+ CF_UPPER(cf_tr_func,$1)
+ AC_DEFINE_UNQUOTED(HAVE_$cf_tr_func)
+ ac_cv_func_$1=yes
+ $3="-l$2 [$]$3"],[
+ ac_cv_func_$1=unknown
+ unset ac_cv_func_$1 2>/dev/null
+ $4],
+ [[$]$3])
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for broken definition of 'remove()'. This is (in particular) broken
+dnl on the older version of SCO (I'd cite version if I knew where to look) by
+dnl having <stdio.h> #define remove to __unlink, which appears in no library.
+dnl
+dnl Fortuitously, we can combine this with a more general test: do we have
+dnl 'unlink()' but no 'remove()'. Note, however, that we cannot simply #define
+dnl remove to unlink, but have to make a fallback function.
+dnl
+AC_DEFUN([CF_REMOVE_BROKEN],
+[
+AC_MSG_CHECKING(for broken/missing definition of remove)
+AC_CACHE_VAL(cf_cv_baddef_remove,[
+AC_TRY_LINK(
+ [#include <stdio.h>],
+ [remove("dummy")],
+ [cf_cv_baddef_remove=no],
+ [AC_TRY_LINK(
+ [#include <stdio.h>
+ int __unlink(name) { return unlink(name); } ],
+ [remove("dummy")],
+ [cf_cv_baddef_remove=yes],
+ [cf_cv_baddef_remove=unknown])
+ ])
+])
+AC_MSG_RESULT($cf_cv_baddef_remove)
+test "$cf_cv_baddef_remove" != no && AC_DEFINE(NEED_REMOVE)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for definitions & structures needed for window size-changing
+dnl FIXME: check that this works with "snake" (HP-UX 10.x)
+AC_DEFUN([CF_SIZECHANGE],
+[
+AC_MSG_CHECKING([declaration of size-change])
+AC_CACHE_VAL(cf_cv_sizechange,[
+ cf_cv_sizechange=unknown
+ cf_save_CFLAGS="$CFLAGS"
+
+for cf_opts in "" "NEED_PTEM_H"
+do
+
+ CFLAGS="$cf_save_CFLAGS"
+ test -n "$cf_opts" && CFLAGS="$CFLAGS -D$cf_opts"
+ AC_TRY_COMPILE([#include <sys/types.h>
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#else
+#if HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#endif
+#if NEED_PTEM_H
+/* This is a workaround for SCO: they neglected to define struct winsize in
+ * termios.h -- it's only in termio.h and ptem.h
+ */
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#if !defined(sun) || !defined(HAVE_TERMIOS_H)
+#include <sys/ioctl.h>
+#endif
+],[
+#ifdef TIOCGSIZE
+ struct ttysize win; /* FIXME: what system is this? */
+ int y = win.ts_lines;
+ int x = win.ts_cols;
+#else
+#ifdef TIOCGWINSZ
+ struct winsize win;
+ int y = win.ws_row;
+ int x = win.ws_col;
+#else
+ no TIOCGSIZE or TIOCGWINSZ
+#endif /* TIOCGWINSZ */
+#endif /* TIOCGSIZE */
+ ],
+ [cf_cv_sizechange=yes],
+ [cf_cv_sizechange=no])
+
+ CFLAGS="$cf_save_CFLAGS"
+ if test "$cf_cv_sizechange" = yes ; then
+ echo "size-change succeeded ($cf_opts)" >&AC_FD_CC
+ test -n "$cf_opts" && AC_DEFINE_UNQUOTED($cf_opts)
+ break
+ fi
+done
+ ])
+AC_MSG_RESULT($cf_cv_sizechange)
+test $cf_cv_sizechange != no && AC_DEFINE(HAVE_SIZECHANGE)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Look for the slang header files in the standard places, adjusting the
+dnl CPPFLAGS variable.
+dnl
+AC_DEFUN([CF_SLANG_CPPFLAGS],
+[
+AC_MSG_CHECKING(for slang header file)
+AC_CACHE_VAL(cf_cv_slang_header,[
+ AC_TRY_COMPILE([#include <slang.h>],
+ [printf("%s\n", SLANG_VERSION)],
+ [cf_cv_slang_header=predefined],[
+ CF_HEADER_PATH(cf_search,slang)
+ for cf_incdir in $cf_search
+ do
+ for cf_header in \
+ slang.h
+ do
+ echo trying $cf_incdir/$cf_header 1>&AC_FD_CC
+ if egrep "SLANG_VERSION" $cf_incdir/$cf_header 1>&AC_FD_CC 2>&1; then
+ cf_cv_slang_header=$cf_incdir/$cf_header
+ break
+ fi
+ done
+ test -n "$cf_cv_slang_header" && break
+ done
+ test -z "$cf_cv_slang_header" && AC_ERROR(not found)
+ ])])
+AC_MSG_RESULT($cf_cv_slang_header)
+AC_DEFINE(USE_SLANG)
+
+changequote(,)dnl
+cf_incdir=`echo $cf_cv_slang_header | sed -e 's:/[^/]*$::'`
+changequote([,])dnl
+
+case $cf_cv_slang_header in # (vi
+predefined) # (vi
+ ;;
+*)
+ CF_ADD_INCDIR($cf_incdir)
+ ;;
+esac
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Look for the slang library.
+AC_DEFUN([CF_SLANG_LIBS],
+[
+cf_slang_LIBS1="$LIBS"
+CF_TERMCAP_LIBS
+cf_slang_LIBS2="$LIBS"
+AC_CHECK_FUNC(acos,,[CF_RECHECK_FUNC(acos,m,LIBS)])
+CF_FIND_LIBRARY(slang,
+ [#include <slang.h>],
+ [SLtt_get_screen_size()],
+ SLtt_get_screen_size)
+cf_slang_LIBS3="$LIBS"
+AC_MSG_CHECKING(if we can link slang without termcap)
+if test -n "`echo $cf_slang_LIBS1 | sed -e 's/ //g'`" ; then
+ cf_exclude=`echo ".$cf_slang_LIBS2" | sed -e "s@$cf_slang_LIBS1@@" -e 's@^.@@'`
+else
+ cf_exclude="$cf_slang_LIBS2"
+fi
+LIBS=`echo ".$cf_slang_LIBS3" | sed -e "s@$cf_exclude@@" -e 's@^.@@'`
+AC_TRY_LINK([#include <slang.h>],
+ [SLtt_get_screen_size()],
+ [cf_result=yes],
+ [cf_result=no])
+AC_MSG_RESULT($cf_result)
+test $cf_result = no && LIBS="$cf_slang_LIBS3"
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Remove "-g" option from the compiler options
+AC_DEFUN([CF_STRIP_G_OPT],
+[$1=`echo ${$1} | sed -e 's/-g //' -e 's/-g$//'`])dnl
+dnl ---------------------------------------------------------------------------
+dnl Remove "-O" option from the compiler options
+AC_DEFUN([CF_STRIP_O_OPT],[
+changequote(,)dnl
+$1=`echo ${$1} | sed -e 's/-O[1-9]\? //' -e 's/-O[1-9]\?$//'`
+changequote([,])dnl
+])dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([CF_SYSTEM_MAIL_FLAGS],
+[
+AC_MSG_CHECKING([system mail flags])
+AC_CACHE_VAL(cf_cv_system_mail_flags,[
+ case $cf_cv_SYSTEM_MAIL in
+ */mmdf/*)
+ [cf_cv_system_mail_flags="-mlruxto,cc\\\\*"]
+ ;;
+ *)
+ [cf_cv_system_mail_flags="-t -oi"]
+ esac
+ ])
+AC_MSG_RESULT($cf_cv_system_mail_flags)
+AC_DEFINE_UNQUOTED(SYSTEM_MAIL_FLAGS, "$cf_cv_system_mail_flags")
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check for declaration of sys_nerr and sys_errlist in one of stdio.h and
+dnl errno.h. Declaration of sys_errlist on BSD4.4 interferes with our
+dnl declaration. Reported by Keith Bostic.
+AC_DEFUN([CF_SYS_ERRLIST],
+[
+for cf_name in sys_nerr sys_errlist
+do
+ CF_CHECK_ERRNO($cf_name)
+done
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Look for termcap libraries, needed by some versions of slang.
+AC_DEFUN([CF_TERMCAP_LIBS],
+[
+AC_CACHE_VAL(cf_cv_lib_termcap,[
+cf_cv_lib_termcap=none
+# HP-UX 9.x terminfo has setupterm, but no tigetstr.
+if test "$termlib" = none; then
+ AC_CHECK_LIB(termlib, tigetstr, [LIBS="$LIBS -ltermlib" cf_cv_lib_termcap=terminfo])
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ AC_CHECK_LIB(termlib, tgoto, [LIBS="$LIBS -ltermlib" cf_cv_lib_termcap=termcap])
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ # allow curses library for broken AIX system.
+ AC_CHECK_LIB(curses, initscr, [LIBS="$LIBS -lcurses" cf_cv_lib_termcap=termcap])
+ AC_CHECK_LIB(termcap, tgoto, [LIBS="$LIBS -ltermcap" cf_cv_lib_termcap=termcap])
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ AC_CHECK_LIB(termcap, tgoto, [LIBS="$LIBS -ltermcap" cf_cv_lib_termcap=termcap])
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ AC_CHECK_LIB(ncurses, tgoto, [LIBS="$LIBS -lncurses" cf_cv_lib_termcap=ncurses])
+fi
+])
+if test "$cf_cv_lib_termcap" = none; then
+ AC_ERROR([Can't find -ltermlib, -lcurses, or -ltermcap])
+fi
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Check if including both termio.h and termios.h die like on DG.UX
+AC_DEFUN([CF_TERMIO_AND_TERMIOS],
+[
+AC_MSG_CHECKING([termio.h and termios.h])
+AC_CACHE_VAL(cf_cv_termio_and_termios,[
+ AC_TRY_COMPILE([
+#if HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#endif ],
+ [putchar (0x0a)],
+ [cf_cv_termio_and_termios=yes],
+ [cf_cv_termio_and_termios=no])])
+AC_MSG_RESULT($cf_cv_termio_and_termios)
+test $cf_cv_termio_and_termios = no && AC_DEFINE(TERMIO_AND_TERMIOS)
+])dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([CF_TTYTYPE],
+[
+AC_MSG_CHECKING(if ttytype is declared in curses library)
+AC_CACHE_VAL(cf_cv_have_ttytype,[
+ AC_TRY_LINK([#include <$cf_cv_ncurses_header>],
+ [char *x = &ttytype[1]; *x = 1],
+ [cf_cv_have_ttytype=yes],
+ [cf_cv_have_ttytype=no])
+ ])
+AC_MSG_RESULT($cf_cv_have_ttytype)
+test $cf_cv_have_ttytype = yes && AC_DEFINE(HAVE_TTYTYPE)
+])
+dnl ---------------------------------------------------------------------------
+dnl Check to see if the BSD-style union wait is declared. Some platforms may
+dnl use this, though it is deprecated in favor of the 'int' type in Posix.
+dnl Some vendors provide a bogus implementation that declares union wait, but
+dnl uses the 'int' type instead; we try to spot these by checking for the
+dnl associated macros.
+dnl
+dnl Ahem. Some implementers cast the status value to an int*, as an attempt to
+dnl use the macros for either union wait or int. So we do a check compile to
+dnl see if the macros are defined and apply to an int.
+dnl
+dnl Sets: $cf_cv_type_unionwait
+dnl Defines: HAVE_TYPE_UNIONWAIT
+AC_DEFUN([CF_UNION_WAIT],
+[
+AC_REQUIRE([CF_WAIT_HEADERS])
+AC_MSG_CHECKING([for union wait])
+AC_CACHE_VAL(cf_cv_type_unionwait,[
+ AC_TRY_LINK($cf_wait_headers,
+ [int x;
+ int y = WEXITSTATUS(x);
+ int z = WTERMSIG(x);
+ wait(&x);
+ ],
+ [cf_cv_type_unionwait=no
+ echo compiles ok w/o union wait 1>&AC_FD_CC
+ ],[
+ AC_TRY_LINK($cf_wait_headers,
+ [union wait x;
+#ifdef WEXITSTATUS
+ int y = WEXITSTATUS(x);
+#endif
+#ifdef WTERMSIG
+ int z = WTERMSIG(x);
+#endif
+ wait(&x);
+ ],
+ [cf_cv_type_unionwait=yes
+ echo compiles ok with union wait and possibly macros too 1>&AC_FD_CC
+ ],
+ [cf_cv_type_unionwait=no])])])
+AC_MSG_RESULT($cf_cv_type_unionwait)
+test $cf_cv_type_unionwait = yes && AC_DEFINE(HAVE_TYPE_UNIONWAIT)
+])dnl
+dnl ---------------------------------------------------------------------------
+dnl Make an uppercase version of a variable
+dnl $1=uppercase($2)
+AC_DEFUN([CF_UPPER],
+[
+changequote(,)dnl
+$1=`echo $2 | tr '[a-z]' '[A-Z]'`
+changequote([,])dnl
+])dnl
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([CF_UTMP],
+[
+AC_MSG_CHECKING(if struct utmp is declared)
+AC_CACHE_VAL(cf_cv_have_utmp,[
+ AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <utmp.h>],
+ [struct utmp x; char *y = &x.ut_host[0]],
+ [cf_cv_have_utmp=yes],
+ [AC_TRY_COMPILE([#include <utmpx.h>],
+ [struct utmpx x; char *y = &x.ut_host[0]],
+ [cf_cv_have_utmp=utmpx],
+ [cf_cv_have_utmp=no])
+ ])
+ ])
+AC_MSG_RESULT($cf_cv_have_utmp)
+test $cf_cv_have_utmp != no && AC_DEFINE(HAVE_UTMP)
+test $cf_cv_have_utmp = utmpx && AC_DEFINE(UTMPX_FOR_UTMP)
+])
+dnl ---------------------------------------------------------------------------
+dnl Build up an expression $cf_wait_headers with the header files needed to
+dnl compile against the prototypes for 'wait()', 'waitpid()', etc. Assume it's
+dnl Posix, which uses <sys/types.h> and <sys/wait.h>, but allow SVr4 variation
+dnl with <wait.h>.
+AC_DEFUN([CF_WAIT_HEADERS],
+[
+AC_HAVE_HEADERS(sys/wait.h)
+cf_wait_headers="#include <sys/types.h>
+"
+if test $ac_cv_header_sys_wait_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <sys/wait.h>
+"
+else
+AC_HAVE_HEADERS(wait.h)
+AC_HAVE_HEADERS(waitstatus.h)
+if test $ac_cv_header_wait_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <wait.h>
+"
+fi
+if test $ac_cv_header_waitstatus_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <waitstatus.h>
+"
+fi
+fi
+])dnl
diff --git a/gnu/usr.bin/lynx/build-slang.com b/gnu/usr.bin/lynx/build-slang.com
new file mode 100644
index 00000000000..852afcae247
--- /dev/null
+++ b/gnu/usr.bin/lynx/build-slang.com
@@ -0,0 +1,359 @@
+$ v = 'f$verify(0)'
+$! BUILD-SLANG.COM
+$!
+$! Command file to build LYNX.EXE with SLANG instead of CURSES on VMS.
+$! Assumes you have SLANG v0.99-27 or higher, available from:
+$! ftp://space.mit.edu/pub/davis
+$! Also invokes build of the WWWLibrary if its
+$! object library does not already exist.
+$!=========================================================================
+$! NOTE: Set SLANGINC to the location of your slang.h and slcurses.h,
+$! ==== and SLANGLIB to the location of your slang.olb (can be relative
+$! to the lynx2-8.src subdirectory of this distribution):
+$!
+$! SLANGINC = "[-.slang.src]"
+$! SLANGLIB = "[-.slang.src]"
+$!
+$!=========================================================================
+$ If f$type(SLANGINC) .nes. "STRING" .or. f$type(SLANGLIB) .nes. "STRING"
+$ Then
+$ write sys$output ""
+$ write sys$output " READ the header of this command procedure!!!"
+$ write sys$output ""
+$ exit
+$ EndIf
+$!==========================================================================
+$!
+$! 08-Oct-1997 F.Macrides macrides@sci.wfeb.edu
+$! Added comments and minor tweaks for convenient addition of
+$! compiler definitions and compiler and linker options.
+$! 28-Jun-1997 F.Macrides macrides@sci.wfeb.edu
+$! Added chartrans support.
+$! 29-Mar-1996 F.Macrides macrides@sci.wfeb.edu
+$! Modified build.com to create build-slang.com
+$! 29-Feb-1996 F.Macrides macrides@sci.wfeb.edu
+$! Added LYMap to the compilation and link lists.
+$! 26-Jul-1995 F.Macrides macrides@sci.wfeb.edu
+$! Reorganized the option files into ones for the transport and
+$! ones for the compiler, and adding support for GNUC.
+$! 14-Jun-1995 F.Macrides macrides@sci.wfeb.edu
+$! Added LYList.
+$! 03-May-1995 F.Macrides macrides@sci.wfeb.edu
+$! Include /nomember for compilations with DECC. It's not the
+$! default on AXP and the code assumes byte alignment.
+$! 23-Mar-1995 F.Macrides macrides@sci.wfeb.edu
+$! Replaced references to v2.3.8 or v2.3.9 with v2.3-FM to avoid
+$! any confusion with official releases at UKans.
+$! 16-Mar-1995 F.Macrides macrides@sci.wfeb.edu
+$! Updated to permit submission to BATCH.
+$! 17-Feb-1995 F.Macrides macriees@sci.wfeb.edu
+$! Updated for v2.3-FM
+$! 07-Dec-1994 F.Macrides macrides@sci.wfeb.edu
+$! Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+$! 03-OCT-1994 A.Harper A.Harper@kcl.ac.uk
+$! Mods to support SOCKETSHR/NETLIB and add a /DEBUG/NOOPT option
+$! 02-Jun-1994 F.Macrides macrides@sci.wfeb.edu
+$! Mods to support TCPWare (To use non-blocking connects, you need
+$! the DRIVERS_V405B.INC patch from FTP.PROCESS.COM for TCPware for
+$! OpenVMS Version 4.0-5, or a higher version of TCPWare, which will
+$! have that bug in the TCPDRIVER fixed. Otherwise, add NO_IOCTL to
+$! the $ cc := cc/define=(...) list in [.WWW.Library.VMS]libmake.com).
+$! 20-May-1994 Andy Harper A.Harper@bay.cc.kcl.ac.uk
+$! Mods to support CMU TCP/IP
+$! 13-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Mods for conditional compilations with VAXC versus DECC
+$! 10-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for Lynx v2.1
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$ proc = f$environment("PROCEDURE")
+$ where = f$parse(proc,,,"DEVICE") + f$parse(proc,,,"DIRECTORY")
+$ set default 'where'
+$ write sys$output "Default directory:"
+$ show default
+$ write sys$output ""
+$!
+$! Compiler definitions can be added here as a comma separated
+$! list with a lead comma, e.g., ",HAVE_FOO_H,DO_BLAH". The
+$! definitions will apply only to the LYfoo.c modules. Ones
+$! for the libwww-FM modules can be added equivalently in
+$! [.WWW.Library.vms]libmake.com. - FM
+$!
+$ extra = ""
+$!
+$! If no TCP/IP agent is specified (as the first argument),
+$! prompt for a number from the list. Note that the agent
+$! must be the first argument if the debugger mode is to be
+$! set via a second argument (see below). - FM
+$!
+$ agent = 0
+$ IF P1 .EQS. ""
+$ THEN
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output "TCP/IP agent not specified!"
+$ write sys$output "Defaulting to MULTINET"
+$ agent = 1
+$ Else
+$ write sys$output "Acceptable TCP/IP agents are"
+$ write sys$output " [1] MULTINET (default)"
+$ write sys$output " [2] UCX"
+$ write sys$output " [3] WIN_TCP"
+$ write sys$output " [4] CMU_TCP"
+$ write sys$output " [5] SOCKETSHR_TCP"
+$ write sys$output " [6] TCPWARE"
+$ read sys$command/prompt="Agent [1,2,3,4,5,6] (RETURN = [1]) " agent
+$ EndIf
+$ ENDIF
+$ option = ""
+$ if agent .eq. 1 .or. agent .eqs. "" .or. p1 .eqs. "MULTINET" then -
+ option = "MULTINET"
+$ if agent .eq. 2 .or. p1 .eqs. "UCX" then option = "UCX"
+$ if agent .eq. 3 .or. p1 .eqs. "WIN_TCP" then option = "WIN_TCP"
+$ if agent .eq. 4 .or. p1 .eqs. "CMU_TCP" then option = "CMU_TCP"
+$ if agent .eq. 5 .or. p1 .eqs. "SOCKETSHR_TCP" then option = "SOCKETSHR_TCP"
+$ if agent .eq. 6 .or. p1 .eqs. "TCPWARE" then option = "TCPWARE"
+$!
+$ if option .eqs. "TCPWARE"
+$ then
+$ write sys$output "Building Lynx for TCPWARE with UCX emulation..."
+$ extra = extra + ",UCX"
+$ endif
+$!
+$ optfile = "''option'"
+$!
+$! Compiler and linker options can be specified here. If
+$! there was a second argument (with any value), then debugger
+$! mode with no optimization will be specified as well. The
+$! compiler options will apply only to the LYfoo.c and UCfoo.c
+$! modules. Ones for the libwww-FM modules can be specified
+$! in [.WWW.Library.vms]libmake.com. - FM
+$!
+$ cc_opts = ""
+$ link_opts = ""
+$!
+$ if p2 .nes. ""
+$ then
+$ debug_arg = "DEBUG"
+$ cc_opts = cc_opts + "/DEBUG/NOOPT"
+$ link_opts = link_opts + "/DEBUG"
+$ else
+$ debug_arg = ""
+$ endif
+$!
+$ IF f$search("[.WWW.Library.Implementation]WWWLib_''option'.olb") .nes. ""
+$ THEN
+$ write sys$output " WWWLib_''option'.olb already exists."
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output " Updating WWWLib_''option'.olb"
+$ Else
+$ read sys$command/prompt=" Update it [default Y]? " reply
+$ if reply .nes. "" .and. -
+ f$extract(0,1,f$edit(reply, "TRIM, UPCASE")) .nes. "Y" then -
+$ goto Compile_CHRTRANS
+$ EndIf
+$ ENDIF
+$ v1 = f$verify(1)
+$!
+$! Build the WWWLibrary
+$!
+$ set default [.WWW.Library.VMS]
+$ v1 = 'f$verify(0)'
+$ @libmake 'option' 'debug_arg'
+$ v1 = f$verify(1)
+$ set default [-.-.-]
+$ v1 = 'f$verify(0)'
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$!
+$Compile_CHRTRANS:
+$ IF f$search("[.src.chrtrans]makeuctb.exe") .nes. ""
+$ THEN
+$ write sys$output " [.src.chrtrans]makeuctb.exe already exists."
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output " Updating makeuctb.exe and chrtrans header files."
+$ Else
+$ read sys$command -
+ /prompt=" Update it and chrtrans header files [default Y]? " reply
+$ if reply .nes. "" .and. -
+ f$extract(0,1,f$edit(reply, "TRIM, UPCASE")) .nes. "Y" then -
+$ goto Compile_SRC
+$ EndIf
+$ ENDIF
+$!
+$ v1 = f$verify(1)
+$!
+$! Build the chrtrans modules.
+$!
+$ set default [.src.chrtrans]
+$ v1 = 'f$verify(0)'
+$ @build-chrtrans
+$ v1 = f$verify(1)
+$ set default [-.-]
+$ v1 = 'f$verify(0)'
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$!
+$Compile_SRC:
+$ v1 = f$verify(1)
+$!
+$! Compile the Lynx [.SRC] modules
+$!
+$ set default [.SRC]
+$ v1 = 'f$verify(0)'
+$ IF f$trnlnm("VAXCMSG") .eqs. "DECC$MSG" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/DECC" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/VAXC"
+$ THEN
+$ compiler := "DECC"
+$ if option .eqs. "UCX" then optfile = "UCXSHR"
+$ if option .eqs. "TCPWARE" then optfile = "TCPWARESHR"
+$ if option .eqs. "MULTINET" then -
+ extra = extra + ",_DECC_V4_SOURCE,__SOCKET_TYPEDEFS"
+$ v1 = f$verify(1)
+$! DECC:
+$ cc := cc/decc/prefix=all/nomember'cc_opts' -
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra',USE_SLANG,__VMS_CURSES)-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],'SLANGINC')
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ if option .eqs. "UCX" then optfile = "UCXOLB"
+$ if option .eqs. "TCPWARE" then optfile = "TCPWAREOLB"
+$ IF f$search("gnu_cc:[000000]gcclib.olb") .nes. ""
+$ THEN
+$ compiler := "GNUC"
+$ v1 = f$verify(1)
+$! GNUC:
+$ cc := gcc'cc_opts' -
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra',USE_SLANG)-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],'SLANGINC')
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ compiler := "VAXC"
+$ v1 = f$verify(1)
+$! VAXC:
+$ cc := cc'cc_opts' -
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra',USE_SLANG)-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],'SLANGINC')
+$ v1 = 'f$verify(0)'
+$ ENDIF
+$ ENDIF
+$ v1 = f$verify(1)
+$!
+$ cc DefaultStyle
+$ cc GridText
+$ cc HTAlert
+$ cc HTFWriter
+$ cc HTInit
+$ cc HTML
+$ cc LYBookmark
+$ cc LYCgi
+$ cc LYCharSets
+$ cc LYCharUtils
+$ cc LYClean
+$ cc LYCookie
+$ cc LYCurses
+$ cc LYDownload
+$ cc LYEdit
+$ cc LYEditmap
+$ cc LYexit
+$ cc LYForms
+$ cc LYGetFile
+$ cc LYHistory
+$ cc LYJump
+$ cc LYKeymap
+$ cc LYLeaks
+$ cc LYList
+$ cc LYMail
+$ cc LYMain
+$ cc LYMainLoop
+$ cc LYMap
+$ cc LYNews
+$ cc LYOptions
+$ cc LYPrint
+$ cc LYrcFile
+$ cc LYReadCFG
+$ cc LYSearch
+$ cc LYShowInfo
+$ cc LYStrings
+$ cc LYTraversal
+$ cc LYUpload
+$ cc LYUtils
+$ cc UCAuto
+$ cc UCAux
+$ cc UCdomap
+$!
+$! Link the objects and libaries.
+$!
+$ link/exe=lynx.exe'link_opts' -
+DefaultStyle.obj, -
+GridText.obj, -
+HTAlert.obj, -
+HTFWriter.obj, -
+HTInit.obj, -
+HTML.obj, -
+LYBookmark.obj, -
+LYCgi.obj, -
+LYCharSets.obj, -
+LYCharUtils.obj, -
+LYClean.obj, -
+LYCookie.obj, -
+LYCurses.obj, -
+LYDownload.obj, -
+LYEdit.obj, -
+LYEditmap.obj, -
+LYexit.obj, -
+LYForms.obj, -
+LYGetFile.obj, -
+LYHistory.obj, -
+LYJump.obj, -
+LYKeymap.obj, -
+LYLeaks.obj, -
+LYList.obj, -
+LYMail.obj, -
+LYMain.obj, -
+LYMainLoop.obj, -
+LYMap.obj, -
+LYNews.obj, -
+LYOptions.obj, -
+LYPrint.obj, -
+LYrcFile.obj, -
+LYReadCFG.obj, -
+LYSearch.obj, -
+LYShowInfo.obj, -
+LYStrings.obj, -
+LYTraversal.obj, -
+LYUpload.obj, -
+LYUtils.obj, -
+UCAuto.obj, -
+UCAux.obj, -
+UCdomap.obj, -
+[-.WWW.Library.Implementation]WWWLib_'option'.olb/library, -
+'SLANGLIB'slang.olb/lib, -
+sys$disk:[]'optfile'.opt/opt, sys$disk:[]'compiler'.opt/opt
+$!
+$! Copy the executable to the top directory and restore the default.
+$!
+$ copy lynx.exe [-]
+$ set def [-]
+$!
+$ v1 = 'f$verify(0)'
+$!
+$! Issue message on how to include LYNX.HLP in the system HELP library
+$!
+$ write sys$output ""
+$ write sys$output " To install or update lynx.hlp in the system HELP library,"
+$ write sys$output " use:"
+$ write sys$output " library/replace sys$help:helplib.hlb lynx.hlp"
+$ write sys$output ""
+$!
+$ CLEANUP:
+$ v1 = 'f$verify(0)'
+$ set default 'where'
+$ write sys$output "Default directory:"
+$ show default
+$ v1 = f$verify(v)
+$ exit
diff --git a/gnu/usr.bin/lynx/build.com b/gnu/usr.bin/lynx/build.com
new file mode 100644
index 00000000000..bfec6e39d25
--- /dev/null
+++ b/gnu/usr.bin/lynx/build.com
@@ -0,0 +1,337 @@
+$ v = 'f$verify(0)'
+$! BUILD.COM
+$!
+$! Command file to build LYNX.EXE on VMS systems.
+$! Also invokes build of the WWWLibrary if its
+$! object library does not already exist.
+$!
+$! 08-Oct-1997 F.Macrides macrides@sci.wfeb.edu
+$! Added comments and minor tweaks for convenient addition of
+$! compiler definitions and compiler and linker options.
+$! 28-Jun-1997 F.Macrides macrides@sci.wfeb.edu
+$! Added chartrans support.
+$! 29-Feb-1996 F.Macrides macrides@sci.wfeb.edu
+$! Added LYMap to the compilation and link lists.
+$! 26-Jul-1995 F.Macrides macrides@sci.wfeb.edu
+$! Reorganized the option files into ones for the transport and
+$! ones for the compiler, and adding support for GNUC.
+$! 14-Jun-1995 F.Macrides macrides@sci.wfeb.edu
+$! Added LYList.
+$! 03-May-1995 F.Macrides macrides@sci.wfeb.edu
+$! Include /nomember for compilations with DECC. It's not the
+$! default on AXP and the code assumes byte alignment.
+$! 23-Mar-1995 F.Macrides macrides@sci.wfeb.edu
+$! Replaced references to v2.3.8 or v2.3.9 with v2.3-FM to avoid
+$! any confusion with official releases at UKans.
+$! 16-Mar-1995 F.Macrides macrides@sci.wfeb.edu
+$! Updated to permit submission to BATCH.
+$! 17-Feb-1995 F.Macrides macriees@sci.wfeb.edu
+$! Updated for v2.3-FM
+$! 07-Dec-1994 F.Macrides macrides@sci.wfeb.edu
+$! Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+$! 03-OCT-1994 A.Harper A.Harper@kcl.ac.uk
+$! Mods to support SOCKETSHR/NETLIB and add a /DEBUG/NOOPT option
+$! 02-Jun-1994 F.Macrides macrides@sci.wfeb.edu
+$! Mods to support TCPWare (To use non-blocking connects, you need
+$! the DRIVERS_V405B.INC patch from FTP.PROCESS.COM for TCPware for
+$! OpenVMS Version 4.0-5, or a higher version of TCPWare, which will
+$! have that bug in the TCPDRIVER fixed. Otherwise, add NO_IOCTL to
+$! the $ cc := cc/define=(...) list in [.WWW.Library.VMS]libmake.com).
+$! 20-May-1994 Andy Harper A.Harper@bay.cc.kcl.ac.uk
+$! Mods to support CMU TCP/IP
+$! 13-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Mods for conditional compilations with VAXC versus DECC
+$! 10-Dec-1993 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for Lynx v2.1
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$ proc = f$environment("PROCEDURE")
+$ where = f$parse(proc,,,"DEVICE") + f$parse(proc,,,"DIRECTORY")
+$ set default 'where'
+$ write sys$output "Default directory:"
+$ show default
+$ write sys$output ""
+$!
+$! Compiler definitions can be added here as a comma separated
+$! list with a lead comma, e.g., ",HAVE_FOO_H,DO_BLAH". The
+$! definitions will apply only to the LYfoo.c modules. Ones
+$! for the libwww-FM modules can be added equivalently in
+$! [.WWW.Library.vms]libmake.com. - FM
+$!
+$ extra = ""
+$!
+$! If no TCP/IP agent is specified (as the first argument),
+$! prompt for a number from the list. Note that the agent
+$! must be the first argument if the debugger mode is to be
+$! set via a second argument (see below). - FM
+$!
+$ agent = 0
+$ IF P1 .EQS. ""
+$ THEN
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output "TCP/IP agent not specified!"
+$ write sys$output "Defaulting to MULTINET"
+$ agent = 1
+$ Else
+$ write sys$output "Acceptable TCP/IP agents are"
+$ write sys$output " [1] MULTINET (default)"
+$ write sys$output " [2] UCX"
+$ write sys$output " [3] WIN_TCP"
+$ write sys$output " [4] CMU_TCP"
+$ write sys$output " [5] SOCKETSHR_TCP"
+$ write sys$output " [6] TCPWARE"
+$ read sys$command/prompt="Agent [1,2,3,4,5,6] (RETURN = [1]) " agent
+$ EndIf
+$ ENDIF
+$ option = ""
+$ if agent .eq. 1 .or. agent .eqs. "" .or. p1 .eqs. "MULTINET" then -
+ option = "MULTINET"
+$ if agent .eq. 2 .or. p1 .eqs. "UCX" then option = "UCX"
+$ if agent .eq. 3 .or. p1 .eqs. "WIN_TCP" then option = "WIN_TCP"
+$ if agent .eq. 4 .or. p1 .eqs. "CMU_TCP" then option = "CMU_TCP"
+$ if agent .eq. 5 .or. p1 .eqs. "SOCKETSHR_TCP" then option = "SOCKETSHR_TCP"
+$ if agent .eq. 6 .or. p1 .eqs. "TCPWARE" then option = "TCPWARE"
+$!
+$ if option .eqs. "TCPWARE"
+$ then
+$ write sys$output "Building Lynx for TCPWARE with UCX emulation..."
+$ extra = extra + ",UCX"
+$ endif
+$!
+$ optfile = "''option'"
+$!
+$! Compiler and linker options can be specified here. If
+$! there was a second argument (with any value), then debugger
+$! mode with no optimization will be specified as well. The
+$! compiler options will apply only to the LYfoo.c and UCfoo.c
+$! modules. Ones for the libwww-FM modules can be specified
+$! in [.WWW.Library.vms]libmake.com. - FM
+$!
+$ cc_opts = ""
+$ link_opts = ""
+$!
+$ if p2 .nes. ""
+$ then
+$ debug_arg = "DEBUG"
+$ cc_opts = cc_opts + "/DEBUG/NOOPT"
+$ link_opts = link_opts + "/DEBUG"
+$ else
+$ debug_arg = ""
+$ endif
+$!
+$ IF f$search("[.WWW.Library.Implementation]WWWLib_''option'.olb") .nes. ""
+$ THEN
+$ write sys$output " WWWLib_''option'.olb already exists."
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output " Updating WWWLib_''option'.olb"
+$ Else
+$ read sys$command/prompt=" Update it [default Y]? " reply
+$ if reply .nes. "" .and. -
+ f$extract(0,1,f$edit(reply, "TRIM, UPCASE")) .nes. "Y" then -
+$ goto Compile_CHRTRANS
+$ EndIf
+$ ENDIF
+$ v1 = f$verify(1)
+$!
+$! Build the WWWLibrary
+$!
+$ set default [.WWW.Library.VMS]
+$ v1 = 'f$verify(0)'
+$ @libmake 'option' 'debug_arg'
+$ v1 = f$verify(1)
+$ set default [-.-.-]
+$ v1 = 'f$verify(0)'
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$!
+$Compile_CHRTRANS:
+$ IF f$search("[.src.chrtrans]makeuctb.exe") .nes. ""
+$ THEN
+$ write sys$output " [.src.chrtrans]makeuctb.exe already exists."
+$ If f$mode() .eqs. "BATCH"
+$ Then
+$ write sys$output " Updating makeuctb.exe and chrtrans header files."
+$ Else
+$ read sys$command -
+ /prompt=" Update it and chrtrans header files [default Y]? " reply
+$ if reply .nes. "" .and. -
+ f$extract(0,1,f$edit(reply, "TRIM, UPCASE")) .nes. "Y" then -
+$ goto Compile_SRC
+$ EndIf
+$ ENDIF
+$!
+$ v1 = f$verify(1)
+$!
+$! Build the chrtrans modules.
+$!
+$ set default [.src.chrtrans]
+$ v1 = 'f$verify(0)'
+$ @build-chrtrans
+$ v1 = f$verify(1)
+$ set default [-.-]
+$ v1 = 'f$verify(0)'
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$!
+$Compile_SRC:
+$ v1 = f$verify(1)
+$!
+$! Compile the Lynx [.SRC] modules
+$!
+$ set default [.SRC]
+$ v1 = 'f$verify(0)'
+$ IF f$trnlnm("VAXCMSG") .eqs. "DECC$MSG" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/DECC" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/VAXC"
+$ THEN
+$ compiler := "DECC"
+$ if option .eqs. "UCX" then optfile = "UCXSHR"
+$ if option .eqs. "TCPWARE" then optfile = "TCPWARESHR"
+$ if option .eqs. "MULTINET" then -
+ extra = extra + ",_DECC_V4_SOURCE,__SOCKET_TYPEDEFS"
+$ v1 = f$verify(1)
+$! DECC:
+$ cc := cc/decc/prefix=all/nomember'cc_opts'-
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra',__VMS_CURSES)-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],[.chrtrans])
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ if option .eqs. "UCX" then optfile = "UCXOLB"
+$ if option .eqs. "TCPWARE" then optfile = "TCPWAREOLB"
+$ IF f$search("gnu_cc:[000000]gcclib.olb") .nes. ""
+$ THEN
+$ compiler := "GNUC"
+$ v1 = f$verify(1)
+$! GNUC:
+$ cc := gcc'cc_opts' -
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra')-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],[.chrtrans])
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ compiler := "VAXC"
+$ v1 = f$verify(1)
+$! VAXC:
+$ cc := cc'cc_opts' -
+ /DEFINE=(DEBUG,ACCESS_AUTH,'option''extra')-
+ /INCLUDE=([-],[-.WWW.Library.Implementation],[.chrtrans])
+$ v1 = 'f$verify(0)'
+$ ENDIF
+$ ENDIF
+$ v1 = f$verify(1)
+$!
+$ cc DefaultStyle
+$ cc GridText
+$ cc HTAlert
+$ cc HTFWriter
+$ cc HTInit
+$ cc HTML
+$ cc LYBookmark
+$ cc LYCgi
+$ cc LYCharSets
+$ cc LYCharUtils
+$ cc LYClean
+$ cc LYCookie
+$ cc LYCurses
+$ cc LYDownload
+$ cc LYEdit
+$ cc LYEditmap
+$ cc LYexit
+$ cc LYForms
+$ cc LYGetFile
+$ cc LYHistory
+$ cc LYJump
+$ cc LYKeymap
+$ cc LYLeaks
+$ cc LYList
+$ cc LYMail
+$ cc LYMain
+$ cc LYMainLoop
+$ cc LYMap
+$ cc LYNews
+$ cc LYOptions
+$ cc LYPrint
+$ cc LYrcFile
+$ cc LYReadCFG
+$ cc LYSearch
+$ cc LYShowInfo
+$ cc LYStrings
+$ cc LYTraversal
+$ cc LYUpload
+$ cc LYUtils
+$ cc UCAuto
+$ cc UCAux
+$ cc UCdomap
+$!
+$! Link the objects and libaries.
+$!
+$ link/exe=lynx.exe'link_opts' -
+DefaultStyle.obj, -
+GridText.obj, -
+HTAlert.obj, -
+HTFWriter.obj, -
+HTInit.obj, -
+HTML.obj, -
+LYBookmark.obj, -
+LYCgi.obj, -
+LYCharSets.obj, -
+LYCharUtils.obj, -
+LYClean.obj, -
+LYCookie.obj, -
+LYCurses.obj, -
+LYDownload.obj, -
+LYEdit.obj, -
+LYEditmap.obj, -
+LYexit.obj, -
+LYForms.obj, -
+LYGetFile.obj, -
+LYHistory.obj, -
+LYJump.obj, -
+LYKeymap.obj, -
+LYLeaks.obj, -
+LYList.obj, -
+LYMail.obj, -
+LYMain.obj, -
+LYMainLoop.obj, -
+LYMap.obj, -
+LYNews.obj, -
+LYOptions.obj, -
+LYPrint.obj, -
+LYrcFile.obj, -
+LYReadCFG.obj, -
+LYSearch.obj, -
+LYShowInfo.obj, -
+LYStrings.obj, -
+LYTraversal.obj, -
+LYUpload.obj, -
+LYUtils.obj, -
+UCAuto.obj, -
+UCAux.obj, -
+UCdomap.obj, -
+[-.WWW.Library.Implementation]WWWLib_'option'.olb/library, -
+sys$disk:[]'optfile'.opt/opt, sys$disk:[]'compiler'.opt/opt
+$!
+$! Copy the executable to the top directory and restore the default.
+$!
+$ copy lynx.exe [-]
+$ set def [-]
+$!
+$ v1 = 'f$verify(0)'
+$!
+$! Issue message on how to include LYNX.HLP in the system HELP library
+$!
+$ write sys$output ""
+$ write sys$output " To install or update lynx.hlp in the system HELP library,"
+$ write sys$output " use:"
+$ write sys$output " library/replace sys$help:helplib.hlb lynx.hlp"
+$ write sys$output ""
+$!
+$ CLEANUP:
+$ v1 = 'f$verify(0)'
+$ set default 'where'
+$ write sys$output "Default directory:"
+$ show default
+$ v1 = f$verify(v)
+$ exit
diff --git a/gnu/usr.bin/lynx/config.guess b/gnu/usr.bin/lynx/config.guess
new file mode 100644
index 00000000000..5bb9a89ddc9
--- /dev/null
+++ b/gnu/usr.bin/lynx/config.guess
@@ -0,0 +1,696 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo alpha-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//'`
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-cbm-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-atari-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-sun-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-apple-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[3478]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
+ 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp3[0-9][05]:OpenBSD:*:*)
+ echo m68k-hp-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo i386-pc-cygwin32
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,/.*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ if echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf_i.86"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86linux"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: i.86coff"; then
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68kelf"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnu" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: m68klinux"; then
+ echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0
+ elif echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations: elf32ppc"; then
+ echo "powerpc-unknown-linux-gnu" ; exit 0
+ elif test "${UNAME_MACHINE}" = "alpha" ; then
+ echo alpha-unknown-linux-gnu ; exit 0
+ elif test "${UNAME_MACHINE}" = "sparc" ; then
+ echo sparc-unknown-linux-gnu ; exit 0
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or one that does not give us
+ # useful --help. Gcc wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ test ! -d /usr/lib/ldscripts/. \
+ && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+main(argc, argv)
+int argc;
+char *argv[];
+{
+#ifdef __ELF__
+ printf ("%s-pc-linux-gnu\n", argv[1]);
+#else
+ printf ("%s-pc-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/gnu/usr.bin/lynx/config.hin b/gnu/usr.bin/lynx/config.hin
new file mode 100644
index 00000000000..11ac7008aea
--- /dev/null
+++ b/gnu/usr.bin/lynx/config.hin
@@ -0,0 +1,144 @@
+/* The configure script translates "config.hin" into "lynx_cfg.h" */
+#ifndef LYNX_CFG_H
+#define LYNX_CFG_H 1
+
+#undef ALT_CHAR_SET /* CF_ALT_CHAR_SET */
+#undef ARCHIVE_ONLY /* CF_ARG_DISABLE(dired-archive) */
+#undef CHMOD_PATH /* CF_PATH_PROG(chmod) */
+#undef COLOR_CURSES /* defined by CF_COLOR_CURSES */
+#undef COMPRESS_PATH /* CF_PATH_PROG(compress) */
+#undef COPY_PATH /* CF_PATH_PROG(cp) */
+#undef CURS_PERFORMANCE /* CF_CURS_PERFORMANCE */
+#undef DEBUG /* configure --enable-debug */
+#undef DECL_GETGRGID
+#undef DECL_GETGRNAM
+#undef DECL_STRSTR
+#undef DECL_SYS_ERRLIST
+#undef DIRED_SUPPORT /* AC_ARG_WITH(dired) */
+#undef DONT_TRACK_INTERNAL_LINKS /* CF_ARG_DISABLE(internal-links) */
+#undef EXP_8BIT_TOUPPER /* AC_ARG_WITH(8bit-toupper) */
+#undef EXP_CHARTRANS_AUTOSWITCH /* AC_ARG_WITH(font-switch) */
+#undef FANCY_CURSES /* defined by CF_FANCY_CURSES */
+#undef GCC_UNUSED /* CF_GCC_ATTRIBUTES */
+#undef GZIP_PATH /* CF_PATH_PROG(gzip) */
+#undef HAVE_CBREAK
+#undef HAVE_CUSERID
+#undef HAVE_DIRENT_H /* defined by AC_HEADER_DIRENT */
+#undef HAVE_FCNTL_H /* have <fcntl.h> */
+#undef HAVE_GETBKGD /* defined by CF_COLOR_CURSES */
+#undef HAVE_GETCWD
+#undef HAVE_GETGROUPS
+#undef HAVE_KEYPAD
+#undef HAVE_LIMITS_H
+#undef HAVE_LSTAT /* defined by CF_FUNC_LSTAT */
+#undef HAVE_NCURSES_H /* defined if we include <ncurses.h> */
+#undef HAVE_PUTENV
+#undef HAVE_READDIR
+#undef HAVE_SIZECHANGE /* defined by CF_SIZECHANGE */
+#undef HAVE_STDLIB_H
+#undef HAVE_STRERROR
+#undef HAVE_STRING_H
+#undef HAVE_SYS_DIR_H /* defined by AC_HEADER_DIRENT */
+#undef HAVE_SYS_FCNTL_H /* have <sys/fcntl.h> */
+#undef HAVE_SYS_FILIO_H /* have <sys/filio.h> */
+#undef HAVE_SYS_IOCTL_H /* have <sys/ioctl.h> */
+#undef HAVE_SYS_NDIR_H /* defined by AC_HEADER_DIRENT */
+#undef HAVE_SYS_WAIT_H /* have <sys/wait.h> */
+#undef HAVE_TERMIOS_H /* have <termios.h> */
+#undef HAVE_TTYTYPE
+#undef HAVE_TYPE_UNIONWAIT /* CF_UNION_WAIT */
+#undef HAVE_UNISTD_H /* have <unistd.h> */
+#undef HAVE_USE_DEFAULT_COLORS /* ncurses extension */
+#undef HAVE_UTMP
+#undef HAVE_WAITPID
+#undef HAVE_WBORDER
+#undef IGNORE_CTRL_C /* FIXME: make tests? */
+#undef INSTALL_ARGS /* CF_PATH_PROG(install) */
+#undef INSTALL_PATH /* CF_PATH_PROG(install) */
+#undef LINKEDSTYLES /* see USE_COLOR_STYLE */
+#undef LINUX /* FIXME: make tests? */
+#undef LOCALE /* for locale support */
+#undef LONG_LIST /* CF_ARG_DISABLE(long-list) */
+#undef LYNX_CFG_FILE /* $libdir/lynx.cfg */
+#undef LYNX_LSS_FILE /* $libdir/lynx.lss */
+#undef LY_FIND_LEAKS /* configure --disable-leaks */
+#undef MKDIR_PATH /* CF_PATH_PROG(mkdir) */
+#undef MV_PATH /* CF_PATH_PROG(mv) */
+#undef NCURSES /* defined for ncurses support */
+#undef NCURSES_BROKEN /* defined for ncurses color support */
+#undef NEED_PTEM_H /* defined by CF_SIZECHANGE */
+#undef NEED_REMOVE /* defined by CF_REMOVE_BROKEN */
+#undef NGROUPS /* defined by CF_NGROUPS */
+#undef NO_CHANGE_EXECUTE_PERMS /* CF_ARG_DISABLE(dired-xpermit) */
+#undef NO_EXTENDED_HTMLDTD /* CF_ARG_DISABLE(extended-dtd) */
+#undef NO_PARENT_DIR_REFERENCE /* configure --disable-parent-dir */
+#undef NSL_FORK /* CF_ARG_ENABLE(nsl-fork) */
+#undef OK_GZIP /* CF_ARG_DISABLE(dired-gzip) */
+#undef OK_OVERRIDE /* CF_ARG_DISABLE(dired-override) */
+#undef OK_PERMIT /* CF_ARG_DISABLE(dired-permit) */
+#undef OK_TAR /* CF_ARG_DISABLE(dired-tar) */
+#undef OK_UUDECODE /* CF_ARG_DISABLE(dired-uudecode) */
+#undef OK_ZIP /* CF_ARG_DISABLE(dired-zip) */
+#undef RM_PATH /* CF_PATH_PROG(rm) */
+#undef STDC_HEADERS
+#undef SYSTEM_MAIL /* CF_DEFINE_PROG */
+#undef SYSTEM_MAIL_FLAGS /* defined by CF_SYSTEM_MAIL_FLAGS */
+#undef TAR_PATH /* CF_PATH_PROG(tar) */
+#undef TERMIO_AND_TERMIOS /* termio.h and termios.h combo bug */
+#undef TOUCH_PATH /* CF_PATH_PROG(touch) */
+#undef ULTRIX /* config.sub */
+#undef UNCOMPRESS_PATH /* CF_PATH_PROG(gunzip) */
+#undef UNDERLINE_LINKS /* CF_ARG_ENABLE(underlines) */
+#undef UNIX
+#undef UNZIP_PATH /* CF_PATH_PROG(unzip) */
+#undef USE_COLOR_STYLE /* CF_ARG_ENABLE(color-style) */
+#undef USE_DEFAULT_COLORS /* CF_ARG_ENABLE(default-colors) */
+#undef USE_EXTERNALS /* CF_ARG_ENABLE(externs) */
+#undef USE_FCNTL /* CF_FIONBIO */
+#undef USE_HASH /* see USE_COLOR_STYLE */
+#undef USE_SIZECHANGEHACK /* FIXME: find a case where this works! */
+#undef USE_SLANG /* AC_ARG_WITH(screen=slang) */
+#undef USE_ZLIB /* AC_ARG_WITH(zlib) */
+#undef UTMPX_FOR_UTMP /* use <utmpx.h> since <utmp.h> not found */
+#undef UUDECODE_PATH /* CF_PATH_PROG(uudecode) */
+#undef WAITPID_USES_UNION /* CF_FUNC_WAIT */
+#undef WAIT_USES_UNION /* CF_FUNC_WAIT */
+#undef ZCAT_PATH /* CF_PATH_PROG(zcat) */
+#undef ZIP_PATH /* CF_PATH_PROG(zip) */
+#undef const /* defined by AC_C_CONST */
+#undef mode_t /* defined by AC_TYPE_MODE_T */
+#undef vfork /* defined by AC_FUNC_FORK */
+/* FIXME:ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+/* FIXME:BSDI */
+/* FIXME:DECLARE_WAIS_LOGFILES */
+/* FIXME:DGUX */
+/* FIXME:DGUX_OLD */
+/* FIXME:EXEC_LINKS */
+/* FIXME:EXEC_SCRIPTS */
+/* FIXME:HP_TERMINAL */
+/* FIXME:NOPORT */
+/* FIXME:POSIX_JC */
+/* FIXME:REVERSE_CLEAR_SCREEN_PROBLEM */
+/* FIXME:SHORTENED_RBIND */
+/* FIXME:SNAKE */
+/* FIXME:SOCKS */
+/* FIXME:SVR4_BSDSELECT */
+/* FIXME:SYSLOG_REQUESTED_URLS */
+
+#ifndef HAVE_LSTAT
+#define lstat stat
+#endif
+
+#ifdef DECL_GETGRGID
+extern struct group * getgrgid ();
+#endif
+
+#ifdef DECL_GETGRNAM
+extern struct group * getgrnam ();
+#endif
+
+#ifdef DECL_STRSTR
+extern char * strstr ();
+#endif
+
+#endif /* LYNX_CFG_H */
diff --git a/gnu/usr.bin/lynx/config.sub b/gnu/usr.bin/lynx/config.sub
new file mode 100644
index 00000000000..0432524944d
--- /dev/null
+++ b/gnu/usr.bin/lynx/config.sub
@@ -0,0 +1,927 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m68k | m68000 | m88k | ns32k | arm \
+ | arme[lb] | pyramid \
+ | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
+ | alpha | we32k | ns16k | clipper | i370 | sh \
+ | powerpc | powerpcle | 1750a | dsp16xx | mips64 | mipsel \
+ | pdp11 | mips64el | mips64orion | mips64orionel \
+ | sparc | sparclet | sparclite | sparc64)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[3456]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[3456]86-* | i860-* | m68k-* | m68000-* | m88k-* \
+ | sparc-* | ns32k-* | fx80-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* | power-* \
+ | none-* | 580-* | cray2-* | h8300-* | i960-* | xmp-* | ymp-* \
+ | hppa-* | hppa1.0-* | hppa1.1-* | alpha-* | we32k-* | cydra-* | ns16k-* \
+ | pn-* | np1-* | xps100-* | clipper-* | orion-* | sparclite-* \
+ | pdp11-* | sh-* | powerpc-* | powerpcle-* | sparc64-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* | f301-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigados)
+ basic_machine=m68k-cbm
+ os=-amigados
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[3456]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[3456]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[3456]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[3456]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5)
+ basic_machine=i586-intel
+ ;;
+ pentiumpro | p6)
+ basic_machine=i686-intel
+ ;;
+ pentium-* | p5-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ k5)
+ # We don't have specific support for AMD's K5 yet, so just call it a Pentium
+ basic_machine=i586-amd
+ ;;
+ nexen)
+ # We don't have specific support for Nexgen yet, so just call it a Pentium
+ basic_machine=i586-nexgen
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ mips)
+ basic_machine=mips-mips
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -unixware* | svr4*)
+ os=-sysv4
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigados* | -msdos* | -newsos* | -unicos* | -aof* | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -linux-gnu* | -uxpv*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigados
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/gnu/usr.bin/lynx/configure b/gnu/usr.bin/lynx/configure
new file mode 100644
index 00000000000..c3bd9b97a2d
--- /dev/null
+++ b/gnu/usr.bin/lynx/configure
@@ -0,0 +1,8185 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.12.971230
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_default_prefix=/usr/local
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+cat <<EOF
+--enable and --with options recognized:
+Development Options:
+ --disable-echo test: display "compiling" commands (default: on)
+ --enable-find-leaks logic for testing memory leaks (default: off)
+ --enable-debug logic for traces/debugging (default: off)
+ --enable-warnings GCC compiler warnings (default: off)
+Basic Configuration Options:
+ --disable-full-paths control whether full utility pathnames are used (default: on)
+ --with-screen=XXX select screen type
+ (XXX is curses (default), ncurses or slang)
+Miscellaneous Options:
+ --enable-8bit-toupper use experimental 8-bit case-conversion (default: off)
+ --enable-color-style use optional/experimental color style (default: off)
+ --enable-default-colors enable use of default-colors (ncurses/slang) (default: off)
+ --disable-extended-dtd disable extended HTML DTD logic (default: on)
+EOF
+cat <<EOF
+ --enable-externs use external commands (default: off)
+ --enable-font-switch use Linux setfont for character-translation (default: off)
+ --enable-internal-links handle following links to same doc differently (default: off)
+ --enable-nsl-fork fork NSL requests, allowing them to be aborted (default: off)
+ --enable-underlines underline links rather than using boldface (default: off)
+ --with-zlib use zlib for decompression of some gzip files
+Directory Editor Options:
+ --disable-dired enable optional directory-editor, DirEd (default: on)
+ --disable-dired-archive disable dearchiving commands (default: on)
+ --disable-dired-override disable private keymaps (default: on)
+ --disable-dired-permit disable chmod/attrib commands (default: on)
+ --disable-dired-xpermit disable chmod/attrib commands (default: on)
+EOF
+cat <<EOF
+ --disable-dired-tar disable "tar" command (default: on)
+ --disable-dired-uudecode disable "uudecode" command (default: on)
+ --disable-dired-zip disable "zip", "unzip" commands (default: on)
+ --disable-dired-gzip disable "gzip", "gunzip" commands (default: on)
+ --disable-long-list disable long "ls -l" directory listings (default: on)
+ --disable-parent-dir-refs
+ disable "Up-to" links in directory listings (default: on)
+EOF
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.12.971230"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=userdefs.h
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:589: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:614: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:643: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:691: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext <<EOF
+#line 701 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+if { (eval echo configure:705: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:725: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:730: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:739: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:754: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:782: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 797 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:803: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 814 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:820: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:845: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+echo "configure:872: checking whether ${MAKE-make} sets \${MAKE}" >&5
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftestmake <<\EOF
+all:
+ @echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+ eval ac_cv_prog_make_${ac_make}_set=yes
+else
+ eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ SET_MAKE=
+else
+ echo "$ac_t""no" 1>&6
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+echo $ac_n "checking for style of include in makefiles""... $ac_c" 1>&6
+echo "configure:900: checking for style of include in makefiles" >&5
+
+make_include_left=""
+make_include_right=""
+make_include_quote="unknown"
+
+cf_inc=head$$
+cf_dir=subd$$
+echo 'RESULT=OK' >$cf_inc
+mkdir $cf_dir
+
+for cf_include in "include" ".include" "!include"
+do
+ for cf_quote in '' '"'
+ do
+ cat >$cf_dir/makefile <<CF_EOF
+SHELL=/bin/sh
+${cf_include} ${cf_quote}../$cf_inc${cf_quote}
+all :
+ @echo 'cf_make_include=\$(RESULT)'
+CF_EOF
+ cf_make_include=""
+ eval `cd $cf_dir && ${MAKE-make} 2>&5 | grep cf_make_include=OK`
+ if test -n "$cf_make_include"; then
+ make_include_left="$cf_include"
+ make_include_quote="$cf_quote"
+ break
+ else
+ echo Tried 1>&5
+ cat $cf_dir/makefile 1>&5
+ fi
+ done
+ test -n "$cf_make_include" && break
+done
+
+rm -rf $cf_inc $cf_dir
+
+if test -z "$make_include_left" ; then
+ { echo "configure: error: Your $ac_make program does not support includes" 1>&2; exit 1; }
+fi
+if test ".$make_include_quote" != .unknown ; then
+ make_include_left="$make_include_left $make_include_quote"
+ make_include_right="$make_include_quote"
+fi
+
+echo "$ac_t""${make_include_left}file${make_include_right}" 1>&6
+
+
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:961: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+for ac_prog in lint alint lclint tdlint
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1015: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LINT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$LINT"; then
+ ac_cv_prog_LINT="$LINT" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_LINT="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+LINT="$ac_cv_prog_LINT"
+if test -n "$LINT"; then
+ echo "$ac_t""$LINT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$LINT" && break
+done
+
+
+
+
+
+
+echo $ac_n "checking if you want to see long compiling messages""... $ac_c" 1>&6
+echo "configure:1049: checking if you want to see long compiling messages" >&5
+
+# Check whether --enable-echo or --disable-echo was given.
+if test "${enable_echo+set}" = set; then
+ enableval="$enable_echo"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+
+ ECHO_LD='@echo linking $@;'
+ RULE_CC=' @echo compiling $<'
+ SHOW_CC=' @echo compiling $@'
+ ECHO_CC='@'
+
+ else
+
+ ECHO_LD=''
+ RULE_CC='# compiling'
+ SHOW_CC='# compiling'
+ ECHO_CC=''
+
+ fi
+else
+ enableval=yes
+
+ ECHO_LD=''
+ RULE_CC='# compiling'
+ SHOW_CC='# compiling'
+ ECHO_CC=''
+
+
+fi
+
+echo "$ac_t""$enableval" 1>&6
+
+
+
+
+
+
+echo $ac_n "checking if you want to check memory-leaks""... $ac_c" 1>&6
+echo "configure:1089: checking if you want to check memory-leaks" >&5
+
+# Check whether --enable-find-leaks or --disable-find-leaks was given.
+if test "${enable_find_leaks+set}" = set; then
+ enableval="$enable_find_leaks"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ with_leak_checks=yes
+ else
+ with_leak_checks=no
+ fi
+else
+ enableval=no
+ with_leak_checks=no
+
+fi
+
+echo "$ac_t""$with_leak_checks" 1>&6
+test "$with_leak_checks" = "yes" && cat >> confdefs.h <<\EOF
+#define LY_FIND_LEAKS 1
+EOF
+
+
+echo $ac_n "checking if you want to enable debug-code""... $ac_c" 1>&6
+echo "configure:1113: checking if you want to enable debug-code" >&5
+
+# Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ with_debug=yes
+ else
+ with_debug=no
+ fi
+else
+ enableval=no
+ with_debug=no
+
+fi
+
+echo "$ac_t""$with_debug" 1>&6
+if test "$with_debug" = "yes" ; then
+ case $host_os in
+ ultrix*|osf*)
+
+CFLAGS=`echo ${CFLAGS} | sed -e 's/-O[1-9]\? //' -e 's/-O[1-9]\?$//'`
+
+ if test -z "$GCC" ; then
+ CFLAGS="$CFLAGS -g3"
+ fi
+ ;;
+ esac
+else
+ case $host_os in
+ ultrix*|osf*) #(vi
+ CFLAGS=`echo ${CFLAGS} | sed -e 's/-g //' -e 's/-g$//'`
+ ;;
+ *)
+ CFLAGS=`echo ${CFLAGS} | sed -e 's/-g //' -e 's/-g$//'`
+ ;;
+ esac
+fi
+
+
+
+if test -n "$GCC"
+then
+echo $ac_n "checking if you want to turn on gcc warnings""... $ac_c" 1>&6
+echo "configure:1158: checking if you want to turn on gcc warnings" >&5
+
+# Check whether --enable-warnings or --disable-warnings was given.
+if test "${enable_warnings+set}" = set; then
+ enableval="$enable_warnings"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ with_warnings=yes
+ else
+ with_warnings=no
+ fi
+else
+ enableval=no
+ with_warnings=no
+
+fi
+
+echo "$ac_t""$with_warnings" 1>&6
+if test "$with_warnings" = "yes"
+then
+
+if test -n "$GCC"
+then
+cat > conftest.i <<EOF
+#ifndef GCC_PRINTF
+#define GCC_PRINTF 0
+#endif
+#ifndef GCC_SCANF
+#define GCC_SCANF 0
+#endif
+#ifndef GCC_NORETURN
+#define GCC_NORETURN /* nothing */
+#endif
+#ifndef GCC_UNUSED
+#define GCC_UNUSED /* nothing */
+#endif
+EOF
+if test -n "$GCC"
+then
+ echo "checking for gcc __attribute__ directives" 1>&6
+echo "configure:1198: checking for gcc __attribute__ directives" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 1200 "configure"
+#include "confdefs.h"
+#include "conftest.h"
+#include "conftest.i"
+#if GCC_PRINTF
+#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var)))
+#else
+#define GCC_PRINTFLIKE(fmt,var) /*nothing*/
+#endif
+#if GCC_SCANF
+#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var)))
+#else
+#define GCC_SCANFLIKE(fmt,var) /*nothing*/
+#endif
+extern void wow(char *,...) GCC_SCANFLIKE(1,2);
+extern void oops(char *,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN;
+extern void foo(void) GCC_NORETURN;
+int main(int argc GCC_UNUSED, char *argv[] GCC_UNUSED) { return 0; }
+EOF
+ for cf_attribute in scanf printf unused noreturn
+ do
+
+CF_ATTRIBUTE=`echo $cf_attribute | tr '[a-z]' '[A-Z]'`
+
+ cf_directive="__attribute__(($cf_attribute))"
+ echo "checking for gcc $cf_directive" 1>&5
+ case $cf_attribute in
+ scanf|printf)
+ cat >conftest.h <<EOF
+#define GCC_$CF_ATTRIBUTE 1
+EOF
+ ;;
+ *)
+ cat >conftest.h <<EOF
+#define GCC_$CF_ATTRIBUTE $cf_directive
+EOF
+ ;;
+ esac
+ if { (eval echo configure:1238: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ test -n "$verbose" && echo "$ac_t""... $cf_attribute" 1>&6
+ cat conftest.h >>confdefs.h
+# else
+# sed -e 's/__attr.*/\/*nothing*\//' conftest.h >>confdefs.h
+ fi
+ done
+else
+ fgrep define conftest.i >>confdefs.h
+fi
+rm -rf conftest*
+fi
+
+
+if test -n "$GCC"
+then
+ cat > conftest.$ac_ext <<EOF
+#line 1255 "configure"
+int main(int argc, char *argv[]) { return argv[argc-1] == 0; }
+EOF
+ echo "checking for gcc warning options" 1>&6
+echo "configure:1259: checking for gcc warning options" >&5
+ cf_save_CFLAGS="$CFLAGS"
+ EXTRA_CFLAGS="-W -Wall"
+ cf_warn_CONST=""
+ test "$with_ext_const" = yes && cf_warn_CONST="Wwrite-strings"
+ for cf_opt in \
+ Wbad-function-cast \
+ Wcast-align \
+ Wcast-qual \
+ Winline \
+ Wmissing-declarations \
+ Wmissing-prototypes \
+ Wnested-externs \
+ Wpointer-arith \
+ Wshadow \
+ Wstrict-prototypes $cf_warn_CONST
+ do
+ CFLAGS="$cf_save_CFLAGS $EXTRA_CFLAGS -$cf_opt"
+ if { (eval echo configure:1277: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ test -n "$verbose" && echo "$ac_t""... -$cf_opt" 1>&6
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -$cf_opt"
+ test "$cf_opt" = Wcast-qual && EXTRA_CFLAGS="$EXTRA_CFLAGS -DXTSTRINGDEFINES"
+ fi
+ done
+ rm -f conftest*
+ CFLAGS="$cf_save_CFLAGS"
+fi
+
+
+fi
+fi
+
+
+
+
+echo $ac_n "checking if you want full utility pathnames""... $ac_c" 1>&6
+echo "configure:1295: checking if you want full utility pathnames" >&5
+
+# Check whether --enable-full-paths or --disable-full-paths was given.
+if test "${enable_full_paths+set}" = set; then
+ enableval="$enable_full_paths"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ with_full_paths=no
+ else
+ with_full_paths=yes
+ fi
+else
+ enableval=yes
+ with_full_paths=yes
+
+fi
+
+echo "$ac_t""$with_full_paths" 1>&6
+
+
+echo $ac_n "checking for system mailer""... $ac_c" 1>&6
+echo "configure:1316: checking for system mailer" >&5
+if eval "test \"`echo '$''{'cf_cv_SYSTEM_MAIL'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cf_cv_SYSTEM_MAIL=unknown
+ for cv_path in /usr/mmdf/bin/submit \
+ /usr/sbin/sendmail \
+ /usr/lib/sendmail \
+
+ do
+ if test -f $cv_path ; then
+ cf_cv_SYSTEM_MAIL=$cv_path
+ break
+ fi
+ done
+
+fi
+
+echo "$ac_t""$cf_cv_SYSTEM_MAIL" 1>&6
+cat >> confdefs.h <<EOF
+#define SYSTEM_MAIL "$cf_cv_SYSTEM_MAIL"
+EOF
+
+
+
+echo $ac_n "checking system mail flags""... $ac_c" 1>&6
+echo "configure:1343: checking system mail flags" >&5
+if eval "test \"`echo '$''{'cf_cv_system_mail_flags'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ case $cf_cv_SYSTEM_MAIL in
+ */mmdf/*)
+ cf_cv_system_mail_flags="-mlruxto,cc\\\\*"
+ ;;
+ *)
+ cf_cv_system_mail_flags="-t -oi"
+ esac
+
+fi
+
+echo "$ac_t""$cf_cv_system_mail_flags" 1>&6
+cat >> confdefs.h <<EOF
+#define SYSTEM_MAIL_FLAGS "$cf_cv_system_mail_flags"
+EOF
+
+
+
+
+test -z "$CHMOD" && CHMOD=chmod
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "chmod", so it can be a program name with args.
+set dummy chmod; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1371: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_CHMOD'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$CHMOD" in
+ /*)
+ ac_cv_path_CHMOD="$CHMOD" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_CHMOD="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_CHMOD" && ac_cv_path_CHMOD="$CHMOD"
+ ;;
+esac
+fi
+CHMOD="$ac_cv_path_CHMOD"
+if test -n "$CHMOD"; then
+ echo "$ac_t""$CHMOD" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for chmod""... $ac_c" 1>&6
+echo "configure:1402: checking for chmod" >&5
+ echo "$ac_t""$CHMOD" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_CHMOD
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define CHMOD_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define CHMOD_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$COMPRESS" && COMPRESS=compress
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "compress", so it can be a program name with args.
+set dummy compress; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1436: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_COMPRESS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$COMPRESS" in
+ /*)
+ ac_cv_path_COMPRESS="$COMPRESS" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_COMPRESS="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_COMPRESS" && ac_cv_path_COMPRESS="$COMPRESS"
+ ;;
+esac
+fi
+COMPRESS="$ac_cv_path_COMPRESS"
+if test -n "$COMPRESS"; then
+ echo "$ac_t""$COMPRESS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for compress""... $ac_c" 1>&6
+echo "configure:1467: checking for compress" >&5
+ echo "$ac_t""$COMPRESS" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_COMPRESS
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define COMPRESS_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define COMPRESS_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$COPY" && COPY=cp
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "cp", so it can be a program name with args.
+set dummy cp; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1501: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_COPY'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$COPY" in
+ /*)
+ ac_cv_path_COPY="$COPY" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_COPY="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_COPY" && ac_cv_path_COPY="$COPY"
+ ;;
+esac
+fi
+COPY="$ac_cv_path_COPY"
+if test -n "$COPY"; then
+ echo "$ac_t""$COPY" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for cp""... $ac_c" 1>&6
+echo "configure:1532: checking for cp" >&5
+ echo "$ac_t""$COPY" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_COPY
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define COPY_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define COPY_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$GZIP" && GZIP=gzip
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "gzip", so it can be a program name with args.
+set dummy gzip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1566: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_GZIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$GZIP" in
+ /*)
+ ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_GZIP="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_GZIP" && ac_cv_path_GZIP="$GZIP"
+ ;;
+esac
+fi
+GZIP="$ac_cv_path_GZIP"
+if test -n "$GZIP"; then
+ echo "$ac_t""$GZIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for gzip""... $ac_c" 1>&6
+echo "configure:1597: checking for gzip" >&5
+ echo "$ac_t""$GZIP" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_GZIP
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define GZIP_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define GZIP_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$MKDIR" && MKDIR=mkdir
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "mkdir", so it can be a program name with args.
+set dummy mkdir; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1631: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MKDIR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MKDIR" in
+ /*)
+ ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_MKDIR="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MKDIR" && ac_cv_path_MKDIR="$MKDIR"
+ ;;
+esac
+fi
+MKDIR="$ac_cv_path_MKDIR"
+if test -n "$MKDIR"; then
+ echo "$ac_t""$MKDIR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for mkdir""... $ac_c" 1>&6
+echo "configure:1662: checking for mkdir" >&5
+ echo "$ac_t""$MKDIR" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_MKDIR
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define MKDIR_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define MKDIR_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$MV" && MV=mv
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "mv", so it can be a program name with args.
+set dummy mv; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1696: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_MV'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$MV" in
+ /*)
+ ac_cv_path_MV="$MV" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_MV="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_MV" && ac_cv_path_MV="$MV"
+ ;;
+esac
+fi
+MV="$ac_cv_path_MV"
+if test -n "$MV"; then
+ echo "$ac_t""$MV" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for mv""... $ac_c" 1>&6
+echo "configure:1727: checking for mv" >&5
+ echo "$ac_t""$MV" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_MV
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define MV_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define MV_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$RM" && RM=rm
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "rm", so it can be a program name with args.
+set dummy rm; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1761: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_RM'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$RM" in
+ /*)
+ ac_cv_path_RM="$RM" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_RM="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_RM" && ac_cv_path_RM="$RM"
+ ;;
+esac
+fi
+RM="$ac_cv_path_RM"
+if test -n "$RM"; then
+ echo "$ac_t""$RM" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for rm""... $ac_c" 1>&6
+echo "configure:1792: checking for rm" >&5
+ echo "$ac_t""$RM" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_RM
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define RM_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define RM_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$TAR" && TAR=tar
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "tar", so it can be a program name with args.
+set dummy tar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1826: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_TAR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$TAR" in
+ /*)
+ ac_cv_path_TAR="$TAR" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_TAR="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_TAR" && ac_cv_path_TAR="$TAR"
+ ;;
+esac
+fi
+TAR="$ac_cv_path_TAR"
+if test -n "$TAR"; then
+ echo "$ac_t""$TAR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for tar""... $ac_c" 1>&6
+echo "configure:1857: checking for tar" >&5
+ echo "$ac_t""$TAR" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_TAR
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define TAR_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define TAR_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$TOUCH" && TOUCH=touch
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "touch", so it can be a program name with args.
+set dummy touch; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1891: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_TOUCH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$TOUCH" in
+ /*)
+ ac_cv_path_TOUCH="$TOUCH" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_TOUCH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_TOUCH" && ac_cv_path_TOUCH="$TOUCH"
+ ;;
+esac
+fi
+TOUCH="$ac_cv_path_TOUCH"
+if test -n "$TOUCH"; then
+ echo "$ac_t""$TOUCH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for touch""... $ac_c" 1>&6
+echo "configure:1922: checking for touch" >&5
+ echo "$ac_t""$TOUCH" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_TOUCH
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define TOUCH_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define TOUCH_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$UNCOMPRESS" && UNCOMPRESS=gunzip
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "gunzip", so it can be a program name with args.
+set dummy gunzip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1956: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_UNCOMPRESS'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$UNCOMPRESS" in
+ /*)
+ ac_cv_path_UNCOMPRESS="$UNCOMPRESS" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_UNCOMPRESS="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_UNCOMPRESS" && ac_cv_path_UNCOMPRESS="$UNCOMPRESS"
+ ;;
+esac
+fi
+UNCOMPRESS="$ac_cv_path_UNCOMPRESS"
+if test -n "$UNCOMPRESS"; then
+ echo "$ac_t""$UNCOMPRESS" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for gunzip""... $ac_c" 1>&6
+echo "configure:1987: checking for gunzip" >&5
+ echo "$ac_t""$UNCOMPRESS" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_UNCOMPRESS
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define UNCOMPRESS_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define UNCOMPRESS_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$UNZIP" && UNZIP=unzip
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "unzip", so it can be a program name with args.
+set dummy unzip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2021: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_UNZIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$UNZIP" in
+ /*)
+ ac_cv_path_UNZIP="$UNZIP" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_UNZIP="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_UNZIP" && ac_cv_path_UNZIP="$UNZIP"
+ ;;
+esac
+fi
+UNZIP="$ac_cv_path_UNZIP"
+if test -n "$UNZIP"; then
+ echo "$ac_t""$UNZIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for unzip""... $ac_c" 1>&6
+echo "configure:2052: checking for unzip" >&5
+ echo "$ac_t""$UNZIP" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_UNZIP
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define UNZIP_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define UNZIP_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$UUDECODE" && UUDECODE=uudecode
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "uudecode", so it can be a program name with args.
+set dummy uudecode; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2086: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_UUDECODE'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$UUDECODE" in
+ /*)
+ ac_cv_path_UUDECODE="$UUDECODE" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_UUDECODE="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_UUDECODE" && ac_cv_path_UUDECODE="$UUDECODE"
+ ;;
+esac
+fi
+UUDECODE="$ac_cv_path_UUDECODE"
+if test -n "$UUDECODE"; then
+ echo "$ac_t""$UUDECODE" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for uudecode""... $ac_c" 1>&6
+echo "configure:2117: checking for uudecode" >&5
+ echo "$ac_t""$UUDECODE" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_UUDECODE
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define UUDECODE_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define UUDECODE_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$ZCAT" && ZCAT=zcat
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "zcat", so it can be a program name with args.
+set dummy zcat; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2151: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_ZCAT'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$ZCAT" in
+ /*)
+ ac_cv_path_ZCAT="$ZCAT" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_ZCAT="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_ZCAT" && ac_cv_path_ZCAT="$ZCAT"
+ ;;
+esac
+fi
+ZCAT="$ac_cv_path_ZCAT"
+if test -n "$ZCAT"; then
+ echo "$ac_t""$ZCAT" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for zcat""... $ac_c" 1>&6
+echo "configure:2182: checking for zcat" >&5
+ echo "$ac_t""$ZCAT" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_ZCAT
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define ZCAT_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define ZCAT_ARGS "$cf_path_args"
+EOF
+
+
+
+test -z "$ZIP" && ZIP=zip
+if test "$with_full_paths" = yes ; then
+ # Extract the first word of "zip", so it can be a program name with args.
+set dummy zip; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2216: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_ZIP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$ZIP" in
+ /*)
+ ac_cv_path_ZIP="$ZIP" # Let the user override the test with a path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_ZIP="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_path_ZIP" && ac_cv_path_ZIP="$ZIP"
+ ;;
+esac
+fi
+ZIP="$ac_cv_path_ZIP"
+if test -n "$ZIP"; then
+ echo "$ac_t""$ZIP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ echo $ac_n "checking for zip""... $ac_c" 1>&6
+echo "configure:2247: checking for zip" >&5
+ echo "$ac_t""$ZIP" 1>&6
+fi
+
+cf_path_prog=""
+cf_path_args=""
+IFS="${IFS= }"; cf_save_ifs="$IFS"; IFS="${IFS}:"
+for cf_temp in $ac_cv_path_ZIP
+do
+ if test -z "$cf_path_prog" ; then
+ cf_path_prog="$cf_temp"
+ elif test -z "$cf_path_args" ; then
+ cf_path_args="$cf_temp"
+ else
+ cf_path_args="$cf_path_args $cf_temp"
+ fi
+done
+IFS="$cf_save_ifs"
+
+cat >> confdefs.h <<EOF
+#define ZIP_PATH "$cf_path_prog"
+EOF
+
+test -n "$cf_path_args" && cat >> confdefs.h <<EOF
+#define ZIP_ARGS "$cf_path_args"
+EOF
+
+
+
+case "$INSTALL" in
+$srcdir*) # (vi
+ cat >> confdefs.h <<EOF
+#define INSTALL_PATH "install"
+EOF
+
+ ;;
+*) # (vi
+ cat >> confdefs.h <<EOF
+#define INSTALL_PATH "$INSTALL"
+EOF
+
+ ;;
+esac
+
+
+cat >> confdefs.h <<\EOF
+#define UNIX 1
+EOF
+
+
+if test -z "$GCC" ; then
+
+echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6
+echo "configure:2300: checking for ${CC-cc} option to accept ANSI C" >&5
+if eval "test \"`echo '$''{'cf_cv_ansi_cc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cf_cv_ansi_cc=no
+cf_save_CFLAGS="$CFLAGS"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc
+# UnixWare 1.2 (cannot use -Xc, since ANSI/POSIX clashes)
+for cf_arg in "-DCC_HAS_PROTOS" "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" -Xc
+do
+ CFLAGS="$cf_save_CFLAGS $cf_arg"
+ cat > conftest.$ac_ext <<EOF
+#line 2318 "configure"
+#include "confdefs.h"
+
+#ifndef CC_HAS_PROTOS
+#if !defined(__STDC__) || __STDC__ != 1
+choke me
+#endif
+#endif
+
+int main() {
+
+ int test (int i, double x);
+ struct s1 {int (*f) (int a);};
+ struct s2 {int (*f) (double a);};
+; return 0; }
+EOF
+if { (eval echo configure:2334: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_ansi_cc="$cf_arg"; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+CFLAGS="$cf_save_CFLAGS"
+
+fi
+
+echo "$ac_t""$cf_cv_ansi_cc" 1>&6
+
+if test "$cf_cv_ansi_cc" != "no"; then
+if test ".$cf_cv_ansi_cc" != ".-DCC_HAS_PROTOS"; then
+ CFLAGS="$CFLAGS $cf_cv_ansi_cc"
+else
+ cat >> confdefs.h <<\EOF
+#define CC_HAS_PROTOS 1
+EOF
+
+fi
+fi
+
+fi
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2362: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2367 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2416: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+
+PROG_EXT=
+case $host_os in
+aix4*)
+ CFLAGS="$CFLAGS -DAIX4 -D_BSD=44"
+ LIBS="$LIBS -lbsd"
+ ;;
+aix*)
+ LIBS="$LIBS -lbsd"
+ ;;
+apollo*)
+ CFLAGS="$CFLAGS -D_BUILTINS -W0,-opt,4"
+ ;;
+bsdi*)
+ CFLAGS="$CFLAGS -DBSDI"
+ ;;
+clix*)
+ # Tested on CLIX 3.1 (T.Dickey). The original makefile entry
+ # contributed by Alex Matulich (matuli_a@marlin.navsea.navy.mil) also
+ # references -lmalloc and -lbsd.
+ echo $ac_n "checking for strcmp in -lc_s""... $ac_c" 1>&6
+echo "configure:2457: checking for strcmp in -lc_s" >&5
+ac_lib_var=`echo c_s'_'strcmp | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lc_s $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2465 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strcmp();
+
+int main() {
+strcmp()
+; return 0; }
+EOF
+if { (eval echo configure:2476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo c_s | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lc_s $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+convex*)
+ CFLAGS="$CFLAGS -D__STDC__ -Dunix"
+ ;;
+dgux*)
+ CFLAGS="$CFLAGS -DDGUX"
+ ;;
+hpux*)
+ CFLAGS="$CFLAGS -DSNAKE"
+ ;;
+isc*)
+ # -DPOSIX_JC is necessary, else LYBookmark.c never finds out what a mode_t is.
+ CFLAGS="$CFLAGS -DISC -DPOSIX_JC"
+ LIBS="$LIBS -linet -lnsl_s -lcposix"
+ ;;
+irix*)
+ # The original makefile used the $CFLAGS option -cckr for some form
+ # of K&R compatibility. However, this causes compilation warnings for
+ # varargs on IRIX 5.2, and does not appear to be needed.
+ #removed: CFLAGS="$CFLAGS -cckr"
+ ;;
+linux*)
+ CFLAGS="$CFLAGS -DLINUX"
+ ;;
+next*)
+ CFLAGS="$CFLAGS -DNEXT -DXMOSAIC_HACK"
+ ;;
+openbsd*)
+ LIBS="$LIBS -lcompat"
+ ;;
+os2*)
+ # We make sure -Zexe is not used -- it would interfere with @PROG_EXT@
+ CFLAGS="$CFLAGS -Zmt -D__ST_MT_ERRNO__"
+ LDFLAGS=`echo "$LDFLAGS -Zmt -Zcrtdll" | sed "s/-Zexe//g"`
+ PROG_EXT=".exe"
+ ;;
+osf*)
+ # Increase the maximum size of functions that will be optimized.
+ test -z "$GCC" && CFLAGS="$CFLAGS -O -Olimit 4000"
+ CFLAGS="$CFLAGS -DDSYS5"
+ ;;
+sco3.2v5*)
+ test $ac_cv_prog_gcc != yes && CC="cc -belf"
+ ;;
+sco*)
+ LIBS="$LIBS -lmalloc"
+ # It's a little late to do much, but try to warn user if he's using
+ # SCO's cc (which is reported to have broken const/volatile).
+ case "$CC" in #(vi
+ cc|*/cc)
+ echo "configure: warning: You should consider using gcc or rcc if available" 1>&2
+ unset ac_cv_prog_CC
+ for ac_prog in gcc rcc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2560: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$CC" && break
+done
+test -n "$CC" || CC="$CC"
+
+ ;;
+ esac
+ ;;
+sequent-ptx)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT -DNO_IOCTL -DUSE_FCNTL"
+ ;;
+sequent-ptx2)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT"
+ ;;
+sony-newsos*)
+ CFLAGS="$CFLAGS -I/usr/sony/include"
+ for ac_hdr in jcurses.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2604: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2609 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2614: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ ;;
+svr4)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT -DSVR4"
+ ;;
+sunos3*)
+ CFLAGS="$CFLAGS -DSUN"
+ ;;
+sunos4*)
+ CFLAGS="$CFLAGS -DSUN -DSUN4"
+ ;;
+ultrix*)
+ # Increase the maximum size of functions that will be optimized.
+ test -z "$GCC" && CFLAGS="$CFLAGS -O -Olimit 600 -G 7"
+ CFLAGS="$CFLAGS -DULTRIX"
+ for ac_hdr in cursesX.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2658: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2663 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2668: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ cf_cv_ncurses_header=cursesX.h
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ ;;
+esac
+
+
+
+
+cf_test_netlibs=no
+echo $ac_n "checking for network libraries""... $ac_c" 1>&6
+echo "configure:2702: checking for network libraries" >&5
+if eval "test \"`echo '$''{'cf_cv_netlibs'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+echo "$ac_t""working..." 1>&6
+cf_cv_netlibs=""
+cf_test_netlibs=yes
+for ac_func in gethostname
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2713: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2718 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2741: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for gethostname in -lnsl""... $ac_c" 1>&6
+echo "configure:2764: checking for gethostname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2772 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostname();
+
+int main() {
+gethostname()
+; return 0; }
+EOF
+if { (eval echo configure:2783: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo gethostname | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_gethostname=yes
+ cf_cv_netlibs="-lnsl $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_gethostname=unknown
+ unset ac_cv_func_gethostname 2>/dev/null
+
+
+echo $ac_n "checking for gethostname in -lsocket""... $ac_c" 1>&6
+echo "configure:2816: checking for gethostname in -lsocket" >&5
+ac_lib_var=`echo socket'_'gethostname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2824 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostname();
+
+int main() {
+gethostname()
+; return 0; }
+EOF
+if { (eval echo configure:2835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo gethostname | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_gethostname=yes
+ cf_cv_netlibs="-lsocket $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_gethostname=unknown
+ unset ac_cv_func_gethostname 2>/dev/null
+
+fi
+
+
+fi
+
+
+fi
+done
+
+#
+# FIXME: sequent needs this library (i.e., -lsocket -linet -lnsl), but
+# I don't know the entrypoints - 97/7/22 TD
+echo $ac_n "checking for -linet""... $ac_c" 1>&6
+echo "configure:2879: checking for -linet" >&5
+if eval "test \"`echo '$''{'ac_cv_lib_inet'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-linet $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2886 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:2893: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ ac_cv_lib_inet=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_lib_inet=no
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+echo "$ac_t""$ac_cv_lib_inet" 1>&6
+if test "$ac_cv_lib_inet" = yes; then
+ cf_cv_netlibs="-linet $cf_cv_netlibs"
+fi
+
+#
+if test "$ac_cv_func_lsocket" != no ; then
+for ac_func in socket
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2916: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2921 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:2967: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2975 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:2986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo socket | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_socket=yes
+ cf_cv_netlibs="-lsocket $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_socket=unknown
+ unset ac_cv_func_socket 2>/dev/null
+
+
+echo $ac_n "checking for socket in -lbsd""... $ac_c" 1>&6
+echo "configure:3019: checking for socket in -lbsd" >&5
+ac_lib_var=`echo bsd'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lbsd $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3027 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:3038: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo socket | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_socket=yes
+ cf_cv_netlibs="-lbsd $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_socket=unknown
+ unset ac_cv_func_socket 2>/dev/null
+
+fi
+
+
+fi
+
+
+fi
+done
+
+fi
+#
+for ac_func in gethostbyname
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3083: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3088 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3111: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:3134: checking for gethostbyname in -lnsl" >&5
+ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3142 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gethostbyname();
+
+int main() {
+gethostbyname()
+; return 0; }
+EOF
+if { (eval echo configure:3153: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo gethostbyname | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_gethostbyname=yes
+ cf_cv_netlibs="-lnsl $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_gethostbyname=unknown
+ unset ac_cv_func_gethostbyname 2>/dev/null
+
+fi
+
+
+fi
+done
+
+#
+for ac_func in strcasecmp
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3194: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3199 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for strcasecmp in -lresolv""... $ac_c" 1>&6
+echo "configure:3245: checking for strcasecmp in -lresolv" >&5
+ac_lib_var=`echo resolv'_'strcasecmp | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $cf_cv_netlibs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3253 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char strcasecmp();
+
+int main() {
+strcasecmp()
+; return 0; }
+EOF
+if { (eval echo configure:3264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo strcasecmp | tr 'a-z' 'A-Z'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_strcasecmp=yes
+ cf_cv_netlibs="-lresolv $cf_cv_netlibs"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_strcasecmp=unknown
+ unset ac_cv_func_strcasecmp 2>/dev/null
+
+fi
+
+
+fi
+done
+
+
+fi
+
+LIBS="$LIBS $cf_cv_netlibs"
+test $cf_test_netlibs = no && echo "$cf_cv_netlibs" >&6
+
+
+echo $ac_n "checking for screen type""... $ac_c" 1>&6
+echo "configure:3309: checking for screen type" >&5
+if eval "test \"`echo '$''{'cf_cv_screen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+
+# Check whether --with-screen or --without-screen was given.
+if test "${with_screen+set}" = set; then
+ withval="$with_screen"
+
+case $withval in
+curses|ncurses|slang)
+ cf_cv_screen=$withval
+ ;;
+*) { echo "configure: error: Unexpected value" 1>&2; exit 1; }
+ ;;
+esac
+else
+ cf_cv_screen=curses
+fi
+
+fi
+
+echo "$ac_t""$cf_cv_screen" 1>&6
+
+if test $cf_cv_screen != ncurses ; then
+ if eval "test \"`echo '$''{'cf_cv_ncurses_header'+set}'`\" != set"; then
+ cf_cv_ncurses_header=curses.h
+ fi
+fi
+
+case $cf_cv_screen in
+curses)
+
+echo $ac_n "checking for initscr""... $ac_c" 1>&6
+echo "configure:3344: checking for initscr" >&5
+if eval "test \"`echo '$''{'ac_cv_func_initscr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3349 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char initscr(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_initscr) || defined (__stub___initscr)
+choke me
+#else
+initscr();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3372: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_initscr=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_initscr=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'initscr`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+case $host_os in #(vi
+freebsd*) #(vi
+ echo $ac_n "checking for tgoto in -lmytinfo""... $ac_c" 1>&6
+echo "configure:3393: checking for tgoto in -lmytinfo" >&5
+ac_lib_var=`echo mytinfo'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lmytinfo $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3401 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:3412: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="-lmytinfo $LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+hpux10.*)
+ echo $ac_n "checking for initscr in -lcur_colr""... $ac_c" 1>&6
+echo "configure:3435: checking for initscr in -lcur_colr" >&5
+ac_lib_var=`echo cur_colr'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcur_colr $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3443 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:3454: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+ LIBS="-lcur_colr $LIBS"
+ CFLAGS="-I/usr/include/curses_colr $CFLAGS"
+ ac_cv_func_initscr=yes
+
+else
+ echo "$ac_t""no" 1>&6
+
+ echo $ac_n "checking for initscr in -lHcurses""... $ac_c" 1>&6
+echo "configure:3478: checking for initscr in -lHcurses" >&5
+ac_lib_var=`echo Hcurses'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lHcurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3486 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:3497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+ # HP's header uses __HP_CURSES, but user claims _HP_CURSES.
+ LIBS="-lHcurses $LIBS"
+ CFLAGS="-D__HP_CURSES -D_HP_CURSES $CFLAGS"
+ ac_cv_func_initscr=yes
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+ ;;
+esac
+
+if test ".$With5lib" != ".no" ; then
+if test -d /usr/5lib ; then
+ # SunOS 3.x or 4.x
+ CPPFLAGS="$CPPFLAGS -I/usr/5include"
+ LIBS="$LIBS -L/usr/5lib"
+fi
+fi
+
+if test ".$ac_cv_func_initscr" != .yes ; then
+ cf_save_LIBS="$LIBS"
+ cf_term_lib=""
+ cf_curs_lib=""
+
+ # Check for library containing tgoto. Do this before curses library
+ # because it may be needed to link the test-case for initscr.
+ echo $ac_n "checking for tgoto""... $ac_c" 1>&6
+echo "configure:3543: checking for tgoto" >&5
+if eval "test \"`echo '$''{'ac_cv_func_tgoto'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3548 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char tgoto(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_tgoto) || defined (__stub___tgoto)
+choke me
+#else
+tgoto();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3571: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_tgoto=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_tgoto=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'tgoto`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cf_term_lib=predefined
+else
+ echo "$ac_t""no" 1>&6
+
+ for cf_term_lib in termcap termlib unknown
+ do
+ echo $ac_n "checking for tgoto in -l$cf_term_lib""... $ac_c" 1>&6
+echo "configure:3592: checking for tgoto in -l$cf_term_lib" >&5
+ac_lib_var=`echo $cf_term_lib'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-l$cf_term_lib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3600 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:3611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ done
+
+fi
+
+
+ # Check for library containing initscr
+ test "$cf_term_lib" != predefined && test "$cf_term_lib" != unknown && LIBS="-l$cf_term_lib $cf_save_LIBS"
+ for cf_curs_lib in curses ncurses xcurses cursesX jcurses unknown
+ do
+ echo $ac_n "checking for initscr in -l$cf_curs_lib""... $ac_c" 1>&6
+echo "configure:3641: checking for initscr in -l$cf_curs_lib" >&5
+ac_lib_var=`echo $cf_curs_lib'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-l$cf_curs_lib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3649 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:3660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ break
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ done
+ test $cf_curs_lib = unknown && { echo "configure: error: no curses library found" 1>&2; exit 1; }
+
+ LIBS="-l$cf_curs_lib $cf_save_LIBS"
+ if test "$cf_term_lib" = unknown ; then
+ echo $ac_n "checking if we can link with $cf_curs_lib library""... $ac_c" 1>&6
+echo "configure:3686: checking if we can link with $cf_curs_lib library" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 3688 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:3695: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_result=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_result=no
+fi
+rm -f conftest*
+ echo "$ac_t""$cf_result" 1>&6
+ test $cf_result = no && { echo "configure: error: Cannot link curses library" 1>&2; exit 1; }
+ elif test "$cf_term_lib" != predefined ; then
+ echo $ac_n "checking if we need both $cf_curs_lib and $cf_term_lib libraries""... $ac_c" 1>&6
+echo "configure:3709: checking if we need both $cf_curs_lib and $cf_term_lib libraries" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 3711 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr(); tgoto((char *)0, 0, 0);
+; return 0; }
+EOF
+if { (eval echo configure:3718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_result=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+ LIBS="-l$cf_curs_lib -l$cf_term_lib $cf_save_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 3728 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:3735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_result=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_result=error
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+ echo "$ac_t""$cf_result" 1>&6
+ fi
+fi
+
+
+fi
+
+
+echo $ac_n "checking for curses performance tradeoff""... $ac_c" 1>&6
+echo "configure:3757: checking for curses performance tradeoff" >&5
+if eval "test \"`echo '$''{'cf_cv_curs_performance'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cf_cv_curs_performance=no
+ cat > conftest.$ac_ext <<EOF
+#line 3764 "configure"
+#include "confdefs.h"
+
+#include <$cf_cv_ncurses_header>
+int main() {
+
+#if defined(wbkgdset) && defined(clearok) && defined(getbkgd)
+ int x = ERR;
+#else
+ int x = ; /* force an error */
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3778: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+
+ cat > conftest.$ac_ext <<EOF
+#line 3782 "configure"
+#include "confdefs.h"
+
+#define CURS_PERFORMANCE
+#include <$cf_cv_ncurses_header>
+int main() {
+
+#if defined(wbkgdset) && defined(clearok) && defined(getbkgd)
+ int x = ; /* force an error */
+#else
+ int x = ERR;
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3797: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_curs_performance=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_curs_performance" 1>&6
+test $cf_cv_curs_performance = yes && cat >> confdefs.h <<\EOF
+#define CURS_PERFORMANCE 1
+EOF
+
+
+ ;;
+ncurses)
+
+echo $ac_n "checking for ncurses header file""... $ac_c" 1>&6
+echo "configure:3822: checking for ncurses header file" >&5
+if eval "test \"`echo '$''{'cf_cv_ncurses_header'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 3828 "configure"
+#include "confdefs.h"
+#include <curses.h>
+int main() {
+
+#ifdef NCURSES_VERSION
+printf("%s\n", NCURSES_VERSION);
+#else
+#ifdef __NCURSES_H
+printf("old\n");
+#else
+make an error
+#endif
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3845: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_ncurses_header=predefined
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+ cf_search=""
+if test -d "$includedir" ; then
+test "$includedir" != NONE && cf_search="$cf_search $includedir $includedir/ncurses"
+fi
+if test -d "$oldincludedir" ; then
+test "$oldincludedir" != NONE && cf_search="$cf_search $oldincludedir $oldincludedir/ncurses"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && cf_search="$cf_search $prefix/include $prefix/include/ncurses"
+fi
+test "$prefix" != /usr/local && cf_search="$cf_search /usr/local/include /usr/local/include/ncurses"
+test "$prefix" != /usr && cf_search="$cf_search /usr/include /usr/include/ncurses"
+
+ test -n "$verbose" && echo
+ for cf_incdir in $cf_search
+ do
+ for cf_header in \
+ curses.h \
+ ncurses.h
+ do
+ if egrep "NCURSES_[VH]" $cf_incdir/$cf_header 1>&5 2>&1; then
+ cf_cv_ncurses_header=$cf_incdir/$cf_header
+ test -n "$verbose" && echo $ac_n " ... found $ac_c" 1>&6
+ break
+ fi
+ test -n "$verbose" && echo " ... tested $cf_incdir/$cf_header" 1>&6
+ done
+ test -n "$cf_cv_ncurses_header" && break
+ done
+ test -z "$cf_cv_ncurses_header" && { echo "configure: error: not found" 1>&2; exit 1; }
+
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_ncurses_header" 1>&6
+cat >> confdefs.h <<\EOF
+#define NCURSES 1
+EOF
+
+
+cf_incdir=`echo $cf_cv_ncurses_header | sed -e 's:/[^/]*$::'`
+
+case $cf_cv_ncurses_header in # (vi
+*/ncurses.h)
+ cat >> confdefs.h <<\EOF
+#define HAVE_NCURSES_H 1
+EOF
+
+ ;;
+esac
+
+case $cf_cv_ncurses_header in # (vi
+predefined) # (vi
+ cf_cv_ncurses_header=curses.h
+ ;;
+*)
+
+for cf_add_incdir in $cf_incdir
+do
+ while true
+ do
+ case $cf_add_incdir in
+ /usr/include) # (vi
+ ;;
+ *) # (vi
+ CPPFLAGS="$CPPFLAGS -I$cf_add_incdir"
+ ;;
+ esac
+ cf_top_incdir=`echo $cf_add_incdir | sed -e 's:/include/.*$:/include:'`
+ test "$cf_top_incdir" = "$cf_add_incdir" && break
+ cf_add_incdir="$cf_top_incdir"
+ done
+done
+
+ ;;
+esac
+echo $ac_n "checking for ncurses version""... $ac_c" 1>&6
+echo "configure:3931: checking for ncurses version" >&5
+if eval "test \"`echo '$''{'cf_cv_ncurses_version'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cf_cv_ncurses_version=no
+ cf_tempfile=out$$
+ if test "$cross_compiling" = yes; then
+
+
+ # This will not work if the preprocessor splits the line after the
+ # Autoconf token. The 'unproto' program does that.
+ cat > conftest.$ac_ext <<EOF
+#include <${cf_cv_ncurses_header-curses.h}>
+#undef Autoconf
+#ifdef NCURSES_VERSION
+Autoconf NCURSES_VERSION
+#else
+#ifdef __NCURSES_H
+Autoconf "old"
+#endif
+;
+#endif
+EOF
+ cf_try="$ac_cpp conftest.$ac_ext 2>&5 | grep '^Autoconf ' >conftest.out"
+ { (eval echo configure:3956: \"$cf_try\") 1>&5; (eval $cf_try) 2>&5; }
+ if test -f conftest.out ; then
+ cf_out=`cat conftest.out | sed -e 's@^Autoconf @@' -e 's@^[^"]*"@@' -e 's@".*@@'`
+ test -n "$cf_out" && cf_cv_ncurses_version="$cf_out"
+ rm -f conftest.out
+ fi
+
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3965 "configure"
+#include "confdefs.h"
+
+#include <${cf_cv_ncurses_header-curses.h}>
+int main()
+{
+ FILE *fp = fopen("$cf_tempfile", "w");
+#ifdef NCURSES_VERSION
+# ifdef NCURSES_VERSION_PATCH
+ fprintf(fp, "%s.%d\n", NCURSES_VERSION, NCURSES_VERSION_PATCH);
+# else
+ fprintf(fp, "%s\n", NCURSES_VERSION);
+# endif
+#else
+# ifdef __NCURSES_H
+ fprintf(fp, "old\n");
+# else
+ make an error
+# endif
+#endif
+ exit(0);
+}
+EOF
+if { (eval echo configure:3988: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+
+ cf_cv_ncurses_version=`cat $cf_tempfile`
+ rm -f $cf_tempfile
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$cf_cv_ncurses_version" 1>&6
+
+
+
+
+ # This works, except for the special case where we find gpm, but
+ # ncurses is in a nonstandard location via $LIBS, and we really want
+ # to link gpm.
+cf_ncurses_LIBS=""
+cf_ncurses_SAVE="$LIBS"
+echo $ac_n "checking for Gpm_Open in -lgpm""... $ac_c" 1>&6
+echo "configure:4013: checking for Gpm_Open in -lgpm" >&5
+ac_lib_var=`echo gpm'_'Gpm_Open | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgpm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4021 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char Gpm_Open();
+
+int main() {
+Gpm_Open()
+; return 0; }
+EOF
+if { (eval echo configure:4032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ echo $ac_n "checking for initscr in -lgpm""... $ac_c" 1>&6
+echo "configure:4048: checking for initscr in -lgpm" >&5
+ac_lib_var=`echo gpm'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgpm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4056 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:4067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$cf_ncurses_SAVE"
+else
+ echo "$ac_t""no" 1>&6
+cf_ncurses_LIBS="-lgpm"
+fi
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+case $host_os in #(vi
+freebsd*)
+ # This is only necessary if you are linking against an obsolete
+ # version of ncurses (but it should do no harm, since it's static).
+ echo $ac_n "checking for tgoto in -lmytinfo""... $ac_c" 1>&6
+echo "configure:4098: checking for tgoto in -lmytinfo" >&5
+ac_lib_var=`echo mytinfo'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lmytinfo $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4106 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:4117: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cf_ncurses_LIBS="-lmytinfo $cf_ncurses_LIBS"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+esac
+
+LIBS="$cf_ncurses_LIBS $LIBS"
+
+ cf_cv_have_lib_ncurses=no
+ cf_libdir=""
+ echo $ac_n "checking for initscr""... $ac_c" 1>&6
+echo "configure:4145: checking for initscr" >&5
+if eval "test \"`echo '$''{'ac_cv_func_initscr'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4150 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char initscr(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_initscr) || defined (__stub___initscr)
+choke me
+#else
+initscr();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4173: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_initscr=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_initscr=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'initscr`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_ncurses=yes
+else
+ echo "$ac_t""no" 1>&6
+
+ cf_save_LIBS="$LIBS"
+ echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6
+echo "configure:4193: checking for initscr in -lncurses" >&5
+ LIBS="-lncurses $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4196 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:4203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_ncurses=yes
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ cf_search=""
+if test -d "$libdir" ; then
+test "$libdir" != NONE && cf_search="$cf_search $libdir $libdir/ncurses"
+fi
+if test -d "$exec_prefix"; then
+test "$exec_prefix" != NONE && cf_search="$cf_search $exec_prefix/lib $exec_prefix/lib/ncurses"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && \
+test "$prefix" != "$exec_prefix" && cf_search="$cf_search $prefix/lib $prefix/lib/ncurses"
+fi
+test "$prefix" != /usr/local && cf_search="$cf_search /usr/local/lib /usr/local/lib/ncurses"
+test "$prefix" != /usr && cf_search="$cf_search /usr/lib /usr/lib/ncurses"
+
+ for cf_libdir in $cf_search
+ do
+ echo $ac_n "checking for -lncurses in $cf_libdir""... $ac_c" 1>&6
+echo "configure:4230: checking for -lncurses in $cf_libdir" >&5
+ LIBS="-L$cf_libdir -lncurses $cf_save_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4233 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:4240: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_ncurses=yes
+ break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ LIBS="$cf_save_LIBS"
+fi
+rm -f conftest*
+ done
+
+fi
+rm -f conftest*
+
+fi
+
+if test $cf_cv_have_lib_ncurses = no ; then
+ { echo "configure: error: Cannot link ncurses library" 1>&2; exit 1; }
+fi
+case $host_os in #(vi
+linux*) # Suse Linux does not follow /usr/lib convention
+ ncurses="$ncurses /lib"
+ ;;
+esac
+
+
+if test -n "$cf_ncurses_LIBS" ; then
+ echo $ac_n "checking if we can link ncurses without $cf_ncurses_LIBS""... $ac_c" 1>&6
+echo "configure:4272: checking if we can link ncurses without $cf_ncurses_LIBS" >&5
+ cf_ncurses_SAVE="$LIBS"
+ for p in $cf_ncurses_LIBS ; do
+ q=`echo $LIBS | sed -e 's/'$p' //' -e 's/'$p'$//'`
+ if test "$q" != "$LIBS" ; then
+ LIBS="$q"
+ fi
+ done
+ cat > conftest.$ac_ext <<EOF
+#line 4281 "configure"
+#include "confdefs.h"
+#include <${cf_cv_ncurses_header-curses.h}>
+int main() {
+initscr(); mousemask(0,0); tgoto((char *)0, 0, 0);
+; return 0; }
+EOF
+if { (eval echo configure:4288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ LIBS="$cf_ncurses_SAVE"
+fi
+rm -f conftest*
+fi
+
+ ;;
+slang)
+
+echo $ac_n "checking for slang header file""... $ac_c" 1>&6
+echo "configure:4305: checking for slang header file" >&5
+if eval "test \"`echo '$''{'cf_cv_slang_header'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 4311 "configure"
+#include "confdefs.h"
+#include <slang.h>
+int main() {
+printf("%s\n", SLANG_VERSION)
+; return 0; }
+EOF
+if { (eval echo configure:4318: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_slang_header=predefined
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+ cf_search=""
+if test -d "$includedir" ; then
+test "$includedir" != NONE && cf_search="$cf_search $includedir $includedir/slang"
+fi
+if test -d "$oldincludedir" ; then
+test "$oldincludedir" != NONE && cf_search="$cf_search $oldincludedir $oldincludedir/slang"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && cf_search="$cf_search $prefix/include $prefix/include/slang"
+fi
+test "$prefix" != /usr/local && cf_search="$cf_search /usr/local/include /usr/local/include/slang"
+test "$prefix" != /usr && cf_search="$cf_search /usr/include /usr/include/slang"
+
+ for cf_incdir in $cf_search
+ do
+ for cf_header in \
+ slang.h
+ do
+ echo trying $cf_incdir/$cf_header 1>&5
+ if egrep "SLANG_VERSION" $cf_incdir/$cf_header 1>&5 2>&1; then
+ cf_cv_slang_header=$cf_incdir/$cf_header
+ break
+ fi
+ done
+ test -n "$cf_cv_slang_header" && break
+ done
+ test -z "$cf_cv_slang_header" && { echo "configure: error: not found" 1>&2; exit 1; }
+
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_slang_header" 1>&6
+cat >> confdefs.h <<\EOF
+#define USE_SLANG 1
+EOF
+
+
+cf_incdir=`echo $cf_cv_slang_header | sed -e 's:/[^/]*$::'`
+
+case $cf_cv_slang_header in # (vi
+predefined) # (vi
+ ;;
+*)
+
+for cf_add_incdir in $cf_incdir
+do
+ while true
+ do
+ case $cf_add_incdir in
+ /usr/include) # (vi
+ ;;
+ *) # (vi
+ CPPFLAGS="$CPPFLAGS -I$cf_add_incdir"
+ ;;
+ esac
+ cf_top_incdir=`echo $cf_add_incdir | sed -e 's:/include/.*$:/include:'`
+ test "$cf_top_incdir" = "$cf_add_incdir" && break
+ cf_add_incdir="$cf_top_incdir"
+ done
+done
+
+ ;;
+esac
+
+
+cf_slang_LIBS1="$LIBS"
+
+if eval "test \"`echo '$''{'cf_cv_lib_termcap'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cf_cv_lib_termcap=none
+# HP-UX 9.x terminfo has setupterm, but no tigetstr.
+if test "$termlib" = none; then
+ echo $ac_n "checking for tigetstr in -ltermlib""... $ac_c" 1>&6
+echo "configure:4402: checking for tigetstr in -ltermlib" >&5
+ac_lib_var=`echo termlib'_'tigetstr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermlib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4410 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tigetstr();
+
+int main() {
+tigetstr()
+; return 0; }
+EOF
+if { (eval echo configure:4421: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ltermlib" cf_cv_lib_termcap=terminfo
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ echo $ac_n "checking for tgoto in -ltermlib""... $ac_c" 1>&6
+echo "configure:4444: checking for tgoto in -ltermlib" >&5
+ac_lib_var=`echo termlib'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermlib $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4452 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:4463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ltermlib" cf_cv_lib_termcap=termcap
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ # allow curses library for broken AIX system.
+ echo $ac_n "checking for initscr in -lcurses""... $ac_c" 1>&6
+echo "configure:4487: checking for initscr in -lcurses" >&5
+ac_lib_var=`echo curses'_'initscr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4495 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char initscr();
+
+int main() {
+initscr()
+; return 0; }
+EOF
+if { (eval echo configure:4506: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lcurses" cf_cv_lib_termcap=termcap
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for tgoto in -ltermcap""... $ac_c" 1>&6
+echo "configure:4527: checking for tgoto in -ltermcap" >&5
+ac_lib_var=`echo termcap'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermcap $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4535 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:4546: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ltermcap" cf_cv_lib_termcap=termcap
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ echo $ac_n "checking for tgoto in -ltermcap""... $ac_c" 1>&6
+echo "configure:4569: checking for tgoto in -ltermcap" >&5
+ac_lib_var=`echo termcap'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ltermcap $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4577 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:4588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ltermcap" cf_cv_lib_termcap=termcap
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+if test "$cf_cv_lib_termcap" = none; then
+ echo $ac_n "checking for tgoto in -lncurses""... $ac_c" 1>&6
+echo "configure:4611: checking for tgoto in -lncurses" >&5
+ac_lib_var=`echo ncurses'_'tgoto | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lncurses $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4619 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char tgoto();
+
+int main() {
+tgoto()
+; return 0; }
+EOF
+if { (eval echo configure:4630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lncurses" cf_cv_lib_termcap=ncurses
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+fi
+
+if test "$cf_cv_lib_termcap" = none; then
+ { echo "configure: error: Can't find -ltermlib, -lcurses, or -ltermcap" 1>&2; exit 1; }
+fi
+
+cf_slang_LIBS2="$LIBS"
+echo $ac_n "checking for acos""... $ac_c" 1>&6
+echo "configure:4660: checking for acos" >&5
+if eval "test \"`echo '$''{'ac_cv_func_acos'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4665 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char acos(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acos();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_acos) || defined (__stub___acos)
+choke me
+#else
+acos();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_acos=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_acos=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'acos`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+echo $ac_n "checking for acos in -lm""... $ac_c" 1>&6
+echo "configure:4707: checking for acos in -lm" >&5
+ac_lib_var=`echo m'_'acos | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lm $LIBS $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4715 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char acos();
+
+int main() {
+acos()
+; return 0; }
+EOF
+if { (eval echo configure:4726: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+
+
+cf_tr_func=`echo acos | tr '[a-z]' '[A-Z]'`
+
+ cat >> confdefs.h <<EOF
+#define HAVE_$cf_tr_func 1
+EOF
+
+ ac_cv_func_acos=yes
+ LIBS="-lm $LIBS"
+else
+ echo "$ac_t""no" 1>&6
+
+ ac_cv_func_acos=unknown
+ unset ac_cv_func_acos 2>/dev/null
+
+fi
+
+
+fi
+
+
+ cf_cv_have_lib_slang=no
+ cf_libdir=""
+ echo $ac_n "checking for SLtt_get_screen_size""... $ac_c" 1>&6
+echo "configure:4766: checking for SLtt_get_screen_size" >&5
+if eval "test \"`echo '$''{'ac_cv_func_SLtt_get_screen_size'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4771 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char SLtt_get_screen_size(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char SLtt_get_screen_size();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_SLtt_get_screen_size) || defined (__stub___SLtt_get_screen_size)
+choke me
+#else
+SLtt_get_screen_size();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:4794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_SLtt_get_screen_size=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_SLtt_get_screen_size=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'SLtt_get_screen_size`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_slang=yes
+else
+ echo "$ac_t""no" 1>&6
+
+ cf_save_LIBS="$LIBS"
+ echo $ac_n "checking for SLtt_get_screen_size in -lslang""... $ac_c" 1>&6
+echo "configure:4814: checking for SLtt_get_screen_size in -lslang" >&5
+ LIBS="-lslang $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4817 "configure"
+#include "confdefs.h"
+#include <slang.h>
+int main() {
+SLtt_get_screen_size()
+; return 0; }
+EOF
+if { (eval echo configure:4824: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_slang=yes
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ cf_search=""
+if test -d "$libdir" ; then
+test "$libdir" != NONE && cf_search="$cf_search $libdir $libdir/slang"
+fi
+if test -d "$exec_prefix"; then
+test "$exec_prefix" != NONE && cf_search="$cf_search $exec_prefix/lib $exec_prefix/lib/slang"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && \
+test "$prefix" != "$exec_prefix" && cf_search="$cf_search $prefix/lib $prefix/lib/slang"
+fi
+test "$prefix" != /usr/local && cf_search="$cf_search /usr/local/lib /usr/local/lib/slang"
+test "$prefix" != /usr && cf_search="$cf_search /usr/lib /usr/lib/slang"
+
+ for cf_libdir in $cf_search
+ do
+ echo $ac_n "checking for -lslang in $cf_libdir""... $ac_c" 1>&6
+echo "configure:4851: checking for -lslang in $cf_libdir" >&5
+ LIBS="-L$cf_libdir -lslang $cf_save_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4854 "configure"
+#include "confdefs.h"
+#include <slang.h>
+int main() {
+SLtt_get_screen_size()
+; return 0; }
+EOF
+if { (eval echo configure:4861: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_slang=yes
+ break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ LIBS="$cf_save_LIBS"
+fi
+rm -f conftest*
+ done
+
+fi
+rm -f conftest*
+
+fi
+
+if test $cf_cv_have_lib_slang = no ; then
+ { echo "configure: error: Cannot link slang library" 1>&2; exit 1; }
+fi
+case $host_os in #(vi
+linux*) # Suse Linux does not follow /usr/lib convention
+ slang="$slang /lib"
+ ;;
+esac
+
+cf_slang_LIBS3="$LIBS"
+echo $ac_n "checking if we can link slang without termcap""... $ac_c" 1>&6
+echo "configure:4892: checking if we can link slang without termcap" >&5
+if test -n "`echo $cf_slang_LIBS1 | sed -e 's/ //g'`" ; then
+ cf_exclude=`echo ".$cf_slang_LIBS2" | sed -e "s@$cf_slang_LIBS1@@" -e 's@^.@@'`
+else
+ cf_exclude="$cf_slang_LIBS2"
+fi
+LIBS=`echo ".$cf_slang_LIBS3" | sed -e "s@$cf_exclude@@" -e 's@^.@@'`
+cat > conftest.$ac_ext <<EOF
+#line 4900 "configure"
+#include "confdefs.h"
+#include <slang.h>
+int main() {
+SLtt_get_screen_size()
+; return 0; }
+EOF
+if { (eval echo configure:4907: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_result=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_result=no
+fi
+rm -f conftest*
+echo "$ac_t""$cf_result" 1>&6
+test $cf_result = no && LIBS="$cf_slang_LIBS3"
+
+ ;;
+esac
+
+eval cf_libdir=$libdir
+cf_libdir=`echo $cf_libdir | sed -e s@'^NONE/'@$prefix/@ -e s@'^NONE/'@$ac_default_prefix/@`
+
+echo $ac_n "checking for location of config-file""... $ac_c" 1>&6
+echo "configure:4927: checking for location of config-file" >&5
+LYNX_CFG_FILE=$cf_libdir/lynx.cfg
+cat >> confdefs.h <<EOF
+#define LYNX_CFG_FILE "$LYNX_CFG_FILE"
+EOF
+
+echo "$ac_t""$LYNX_CFG_FILE" 1>&6
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:4937: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4942 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4950: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 4967 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 4985 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5006 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:5017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:5041: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5046 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:5055: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:5080: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5085 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:5093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:5118: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5126 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:5137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:5159: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 5167 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:5178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+for ac_hdr in \
+ fcntl.h \
+ limits.h \
+ stdlib.h \
+ string.h \
+ sys/fcntl.h \
+ sys/filio.h \
+ sys/ioctl.h \
+ sys/param.h \
+ sys/time.h \
+ termio.h \
+ termios.h \
+ unistd.h \
+
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5217: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5222 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5227: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking termio.h and termios.h""... $ac_c" 1>&6
+echo "configure:5255: checking termio.h and termios.h" >&5
+if eval "test \"`echo '$''{'cf_cv_termio_and_termios'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 5261 "configure"
+#include "confdefs.h"
+
+#if HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+int main() {
+putchar (0x0a)
+; return 0; }
+EOF
+if { (eval echo configure:5274: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_termio_and_termios=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_termio_and_termios=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_termio_and_termios" 1>&6
+test $cf_cv_termio_and_termios = no && cat >> confdefs.h <<\EOF
+#define TERMIO_AND_TERMIOS 1
+EOF
+
+
+
+for ac_hdr in sys/wait.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5297: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5302 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5307: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+cf_wait_headers="#include <sys/types.h>
+"
+if test $ac_cv_header_sys_wait_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <sys/wait.h>
+"
+else
+for ac_hdr in wait.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5344: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5349 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5354: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in waitstatus.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:5384: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5389 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5394: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+if test $ac_cv_header_wait_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <wait.h>
+"
+fi
+if test $ac_cv_header_waitstatus_h = yes; then
+cf_wait_headers="$cf_wait_headers
+#include <waitstatus.h>
+"
+fi
+fi
+
+
+
+echo $ac_n "checking for union wait""... $ac_c" 1>&6
+echo "configure:5435: checking for union wait" >&5
+if eval "test \"`echo '$''{'cf_cv_type_unionwait'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 5441 "configure"
+#include "confdefs.h"
+$cf_wait_headers
+int main() {
+int x;
+ int y = WEXITSTATUS(x);
+ int z = WTERMSIG(x);
+ wait(&x);
+
+; return 0; }
+EOF
+if { (eval echo configure:5452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_type_unionwait=no
+ echo compiles ok w/o union wait 1>&5
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+ cat > conftest.$ac_ext <<EOF
+#line 5463 "configure"
+#include "confdefs.h"
+$cf_wait_headers
+int main() {
+union wait x;
+#ifdef WEXITSTATUS
+ int y = WEXITSTATUS(x);
+#endif
+#ifdef WTERMSIG
+ int z = WTERMSIG(x);
+#endif
+ wait(&x);
+
+; return 0; }
+EOF
+if { (eval echo configure:5478: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_type_unionwait=yes
+ echo compiles ok with union wait and possibly macros too 1>&5
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_type_unionwait=no
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_type_unionwait" 1>&6
+test $cf_cv_type_unionwait = yes && cat >> confdefs.h <<\EOF
+#define HAVE_TYPE_UNIONWAIT 1
+EOF
+
+
+
+
+if test $cf_cv_type_unionwait = yes; then
+
+ echo $ac_n "checking if union wait can be used as wait-arg""... $ac_c" 1>&6
+echo "configure:5505: checking if union wait can be used as wait-arg" >&5
+ if eval "test \"`echo '$''{'cf_cv_arg_union_wait'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 5511 "configure"
+#include "confdefs.h"
+$cf_wait_headers
+int main() {
+union wait x; wait(&x)
+; return 0; }
+EOF
+if { (eval echo configure:5518: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_arg_union_wait=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_arg_union_wait=no
+fi
+rm -f conftest*
+
+fi
+
+ echo "$ac_t""$cf_cv_arg_union_wait" 1>&6
+ test $cf_cv_arg_union_wait = yes && cat >> confdefs.h <<\EOF
+#define WAIT_USES_UNION 1
+EOF
+
+
+ echo $ac_n "checking if union wait can be used as waitpid-arg""... $ac_c" 1>&6
+echo "configure:5538: checking if union wait can be used as waitpid-arg" >&5
+ if eval "test \"`echo '$''{'cf_cv_arg_union_waitpid'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 5544 "configure"
+#include "confdefs.h"
+$cf_wait_headers
+int main() {
+union wait x; waitpid(0, &x, 0)
+; return 0; }
+EOF
+if { (eval echo configure:5551: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_arg_union_waitpid=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_arg_union_waitpid=no
+fi
+rm -f conftest*
+
+fi
+
+ echo "$ac_t""$cf_cv_arg_union_waitpid" 1>&6
+ test $cf_cv_arg_union_waitpid = yes && cat >> confdefs.h <<\EOF
+#define WAITPID_USES_UNION 1
+EOF
+
+
+fi
+
+echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+echo "configure:5573: checking for mode_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5578 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_mode_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_mode_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_mode_t" 1>&6
+if test $ac_cv_type_mode_t = no; then
+ cat >> confdefs.h <<\EOF
+#define mode_t int
+EOF
+
+fi
+
+
+
+echo $ac_n "checking for pid_t""... $ac_c" 1>&6
+echo "configure:5608: checking for pid_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5613 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_pid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_pid_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_pid_t" 1>&6
+if test $ac_cv_type_pid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define pid_t int
+EOF
+
+fi
+
+ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
+echo "configure:5642: checking for vfork.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5647 "configure"
+#include "confdefs.h"
+#include <vfork.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:5652: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_VFORK_H 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for working vfork""... $ac_c" 1>&6
+echo "configure:5677: checking for working vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ echo $ac_n "checking for vfork""... $ac_c" 1>&6
+echo "configure:5683: checking for vfork" >&5
+if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5688 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vfork(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vfork();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vfork) || defined (__stub___vfork)
+choke me
+#else
+vfork();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:5711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_vfork=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ cat > conftest.$ac_ext <<EOF
+#line 5732 "configure"
+#include "confdefs.h"
+/* Thanks to Paul Eggert for this test. */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+ argument registers are propagated back to the parent.
+ The compiler is told about this with #include <vfork.h>,
+ but some compilers (e.g. gcc -O) don't grok <vfork.h>.
+ Test for this by using a static variable whose address
+ is put into a register that is clobbered by the vfork. */
+static
+#ifdef __cplusplus
+sparc_address_test (int arg)
+#else
+sparc_address_test (arg) int arg;
+#endif
+{
+ static pid_t child;
+ if (!child) {
+ child = vfork ();
+ if (child < 0) {
+ perror ("vfork");
+ _exit(2);
+ }
+ if (!child) {
+ arg = getpid();
+ write(-1, "", 0);
+ _exit (arg);
+ }
+ }
+}
+main() {
+ pid_t parent = getpid ();
+ pid_t child;
+
+ sparc_address_test ();
+
+ child = vfork ();
+
+ if (child == 0) {
+ /* Here is another test for sparc vfork register problems.
+ This test uses lots of local variables, at least
+ as many local variables as main has allocated so far
+ including compiler temporaries. 4 locals are enough for
+ gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe.
+ A buggy compiler should reuse the register of parent
+ for one of the local variables, since it will think that
+ parent can't possibly be used any more in this routine.
+ Assigning to the local variable will thus munge parent
+ in the parent process. */
+ pid_t
+ p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+ p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+ /* Convince the compiler that p..p7 are live; otherwise, it might
+ use the same hardware register for all 8 local variables. */
+ if (p != p1 || p != p2 || p != p3 || p != p4
+ || p != p5 || p != p6 || p != p7)
+ _exit(1);
+
+ /* On some systems (e.g. IRIX 3.3),
+ vfork doesn't separate parent from child file descriptors.
+ If the child closes a descriptor before it execs or exits,
+ this munges the parent's descriptor as well.
+ Test for this by closing stdout in the child. */
+ _exit(close(fileno(stdout)) != 0);
+ } else {
+ int status;
+ struct stat st;
+
+ while (wait(&status) != child)
+ ;
+ exit(
+ /* Was there some problem with vforking? */
+ child < 0
+
+ /* Did the child fail? (This shouldn't happen.) */
+ || status
+
+ /* Did the vfork/compiler bug occur? */
+ || parent != getpid()
+
+ /* Did the file descriptor bug occur? */
+ || fstat(fileno(stdout), &st) != 0
+ );
+ }
+}
+EOF
+if { (eval echo configure:5827: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_vfork_works=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_vfork_works=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_vfork_works" 1>&6
+if test $ac_cv_func_vfork_works = no; then
+ cat >> confdefs.h <<\EOF
+#define vfork fork
+EOF
+
+fi
+
+
+echo $ac_n "checking if we should use fcntl or ioctl""... $ac_c" 1>&6
+echo "configure:5851: checking if we should use fcntl or ioctl" >&5
+if eval "test \"`echo '$''{'cf_cv_fionbio'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 5857 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+int main() {
+
+ int ret = ioctl(0, FIONBIO, (char *)0);
+
+; return 0; }
+EOF
+if { (eval echo configure:5869: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_fionbio=ioctl
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 5878 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif
+int main() {
+
+ int ret = fcntl(0, F_SETFL, O_NONBLOCK);
+
+; return 0; }
+EOF
+if { (eval echo configure:5895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_fionbio=fcntl
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_fionbio=unknown
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_fionbio" 1>&6
+test "$cf_cv_fionbio" = "fcntl" && cat >> confdefs.h <<\EOF
+#define USE_FCNTL 1
+EOF
+
+
+
+echo $ac_n "checking for broken/missing definition of remove""... $ac_c" 1>&6
+echo "configure:5918: checking for broken/missing definition of remove" >&5
+if eval "test \"`echo '$''{'cf_cv_baddef_remove'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 5924 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main() {
+remove("dummy")
+; return 0; }
+EOF
+if { (eval echo configure:5931: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_baddef_remove=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 5939 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+ int __unlink(name) { return unlink(name); }
+int main() {
+remove("dummy")
+; return 0; }
+EOF
+if { (eval echo configure:5947: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_baddef_remove=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_baddef_remove=unknown
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_baddef_remove" 1>&6
+test "$cf_cv_baddef_remove" != no && cat >> confdefs.h <<\EOF
+#define NEED_REMOVE 1
+EOF
+
+
+
+echo $ac_n "checking for lstat""... $ac_c" 1>&6
+echo "configure:5971: checking for lstat" >&5
+if eval "test \"`echo '$''{'ac_cv_func_lstat'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 5977 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+lstat(".", (struct stat *)0)
+; return 0; }
+EOF
+if { (eval echo configure:5986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ ac_cv_func_lstat=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_func_lstat=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_func_lstat " 1>&6
+if test $ac_cv_func_lstat = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LSTAT 1
+EOF
+
+fi
+
+for ac_func in \
+ cuserid \
+ getcwd \
+ getgroups \
+ putenv \
+ readdir \
+ strerror \
+ waitpid \
+
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6018: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6023 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6046: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in \
+ mktime \
+ strstr \
+
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:6076: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6081 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6104: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.o"
+fi
+done
+
+
+
+for ac_func in strstr
+do
+
+echo $ac_n "checking for $ac_func declaration""... $ac_c" 1>&6
+echo "configure:6135: checking for $ac_func declaration" >&5
+if eval "test \"`echo '$''{'ac_cv_func_decl_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6140 "configure"
+#include "confdefs.h"
+#include <string.h>
+int main() {
+#ifndef ${ac_func}
+extern int ${ac_func}();
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:6149: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 6153 "configure"
+#include "confdefs.h"
+#include <string.h>
+int main() {
+#ifndef ${ac_func}
+int (*p)() = ${ac_func};
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:6162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=no"
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=yes"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'decl_$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+
+ac_tr_func=`echo DECL_$ac_func | tr '[a-z]' '[A-Z]'`
+
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+fi
+done
+
+for ac_func in getgrgid getgrnam
+do
+
+echo $ac_n "checking for $ac_func declaration""... $ac_c" 1>&6
+echo "configure:6204: checking for $ac_func declaration" >&5
+if eval "test \"`echo '$''{'ac_cv_func_decl_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6209 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <grp.h>
+int main() {
+#ifndef ${ac_func}
+extern int ${ac_func}();
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:6220: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 6224 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#include <grp.h>
+int main() {
+#ifndef ${ac_func}
+int (*p)() = ${ac_func};
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:6235: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=no"
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+
+eval "ac_cv_func_decl_$ac_func=yes"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'decl_$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+
+ac_tr_func=`echo DECL_$ac_func | tr '[a-z]' '[A-Z]'`
+
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+fi
+done
+
+
+
+
+echo $ac_n "checking if TRUE/FALSE are defined""... $ac_c" 1>&6
+echo "configure:6277: checking if TRUE/FALSE are defined" >&5
+if eval "test \"`echo '$''{'cf_cv_bool_defs'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 6283 "configure"
+#include "confdefs.h"
+
+#include <$cf_cv_ncurses_header>
+#include <stdio.h>
+int main() {
+int x = TRUE, y = FALSE
+; return 0; }
+EOF
+if { (eval echo configure:6292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_bool_defs=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_bool_defs=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_bool_defs" 1>&6
+if test "$cf_cv_bool_defs" = no ; then
+ cat >> confdefs.h <<\EOF
+#define TRUE (1)
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define FALSE (0)
+EOF
+
+fi
+
+
+
+echo $ac_n "checking declaration of errno""... $ac_c" 1>&6
+echo "configure:6319: checking declaration of errno" >&5
+if eval "test \"`echo '$''{'cf_cv_dcl_errno'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6325 "configure"
+#include "confdefs.h"
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+int main() {
+long x = (long) errno
+; return 0; }
+EOF
+if { (eval echo configure:6338: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval 'cf_cv_dcl_'errno'=yes'
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval 'cf_cv_dcl_'errno'=no'
+fi
+rm -f conftest*
+fi
+
+eval 'cf_result=$cf_cv_dcl_'errno
+echo "$ac_t""$cf_result" 1>&6
+
+# It's possible (for near-UNIX clones) that the data doesn't exist
+if eval "test \"`echo '$''{'cf_cv_have_errno'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+if test $cf_result = no ; then
+ eval 'cf_result=DECL_'errno
+
+cf_result=`echo $cf_result | tr '[a-z]' '[A-Z]'`
+
+ cat >> confdefs.h <<EOF
+#define $cf_result 1
+EOF
+
+ echo $ac_n "checking existence of errno""... $ac_c" 1>&6
+echo "configure:6368: checking existence of errno" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 6370 "configure"
+#include "confdefs.h"
+
+#undef errno
+extern long errno;
+
+int main() {
+errno = 2
+; return 0; }
+EOF
+if { (eval echo configure:6380: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval 'cf_cv_have_'errno'=yes'
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval 'cf_cv_have_'errno'=no'
+fi
+rm -f conftest*
+ eval 'cf_result=$cf_cv_have_'errno
+ echo "$ac_t""$cf_result" 1>&6
+else
+ eval 'cf_cv_have_'errno'=yes'
+fi
+
+fi
+
+eval 'cf_result=HAVE_'errno
+
+cf_result=`echo $cf_result | tr '[a-z]' '[A-Z]'`
+
+eval 'test $cf_cv_have_'errno' = yes && cat >> confdefs.h <<EOF
+#define $cf_result 1
+EOF
+'
+
+
+
+echo $ac_n "checking for setlocale()""... $ac_c" 1>&6
+echo "configure:6410: checking for setlocale()" >&5
+if eval "test \"`echo '$''{'cf_cv_locale'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 6416 "configure"
+#include "confdefs.h"
+#include <locale.h>
+int main() {
+setlocale(LC_ALL, "")
+; return 0; }
+EOF
+if { (eval echo configure:6423: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_locale=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_locale=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_locale" 1>&6
+test $cf_cv_locale = yes && cat >> confdefs.h <<\EOF
+#define LOCALE 1
+EOF
+
+
+
+echo $ac_n "checking if NGROUPS is defined""... $ac_c" 1>&6
+echo "configure:6444: checking if NGROUPS is defined" >&5
+if eval "test \"`echo '$''{'cf_cv_ngroups'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 6450 "configure"
+#include "confdefs.h"
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+int main() {
+int x = NGROUPS
+; return 0; }
+EOF
+if { (eval echo configure:6464: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_ngroups=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 6472 "configure"
+#include "confdefs.h"
+
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+int main() {
+int x = NGROUPS_MAX
+; return 0; }
+EOF
+if { (eval echo configure:6486: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_ngroups=NGROUPS_MAX
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_ngroups=no
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+echo "$ac_t""$cf_cv_ngroups" 1>&6
+if test "$cf_cv_ngroups" = no ; then
+ cat >> confdefs.h <<\EOF
+#define NGROUPS 16
+EOF
+
+elif test "$cf_cv_ngroups" = NGROUPS_MAX ; then
+ cat >> confdefs.h <<\EOF
+#define NGROUPS NGROUPS_MAX
+EOF
+
+fi
+
+fi
+
+
+
+for cf_name in sys_nerr sys_errlist
+do
+
+echo $ac_n "checking declaration of $cf_name""... $ac_c" 1>&6
+echo "configure:6520: checking declaration of $cf_name" >&5
+if eval "test \"`echo '$''{'cf_cv_dcl_$cf_name'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6526 "configure"
+#include "confdefs.h"
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+int main() {
+long x = (long) $cf_name
+; return 0; }
+EOF
+if { (eval echo configure:6539: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval 'cf_cv_dcl_'$cf_name'=yes'
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval 'cf_cv_dcl_'$cf_name'=no'
+fi
+rm -f conftest*
+fi
+
+eval 'cf_result=$cf_cv_dcl_'$cf_name
+echo "$ac_t""$cf_result" 1>&6
+
+# It's possible (for near-UNIX clones) that the data doesn't exist
+if eval "test \"`echo '$''{'cf_cv_have_$cf_name'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+if test $cf_result = no ; then
+ eval 'cf_result=DECL_'$cf_name
+
+cf_result=`echo $cf_result | tr '[a-z]' '[A-Z]'`
+
+ cat >> confdefs.h <<EOF
+#define $cf_result 1
+EOF
+
+ echo $ac_n "checking existence of $cf_name""... $ac_c" 1>&6
+echo "configure:6569: checking existence of $cf_name" >&5
+ cat > conftest.$ac_ext <<EOF
+#line 6571 "configure"
+#include "confdefs.h"
+
+#undef $cf_name
+extern long $cf_name;
+
+int main() {
+$cf_name = 2
+; return 0; }
+EOF
+if { (eval echo configure:6581: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval 'cf_cv_have_'$cf_name'=yes'
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval 'cf_cv_have_'$cf_name'=no'
+fi
+rm -f conftest*
+ eval 'cf_result=$cf_cv_have_'$cf_name
+ echo "$ac_t""$cf_result" 1>&6
+else
+ eval 'cf_cv_have_'$cf_name'=yes'
+fi
+
+fi
+
+eval 'cf_result=HAVE_'$cf_name
+
+cf_result=`echo $cf_result | tr '[a-z]' '[A-Z]'`
+
+eval 'test $cf_cv_have_'$cf_name' = yes && cat >> confdefs.h <<EOF
+#define $cf_result 1
+EOF
+'
+
+done
+
+
+echo $ac_n "checking if struct utmp is declared""... $ac_c" 1>&6
+echo "configure:6612: checking if struct utmp is declared" >&5
+if eval "test \"`echo '$''{'cf_cv_have_utmp'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6618 "configure"
+#include "confdefs.h"
+
+#include <sys/types.h>
+#include <utmp.h>
+int main() {
+struct utmp x; char *y = &x.ut_host[0]
+; return 0; }
+EOF
+if { (eval echo configure:6627: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_have_utmp=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat > conftest.$ac_ext <<EOF
+#line 6635 "configure"
+#include "confdefs.h"
+#include <utmpx.h>
+int main() {
+struct utmpx x; char *y = &x.ut_host[0]
+; return 0; }
+EOF
+if { (eval echo configure:6642: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_have_utmp=utmpx
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_have_utmp=no
+fi
+rm -f conftest*
+
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_have_utmp" 1>&6
+test $cf_cv_have_utmp != no && cat >> confdefs.h <<\EOF
+#define HAVE_UTMP 1
+EOF
+
+test $cf_cv_have_utmp = utmpx && cat >> confdefs.h <<\EOF
+#define UTMPX_FOR_UTMP 1
+EOF
+
+
+
+### These tests must be run after establishing the curses library.
+if test $cf_cv_screen != slang ; then
+
+echo $ac_n "checking if curses supports alternate-character set""... $ac_c" 1>&6
+echo "configure:6673: checking if curses supports alternate-character set" >&5
+if eval "test \"`echo '$''{'cf_cv_alt_char_set'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6679 "configure"
+#include "confdefs.h"
+
+#include <$cf_cv_ncurses_header>
+
+int main() {
+chtype x = acs_map['l']; acs_map['m'] = 0
+; return 0; }
+EOF
+if { (eval echo configure:6688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_alt_char_set=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_alt_char_set=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$cf_cv_alt_char_set" 1>&6
+test $cf_cv_alt_char_set = yes && cat >> confdefs.h <<\EOF
+#define ALT_CHAR_SET 1
+EOF
+
+
+
+echo $ac_n "checking if curses supports fancy attributes""... $ac_c" 1>&6
+echo "configure:6708: checking if curses supports fancy attributes" >&5
+if eval "test \"`echo '$''{'cf_cv_fancy_curses'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6714 "configure"
+#include "confdefs.h"
+
+#include <$cf_cv_ncurses_header>
+
+int main() {
+attrset(A_UNDERLINE|A_BOLD|A_REVERSE);
+ wattrset(stdscr, A_BLINK|A_DIM);
+ attroff(A_BOLD);
+ keypad(stdscr,TRUE);
+
+; return 0; }
+EOF
+if { (eval echo configure:6727: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_fancy_curses=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_fancy_curses=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_fancy_curses" 1>&6
+test $cf_cv_fancy_curses = yes && cat >> confdefs.h <<\EOF
+#define FANCY_CURSES 1
+EOF
+
+
+ echo $ac_n "checking for ncurses version""... $ac_c" 1>&6
+echo "configure:6747: checking for ncurses version" >&5
+if eval "test \"`echo '$''{'cf_cv_ncurses_version'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cf_cv_ncurses_version=no
+ cf_tempfile=out$$
+ if test "$cross_compiling" = yes; then
+
+
+ # This will not work if the preprocessor splits the line after the
+ # Autoconf token. The 'unproto' program does that.
+ cat > conftest.$ac_ext <<EOF
+#include <${cf_cv_ncurses_header-curses.h}>
+#undef Autoconf
+#ifdef NCURSES_VERSION
+Autoconf NCURSES_VERSION
+#else
+#ifdef __NCURSES_H
+Autoconf "old"
+#endif
+;
+#endif
+EOF
+ cf_try="$ac_cpp conftest.$ac_ext 2>&5 | grep '^Autoconf ' >conftest.out"
+ { (eval echo configure:6772: \"$cf_try\") 1>&5; (eval $cf_try) 2>&5; }
+ if test -f conftest.out ; then
+ cf_out=`cat conftest.out | sed -e 's@^Autoconf @@' -e 's@^[^"]*"@@' -e 's@".*@@'`
+ test -n "$cf_out" && cf_cv_ncurses_version="$cf_out"
+ rm -f conftest.out
+ fi
+
+else
+ cat > conftest.$ac_ext <<EOF
+#line 6781 "configure"
+#include "confdefs.h"
+
+#include <${cf_cv_ncurses_header-curses.h}>
+int main()
+{
+ FILE *fp = fopen("$cf_tempfile", "w");
+#ifdef NCURSES_VERSION
+# ifdef NCURSES_VERSION_PATCH
+ fprintf(fp, "%s.%d\n", NCURSES_VERSION, NCURSES_VERSION_PATCH);
+# else
+ fprintf(fp, "%s\n", NCURSES_VERSION);
+# endif
+#else
+# ifdef __NCURSES_H
+ fprintf(fp, "old\n");
+# else
+ make an error
+# endif
+#endif
+ exit(0);
+}
+EOF
+if { (eval echo configure:6804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+
+ cf_cv_ncurses_version=`cat $cf_tempfile`
+ rm -f $cf_tempfile
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$cf_cv_ncurses_version" 1>&6
+
+
+
+if test "$cf_cv_ncurses_version" != no ; then
+echo $ac_n "checking for obsolete/broken version of ncurses""... $ac_c" 1>&6
+echo "configure:6824: checking for obsolete/broken version of ncurses" >&5
+if eval "test \"`echo '$''{'cf_cv_ncurses_broken'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+cat > conftest.$ac_ext <<EOF
+#line 6830 "configure"
+#include "confdefs.h"
+
+#include <$cf_cv_ncurses_header>
+int main() {
+
+#if defined(NCURSES_VERSION) && defined(wgetbkgd)
+ make an error
+#else
+ int x = 1
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_ncurses_broken=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_ncurses_broken=yes
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_ncurses_broken" 1>&6
+if test "$cf_cv_ncurses_broken" = yes ; then
+ echo "configure: warning: hmm... you should get an up-to-date version of ncurses" 1>&2
+ cat >> confdefs.h <<\EOF
+#define NCURSES_BROKEN 1
+EOF
+
+fi
+fi
+
+
+echo $ac_n "checking if curses supports color attributes""... $ac_c" 1>&6
+echo "configure:6869: checking if curses supports color attributes" >&5
+if eval "test \"`echo '$''{'cf_cv_color_curses'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 6875 "configure"
+#include "confdefs.h"
+
+#include <${cf_cv_ncurses_header-curses.h}>
+
+int main() {
+chtype x = COLOR_BLUE;
+ has_colors();
+ start_color();
+#ifndef NCURSES_BROKEN
+ wbkgd(curscr, getbkgd(stdscr)); /* X/Open XPG4 aka SVr4 Curses */
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:6890: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_color_curses=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_color_curses=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_color_curses" 1>&6
+if test $cf_cv_color_curses = yes ; then
+ cat >> confdefs.h <<\EOF
+#define COLOR_CURSES 1
+EOF
+
+ test ".$cf_cv_ncurses_broken" != .yes && cat >> confdefs.h <<\EOF
+#define HAVE_GETBKGD 1
+EOF
+
+fi
+
+
+echo $ac_n "checking declaration of size-change""... $ac_c" 1>&6
+echo "configure:6917: checking declaration of size-change" >&5
+if eval "test \"`echo '$''{'cf_cv_sizechange'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cf_cv_sizechange=unknown
+ cf_save_CFLAGS="$CFLAGS"
+
+for cf_opts in "" "NEED_PTEM_H"
+do
+
+ CFLAGS="$cf_save_CFLAGS"
+ test -n "$cf_opts" && CFLAGS="$CFLAGS -D$cf_opts"
+ cat > conftest.$ac_ext <<EOF
+#line 6931 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#else
+#if HAVE_TERMIO_H
+#include <termio.h>
+#endif
+#endif
+#if NEED_PTEM_H
+/* This is a workaround for SCO: they neglected to define struct winsize in
+ * termios.h -- it's only in termio.h and ptem.h
+ */
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+#if !defined(sun) || !defined(HAVE_TERMIOS_H)
+#include <sys/ioctl.h>
+#endif
+
+int main() {
+
+#ifdef TIOCGSIZE
+ struct ttysize win; /* FIXME: what system is this? */
+ int y = win.ts_lines;
+ int x = win.ts_cols;
+#else
+#ifdef TIOCGWINSZ
+ struct winsize win;
+ int y = win.ws_row;
+ int x = win.ws_col;
+#else
+ no TIOCGSIZE or TIOCGWINSZ
+#endif /* TIOCGWINSZ */
+#endif /* TIOCGSIZE */
+
+; return 0; }
+EOF
+if { (eval echo configure:6970: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ cf_cv_sizechange=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_sizechange=no
+fi
+rm -f conftest*
+
+ CFLAGS="$cf_save_CFLAGS"
+ if test "$cf_cv_sizechange" = yes ; then
+ echo "size-change succeeded ($cf_opts)" >&5
+ test -n "$cf_opts" && cat >> confdefs.h <<EOF
+#define $cf_opts 1
+EOF
+
+ break
+ fi
+done
+
+fi
+
+echo "$ac_t""$cf_cv_sizechange" 1>&6
+test $cf_cv_sizechange != no && cat >> confdefs.h <<\EOF
+#define HAVE_SIZECHANGE 1
+EOF
+
+
+
+echo $ac_n "checking if ttytype is declared in curses library""... $ac_c" 1>&6
+echo "configure:7002: checking if ttytype is declared in curses library" >&5
+if eval "test \"`echo '$''{'cf_cv_have_ttytype'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ cat > conftest.$ac_ext <<EOF
+#line 7008 "configure"
+#include "confdefs.h"
+#include <$cf_cv_ncurses_header>
+int main() {
+char *x = &ttytype[1]; *x = 1
+; return 0; }
+EOF
+if { (eval echo configure:7015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ cf_cv_have_ttytype=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cf_cv_have_ttytype=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$cf_cv_have_ttytype" 1>&6
+test $cf_cv_have_ttytype = yes && cat >> confdefs.h <<\EOF
+#define HAVE_TTYTYPE 1
+EOF
+
+
+ for ac_func in \
+ cbreak \
+ keypad \
+ use_default_colors \
+ wborder \
+
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:7042: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7047 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:7070: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+
+
+
+echo $ac_n "checking if experimental 8-bit case-conversion should be used""... $ac_c" 1>&6
+echo "configure:7100: checking if experimental 8-bit case-conversion should be used" >&5
+
+# Check whether --enable-8bit-toupper or --disable-8bit-toupper was given.
+if test "${enable_8bit_toupper+set}" = set; then
+ enableval="$enable_8bit_toupper"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_8bit_toupper=$enableval
+ else
+ use_8bit_toupper=no
+ fi
+else
+ enableval=no
+ use_8bit_toupper=no
+
+fi
+
+test $use_8bit_toupper != no && cat >> confdefs.h <<\EOF
+#define EXP_8BIT_TOUPPER 1
+EOF
+
+
+echo $ac_n "checking if color-style code should be used""... $ac_c" 1>&6
+echo "configure:7123: checking if color-style code should be used" >&5
+
+# Check whether --enable-color-style or --disable-color-style was given.
+if test "${enable_color_style+set}" = set; then
+ enableval="$enable_color_style"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_color_style=$enableval
+ else
+ use_color_style=no
+ fi
+else
+ enableval=no
+ use_color_style=no
+
+fi
+
+
+if test $use_color_style != no ; then
+ if test .$cf_cv_color_curses != .yes ; then
+ { echo "configure: error: Configuration does not support color-styles" 1>&2; exit 1; }
+ fi
+ if test $cf_cv_screen = slang ; then
+ { echo "configure: error: Configuration does not support color-styles" 1>&2; exit 1; }
+ fi
+ cat >> confdefs.h <<\EOF
+#define USE_HASH 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define LINKEDSTYLES 1
+EOF
+
+fi
+
+case $use_color_style in
+no)
+ echo "$ac_t""no" 1>&6
+ INSTALL_LSS=
+ ;;
+*)
+ cat >> confdefs.h <<\EOF
+#define USE_COLOR_STYLE 1
+EOF
+
+ echo "$ac_t""curses-style" 1>&6
+
+ echo $ac_n "checking for location of style-sheet file""... $ac_c" 1>&6
+echo "configure:7171: checking for location of style-sheet file" >&5
+ LYNX_LSS_FILE=$cf_libdir/lynx.lss
+ cat >> confdefs.h <<EOF
+#define LYNX_LSS_FILE "$LYNX_LSS_FILE"
+EOF
+
+ echo "$ac_t""$LYNX_LSS_FILE" 1>&6
+ INSTALL_LSS=install-lss
+ ;;
+esac
+
+
+use_dft_colors=no
+test ".$cf_cv_screen" = ".slang" && use_dft_colors=maybe
+test ".$ac_cv_func_use_default_colors" = ".yes" && use_dft_colors=maybe
+
+if test "$use_dft_colors" != no ; then
+echo $ac_n "checking if you want to use default-colors""... $ac_c" 1>&6
+echo "configure:7189: checking if you want to use default-colors" >&5
+
+# Check whether --enable-default-colors or --disable-default-colors was given.
+if test "${enable_default_colors+set}" = set; then
+ enableval="$enable_default_colors"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_dft_colors=yes
+ else
+ use_dft_colors=no
+ fi
+else
+ enableval=no
+ use_dft_colors=no
+
+fi
+
+echo "$ac_t""$use_dft_colors" 1>&6
+test $use_dft_colors = "yes" && cat >> confdefs.h <<\EOF
+#define USE_DEFAULT_COLORS 1
+EOF
+
+fi
+
+echo $ac_n "checking if you want to use extended HTML DTD logic""... $ac_c" 1>&6
+echo "configure:7214: checking if you want to use extended HTML DTD logic" >&5
+
+# Check whether --enable-extended-dtd or --disable-extended-dtd was given.
+if test "${enable_extended_dtd+set}" = set; then
+ enableval="$enable_extended_dtd"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ use_ext_htmldtd=no
+ else
+ use_ext_htmldtd=yes
+ fi
+else
+ enableval=yes
+ use_ext_htmldtd=yes
+
+fi
+
+echo "$ac_t""$use_ext_htmldtd" 1>&6
+test $use_ext_htmldtd = "no" && cat >> confdefs.h <<\EOF
+#define NO_EXTENDED_HTMLDTD 1
+EOF
+
+
+echo $ac_n "checking if you want to use external commands""... $ac_c" 1>&6
+echo "configure:7238: checking if you want to use external commands" >&5
+
+# Check whether --enable-externs or --disable-externs was given.
+if test "${enable_externs+set}" = set; then
+ enableval="$enable_externs"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_externs=yes
+ else
+ use_externs=no
+ fi
+else
+ enableval=no
+ use_externs=no
+
+fi
+
+echo "$ac_t""$use_externs" 1>&6
+test $use_externs != ".no" && cat >> confdefs.h <<\EOF
+#define USE_EXTERNALS 1
+EOF
+
+
+echo $ac_n "checking if you want to use setfont support""... $ac_c" 1>&6
+echo "configure:7262: checking if you want to use setfont support" >&5
+
+# Check whether --enable-font-switch or --disable-font-switch was given.
+if test "${enable_font_switch+set}" = set; then
+ enableval="$enable_font_switch"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_setfont=yes
+ else
+ use_setfont=no
+ fi
+else
+ enableval=no
+ use_setfont=no
+
+fi
+
+echo "$ac_t""$use_setfont" 1>&6
+test $use_setfont = yes && cat >> confdefs.h <<\EOF
+#define EXP_CHARTRANS_AUTOSWITCH 1
+EOF
+
+
+echo $ac_n "checking if you want internal-links feature""... $ac_c" 1>&6
+echo "configure:7286: checking if you want internal-links feature" >&5
+
+# Check whether --enable-internal-links or --disable-internal-links was given.
+if test "${enable_internal_links+set}" = set; then
+ enableval="$enable_internal_links"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_internal_links=yes
+ else
+ use_internal_links=no
+ fi
+else
+ enableval=no
+ use_internal_links=no
+
+fi
+
+echo "$ac_t""$use_internal_links" 1>&6
+test $use_internal_links = no && cat >> confdefs.h <<\EOF
+#define DONT_TRACK_INTERNAL_LINKS 1
+EOF
+
+
+echo $ac_n "checking if you want to fork NSL requests""... $ac_c" 1>&6
+echo "configure:7310: checking if you want to fork NSL requests" >&5
+
+# Check whether --enable-nsl-fork or --disable-nsl-fork was given.
+if test "${enable_nsl_fork+set}" = set; then
+ enableval="$enable_nsl_fork"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_nsl_fork=yes
+ else
+ use_nsl_fork=no
+ fi
+else
+ enableval=no
+ use_nsl_fork=no
+
+fi
+
+echo "$ac_t""$use_nsl_fork" 1>&6
+test $use_nsl_fork = yes && cat >> confdefs.h <<\EOF
+#define NSL_FORK 1
+EOF
+
+
+echo $ac_n "checking if you want to underline links""... $ac_c" 1>&6
+echo "configure:7334: checking if you want to underline links" >&5
+
+# Check whether --enable-underlines or --disable-underlines was given.
+if test "${enable_underlines+set}" = set; then
+ enableval="$enable_underlines"
+ test "$enableval" != yes && enableval=no
+ if test "$enableval" != "no" ; then
+ use_underline=yes
+ else
+ use_underline=no
+ fi
+else
+ enableval=no
+ use_underline=no
+
+fi
+
+echo "$ac_t""$use_underline" 1>&6
+test $use_underline = yes && cat >> confdefs.h <<\EOF
+#define UNDERLINE_LINKS 1
+EOF
+
+
+echo $ac_n "checking if you want to use zlib for decompression of some gzip files""... $ac_c" 1>&6
+echo "configure:7358: checking if you want to use zlib for decompression of some gzip files" >&5
+
+# Check whether --with-zlib or --without-zlib was given.
+if test "${with_zlib+set}" = set; then
+ withval="$with_zlib"
+ use_zlib=$withval
+else
+ use_zlib=no
+fi
+
+echo "$ac_t""$use_zlib" 1>&6
+
+if test ".$use_zlib" != ".no" ; then
+
+ cf_cv_have_lib_z=no
+ cf_libdir=""
+ echo $ac_n "checking for gzopen""... $ac_c" 1>&6
+echo "configure:7375: checking for gzopen" >&5
+if eval "test \"`echo '$''{'ac_cv_func_gzopen'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 7380 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char gzopen(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char gzopen();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_gzopen) || defined (__stub___gzopen)
+choke me
+#else
+gzopen();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:7403: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_gzopen=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_gzopen=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'gzopen`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_z=yes
+else
+ echo "$ac_t""no" 1>&6
+
+ cf_save_LIBS="$LIBS"
+ echo $ac_n "checking for gzopen in -lz""... $ac_c" 1>&6
+echo "configure:7423: checking for gzopen in -lz" >&5
+ LIBS="-lz $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 7426 "configure"
+#include "confdefs.h"
+#include <zlib.h>
+int main() {
+gzopen("name","mode")
+; return 0; }
+EOF
+if { (eval echo configure:7433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_z=yes
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ cf_search=""
+if test -d "$libdir" ; then
+test "$libdir" != NONE && cf_search="$cf_search $libdir $libdir/z"
+fi
+if test -d "$exec_prefix"; then
+test "$exec_prefix" != NONE && cf_search="$cf_search $exec_prefix/lib $exec_prefix/lib/z"
+fi
+if test -d "$prefix"; then
+test "$prefix" != NONE && \
+test "$prefix" != "$exec_prefix" && cf_search="$cf_search $prefix/lib $prefix/lib/z"
+fi
+test "$prefix" != /usr/local && cf_search="$cf_search /usr/local/lib /usr/local/lib/z"
+test "$prefix" != /usr && cf_search="$cf_search /usr/lib /usr/lib/z"
+
+ for cf_libdir in $cf_search
+ do
+ echo $ac_n "checking for -lz in $cf_libdir""... $ac_c" 1>&6
+echo "configure:7460: checking for -lz in $cf_libdir" >&5
+ LIBS="-L$cf_libdir -lz $cf_save_LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 7463 "configure"
+#include "confdefs.h"
+#include <zlib.h>
+int main() {
+gzopen("name","mode")
+; return 0; }
+EOF
+if { (eval echo configure:7470: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+ cf_cv_have_lib_z=yes
+ break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+ LIBS="$cf_save_LIBS"
+fi
+rm -f conftest*
+ done
+
+fi
+rm -f conftest*
+
+fi
+
+if test $cf_cv_have_lib_z = no ; then
+ { echo "configure: error: Cannot link z library" 1>&2; exit 1; }
+fi
+case $host_os in #(vi
+linux*) # Suse Linux does not follow /usr/lib convention
+ z="$z /lib"
+ ;;
+esac
+
+ cat >> confdefs.h <<\EOF
+#define USE_ZLIB 1
+EOF
+
+fi
+
+
+
+
+# All DirEd functions that were enabled on compilation can be disabled
+# or modified at run time via DIRED_MENU symbols in lynx.cfg.
+echo $ac_n "checking if directory-editor code should be used""... $ac_c" 1>&6
+echo "configure:7511: checking if directory-editor code should be used" >&5
+
+# Check whether --enable-dired or --disable-dired was given.
+if test "${enable_dired+set}" = set; then
+ enableval="$enable_dired"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ use_dired=$enableval
+ else
+ use_dired=yes
+ fi
+else
+ enableval=yes
+ use_dired=yes
+
+fi
+
+echo "$ac_t""$use_dired" 1>&6
+
+if test ".$use_dired" != ".no" ; then
+ cat >> confdefs.h <<\EOF
+#define DIRED_SUPPORT 1
+EOF
+
+
+ echo $ac_n "checking if you wish to allow extracting from archives via DirEd""... $ac_c" 1>&6
+echo "configure:7537: checking if you wish to allow extracting from archives via DirEd" >&5
+
+# Check whether --enable-dired-archive or --disable-dired-archive was given.
+if test "${enable_dired_archive+set}" = set; then
+ enableval="$enable_dired_archive"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ cat >> confdefs.h <<\EOF
+#define ARCHIVE_ONLY 1
+EOF
+
+ fi
+else
+ enableval=yes
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow users to redefine DirEd keys""... $ac_c" 1>&6
+echo "configure:7556: checking if you wish to allow users to redefine DirEd keys" >&5
+
+# Check whether --enable-dired-override or --disable-dired-override was given.
+if test "${enable_dired_override+set}" = set; then
+ enableval="$enable_dired_override"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_OVERRIDE 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_OVERRIDE 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow permissions commands via DirEd""... $ac_c" 1>&6
+echo "configure:7582: checking if you wish to allow permissions commands via DirEd" >&5
+
+# Check whether --enable-dired-permit or --disable-dired-permit was given.
+if test "${enable_dired_permit+set}" = set; then
+ enableval="$enable_dired_permit"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_PERMIT 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_PERMIT 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow executable-permission commands via DirEd""... $ac_c" 1>&6
+echo "configure:7608: checking if you wish to allow executable-permission commands via DirEd" >&5
+
+# Check whether --enable-dired-xpermit or --disable-dired-xpermit was given.
+if test "${enable_dired_xpermit+set}" = set; then
+ enableval="$enable_dired_xpermit"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ cat >> confdefs.h <<\EOF
+#define NO_CHANGE_EXECUTE_PERMS 1
+EOF
+
+ fi
+else
+ enableval=yes
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow "tar" commands from DirEd""... $ac_c" 1>&6
+echo "configure:7627: checking if you wish to allow "tar" commands from DirEd" >&5
+
+# Check whether --enable-dired-tar or --disable-dired-tar was given.
+if test "${enable_dired_tar+set}" = set; then
+ enableval="$enable_dired_tar"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_TAR 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_TAR 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow "uudecode" commands from DirEd""... $ac_c" 1>&6
+echo "configure:7653: checking if you wish to allow "uudecode" commands from DirEd" >&5
+
+# Check whether --enable-dired-uudecode or --disable-dired-uudecode was given.
+if test "${enable_dired_uudecode+set}" = set; then
+ enableval="$enable_dired_uudecode"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_UUDECODE 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_UUDECODE 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow "zip" and "unzip" commands from DirEd""... $ac_c" 1>&6
+echo "configure:7679: checking if you wish to allow "zip" and "unzip" commands from DirEd" >&5
+
+# Check whether --enable-dired-zip or --disable-dired-zip was given.
+if test "${enable_dired_zip+set}" = set; then
+ enableval="$enable_dired_zip"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_ZIP 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_ZIP 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+
+ echo $ac_n "checking if you wish to allow "gzip" and "gunzip" commands from DirEd""... $ac_c" 1>&6
+echo "configure:7705: checking if you wish to allow "gzip" and "gunzip" commands from DirEd" >&5
+
+# Check whether --enable-dired-gzip or --disable-dired-gzip was given.
+if test "${enable_dired_gzip+set}" = set; then
+ enableval="$enable_dired_gzip"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define OK_GZIP 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define OK_GZIP 1
+EOF
+
+
+fi
+
+ echo "$ac_t""$enableval" 1>&6
+fi
+
+echo $ac_n "checking if you want long-directory listings""... $ac_c" 1>&6
+echo "configure:7732: checking if you want long-directory listings" >&5
+
+# Check whether --enable-long-list or --disable-long-list was given.
+if test "${enable_long_list+set}" = set; then
+ enableval="$enable_long_list"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ :
+ else
+ cat >> confdefs.h <<\EOF
+#define LONG_LIST 1
+EOF
+
+ fi
+else
+ enableval=yes
+ cat >> confdefs.h <<\EOF
+#define LONG_LIST 1
+EOF
+
+
+fi
+
+echo "$ac_t""$enableval" 1>&6
+
+echo $ac_n "checking if parent-directory references are permitted""... $ac_c" 1>&6
+echo "configure:7758: checking if parent-directory references are permitted" >&5
+
+# Check whether --enable-parent-dir-refs or --disable-parent-dir-refs was given.
+if test "${enable_parent_dir_refs+set}" = set; then
+ enableval="$enable_parent_dir_refs"
+ test "$enableval" != no && enableval=yes
+ if test "$enableval" != "yes" ; then
+ cat >> confdefs.h <<\EOF
+#define NO_PARENT_DIR_REFERENCE 1
+EOF
+
+ fi
+else
+ enableval=yes
+fi
+
+echo "$ac_t""$enableval" 1>&6
+
+### Finally, build config.h and the makefiles
+CFLAGS="$CFLAGS $EXTRA_CFLAGS"
+srcdir="$srcdir"
+SRCDIR_CLEAN="#"
+if test -n "$srcdir" ; then
+ echo srcdir is $srcdir
+ $srcdir/mkdirs.sh WWW/Library/unix
+ $srcdir/mkdirs.sh src/chrtrans
+ test "$srcdir" != "." && SRCDIR_CLEAN=""
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set) 2>&1 | grep '^ac_space='` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.12.971230"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "makefile \
+ WWW/Library/unix/makefile \
+ src/makefile \
+ src/chrtrans/makefile \
+ lynx_cfg.h:config.hin" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@RANLIB@%$RANLIB%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@make_include_left@%$make_include_left%g
+s%@make_include_right@%$make_include_right%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LINT@%$LINT%g
+s%@ECHO_LD@%$ECHO_LD%g
+s%@RULE_CC@%$RULE_CC%g
+s%@SHOW_CC@%$SHOW_CC%g
+s%@ECHO_CC@%$ECHO_CC%g
+s%@EXTRA_CFLAGS@%$EXTRA_CFLAGS%g
+s%@CHMOD@%$CHMOD%g
+s%@COMPRESS@%$COMPRESS%g
+s%@COPY@%$COPY%g
+s%@GZIP@%$GZIP%g
+s%@MKDIR@%$MKDIR%g
+s%@MV@%$MV%g
+s%@RM@%$RM%g
+s%@TAR@%$TAR%g
+s%@TOUCH@%$TOUCH%g
+s%@UNCOMPRESS@%$UNCOMPRESS%g
+s%@UNZIP@%$UNZIP%g
+s%@UUDECODE@%$UUDECODE%g
+s%@ZCAT@%$ZCAT%g
+s%@ZIP@%$ZIP%g
+s%@PROG_EXT@%$PROG_EXT%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@INSTALL_LSS@%$INSTALL_LSS%g
+s%@SRCDIR_CLEAN@%$SRCDIR_CLEAN%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"makefile \
+ WWW/Library/unix/makefile \
+ src/makefile \
+ src/chrtrans/makefile \
+"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="lynx_cfg.h:config.hin"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+# Extra initialization commands, if any
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+# Extra commands, if any
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/gnu/usr.bin/lynx/configure.in b/gnu/usr.bin/lynx/configure.in
new file mode 100644
index 00000000000..9a3e37af541
--- /dev/null
+++ b/gnu/usr.bin/lynx/configure.in
@@ -0,0 +1,599 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl written jan/1997
+dnl by T.E.Dickey <dickey@clark.net>
+dnl and Jim Spath <jspath@mail.bcpl.lib.md.us>
+
+AC_PREREQ(2.12)
+AC_INIT(userdefs.h)
+AC_CONFIG_HEADER(lynx_cfg.h:config.hin)
+
+AC_PREFIX_DEFAULT(/usr/local)
+AC_CANONICAL_HOST
+
+dnl --------------------------------------------------------------------------
+dnl Checks for location of programs
+dnl --------------------------------------------------------------------------
+
+AC_PROG_CC
+AC_PROG_CPP
+AC_PROG_RANLIB
+AC_PROG_MAKE_SET
+CF_MAKE_INCLUDE
+AC_PROG_INSTALL
+AC_CHECK_PROGS(LINT, lint alint lclint tdlint, [])
+
+dnl --------------------------------------------------------------------------
+dnl Debug/development/test
+dnl --------------------------------------------------------------------------
+
+CF_HELP_MESSAGE(
+Development Options:)
+
+CF_DISABLE_ECHO
+
+AC_MSG_CHECKING(if you want to check memory-leaks)
+CF_ARG_ENABLE(find-leaks,
+ [ --enable-find-leaks logic for testing memory leaks],
+ [with_leak_checks=yes],
+ [with_leak_checks=no])
+AC_MSG_RESULT($with_leak_checks)
+test "$with_leak_checks" = "yes" && AC_DEFINE(LY_FIND_LEAKS)
+
+AC_MSG_CHECKING(if you want to enable debug-code)
+CF_ARG_ENABLE(debug,
+ [ --enable-debug logic for traces/debugging],
+ [with_debug=yes],
+ [with_debug=no])
+AC_MSG_RESULT($with_debug)
+if test "$with_debug" = "yes" ; then
+ case $host_os in
+ ultrix*|osf*)
+ CF_STRIP_O_OPT(CFLAGS)
+ if test -z "$GCC" ; then
+ CFLAGS="$CFLAGS -g3"
+ fi
+ ;;
+ esac
+else
+ case $host_os in
+ ultrix*|osf*) #(vi
+ CF_STRIP_G_OPT(CFLAGS)
+ ;;
+ *)
+ CF_STRIP_G_OPT(CFLAGS)
+ ;;
+ esac
+fi
+
+
+
+if test -n "$GCC"
+then
+AC_MSG_CHECKING(if you want to turn on gcc warnings)
+CF_ARG_ENABLE(warnings,
+ [ --enable-warnings GCC compiler warnings],
+ [with_warnings=yes],
+ [with_warnings=no])
+AC_MSG_RESULT($with_warnings)
+if test "$with_warnings" = "yes"
+then
+ CF_GCC_ATTRIBUTES
+ CF_GCC_WARNINGS
+fi
+fi
+
+dnl --------------------------------------------------------------------------
+dnl --------------------------------------------------------------------------
+
+CF_HELP_MESSAGE(
+Basic Configuration Options:)
+
+AC_MSG_CHECKING(if you want full utility pathnames)
+CF_ARG_DISABLE(full-paths,
+ [ --disable-full-paths control whether full utility pathnames are used],
+ [with_full_paths=no],
+ [with_full_paths=yes])
+AC_MSG_RESULT($with_full_paths)
+
+CF_DEFINE_PROG(system mailer, SYSTEM_MAIL,
+ /usr/mmdf/bin/submit \
+ /usr/sbin/sendmail \
+ /usr/lib/sendmail \
+ )
+CF_SYSTEM_MAIL_FLAGS
+
+CF_PATH_PROG(CHMOD, chmod)
+CF_PATH_PROG(COMPRESS, compress)
+CF_PATH_PROG(COPY, cp)
+CF_PATH_PROG(GZIP, gzip)
+CF_PATH_PROG(MKDIR, mkdir)
+CF_PATH_PROG(MV, mv)
+CF_PATH_PROG(RM, rm)
+CF_PATH_PROG(TAR, tar)
+CF_PATH_PROG(TOUCH, touch)
+CF_PATH_PROG(UNCOMPRESS,gunzip)
+CF_PATH_PROG(UNZIP, unzip)
+CF_PATH_PROG(UUDECODE, uudecode)
+CF_PATH_PROG(ZCAT, zcat)
+CF_PATH_PROG(ZIP, zip)
+
+dnl 'INSTALL' is a special case, since the configure script has to find a
+dnl BSD-compatible one so the build/install works properly.
+case "$INSTALL" in
+$srcdir*) # (vi
+ AC_DEFINE_UNQUOTED(INSTALL_PATH,"install")
+ ;;
+*) # (vi
+ AC_DEFINE_UNQUOTED(INSTALL_PATH,"$INSTALL")
+ ;;
+esac
+
+dnl --------------------------------------------------------------------------
+dnl Checks for compiler & standard-library characteristics
+dnl --------------------------------------------------------------------------
+
+dnl If we're able to run this script, this is true!
+AC_DEFINE(UNIX)
+
+if test -z "$GCC" ; then
+ CF_ANSI_CC_CHECK
+fi
+AC_C_CONST
+
+dnl Only add to this case statement things that we cannot design tests for.
+PROG_EXT=
+case $host_os in
+aix4*)
+ CFLAGS="$CFLAGS -DAIX4 -D_BSD=44"
+ LIBS="$LIBS -lbsd"
+ ;;
+aix*)
+ LIBS="$LIBS -lbsd"
+ ;;
+apollo*)
+ CFLAGS="$CFLAGS -D_BUILTINS -W0,-opt,4"
+ ;;
+bsdi*)
+ CFLAGS="$CFLAGS -DBSDI"
+ ;;
+clix*)
+ # Tested on CLIX 3.1 (T.Dickey). The original makefile entry
+ # contributed by Alex Matulich (matuli_a@marlin.navsea.navy.mil) also
+ # references -lmalloc and -lbsd.
+ AC_CHECK_LIB(c_s,strcmp)
+ ;;
+convex*)
+ CFLAGS="$CFLAGS -D__STDC__ -Dunix"
+ ;;
+dgux*)
+ CFLAGS="$CFLAGS -DDGUX"
+ ;;
+hpux*)
+ CFLAGS="$CFLAGS -DSNAKE"
+ ;;
+isc*)
+ # -DPOSIX_JC is necessary, else LYBookmark.c never finds out what a mode_t is.
+ CFLAGS="$CFLAGS -DISC -DPOSIX_JC"
+ LIBS="$LIBS -linet -lnsl_s -lcposix"
+ ;;
+irix*)
+ # The original makefile used the $CFLAGS option -cckr for some form
+ # of K&R compatibility. However, this causes compilation warnings for
+ # varargs on IRIX 5.2, and does not appear to be needed.
+ #removed: CFLAGS="$CFLAGS -cckr"
+ ;;
+linux*)
+ CFLAGS="$CFLAGS -DLINUX"
+ ;;
+next*)
+ CFLAGS="$CFLAGS -DNEXT -DXMOSAIC_HACK"
+ ;;
+openbsd*)
+ LIBS="$LIBS -lcompat"
+ ;;
+os2*)
+ # We make sure -Zexe is not used -- it would interfere with @PROG_EXT@
+ CFLAGS="$CFLAGS -Zmt -D__ST_MT_ERRNO__"
+ LDFLAGS=`echo "$LDFLAGS -Zmt -Zcrtdll" | sed "s/-Zexe//g"`
+ PROG_EXT=".exe"
+ ;;
+osf*)
+ # Increase the maximum size of functions that will be optimized.
+ test -z "$GCC" && CFLAGS="$CFLAGS -O -Olimit 4000"
+ CFLAGS="$CFLAGS -DDSYS5"
+ ;;
+sco3.2v5*)
+ test $ac_cv_prog_gcc != yes && CC="cc -belf"
+ ;;
+sco*)
+ LIBS="$LIBS -lmalloc"
+ # It's a little late to do much, but try to warn user if he's using
+ # SCO's cc (which is reported to have broken const/volatile).
+ case "$CC" in #(vi
+ cc|*/cc)
+ AC_MSG_WARN(You should consider using gcc or rcc if available)
+ unset ac_cv_prog_CC
+ AC_CHECK_PROGS(CC,gcc rcc,$CC)
+ ;;
+ esac
+ ;;
+sequent-ptx)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT -DNO_IOCTL -DUSE_FCNTL"
+ ;;
+sequent-ptx2)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT"
+ ;;
+sony-newsos*)
+ CFLAGS="$CFLAGS -I/usr/sony/include"
+ AC_CHECK_HEADERS(jcurses.h)
+ ;;
+svr4)
+ CFLAGS="$CFLAGS -DSVR4_BSDSELECT -DSVR4"
+ ;;
+sunos3*)
+ CFLAGS="$CFLAGS -DSUN"
+ ;;
+sunos4*)
+ CFLAGS="$CFLAGS -DSUN -DSUN4"
+ ;;
+ultrix*)
+ # Increase the maximum size of functions that will be optimized.
+ test -z "$GCC" && CFLAGS="$CFLAGS -O -Olimit 600 -G 7"
+ CFLAGS="$CFLAGS -DULTRIX"
+ AC_CHECK_HEADERS(cursesX.h, cf_cv_ncurses_header=cursesX.h)
+ ;;
+esac
+AC_SUBST(PROG_EXT)
+
+dnl --------------------------------------------------------------------------
+dnl Checks for library configuration (added right-to-left)
+dnl --------------------------------------------------------------------------
+
+CF_NETLIBS
+
+AC_MSG_CHECKING(for screen type)
+dnl This has to be cached, since there's a lot of interdependent tests.
+AC_CACHE_VAL(cf_cv_screen,[
+AC_ARG_WITH(screen,
+[ --with-screen=XXX select screen type
+ (XXX is curses (default), ncurses or slang)],
+ [
+case $withval in
+curses|ncurses|slang)
+ cf_cv_screen=$withval
+ ;;
+*) AC_ERROR(Unexpected value)
+ ;;
+esac],
+ [cf_cv_screen=curses])])
+AC_MSG_RESULT($cf_cv_screen)
+
+if test $cf_cv_screen != ncurses ; then
+ if eval "test \"`echo '$''{'cf_cv_ncurses_header'+set}'`\" != set"; then
+ cf_cv_ncurses_header=curses.h
+ fi
+fi
+
+case $cf_cv_screen in
+curses)
+ CF_CURSES_LIBS
+ CF_CURS_PERFORMANCE
+ ;;
+ncurses)
+ CF_NCURSES_CPPFLAGS
+ CF_NCURSES_LIBS
+ ;;
+slang)
+ CF_SLANG_CPPFLAGS
+ CF_SLANG_LIBS
+ ;;
+esac
+
+dnl Get the actual value for $libdir, which we will compile into Lynx as part of
+dnl the config pathnames.
+eval cf_libdir=$libdir
+cf_libdir=`echo $cf_libdir | sed -e s@'^NONE/'@$prefix/@ -e s@'^NONE/'@$ac_default_prefix/@`
+
+AC_MSG_CHECKING(for location of config-file)
+LYNX_CFG_FILE=$cf_libdir/lynx.cfg
+AC_DEFINE_UNQUOTED(LYNX_CFG_FILE,"$LYNX_CFG_FILE")
+AC_MSG_RESULT($LYNX_CFG_FILE)
+
+dnl --------------------------------------------------------------------------
+dnl Checks for standard headers
+dnl --------------------------------------------------------------------------
+
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_HEADER_DIRENT
+dnl Don't check for sys/wait.h here since it is covered by another test.
+AC_CHECK_HEADERS( \
+ fcntl.h \
+ limits.h \
+ stdlib.h \
+ string.h \
+ sys/fcntl.h \
+ sys/filio.h \
+ sys/ioctl.h \
+ sys/param.h \
+ sys/time.h \
+ termio.h \
+ termios.h \
+ unistd.h \
+)
+CF_TERMIO_AND_TERMIOS
+CF_FUNC_WAIT
+AC_TYPE_MODE_T
+
+dnl --------------------------------------------------------------------------
+dnl Checks for library units
+dnl --------------------------------------------------------------------------
+
+AC_FUNC_VFORK
+CF_FIONBIO
+CF_REMOVE_BROKEN
+CF_FUNC_LSTAT
+AC_CHECK_FUNCS( \
+ cuserid \
+ getcwd \
+ getgroups \
+ putenv \
+ readdir \
+ strerror \
+ waitpid \
+)
+AC_REPLACE_FUNCS( \
+ mktime \
+ strstr \
+)
+
+CF_CHECK_FUNCDECLS([#include <string.h>], strstr)
+CF_CHECK_FUNCDECLS([
+#include <stdio.h>
+#include <grp.h>], getgrgid getgrnam)
+
+dnl --------------------------------------------------------------------------
+dnl Checks for external-data
+dnl --------------------------------------------------------------------------
+
+CF_BOOL_DEFS
+CF_ERRNO
+CF_LOCALE
+CF_NGROUPS
+CF_SYS_ERRLIST
+CF_UTMP
+
+### These tests must be run after establishing the curses library.
+if test $cf_cv_screen != slang ; then
+ CF_ALT_CHAR_SET
+ CF_FANCY_CURSES
+ CF_NCURSES_VERSION
+ CF_NCURSES_BROKEN
+ CF_COLOR_CURSES
+ CF_SIZECHANGE
+ CF_TTYTYPE
+ AC_CHECK_FUNCS( \
+ cbreak \
+ keypad \
+ use_default_colors \
+ wborder \
+ )
+fi
+
+dnl --------------------------------------------------------------------------
+dnl Miscellaneous options that don't need to test system features
+dnl --------------------------------------------------------------------------
+
+CF_HELP_MESSAGE(
+Miscellaneous Options:)
+
+AC_MSG_CHECKING(if experimental 8-bit case-conversion should be used)
+CF_ARG_ENABLE(8bit-toupper,
+[ --enable-8bit-toupper use experimental 8-bit case-conversion],
+ [use_8bit_toupper=$enableval],
+ [use_8bit_toupper=no])
+test $use_8bit_toupper != no && AC_DEFINE(EXP_8BIT_TOUPPER)
+
+AC_MSG_CHECKING(if color-style code should be used)
+CF_ARG_ENABLE(color-style,
+[ --enable-color-style use optional/experimental color style],
+ [use_color_style=$enableval],
+ [use_color_style=no])
+
+if test $use_color_style != no ; then
+ if test .$cf_cv_color_curses != .yes ; then
+ AC_ERROR(Configuration does not support color-styles)
+ fi
+ if test $cf_cv_screen = slang ; then
+ AC_ERROR(Configuration does not support color-styles)
+ fi
+ AC_DEFINE(USE_HASH)
+ AC_DEFINE(LINKEDSTYLES)
+fi
+
+case $use_color_style in
+no)
+ AC_MSG_RESULT(no)
+ INSTALL_LSS=
+ ;;
+*)
+ AC_DEFINE(USE_COLOR_STYLE)
+ AC_MSG_RESULT(curses-style)
+
+ AC_MSG_CHECKING(for location of style-sheet file)
+ LYNX_LSS_FILE=$cf_libdir/lynx.lss
+ AC_DEFINE_UNQUOTED(LYNX_LSS_FILE,"$LYNX_LSS_FILE")
+ AC_MSG_RESULT($LYNX_LSS_FILE)
+ INSTALL_LSS=install-lss
+ ;;
+esac
+AC_SUBST(INSTALL_LSS)
+
+use_dft_colors=no
+test ".$cf_cv_screen" = ".slang" && use_dft_colors=maybe
+test ".$ac_cv_func_use_default_colors" = ".yes" && use_dft_colors=maybe
+
+if test "$use_dft_colors" != no ; then
+AC_MSG_CHECKING(if you want to use default-colors)
+CF_ARG_ENABLE(default-colors,
+[ --enable-default-colors enable use of default-colors (ncurses/slang)],
+ [use_dft_colors=yes],
+ [use_dft_colors=no])
+AC_MSG_RESULT($use_dft_colors)
+test $use_dft_colors = "yes" && AC_DEFINE(USE_DEFAULT_COLORS)
+fi
+
+AC_MSG_CHECKING(if you want to use extended HTML DTD logic)
+CF_ARG_DISABLE(extended-dtd,
+[ --disable-extended-dtd disable extended HTML DTD logic],
+ [use_ext_htmldtd=no],
+ [use_ext_htmldtd=yes])
+AC_MSG_RESULT($use_ext_htmldtd)
+test $use_ext_htmldtd = "no" && AC_DEFINE(NO_EXTENDED_HTMLDTD)
+
+AC_MSG_CHECKING(if you want to use external commands)
+CF_ARG_ENABLE(externs,
+[ --enable-externs use external commands],
+ [use_externs=yes],
+ [use_externs=no])
+AC_MSG_RESULT($use_externs)
+test $use_externs != ".no" && AC_DEFINE(USE_EXTERNALS)
+
+AC_MSG_CHECKING(if you want to use setfont support)
+CF_ARG_ENABLE(font-switch,
+[ --enable-font-switch use Linux setfont for character-translation],
+ [use_setfont=yes],
+ [use_setfont=no])
+AC_MSG_RESULT($use_setfont)
+test $use_setfont = yes && AC_DEFINE(EXP_CHARTRANS_AUTOSWITCH)
+
+AC_MSG_CHECKING(if you want internal-links feature)
+CF_ARG_ENABLE(internal-links,
+[ --enable-internal-links handle following links to same doc differently],
+ [use_internal_links=yes],
+ [use_internal_links=no])
+AC_MSG_RESULT($use_internal_links)
+test $use_internal_links = no && AC_DEFINE(DONT_TRACK_INTERNAL_LINKS)
+
+AC_MSG_CHECKING(if you want to fork NSL requests)
+CF_ARG_ENABLE(nsl-fork,
+[ --enable-nsl-fork fork NSL requests, allowing them to be aborted],
+ [use_nsl_fork=yes],
+ [use_nsl_fork=no])
+AC_MSG_RESULT($use_nsl_fork)
+test $use_nsl_fork = yes && AC_DEFINE(NSL_FORK)
+
+AC_MSG_CHECKING(if you want to underline links)
+CF_ARG_ENABLE(underlines,
+[ --enable-underlines underline links rather than using boldface],
+ [use_underline=yes],
+ [use_underline=no])
+AC_MSG_RESULT($use_underline)
+test $use_underline = yes && AC_DEFINE(UNDERLINE_LINKS)
+
+AC_MSG_CHECKING(if you want to use zlib for decompression of some gzip files)
+AC_ARG_WITH(zlib,
+[ --with-zlib use zlib for decompression of some gzip files],
+ [use_zlib=$withval],
+ [use_zlib=no])
+AC_MSG_RESULT($use_zlib)
+
+if test ".$use_zlib" != ".no" ; then
+ CF_FIND_LIBRARY(z,
+ [#include <zlib.h>],
+ [gzopen("name","mode")],
+ gzopen)
+ AC_DEFINE(USE_ZLIB)
+fi
+
+dnl --------------------------------------------------------------------------
+dnl DirEd (directory-editor) options
+dnl --------------------------------------------------------------------------
+
+CF_HELP_MESSAGE(
+Directory Editor Options:)
+
+# All DirEd functions that were enabled on compilation can be disabled
+# or modified at run time via DIRED_MENU symbols in lynx.cfg.
+AC_MSG_CHECKING(if directory-editor code should be used)
+CF_ARG_DISABLE(dired,
+[ --disable-dired enable optional directory-editor, DirEd],
+ [use_dired=$enableval],
+ [use_dired=yes])
+AC_MSG_RESULT($use_dired)
+
+if test ".$use_dired" != ".no" ; then
+ AC_DEFINE(DIRED_SUPPORT)
+
+ AC_MSG_CHECKING(if you wish to allow extracting from archives via DirEd)
+ CF_ARG_DISABLE(dired-archive,
+ [ --disable-dired-archive disable dearchiving commands],[AC_DEFINE(ARCHIVE_ONLY)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow users to redefine DirEd keys)
+ CF_ARG_DISABLE(dired-override,
+ [ --disable-dired-override disable private keymaps],,[AC_DEFINE(OK_OVERRIDE)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow permissions commands via DirEd)
+ CF_ARG_DISABLE(dired-permit,
+ [ --disable-dired-permit disable chmod/attrib commands],,[AC_DEFINE(OK_PERMIT)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow executable-permission commands via DirEd)
+ CF_ARG_DISABLE(dired-xpermit,
+ [ --disable-dired-xpermit disable chmod/attrib commands],[AC_DEFINE(NO_CHANGE_EXECUTE_PERMS)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow "tar" commands from DirEd)
+ CF_ARG_DISABLE(dired-tar,
+ [ --disable-dired-tar disable "tar" command],,[AC_DEFINE(OK_TAR)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow "uudecode" commands from DirEd)
+ CF_ARG_DISABLE(dired-uudecode,
+ [ --disable-dired-uudecode disable "uudecode" command],,[AC_DEFINE(OK_UUDECODE)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow "zip" and "unzip" commands from DirEd)
+ CF_ARG_DISABLE(dired-zip,
+ [ --disable-dired-zip disable "zip", "unzip" commands],,[AC_DEFINE(OK_ZIP)])
+ AC_MSG_RESULT($enableval)
+
+ AC_MSG_CHECKING(if you wish to allow "gzip" and "gunzip" commands from DirEd)
+ CF_ARG_DISABLE(dired-gzip,
+ [ --disable-dired-gzip disable "gzip", "gunzip" commands],,[AC_DEFINE(OK_GZIP)])
+ AC_MSG_RESULT($enableval)
+fi
+
+AC_MSG_CHECKING(if you want long-directory listings)
+CF_ARG_DISABLE(long-list,
+[ --disable-long-list disable long "ls -l" directory listings],,
+ [AC_DEFINE(LONG_LIST)])
+AC_MSG_RESULT($enableval)
+
+AC_MSG_CHECKING(if parent-directory references are permitted)
+CF_ARG_DISABLE(parent-dir-refs,
+[ --disable-parent-dir-refs
+ disable "Up-to" links in directory listings],
+ [AC_DEFINE(NO_PARENT_DIR_REFERENCE)])
+AC_MSG_RESULT($enableval)
+
+### Finally, build config.h and the makefiles
+CFLAGS="$CFLAGS $EXTRA_CFLAGS"
+srcdir="$srcdir"
+SRCDIR_CLEAN="#"
+if test -n "$srcdir" ; then
+ echo srcdir is $srcdir
+ $srcdir/mkdirs.sh WWW/Library/unix
+ $srcdir/mkdirs.sh src/chrtrans
+ test "$srcdir" != "." && SRCDIR_CLEAN=""
+fi
+
+AC_SUBST(SRCDIR_CLEAN)
+AC_OUTPUT(
+ makefile \
+ WWW/Library/unix/makefile \
+ src/makefile \
+ src/chrtrans/makefile \
+)
diff --git a/gnu/usr.bin/lynx/descrip.mms b/gnu/usr.bin/lynx/descrip.mms
new file mode 100644
index 00000000000..91dde18b1d6
--- /dev/null
+++ b/gnu/usr.bin/lynx/descrip.mms
@@ -0,0 +1,132 @@
+! Make LYNX hypertext browser under VMS
+! =====================================
+!
+! NOTE: Use [.SRC.CHRTRANS]BUILD-CHRTRANS.COM to create the
+! chrtrans header files before using this descrip.mms.
+!
+! History:
+! 01/01/93 creation at KU (Lou montulli@ukanaix.cc.ukans.edu).
+! 04/12/93 (seb@lns61.tn.cornell.edu)
+! modified to support either UCX or MULTINET
+! 12/13/93 (macrides@sci.wfeb.edu)
+! Added conditional compilations for VAXC vs. DECC
+! (dependencies not yet specified; this is just a
+! "starter", should anyone want to do it well).
+! 10/26/94 (dyson@IowaSP.Physics.UIowa.EDU) RLD
+! Updated for AXP/VMS v6.1 and VAX/VMS v5.5-1
+! 12/07/94 (macrides@sci.wfeb.edu)
+! Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+! 02/17/95 (macrides@sci.wfeb.edu)
+! Updated for v2.3-FM
+! 03/23/95 (macrides@sci.wfeb.edu)
+! Replaced references to v2.3.8 or v2.3.9 with v2.3-FM to
+! avoid any confusion with official releases at UKans.
+! 07/29/95 (macrides@sci.wfeb.edu)
+! Added support for GNUC.
+!
+! Instructions:
+! Use the correct command line for your TCP/IP implementation:
+!
+! $ MMS /Macro = (MULTINET=1) for VAXC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1) for VAXC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1) for VAXC - UCX
+! $ MMS /Macro = (CMU_TCP=1) for VAXC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1) for VAXC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1) for VAXC - TCPWare TCP/IP
+! $ MMS /Macro = (DECNET=1) for VAXC - socket emulation over DECnet
+!
+! $ MMS /Macro = (MULTINET=1, DEC_C=1) for DECC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1, DEC_C=1) for DECC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1, DEC_C=1) for DECC - UCX
+! $ MMS /Macro = (CMU_TCP=1, DEC_C=1) for DECC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1,DEC_C=1) for DECC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1, DEC_C=1) for DECC - TCPWare TCP/IP
+! $ MMS /Macro = (DECNET=1, DEC_C=1) for DECC - socket emulation over DECnet
+!
+! $ MMS /Macro = (MULTINET=1, GNU_C=1) for GNUC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1, GNU_C=1) for GNUC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1, GNU_C=1) for GNUC - UCX
+! $ MMS /Macro = (CMU_TCP=1, GNU_C=1) for GNUC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1,GNU_C=1) for GNUC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1, GNU_C=1) for GNUC - TCPWare TCP/IP
+! $ MMS /Macro = (DECNET=1, GNU_C=1) for GNUC - socket emulation over DECnet
+
+.ifdef MULTINET
+TCPM = MULTINET
+.endif
+
+.ifdef WIN_TCP
+TCPM = WIN_TCP
+.endif
+
+.ifdef UCX
+TCPM = UCX
+.endif
+
+.ifdef CMU_TCP
+TCPM = CMU_TCP
+.endif
+
+.ifdef SOCKETSHR_TCP
+TCPM = SOCKETSHR_TCP
+.endif
+
+.ifdef TCPWARE
+TCPM = TCPWARE
+.endif
+
+.ifdef DECNET
+TCPM = DECNET
+.endif
+
+.ifdef TCPM
+.else
+TCPM = MULTINET !Default to MultiNet
+.endif
+
+.ifdef GNU_C
+CC = gcc
+.endif
+
+lynx : lynx.exe
+ ! Finished Building LYNX for VMS!!!
+
+lynx.exe : library exe
+ @ Continue
+
+library :
+ Set Default [.www.library.implementation]
+.ifdef DEC_C
+ $(MMS) /Description = [-.VMS]DESCRIP.MMS /Macro = ($(TCPM)=1, DEC_C=1) Library
+.else
+.ifdef GNU_C
+ $(MMS) /Description = [-.VMS]DESCRIP.MMS /Macro = ($(TCPM)=1, GNU_C=1) Library
+.else
+ $(MMS) /Description = [-.VMS]DESCRIP.MMS /Macro = ($(TCPM)=1) Library
+.endif
+.endif
+ Set Default [---]
+
+exe :
+ Set Default [.src]
+.ifdef DEC_C
+ $(MMS) /Macro = ($(TCPM)=1, DEC_C=1) Lynx
+.else
+.ifdef GNU_C
+ $(MMS) /Macro = ($(TCPM)=1, GNU_C=1) Lynx
+.else
+ $(MMS) /Macro = ($(TCPM)=1) Lynx
+.endif
+.endif
+ Copy /NoLog /NoConfirm lynx.exe [-]
+ Set Protection = (Owner:RWE, World:RE) [-]lynx.exe
+ Set Default [-]
+
+clean :
+ Set Default [.www.library.implementation]
+ $(MMS) /Description = [-.VMS]DESCRIP.MMS clean
+ Set Default [---]
+ Set Default [.src]
+ $(MMS) clean
+ Set Default [-]
+ - Purge /NoLog /NoConfirm
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.3 b/gnu/usr.bin/lynx/docs/CHANGES2.3
new file mode 100644
index 00000000000..f9653d4e6ef
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.3
@@ -0,0 +1,458 @@
+--- RELEASE of 2.3 (19-May-1994) ---
+5-19-94
+* Better memory allocation routines used for some VMS systems.
+5-19-94
+* Non-interactive (-source) access to documents requiring access authorization
+ not allowed to avoid crashes.
+3-30-94
+* Lynx exports the environment variable LYNX_VERSION on UNIX systems
+ with the current version number as the value.
+3-29-94
+* added "action=" handling to ISINDEX tags. (Is that in the spec?)
+3-27-94
+* fixed Telnet security problem
+3-19-94
+* added .mailcap and mailcap support as well as mime.types support
+ for the configuration of viewers and extension mappings.
+ The test command is now implemented so that viewers can be conditionally
+ setup.
+3-17-94
+* Revamped the FTP code to recognize different server types and to parse
+ full directory listings (LIST output). File types, sizes and dates
+ are displayed when possible.
+3-16-94
+* added transparent support for mosaic bookmark files. Just point
+ Lynx at your existing default mosaic bookmark file and Lynx will
+ handle the rest. Viewing, addition, and removal are supported.
+3-15-94
+* added second line of reverse video to show multiline links better.
+3-10-94
+* added configurable MIME types and viewers to lynx.cfg. MIME types
+ and VIEWERS can be configured by following the instructions within
+ the newest lynx.cfg file.
+3-?-94
+* added second %s argument to PRINTER and DOWNLOADER definitions.
+ If a second %s is present in the command definition it will be
+ filled in by a suggested filename which is derived from the URL
+ of the document. See lynx.cfg for more details.
+3-?-94
+* got code from CERN to fix HTBTree FTP bug. Large ftp lists should
+ not crash anymore.
+3-9-94
+* added no_proxy environment variable. set it to a comma delimited list
+ of domains or hosts that should not be proxyed. (Thanks CERN :)
+ USAGE: (UNIX)
+ setenv no_proxy "domain1.dom, domain2.dom, domain3, etc"
+3-?-94
+* Fixed Referer: field handleing so that it doesn't crash on really
+ long URL's
+3-?-94
+* True popup menus are now supported for non-multiple SELECT lists.
+2-28-94
+* fixed the delete-a-bookmark command and bound it to 'r' for remove.
+ (thanks to David Trueman for the fix)
+
+---------- RELEASE of 2.2 ------------------
+2-9-94
+* added 'd' for download current link. Can be used to force a download
+ of any file.
+* 'r' removed as a comment key. Use 'c' or reconfigure your keys to
+ add 'r' back in. (I would like to use 'r' in the future to mean
+ remove current bookmark link)
+* Found the bug in the HTTP redirection code that was causing it
+ not to work. So HTTP redirection appears to work now!
+* Added Referer: header to HTTP requests to list the URL of
+ the document listing the requsted URL. Here's an extract from CERN:
+ This optional header field allows the client to specify,
+ for the server's benefit, the address ( URI ) of the document
+ (or element within the document) from which the URI in the
+ request was obtained.
+
+ This allows a server to generate lists of back-links to documents,
+ for interest, logging, etc. It allows bad links to be traced
+ for maintenance.
+
+2-8-94
+* changed novice line to be displayed on bottom two lines with the
+ status line moved up two lines.
+1-27-94
+* Made configurable keymappings a reality. Keys can be remapped in
+ the lynx.cfg file. (diffs from David Trueman)
+* Got code from Foteos to make 'a' work for VMS connection interrupts.
+1-24-94
+* Moving closer towards configurable keymappings. New keyhandleing
+ code will make it very easy to implement. (diffs from David Trueman)
+1-14-94
+* Lynx FTP now supports PASV code. (fixes to CERN (Dave Raggert?) PASV code
+ from John Ellson) It is not enabled by default. Line 43 in
+ WWW/Library/Implementation/HTFTP must be commented out for
+ PASV code to be used. This was done because not all FTP sites
+ can support PASV FTP.
+1-13-94
+* slight change in forms user interface. For the better, I hope you will
+ agree. Text input fields are now active as soon as the cursor pointer
+ is over them. Therefore you may begin typing into the text field
+ as soon as you come to it. Tab, and up and down arrow keys will
+ move off of the text input field. The only problem with this is as
+ follows. If you are in the habit of using the number keys (keypad)
+ the or h,j,k,l vi keys, as soon as you move over the text link
+ you will begin seeing numbers or hjk or l show up in the text field.
+ In other words, your movement commands are now broken :( You must
+ use true arrow keys or the tab key to move off of the text field.
+ I've tried this out and it seems to work alright. I don't think
+ that users unfamiliar with this will have too hard a time figureing
+ it out. Once you see numbers or letter appearing it becomes fairly
+ obvious whats going on. I'll put a message at the bottom of the
+ screen saying "use tab or arrow keys to move off of link."
+* added mods by David Trueman to implement -restrictions commandline
+ option. -restrictions allows a list of services to be disabled
+ selectively. -restrictions takes the form of
+ "lynx -restrictions=[default],[all],[inside_telnet],[outside_telnet],[shell],\
+ [editor],[bookmark],[option_save],[print],[file_url],[download],[exec]"
+
+ all restricts all options.
+ default same as commandline option -anonymous. Disables
+ default services for anonymous users. Currently set to,
+ all restricted except for: inside_telnet, outside_telnet, and
+ goto. Defaults settable within userdefs.h
+ inside_telnet disallow telnets for people coming from inside your
+ domain.
+ outside_telnet disallow telnets for people coming from outside your
+ domain.
+ shell disallow shell escapes
+ editor disallow editing
+ bookmark disallow changing the location of the bookmark file.
+ options_save disallow saving options in .lynxrc
+ print disallow most print options
+ goto disable the 'g' (goto) command.
+ file_url disallow using G)oto to go to file: URL's
+ download disallow saving binary files to disk in the download menu.
+ exec disable execution scripts
+ exec_frozen disallow the user from changing the execution link
+ setting in the O)ptions menu.
+1-12-93
+* added new more informative messages for form links.
+1-11-93
+* fixed -dump and -source options so that they work for
+ binary files now.
+* Interruptable I/0 now completely works for UNIX systems.
+ VMS is next. Just hit an 'a' for abort anytime during a
+ transfer to abort. If there is a partial file to show, it
+ will be shown.
+* Added command line option -show_curser. If enabled the curser
+ will not be hidden in the right hand corner but will instead
+ be positioned at the start of the currently selected link.
+ show curser is the default for systems without FANCY_CURSES
+ capibilities, and the default configuration can be changed in
+ userdefs.h
+1-9-93
+* Added NNTP posting capibilities. Currently uses external inews
+ program which will be included in the utils directory.
+ Would someone like to patch in some freeware inews code, or
+ send me some?
+1-7-93
+* fixed bug in password handling which cuased it to be displayed
+ accidentally :( (Danny Mayer)
+1-6-94
+* bold and emphasis now use curses underlining to represent
+ ephasized text. The use of _underline_ chars before and after
+ the text is now removed.
+1-5-94
+* Added configurable download menu so that binary files may
+ be downloaded using any protocal. Download menu is displayed
+ after selecting a non-displayable file.
+* Added exec links. 4 types currently defined:
+ files ending in: .csh, .ksh, .sh, (for UNIX) and .com (for VMS);
+ Use exec link controls to turn on and off exec links.
+* Gopher menues are now within PRE so that spaces are not
+ collapsed in menu entries.
+* added configurable character sets. Can be set in lynx.cfg
+ by the user in the options screen or in the users .lynxrc file
+ current sets are: ISO Latin I, IBM PC Character set, & 7 bit
+ approximations. New sets can be added to src/LYCharSets.c
+
+----------RELEASE of Lynx 2.1 and 2.1.1----------------------
+-grey area-
+* Ability to FTP to VMS systems. (Foteos Macrides)
+* Fixed lots of display and interupt problems (Foteos Macrides)
+* The Lynx Bookmark file is now interpreted as an HTML document.
+ Old Lynx bookmark files must be converted using the lynx2html
+ program or deleted.
+* HTML+ forms as implemented by XMosaic now work.
+ fill in the empty spaces and press the submit button to
+ submit the form.
+* The TEXTAREA tag isn't done yet. It will currently only
+ give a one line text area. The next version of Lynx will
+ include a true textarea implementation once I figure out a
+ reasonable interface.
+* Incorporated WWWlib 2.14 and fixed up the descrip.mms files.
+ Foteos Macrides made VMS port changes and wrote a really nice
+ build.com script to make compilation on VMS systems really easy.
+ Foteos also ported Lynx to OpenVMS for alpha axp systems.
+* 's' now means search a searchable indexed document through the
+ server, and can no longer be used to search for strings within
+ the displayed document.
+* '/' now only searches through the current displayed document for
+ strings and can not be used for searchable index documents.
+* Capital 'Q' now quits without asking for confirmation.
+* 'm' for Main Menu now askes for confirmation and does NOT clear
+ the history stack.
+* Blockquote style changed slightly.
+* fixed bug with A and other tags messing up formatting
+ withing PRE segments.
+* Verbose Gopher option removed, verbose gopher functionality
+ is now set permenantly on.
+* Default editor is now configurable in the lynx.cfg file.
+* Default bookmark file is now configurable in the lynx.cfg file.
+
+12-15-93
+* ownership is no longer inherited.
+* link rev="owner" href="mailto:ADDRESS" now accepted as well as
+ link rev="made" href="mailto:ADDRESS" to define the URL of the
+ owner or person responsible for the info.
+* 's' now only searches ISINDEX server documents.
+* '/' always means search within the document.
+
+-grey area-
+* still doing massive rewrite. Debugging!!
+
+11-30-93
+* anonymous users cannot change the bookmark page! (thanks to Jyrki Kuoppal for
+ pointing out a security hole)
+
+-grey area-
+* massive rewrite. Removed all Lynx internal format code and
+ restructured all the source files.
+
+11-8-93
+* added &nbsp; (non-breaking space), &ensp; and &emsp;
+
+---------- RELEASE of 2.0.12 -----------------
+11-1-93
+* Change HTInit.c so that unsupported types are not sent out
+ in accept parameters. For non X screen only text/html and
+ application/octet-stream are sent.
+
+10-26-93
+* descriptive title added to files mailed from lynx
+
+10-25-93
+* disabled FTP connection caching to help fix multiple FTP problems
+
+10-23-93
+* added preliminary level 1 forms support.
+
+10-20-93
+* fixed a bunch of gopher holes
+* gopher lists are turned into URL's now instead of lynx
+ internal format document links
+* local documents ending in .html can now be referenced with
+ just a filename and/or path from the command line.
+
+10-19-93
+* Added preloaded searches to gopher URL's. They previously
+ didn't work. This is readily apparent as preloaded CSO
+ searches, which alot of people wanted.
+* removed old hytelnet compatibility code which looked in
+ multiple directories to find the correct file. If you still
+ need this capibility talk to me.
+
+10-12-93
+* The users specified editor is now spawned for mail messages.
+ If no editor is defined or if the user is anonymous, the built-in
+ lynx mail sender is used.
+
+10-11-93
+* changed all static data structures to be dynamic
+ This was a pretty major change of code which may add several
+ bugs.
+* rewrote parse_links routine to make it more efficient and to
+ work with dynamic structures.
+
+10-6-93
+* added progress messages to HTTP transfers.
+
+10-5-93
+* added -cache=# command line option to specify the number
+ of WWW documents cached in memory.
+
+9-28-93
+* added VMS port fixes from Foteos Macrides. Lynx now
+ compiles and works on VMS!
+* fixed ftp bug in WWWlib that didn't de-escape URL's before
+ sending request to FTP server.
+
+9-21-93
+* fixed coredump bug for some files with no links.
+
+9-3-93
+* Moved many configuration options including printer setup to
+ lynx.cfg file. The default placement of the lynx.cfg file
+ will be /usr/local/lib & sys$public
+
+9-1-93
+* Removed STARTDIR variable from userdefs.h STARTDIR is now inferred
+ from the STARTFILE.
+
+8-30-93
+* Fixed bug with only one link selectable out of many on the last line
+ of the display.
+* Ported to SVR4 courtesy of Nickolay Saukh (from Russia, Wow this is
+ really getting around!)
+* Uneditable documents don't get refetched. (Nickolay Saukh)
+* National language support through LOCALE
+ (instead of ISOLATIN1), protected by #ifdef LOCALE (Nickolay Saukh)
+
+------Release of Lynx 2.0.11--------------------------------
+8-27-93
+* Caused major international incident when a large bug was discovered after
+ release. :)
+* Fixed internal document hypertext refernces with URL's. '#selector'
+ strings now work again.
+
+8-24-93
+* When files come through on pre HTTP/1.0 servers they are now
+ recognized by their file extensions
+
+8-23-93
+* Lynx can now speak to old NCSA pre HTTP/1.0 servers
+* fixed ALT bug that had to do with style changes not
+ happening before the alt was printed.
+
+8-21-93
+* updated the man file lynx.1.
+
+8-19-93
+* updated help and converted it to HTML. Made a new help location and
+ server. The new default help file is
+ http://kufacts.cc.ukans.edu/lynx_help/lynx_help_main.html
+
+8-15-93
+* changed '\' to toggle between source and no source. When you press
+ '\' while viewing a rendered HTML document you will get the HTML source
+ when you press '\' while viewing HTML source you will get the
+ rendered HTML.
+* Added ALT attribute to IMG tag. When ALT is available the contents
+ are displayed. When ALT is missing [IMAGE] is displayed. When
+ ALT="" nothing is displayed.
+
+8-14-93
+* Added document reload command. CTRL-R when pressed will reload
+ the document into memory and redisplay it, clearing the screen.
+ This is very useful when editing documents, outside of Lynx while
+ using Lynx for rendering.
+* Added source view mode. '\' when pressed will reload the document
+ and display the HTML source. (doesn't work for gopher directoryies right
+ now, but gopher isn't HTML anyways)
+* fixed bug in LibWWW that caused it not to be able to convert to
+ www/source.
+* fixed bug in LibWWW that caused most binary file transfers to fail
+* added binary file transfer ability. When binary files are selected
+ the user is prompted for a file name to save to. The default directory
+ is the one the user started in.
+* Lynx now reloads local HTML files and re-renders them after editing.
+
+??-??-??
+* At some point I added the ability to edit HTML files on the local
+ machine.
+
+8-12-93
+* Added Nested Lists, up to six levels, with different bullets
+ for each level.
+* Due to the fact that nearly everyone seems to use P to mean
+ two returns within the same style, and Mosaic has been kind
+ enough to support this meaning, :( :( :( I have changed
+ the P tag to reflect this interpretation. P can be used
+ anywhere and will mean insert two returns. (i.e. two BR tags)
+
+8-11-93
+* Made the default Mime type for unknown file types on ftp servers
+ to be text/plain. Previously the WWWLibrary had the default
+ as application/octet-stream which meant that most files could not
+ be viewed.
+* Changed the ADDRESS style to be more like XMosaic
+ Left flush, newline top and bottom
+* The Statusline now displays the URL when retrieving files.
+* added BR (linebreak) tag!
+ The BR tag inserts a line break and maintains the current style!
+ The BR tag may be used anywhere.
+* added HR (horizontal rule tag!)
+ The HR tag puts a horizontal line seperating two bodies of text.
+ The HR tag may be used anywhere.
+
+8-8-93
+* All spaces, tabs and returns are now collapsed down do one
+ space.
+* fixed bug whiched caused certain links beginning at the
+ begining of a line to be bad.
+* added '*' (stars) to unordered lists and numbers to ordered
+ lists.
+* changed dir lists to be more like menu lists.
+* all emphasis, physical and symantic, now have _underlines_
+ around them to show emphasis.
+
+
+RELEASE OF VER 2.0.10 -----------------------------------------------
+
+7-8-93
+Added [IMAGE] in all places where IMG tags appear.
+added WWW_HOME environment variable support.
+fixed searching in WWW.
+removed tildas from mail messages for security reasons.
+added emacs-like key defs.
+changed gopher dir routines and Verbose format of directories
+
+6-30-93
+Forgot to put all kinds of bug fixes and stuff in here during the
+past month. I have been working on upgrading to the 2.X WWWlibrary
+Today I changed 'g' to mean goto a url, and 'v' to be view the
+bookmark page.
+
+5-30-93
+Fixed problem with ftp: URL not being recognized and not working.
+
+5-28-93
+Tried to remove the use of tabs and replace them with appropriate
+spaces. This was done to support brain dead curses packages that
+don't handle tabs. (like linux)
+
+5-20-93
+Fixed socket problem which was causing a problem with telnet's
+connecting
+
+5-18-93
+Fixed SUN curses problem, now works with the /usr/5lib routines
+
+4-9-93
+Added an option to turn on link numbering
+
+4-7-93
+Fixed read_rc() bug which caused .lynxrc files to be read incorrectly
+Fixed file cacheing bug which only allowed searching to be performed
+once. (it cached the answer and displayed that each time a new
+search was requested)
+
+4-2-93
+Fixed VMS I/O bug and TCP routines.
+
+4-1-93
+Ported 2.0 to VMS
+
+3-17-93
+Fixed a bug: Multiply defined procedure async_abort in
+the files get_file and get_bin_file
+
+3-16-93
+Optomized Gopher TCP routines, increased speed by a factor of 10!
+
+3-9-93
+Added WWW support by integrating the WWWlib1.4
+
+2-10-93
+Added home page support and append features.
+
+12-22-92
+Added support for Image types using xloadimage for X-terminals.
+
+12-1-92
+Added gopher binary file types
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.4 b/gnu/usr.bin/lynx/docs/CHANGES2.4
new file mode 100644
index 00000000000..2d242e2e0f8
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.4
@@ -0,0 +1,891 @@
+--- Rename of Lynx2-3-FM and release as Lynx2-4 (08-June-1995) ---
+==============================================================================
+06-08-95
+* All of the changes from lynx2-3-FM are now located at ftp2.cc.ukans.edu.
+ We will call this version lynx2-4 and all new changes will be added here.
+ - JP
+06-05-95
+* Added isc support based on post to lynx-dev from Ami Fischman
+ (a540ami@pic.ucla.edu). - FM
+06-04-95
+* Initialize t1->name before the StrAllocCopy() in LYMainLoop.c for
+ DIRED_SUPPORT tagging. - Rick Mallett (rmallett@ccs.carleton.ca)
+* Don't bother creating a /tmp copy of local files for downloading
+ under the DIRED_SUPPORT, and don't include "Save to disk" in the
+ download menu for such files. - RM
+* Deal with any newlines or tabs in statusline messages, along lines
+ in patch from Peter Marquardt. - FM
+* Various fixes to ensure terminations of strings, along lines suggested
+ by PM. - FM
+* Made HTAlert messages more readable in trace mode.
+* Replaced info.cern.ch with www.w3.org in userdefs.h and lynx.cfg. - GL
+* Allow definition of the global configuration file (lynx.cfg) path and
+ name via a "LYNX_CFG" VMS logical or Unix environment variable. Will
+ override the "LYNX_CFG_FILE" definition in userdefs.h. The -cfg command
+ line switch will override those. SYS$LOGIN (VMS) or '~' (Unix) can be
+ used in the path to treat the global configuration file as a personal
+ configuration file ($HOME will be substituted for '~'). Meets objective
+ in patch posted by Danny Meyer (mayer@ljsrv2.enet.dec.com) but does
+ not seek lynx.cfg in the user's HOME directory without an explicit
+ directive to do so. Issue a screen message and then exit if the
+ configuration file is not readeable (rather than continuing as if
+ one had been found and read). - FM
+* Added protections from NAMEless INPUT or TEXTAREA tags. - FM
+05-29-95
+* Changed close(*s) typo in HTTCP.c to NETCLOSE(*s). Caused tight loops if
+ on error *s became stdin. - Peter_Marquardt (wwwutz@cha01.tfh-berlin.de)
+05-20-95
+* Mods of proxying/gatewaying code, replace obsolete info.cern.ch default
+ URL addresses with www.w3.org, and add option to use the new www.w3.org
+ wais search gateway in cover page for wais searches. - FM
+05-10-95
+* If a startfile specified on the command line maps to a MIME type
+ which invokes an alternate display device, allow -homepage, if also
+ specified, to be substituted for startfile on quiting from the display
+ device, rather than forcing an exit due to the original startfile having
+ been neither text/html nor text/plain. Based on a patch from GL, with
+ protections against possible infinite getfile() loops added. - FM
+* Include -t switch when pico is the editor for reply_by_mail() in
+ LYMail.c. - GL
+05-04-95
+* Oops. Had zipped the wrong LYReadCFG.c in yesterday's mods. - FM
+05-03-95
+* Do not override any external proxy and no_proxy variables with those
+ in lynx.cfg. Bug fixes in code for setting proxy variables on Unix,
+ based on patches from Roman Czyborra (czyborra@cs.tu-berlin.de). - FM
+* Fixes for tagging when Lynx jumps to another screen and then comes back,
+ and deal with possibility of screen outputs from compress/decompress
+ utilities. - GL
+* Added support for Sequent's DYNIX/ptx operating system, and bug fixes
+ in HTTCP.c's BSDselect(). - Rodney Barnett (RBarnett@us.teltech.com)
+* Increased limits in select() loops to 5000 tries. - FM
+* Specify /nomember for compilations with DECC. It's not the default
+ on AXP and the code assumes byte alignment. - FM
+04-19-95
+* Added Alan Hirsh's script (LynxDir:VMSPrint.com) for dealing with busy
+ VMS print queues such that Lynx might otherwise delete the temporary
+ file before it has been queued for printing. - FM
+* Added lots of type casting to the mathematical operations in GridText.c
+ to minimize possible sizing/alignment problems for DECC/AXP (and any
+ Unix flavors that use the Alpha chip). - FM
+04-17-95
+* Use test=test -z "$LYNX_VERSION" like test=test -n "$LYNX_VERSION"
+ in mailcap files simply as flags for non-LYNX versus LYNX environment,
+ without actually bothering to execute a test. - FM
+* Issue "** Bad HTML!!! Use -trace to diagnose. **" statusline messages
+ when bad HTML is encountered, and suppress those statusline messages in
+ favor of the TRACE messages when -trace is used. - FM
+* Fixed anchor deletion problem in yesterday's ISMAP mods. - FM
+* Removed -ltermcap from AIX makes (AIX doesn't use it). - FM
+04-16-95
+* Send a 0,0 coordinate pair if a user clicks on an ISMAP link, so that
+ it's handled equivalently to clicks on an ISMAP submit button, and
+ (typically) will return the server's default. Note that the default
+ often is the parent document, and if so, the current document will
+ be returned via redirection (pointlessly 8-). However, this mod
+ allows the WebMaster to use a pure-text document as the default for
+ Lynx. - FM
+* Protections against crashes for inappropriately positioned form tags. - FM
+* Fixes in handling of configurable INEWS path. - FM
+* Support for VT500 series terminals. - George Cook (cook@wvnvaxa.wvnet.edu)
+04-12-95
+* Makefile tweaks for bsdi and aix4. - FM
+04-11-95
+* Mods for building with BSD Interative (bsdi). - FM
+04-08-95
+* Added translation of HTML entities and decimal escaping for the
+ VALUEs of INPUT and OPTION tags. - FM
+* For TYPE="image" INPUT tags, use "[IMAGE]-Submit" as a pseudo-ALT
+ string, and submit a 0,0 coordinate pair if it's clicked, which
+ typically will invoke the server's default (I guess something is
+ better than nothing. 8-). - FM
+* Handle (possibly multiple) angle brackets in bookmark and showinfo
+ link names. - FM
+* Fixed typo in for-ultrix code in LYMain.c. - FM
+04-04-95
+* Added ability to set proxy environment variables via lynx.cfg. - FM
+04-01-95
+* Added handling of the HTML 3.0 attributes for ISINDEX tags:
+ ISINDEX HREF="reference" PROMPT="string"
+ The ACTION attribute didn't make it into HTML 2.0. For now, we'll keep
+ supporting it in Lynx by treating it as a synonym for HREF. - FM
+03-31-95
+* Mods for AIX v4.1.1 and addition of make aix4. - FM
+* Added prototype and extern declarations for BSDselect(). - FM
+* Fixed bugs in form_getstr() that could clobber the stack. - GL
+* Fixes for symlink handling. - GL
+* Made LYShowInfo.c aware of the setuid, setgid and sticky file modes,
+ and nicer mode display if the file doesn't have the read bit set. - GL
+03-30-95
+* Fixed glitch in BASE tag handling. - FM
+03-29-95
+* Initialize pointers in add_trusted() of LYGetFile.c before the
+ StrAllocCopy() calls. - FM
+03-26-95
+* Miscellaneous TRACE and related messaging tweaks. - FM
+03-24-95
+* Handle defaulted localhost in file BASE tags, and related tweaks of
+ defaulted localhost handling in file URLs. - FM
+* Use RM_PATH for both file and directory deletions with the DIRED_SUPPORT
+ remove function. - GL
+--- STARTING 2.3-FM ---
+==============================================================================
+03-23-95
+* Designate this code set as lynx2-3-FM to avoid any confusion with the
+ official releases at UKans. - FM
+* Tweaks of code for defaulted localhost in file URLs. Don't require
+ any host field marker in such URLs - FM
+03-21-95
+* Added handling of defaulted localhost in file URLs. - FM
+* More protections against bad HTML. - FM
+* SYSLOGing enhancements. - GL
+* Suspend curses during my_spawn()'s, and fixes of code for the child
+ and error return detection. - GL
+03-20-95
+* More protections against potentially infinite loops. - FM
+03-16-95
+* Enhancements of 'c'omment and mailto handling. - FM
+* Mods to build.com for enabling submission to BATCH. - FM
+* Ultrix terminal-handling fix. - Roman Czyborra (czyborra@cs.tu-berlin.de)
+03-15-95
+* Fixed bug in for-Unix directory listing code to screen out inaccessible
+ parent directories. Was also being applied to ftp listings. - FM
+* Made bolding of H1 through H7 headers a lynx.cfg option, with the
+ non-bolding as the compilation default. - FM
+03-13-95
+* Fixed bug in setting link[].lname elements to empty strings for form
+ INPUT_ANCHORs. Was causing showinfo() to report the links from the
+ previous document (yet another memory leak bites the dust 8-). - FM
+* Numerous fixups of bold and underline handling. - FM
+03-09-95
+* Increased the while() loop limit for select() tries in HTTCP.c to 500. - FM
+* Memory allocation/free fixes in HTAccess.c. - FM
+* Makefile and documentation tweaks. - FM
+03-07-95
+* Implemented HT_BOLD when specified for headers in DefaultStyle.c. H1 is
+ now uppercase, bold, and centered. H2 - H7 are lower or mixed case, bold,
+ and progressively indented. - FM
+* Miscellaneous enhancements of menu displays. - FM
+* Allow tabs and '$' in lynxexec commands. - FM
+* More TOUPPER/TOLOWER fixes. - FM
+03-06-95
+* Added ability to set the INEWS path in lynx.cfg. - FM
+03-05-95
+* Separated the newspost URL into newspost versus newsreply, and modified
+ LYNews.c to behave more rationally for new versus followup posting. - FM
+* Added "mode reader" command for news list and article requests. - FM
+* Enabled saving of list_dir_style settings in the user's RC file. - FM
+* Don't restrict rearming SIGINT in LYClean.c for IGNORE_CTRL_C to just
+ SVR4. - FM
+* Added numerous protections against core_dumps/ACCVIOs in HTML.c for bad
+ HTML. Should also help reduce likelihood of infinite while() loops and
+ a runaway CPU if binary files are mistyped and rendering is attempted. - FM
+* Added (unsigned char) type casts in addch() calls for proper handling of
+ high value ISOLATIN1 characters. - FM
+* Limited the while() loop for select()'s in HTTCP.c to 50 tries, to help
+ reduce likelyhood of a runaway CPU on undetected terminal disconnects. - FM
+* Fixed typo in build.com. - FM
+* Added Craig's lynx_help and about_lynx files for the lynx2-3-7 distribution,
+ updated for lynx2-3-9 BETA. - FM
+--- STARTING 2.3.9 BETA ---
+==============================================================================
+02-20-95
+* Updated doc files and passed on to UKans for archiving on the
+ ftp2.cc.ukans.edu server as 2.3.8 BETA. - FM
+02-17-95
+* Further updates of building procedures for VMS. - FM
+* Further updates of lynx.man, lynx.hlp and documentation. Indicate
+ that the inside_foo and outside_foo restrictions are not selective
+ on systems which lack utmp. - FM
+* Changed yesterday's DGUX define fo DGUX_OLD, because only older
+ Data General systems need it. - FM
+02-16-95
+* Added Jeff's updates of lynx.man and lynx.hlp, further updated for
+ v2.3.8 - FM
+* Fixed typos in LYMail.c and HTTPC.c. - FM
+* Cleaned up #ifdef'ing for -DIGNORE_CTRL_C. - FM
+* Added -DDGUX for using inet_addr(host).s_addr instead of inet_addr(host)
+ in HTParseInet() of HTTCP.c (Data General may need it). - FM
+* Don't report "-help" as an invalid option. - FM
+02-15-95
+* Handle HTML entities and decimal escaping in ALT strings. - FM
+* Build fixups for TCPWARE. - FM
+02-14-95
+* Added transmission of Accept-Language headers. A default preferred
+ language is defined in userdefs.h. It can be overridden via lynx.cfg.
+ Users can change that via the 'o'ptions menu and save their preference
+ in their RC file. - FM
+* Tweak of FIXED record handling on VMS. - FM
+* Defined Unix ZIP_PATH and UNZIP_PATH in userdefs.h. - FM
+02-12-95
+* Added -localhost switch for restricting access to files and servers
+ on the local host. - FM
+* Added -nobrowse switch for disabling directory browsing. - FM
+* Added -selective switch for requiring a .www_browsable file in
+ each directory for browsing access to it. The enabling files
+ are not included in the directory listings. - FM
+* Fixed up displaying of README files in directory listings on
+ VMS. - FM
+* Replaced all tolower() and toupper() calls with the TOUPPER() and
+ TOLOWER() macros in HTUtils.h (should help deal with some of the
+ strange behavior reported for some flavors of Unix; see header of
+ HTUtils.h). - FM
+Worked in mods from David Trueman (david@cs.dal.ca) - FM:
+* Don't issue the ../ link in Unix local directory listings if the parent
+ directory is not readable (was already dealt with on VMS - FM).
+* Include an Organization: header in Unix news postings, if possible
+ (was already dealt with on VMS - FM).
+* Don't allow the editing of Unix mail headers because that is error
+ prone (no change on VMS; editable pseudo-headers are included for
+ informational purposes, but the real headers are those of the
+ account running Lynx - FM).
+* Don't hardcode the Unix mv command; use MV_PATH define in userdefs.h.
+* Moved the Unix COPY_COMAND define to userdefs.h as COPY_PATH.
+* Completed the Unix ZIP support.
+02-10-95
+* Added code for converting the headers of downloaded binaries on VMS
+ to indicate FIXED 512 record format. See the documentation in
+ userdefs.h, lynx.cfg and FIXED512.COM for more information. - FM
+02-08-95
+* Fixed glitch in HTInit.c which mis-casted the default MIME type for
+ files with a .sh extension, causing the EXEC_SCRIPT function to be
+ disfunctional. - FM
+* I think I finally have Lynx showing "(p# of N)" properly in the title
+ lines (we'll see if perfection has really been achieved 8-). - FM
+* Extended directory browsing on VMS to the -homepage specification,
+ if included on the command line, e.g., lynx -homepage=sys$login
+ will start up Lynx with the default startfile, but the 'm'ain menu
+ command will yield listings of the home directory. - FM
+* Added -fileversions switch on VMS for including all versions of files
+ in directory browser listings (otherwise, only the highest version is
+ listed, with no version numbers displayed). - FM
+* Modified LYEdit.c to use fopen(filename,"a") instead of access(filename,2)
+ to verify write access for editing files (checking "append" access appears
+ to be a more reliable way to do it across platforms/flavors). - FM
+02-07-95
+* Implemented directory browsing for VMS. - FM
+* Fixed printer command handling to actually prompt for and use a second
+ filename argument if two "%s" strings are in the command map. - FM
+* Added anti-Unix-shell-spoofing code for all of the filename argument
+ handling. - FM
+* Fixed glitch in getenv(DISPLAY) calls on VMS.
+02-04-95
+* Fixed a glitch in BASE support. Should now work properly when both
+ standard and Lynx-specific hrefs are in the document. - FM
+02-03-95
+* Added support for posting to newsgroups from Lynx on VMS via the
+ ANU-NEWS software. - FM
+* Numerous href parsing enhancements. - FM
+* Enhancements and bug fixes of news displays. - FM
+* Enabled display of Linknames with angle brackets (as for news URLs)
+ in the showinfo page. - FM
+* Ensured that a file URL which is really an ftp URL will yield an
+ "FTP is Disabled" statusline message when it's disabled. - FM
+02-01-95
+* Defined out the LYK_VERSION code and made Control-V a dead key again,
+ since including the Lynx name and version strings in the showinfo ('=')
+ and 'o'ptions displays is adequate, and people on different platforms
+ or flavors associate Control-V with other functions. - FM
+01-31-95
+* Beefed up the BASE support. - FM
+* Made all WWWLib cover pages and menus HTTP/1.0 compliant (to ensure
+ resetting of any BASE tags) and gave them more pizzaz. - FM
+* Trim terminal slashes in ftp paths if not the Welcome directory, so
+ we'll get "Up to" links. Terminal slashes in file paths still force
+ that directory to be treated as the Welcome directory. For example,
+ ftp://host/blah/foo/ will have an "Up to blah" link listed, but
+ file://host/blah/foo/ will treat /blah/foo/ as "Welcome" (both ftp
+ and file "Up to" links are blocked by -DNO_PARENT_DIR_REFERENCE). - FM
+* The VMS SOCKETSHR_TCP support can't yet handle telnet, tn3270 or
+ rlogin URL's (Andy Harper is working on it; be patient 8-). Modified
+ HTTelnet.c to compile properly and behave rationally when such URL's
+ aren't supported. - FM
+* Corrected doc files based on Larry Virden's (lvirden@cas.org) careful
+ (or is it carefull) proof-reading. Thanks Larry! - FM
+* More type casts for ANSI C compliance. - FM
+01-30-95
+* Added numerous type casts for ANSI C compliance. - FM
+01-29-95
+* Prototyped HTHostName() for yesterday's mods in HTAccess.c. - FM
+* Updated lynx.cfg. - FM
+01-28-95
+* Added lynx name and version to the showinfo page and options menu. - FM
+* Tweaked Danny's news proxying mods for selective no_proxy directives
+ with a port field (119) for news, and added equivalent code for wais
+ (port 210). - FM
+* Updated the INSTALLATION file (I hope people read it 8-). - FM
+* Hadn't included last night's typo fix in the archived fileset. - FM
+01-27-95
+* Added Danny Mayer's (mayer@ljo.dec.com) mods for proper handling of
+ no_proxy directives for news (NNTPSERVER) hosts. - FM
+* Worked in Ari Luotonen's (luotonen@dxcern.cern.ch) mods for sending
+ a "Pragma: no-cache" header for use by a proxy server in conjunction
+ with the RELOAD command. - FM
+* Fixed to handle file URL's appropriately in conjunction with proxying
+ of ftp URL's. For file URL's on the local host, direct access is
+ attempted, with no ftp attempt if that fails, whether or not proxying
+ is in effect, and whether or not no_proxy directives have been set.
+ Both ftp URL's, and file URL's on a remote host, are sought via ftp
+ without a direct access attempt. File URL's for remote hosts are
+ converted to ftp URL's before submission to a proxy server, so no
+ special procedure need be implemented to induce the proxy server to
+ act on them (You shouldn't continue using file URL's when you intend
+ ftp, but Lynx will handle such URL's properly when encountered in
+ old documents that use file when ftp is intended.) - FM
+* Fixed typo in yesterday's "psychotherapy". - FM
+01-26-95
+* Escaping of ISINDEX queries needed more tweaks to work properly with
+ high value IsoLatin1 characters. - FM
+* Applied psychotherapy to the schizophrenic behavior that was exhibited
+ when download, upload, print, history or showinfo commands were used
+ during displays of each other's menus or temporary files. - FM
+* Enabled downloading of links from the history page. - FM
+01-25-95
+* Added LYK_VERSION command (^V) for showing version of Lynx. - FM
+* Include file fixes for TCPWARE. - FM
+* Fixed bug in showinfo() which caused core dumps when invoked while
+ positioned on any form field which has a "linkname" but a NULL
+ "filename". - FM
+* Fixed glitch in 'p'rint menu. - FM
+01-24-95
+* Enabled SOCKSification for any Unix flavor via the SITE-LYDEFS,
+ SITE-DEFS and SOCKSLIB definitions in the top-level Makefile. Added
+ info in INSTALLATION on how to do it for VMS. Included notes that you
+ are better off building Lynx normally, and instead using a SOCKSified
+ proxy server to get through a firewall. - FM
+* Added instructions in INSTALLATION for setting up proxy service. - FM
+* Fixed multiple submit button handling to distiguish which button was
+ activated when they have the same name, and include only that button's
+ name/value pair in the submission. - FM
+* Figured out how to apply all security and restrictions checks for
+ redirecting URLs returned by ISINDEX searches, and accordingly lifted
+ the bypasses for the previously insecure access types. - FM
+* Added option to use Jerry Whelan's (guru@bradley.edu) BSDselect() for
+ SVR4 systems with the "type any key" problem. - FM
+01-23-95
+* Fixed up escaping of queries in HTSearch(). - FM
+* Updated the sample jumps files. - FM
+* Worked in socksification mods from Reese Ferry (reesef@VNET.IBM.COM) - FM
+* Enabled use of LOCALE for international characters with any Unix flavor
+ (not just sun) via a define in the top level Makefile. - FM
+01-22-95
+* Updated the lynx.cfg configuration file. - FM
+* Implemented BASE handling. - FM
+01-21-95
+* Fixed -cfg switch handling so that the specified, alternate configuration
+ file properly is read instead of the default system file specified in
+ userdefs.h. - FM
+* Made 'p'rint, 'd'ownload and 'u'pload menu lists single spaced. - FM
+* Fixed HTFileFormat() in HTFile.c so that it properly processes the
+ suffix-to-MIME-type mappings when version numbers are in local file
+ URLs on VMS. We therefore no longer trim off the version number if
+ if was included, and Lynx will now access and process that version
+ rather than only the highest version. - FM
+01-18-95
+* Makefile fixes for convex and linux. - FM
+01-17-95
+* More Makefile fixes. - FM
+01-14-95
+* Fixes for FreeBSD. - FM
+01-12-95
+* Made the "ls -l" emulation in local directory listings a compilation
+ option (see the top level Makefile). - FM
+* Made inclusion of "Up to" parent links in local directory listings a
+ compilation option (see top level Makefile). - FM
+* Message fix for checkmail on Unix. - FM
+* Fixes for SCO with gcc. - FM
+01-11-95
+* Restored original hash table function in HTAnchor.c without (hopefully 8-)
+ reviving anchor deletion problems. - FM
+* Fixed typo in HTAccess.c. - FM
+* Added code in HTFile.c from Timothy Newsham (newsham@aloha.net) for
+ generating long style Unix listings (ls -l). - FM
+01-10-95
+* Escape dashes in lynx.man. - FM
+* Added NetBSD support from Bryan T. Vold (btv@wiley.HealthPartners.COM). - FM
+* Made anchor searches in hash tables case-sensitive (so paths which
+ differ only in their case can be distinguished, as people using the
+ DIRED support kept requesting) without (hopefully 8-) reviving anchor
+ deletion problems. - FM
+01-09-95
+* More Makefile and code fixes for building properly with various systems
+ and compilers. - FM
+01-06-95
+* Numerous fixes for handling signals (e.g., SIGWINCH) received during
+ keystroke fetches, without (hopefully 8-) reviving the problem of
+ runaway CPU's on undetected terminal disconnects. - FM
+* More Makefile and code fixes for building properly with various systems
+ and compilers. - FM
+01-05-95
+* Changed define for syslog() logging to SYSLOG_REQUESTED_URLS and picked up
+ logging of ISINDEX search requests that don't go through getfile(). - FM
+* More fixes for redirection returned via ISINDEX searches. - FM
+* Fixed missing newline character at end of last .lynxrc entry. - FM
+* More Makefile tweaks. - FM
+* More additions in LYCurses.h for compilers which fail to check whether TRUE
+ and FALSE are already defined before defining them in curses.h. - FM
+01-03-95
+* Fix for redirection returned via ISINDEX searches. - FM
+12-29-94
+* Yet more top level Makefile tweaks. - FM
+* Fix bcopy problem for UCX. - Martin Zinser (zinser@vscn.gsi.de)
+* Fix ioctl() problem for UCX. - MZ
+12-27-94
+* More top level Makefile tweaks. - FM
+12-26-94
+* Added Lou Montulli's procedure for PURIFY to the top level Makefile. - FM
+12-23-94
+* Added Lou Montulli's memory leak fixes. - FM
+* Fixed HTLoadedDocumentTitle() call in LYGetFile.c. - FM
+--- RELEASE of 2.3.8 BETA ---
+12-22-94
+* The WFEB code as of 12-15-94 has been archived at UKans as lynx2-3-7,
+ so we'll make this lynx2-3-8 to avoid confusion. - FM
+* Added bookmark_exec restriction for disallowing use of lynxexec URL's
+ in the user's bookmark file or converted Mosaic hotlist. - FM
+* Enable any lynxexec URL in JUMPFILE if EXEC_LINKS has been defined.
+ This allows you to set both LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE
+ to TRUE and a single TRUSTED_EXEC rule that will always fail (e.g.,
+ TRUSTED_EXEC:none), so that *ONLY* the lynxexec URL's in the jumps
+ file will be acted upon. - FM
+* Disallow lynxexec URL's in G)oto if no_shell is set or if
+ LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE is TRUE. - FM
+12-21-94
+* Include LYFLAGS in the BSDI_Makefile. - FM
+* Numerous mods based on patches from David Trueman - FM:
+* Changed SUN4 ifdef for implementing the "reverse clear screen hack" to
+ REVERSE_CLEAR_SCREEN_PROBLEM since not all sun4 systems experience this
+ problem.
+* Changed a few messages to use key_for_func() instead of a hard-coded
+ key mapping.
+* Allow control-C as well as control-G to abort or cancel on Unix (as
+ already on VMS). On VMS, control-C and control-Y evoke a "Do you really
+ want to quit?" prompt, and a 'n'o reply gets handled as if control-G
+ has been entered in the first place. On Unix, control-C is treated
+ simply as a synonym for control-G, and control-Y is not an interrupt
+ signal. This seems the best way to handle those control signals, based
+ on what VMSers versus Unixites would expect them to do.
+* Added code to disallow the writing of files beginning with a dot if
+ NO_DOT_FILES is set TRUE in userdefs.h and/or lynx.cfg.
+* Added possibility of logging URL access via syslog() on Unix (ifdef'd
+ with LOGGING).
+* Improved and made more flexible the security for lynxexec URL's. The
+ default behaviour is the same as now, but source locations and the path
+ (Unix) or name (VMS) of programs to be executed can be restricted via
+ TRUSTED_EXEC rules in the lynx.cfg file.
+* Convert ~ in lynxexec paths to $HOME on Unix.
+* Several changes in DIRED support. Tidied and consolidated code. Changed
+ the way tags are freed (fixing a bug where they did not always get cleared
+ properly). Changed all programs to *_PATH defines. Changed the display
+ of tags so they work with numbered links.
+* Added another restriction to disallow telnet port specifications in
+ G)oto URL's.
+* A bit of special case code in jump handling. If key mapping is G, allow it
+ to be typed as "go target".
+* Change strncmp in remap() to strcmp() (bug fix).
+* Report offending bad option in main().
+* In mainloop(), make \r same as \t and \n.
+* Combine LYK_REMOVE code with LYK_DEL_BOOKMARK so that they can share the
+ same key map.
+* If show_cursor is true, position cursor 1 position before the link, which
+ makes it less likely that the link is obscured in defective terminal
+ programs
+12-15-94
+* More fixes in LYno_attr_char_case_strstr() and LYno_attr_char_strstr() - FM
+* People didn't like having to erase the default WHEREIS ('/') search string
+ when it wasn't what they wanted in a new document (though most didn't know
+ that it can be done easily via ^U), and Lynx doesn't have real editing via
+ LYgetstr() (just deletion from the end of the string), so I got rid of the
+ the editing offer. The previous search string is still buffered across
+ document fetches, and can be used across documents via NEXT ('n'). You
+ also can use WHEREIS without a search string entry to turn off highlighting
+ within the current document, and then NEXT to restore it. If control-G is
+ used instead of a blank string to cancel a WHEREIS command, it does not
+ turn off the highlighting. So everything everyone asked for is now
+ possible (once you figure out how to do it 8-). - FM
+12-14-94
+* Oops! Fixes in tcp.h for MULTINET with DECC/VAX had left SOCKET_ERRNO
+ undefined for all the other VMS TCPIP packages. That's what I get for
+ working on this stuff too late at night. - FM
+* Additional ANSI compliance fixes in HTTCP.c for builds with DECC/VAX and
+ non-MULTINET VMS TCPIP packages. - FM
+12-13-94
+* Modified searches for strings within the currently displayed document
+ ('/', as opposed to 's' for ISINDEX searches) so that the highlighting of
+ the search string is not retained when the current document is changed,
+ and added recall buffering of the search string so that it's offered as
+ the default for editing or reuse on subsequent '/' commands. Also, we
+ now force redraws on invokations of such searches so that hits will be
+ highlighted even if they occur on the current page. Links with hits such
+ that they have embedded highlighting of the search strings will not have
+ the embedded highlighting restored when the cursor is moved onto and then
+ off of them (helps to distinguished whether it's intended or the due to
+ the search), but will be restored whenever the page is redrawn. All
+ embedded highlighting also is restored when the 'n'ext command is used to
+ repeat the search in the current document, even if the returned hits do not
+ cause a page change. Note that these searches first search only the links,
+ and position you on the first link with a hit occurring after the current
+ link. If there were no hits in the links, then the text is searched and
+ the first hit occurring after the current link is positioned at the top of
+ the page. They never did, and still do not, search both the link and text
+ portions of the document simultaneously. Also note that ISINDEX searches
+ never have and still do not yield highlighting of the query string(s) in
+ the returned document.
+* Fixed LYno_attr_char_case_strstr() and LYno_attr_char_strstr() in
+ HTStrings.c so that they properly ignore any attribute characters in
+ the comparison string and return a pointer to the correct location
+ of a match with the target string. - FM
+12-12-94
+* Modified FTP gateway to display 230- as well as 250- information/help
+ messages, and on non-Unix as well as Unix systems. - FM
+--- RELEASE of 2.3.7 BETA ---
+12-11-94
+* Further tweaked explanatory comments in the configuration and samples
+ files, and updated the instruction files. - FM
+12-09-94
+* Modifed PassesTest() in HTInit.c to avoid the overhead of system() calls
+ by using getenv() when test -n "$DISPLAY" and test -z "$DISPLAY"
+ commands are encountered in the mailcap file. Otherwise, needlessly
+ expensive system() calls potentially could be made for virtually every
+ viewer mapping in that file!. For Lynx, those two strings in the mailcap
+ file now are equivalent to the :XWINDOWS and :NON_XWINDOWS flags,
+ respectively, for VIEWER: assignments in lynx.cfg. - FM
+* Also modified PassesTest() so that it simply treats test -n "LYNX_VERSION"
+ as success. Why spawn a system() command to see if Lynx is running, when
+ it obviously is!. However, that string can be included in the mailcap
+ file for assignments that should be restricted to Lynx if other software
+ also uses the file. - FM
+* The above two mods make it unnecessary to actually use a "test" script for
+ differentially setting viewers in XWINDOWS versus NON_XWINDOWS environments,
+ so VMSers also can use the mailcap files for differential assigments of
+ viewers, without those DCL error messages about "test" which have been
+ mystifying so many people. However, yesterday's mods do make it possible
+ for VMSers to use a "test" script for checking other environment or system
+ features, and thereby setting viewer switches differentially, analogously
+ to the command line switches for Lynx itself. - FM
+* Modified comments in samples/mailcap to indicate these enhancements. - FM
+* Modified comments in userdefs.h to describe correctly what the Lynx code
+ does as of v2.3: Any SUFFIX or VIEWER mappings in lynx.cfg will be
+ overridden in src/HTInit.c if they also appear there. Then, any mappings
+ in mime.type or mailcap will override those from lynx.cfg and src/HTInit.c.
+ The XLOADIMAGE definition is used in src/HTIinit.c, and you can use
+ mailcap, but not lynx.cfg, to override it. - FM
+* Modified comments in lynx.cfg and samples/lynx.cfg to indicate what Lynx
+ really does, and the use of mailcap files to do what lynx.cfg had claimed
+ it could do but doesn't. - FM
+* Fully implemented multiple submit button support for both POST and GET
+ forms. - FM
+* Added LYK_RESUBMIT keymap (with default binding to 'x' and 'X') for forcing
+ submissions of forms to servers (i.e., never use cache). LYK_ACTIVATE
+ (with default binding to right-arrow and RETURN) still fetches from cache
+ if available. Statusline help describes these commands when positioned
+ on a submit button. - FM
+12-08-94
+* Fixed HText_submitForm() in GridText.c to handle submitting INPUT types
+ (e.g., type="image") which have name/value pairs. - FM
+* Modified DCLspawn to recognize -1 on failure and 0 or 1 on success as
+ return or exit values of scripts, and report -1 or 0 as it's own return
+ value. If a "test" script is used on VMS in conjunction with .mailcap
+ for setting viewers, it should return -1 if the test fails and 0 or 1 if
+ it passes (the "test" script can be DCL or an exectutable, and should be
+ defined as a foreign command). If you don't have a "test" script, don't
+ include that instruction in .mailcap. - FM
+* The tmpaddress pointer in do_www_search() of GridText.c needed to be
+ initalized to NULL. - FM
+12-07-94
+* Made sufficiently ANSI compliant to build with DECC on VMS without using
+ the /stand=vaxc qualifier, and further modified so that Lynx will build
+ and run (extremely well 8-) with DECC/VAX. Whooh, that took some doing!
+ These mods are also desireable for builds on Unix. - FM
+12-02-94
+* Fixed the query recall buffer in do_www_search() of GridText.c to restore
+ the +'s to spaces and unescape properly. - FM
+* Include file and define fix ups, for SOCKETSHR/NETLIB support and convex
+ builds, in tcp.h, LYShowInfo.c and top level Makefile. - FM
+11-27-94
+* Fixed bugs associated with failure to check the post_data element in
+ addition to the address element when making push/pop decisions for the
+ history stack, and when checking whether a requested document has been
+ loaded successfully. The address element is insufficient for documents
+ returned by POST'ed forms. - FM
+* Check -trace switch earlier in LYMain.c so that trace messages associated
+ with setting up the Lynx configuration will actually be displayed. - GL
+11-23-94
+* More fix ups for the SOCKETSHR/NETLIB support. Close to "all set" but needs
+ more field testing with the full range of TCPIP packages for VMS. - FM
+* Added HP_TERMINAL define for the DIM workaround to the REVERSE problem with
+ HP terminals. If not defined, SNAKE builds will not make that substitution
+ (would be better to do this in a way that checks the terminal at run time,
+ but we'll hold off on that for now). - FM
+--- RELEASE of 2.3.6 BETA ---
+11-21-94
+* Replaced ucx$inetdef.h with socketshr_library:ioctl.h for the
+ SOCKETSHR_TCP builds. Note that the ioctl.h is not presently included
+ in the binary distribution of SOCKETSHR/NETLIB. You have to get it from
+ the sources distribution. - FM
+11-18-94
+* Added Andy Harper's (A.Harper@bay.cc.kcl.ac.uk) "first round" support for
+ SOCKETSHR/NETLIB (see SOCKETSHR.ANNOUNCE). Note that it is presently
+ including ucx$inetdef.h which is not provided with SOCKETSHR or NETLIB
+ source sets, and may not be available to non-UCX sites. We're checking
+ into how to deal with that. - FM
+* Made recall buffering of shortcuts for the 'J'ump command a configuration
+ file option (in userdefs.h and/or lynx.cfg). - FM
+* Added clearerr() before the GetChar() in LYStrings.c. - FM
+* Made the optional novice help lines conform to the "standard default"
+ key bindings. Edit them appropriately in userdefs.h if you plan to use
+ other bindings with that feature.
+* Added George Lindholm's (lindholm@ucs.ubc.ca) Makefile patch for making it
+ just a tad easier to set up local compile options. - FM
+* Eliminated serial free() in LYSanctify() of LYGetFile.c. - FM
+* Restricted all "hack to fix reverse clear screen problem" code to
+ SUN4 (had missed one 8-). - FM
+11-15-94
+* Eliminated separate list and atexit deletions of redirecting anchors. - FM
+* Added Rick Dyson's (Dyson@IowaSP.Physics.UIowa.EDU) updates of the
+ descrip.mms files. - FM
+11-12-94
+* Worked in Malcolm MacArthur's (mcscs2mm@zippy.dct.ac.uk) mods for reading
+ a printer's page length from the configuration file and calculating the
+ correct number of pages for the statusline query on whether to continue
+ if the document is longer than 4 printer pages. Further modified that
+ code to use the current LYlines for the computation when the built in
+ "print to screen" option is selected. See the comments concerning
+ "PRINTER:" definitions in lynx.cfg for more information. - FM
+* Fixed HTInetStatus() in HTTCP.c to use SOCKET_ERRNO instead of errno,
+ based on the platform/transport-specific definitions in tcp.h. Thanks
+ to Danny Mayer (mayer@ljo.dec.com) for tracking down this glitch. - FM
+11-10-94
+* Added David Trueman's latest clever enhancement: The command line option
+ -homepage=URL separates the notion of a home page (or main screen) from
+ the start file. So, lynx -homepage=URL1 URL2 will start up with URL2
+ but the MAIN_MENU key will take the user to URL1 rather than URL2. This
+ is useful for public accounts that start up with an information page or
+ form, that then leads the user to a URL for the actual home page. The
+ MAIN_MENU key can thereafter be used whenever the user wishes to return
+ to the actual home page. - FM
+* Enlarged string buffer in LYEdit.c to handle large paths. - FM
+* Made 'K'eymap title and descriptions easier to edit for alternate languages
+ (e.g., Dutch or Greek) as required by Dick Wesseling (but, alas, the editing
+ still has to be done in LYKeymap.c, because it's too much to move into
+ userdefs.h; someday Lynx will have real internationalization code 8-) - FM
+* Added titles to tops of jumps files so that the nesting level will be reset
+ on reloads. - FM
+11-09-94
+* More prototyping and include file fixes in LYJump.c and LYMainLoop.c - FM
+11-08-94
+* Prototyping fix in LYJump.c. - FM
+* Miscellaneous fixes in src/descrip.mms. - FM
+* Hadn't included patch for latest LYUtils.c in lynx2-3-5.patches. - FM
+11-07-94
+* At popular request (already 8-), changed the "Jump to:" query to work
+ exactly like the "goto:" query. The previous entry is recalled, a '?'
+ must be entered explicitly to fetch the shortcut list (with an instruction
+ about that added to the prompt), and a blank entry or Control-G returns
+ the user to the current document. - FM
+--- RELEASE of 2.3.5 BETA ---
+11-05-94
+* Numerous wonderful enhancements based on patches from David Trueman, and
+ entensions of those mods. Briefly:
+* Implemented 'K'eymap command for showing all of the key bindings currently
+ in effect, with a description of their functions. This is faster and
+ more helpful than the online help's description of the default key
+ bindings. Must be uppercase 'K' if VI keys are ON, otherwise the command
+ is case-insensitive. Try it, you'll love it! - FM
+* Implemented 'J'ump command for using "shortcut" names to access URL's in a
+ local "jumps.html" file that has a sorted DL list which maps each target
+ (shortcut) DT to it's full URL DD (see the sample jumps files added to
+ the distribution). The URL's could be local or remote resources, or
+ lynxexec or launch file URL's for system utilities (e.g., the shortcut
+ "news" could invoke the news reader, "mail" the mail utility, "swing" the
+ VMS File/Directory Management Utility, etc.). This feature is enabled by
+ defining JUMPFILE in userdefs.h or lynx.cfg, and can be disabled via at
+ run time via -restrictions=jump as a commandline switch. Must be uppercase
+ 'J' if VI keys are ON, otherwise the command is case-insensitive. Try it,
+ you'll love this too! - FM
+* Added a CHECKMAIL symbol which if set TRUE in userdefs.h or lynx.cfg will
+ report the existance of unread mail at Lynx startup, and arrivals of new
+ mail, via statusline messages. VMSers can block unsoliticed system NEWMAIL
+ screen broadcasts ($ SET BROADCAST/NOMAIL) when using this feature. It
+ can be disabled at run time via the -restrictions=mail switch, which also
+ disables standard mail functions in Lynx, but still allows 'J'umps via a
+ "mail" shortcut to a lynxexec URL for a script which could perform security
+ functions before permitting or rejecting access to the mail utility. The
+ hackers will really love this! - FM
+* Added ability to toggle the novice help line to show all of the principle
+ commands. - FM
+* Miscellanous bugs and memory leaks found and fixed in conjuction with
+ adding and enhancing the above features. - FM
+* The code may need some tweaking to build and run properly on some flavors
+ of Unix (appears to be all set for VMS). - FM
+11-01-94
+* Fixed bug if editor is dereferenced. - David Trueman (david@cs.dal.ca)
+* Enable alternate boxing of popup windows via defines for BOXVERT and
+ BOXHORI in userdefs.h - Dick Wesseling (ftu@fi.ruu.nl)
+* Check for LYCursesON before making any Curses calls in cleanup() - DW
+10-31-94
+* Looks like the last of the problems deleting anchors has been solved
+ by Dick Wasseling, so the bypass is lifted again. - FM
+* If CANT_EDIT_UNWRITABLE_FILES is defined on Unix, write access is
+ required to edit files (write and delete access are always required
+ on VMS). - Alex Whittaker (alex@biu.icnet.uk)
+* Moved "Press RETURN ..." text to userdefs.h. - AW
+10-28-94
+* Uncache documents or bookmark file before reloads (via Control-R or
+ 'r'emove command) in LYMainLoop.c. - FM
+* Uncache showinfo display or print, download, option, etc, menus before
+ reloading those in GridText.c. - Dick Wesseling (ftu@fi.ruu.nl)
+* Above two fixes still don't completely solve the anchor deletion problem,
+ so we're still bypassing.
+* Enable iso entity translations inside TITLEs - DW
+10-26-94
+* Problems when deleting anchors have been reported, apparently for
+ documents which have been (re)loaded with LYforce_no_cache. So,
+ we'll retore the bypass until that problem is tracked down. - FM
+10-25-94
+* Added coded for disabling mail for -anonymous via CAN_ANONYMOUS_MAIL in
+ userdefs.h, and via -restrictions=mail (default is enabled). - FM
+10-21-94
+* Added Danny Mayer's (mayer@ljo.dec.com) samples/lynx.com - FM
+10-05-94
+* Modified tcp.h to deal with conflicting typedefing in the MultiNet
+ types.h and time.h versus those for DECC. - FM
+* Define FANCY_CURSES for linux-ncurses. - FM
+09-30-94
+* -restrictions help list in LYMain.c should indicate "option_save" (not
+ "options_save") for disabling the saving of options in .lynxrc. - FM
+09-29-94
+Mods based on patches from George Lindholm (lindholm@ucs.ubc.ca) - FM:
+* Fixed problem when IGNORE_CTRL_C is defined, that was created by the
+ fix for runaway processes on Unix when undetected terminal disconnects
+ occurred.
+* Added options to disable rlogin and/or ftp access.
+09-28-94
+* Use "hack to fix reverse clear screen problem" in GridText.c if SUN4 is
+ defined (still need clarification on the exact nature of the problem
+ to decide if this is the best way to handle it; it bothers me to have
+ this kind of hack in the code 8-) - FM
+Mods based on patches from George Lindholm (lindholm@ucs.ubc.ca) - FM:
+* Move the "quit" text to userdefs.h from LYMainLoop.c for easier
+ customization.
+* Typo fix for buttons submit value in GridText.c
+* Renable SIGINT signal for SVR4 machines if control-c is to be ignored
+ when editing.
+* Solaris fixes for LYCurses.h.
+* Recognize pico as a special editor.
+* Fix -restrictions help text.
+* Fix -telnet and -news options so that they actually do something.
+* Fix upload code so that you can have more than one uploader option,
+ and fix for freeing a static variable.
+* Various prototype fixes.
+* -editor command line option signals that the editor can't be changed.
+* Added a SYSTEM_EDITOR option to lynx.cfg for a locked editor.
+--- RELEASE of 2.3.4 BETA ---
+09-27-94
+* Alas! I think I've tracked down and fixed all the bugs that were causing
+ ACCVIOs/CoreDumps if anchors were deleted/freed when freeing the cached
+ documents. So now we do delete/free them. This plugs a major memory
+ leak in Lynx (which we knew about, but heretofore had to live with). - FM
+* Added Danny Mayer's (mayer@ljo.dec.com) fix so that MIME types are handled
+ case-insensitively. - FM
+* Restored text/html (WWW_HTML) as the default MIME type when an HTTP/1.0
+ server fails to send it in the headers. This happens because it's the
+ default in Mosaic and developers using that don't realize their server or
+ script code is failing to send it (other MIME types will be caught as an
+ error, and the code will be fixed by the developers). Garrett's change to
+ application/octet-stream (WWW_UNKNOWN) was technically correct. You can
+ change it back to that where indicated in HTMIME.c if you prefer that Lynx
+ be technically correct but functionally wrong when dealing with this
+ situation. - FM
+--- RELEASE of 2.3.3 BETA ---
+09-22-94
+* Finished up redirection handling. Will now handle serial redirections
+ across multiple sites (with an arbitrary limit of 10, to prevent the
+ possibilily of an infinite loop of circular redirections), works properly
+ with redirections via the VALUE fields of OPTION tags, and no longer alters
+ any anchor addresses, avoiding all the problems that caused in the hash
+ table. - FM
+* Worked in Rick Mallett's (rmallett@ccs.carleton.ca) fix for runaway
+ processes on Unix when undetected terminal disconnects occur. - FM
+* Added Eric Jon Rostetter's (ERIC@uoft02.utoledo.edu) code for proper
+ keyboard handling with DEC eightbit terminals. - FM
+* Added David Greer's (david_greer@robelle.com) mods for curses on
+ HP terminals. - FM
+--- RELEASE of 2.3.2 BETA ---
+09-17-94
+* More fix ups of forms structure handling, freeing and redirecting. - FM
+* Fixed problem with free's of startfile, thanks to Dick Wesseling
+ ftu@fi.ruu.nl - FM
+09-14-94
+* More memory leak and redirection fix ups (still not perfect). - FM
+* Various mods to speed up memory management with VAXC on VAXen (still
+ slow compared to DECC on AXPen). - FM
+09-13-94
+* If an ISINDEX document is one returned by a previous search, the 's'
+ command puts up the query which returned it, for editting as a new query
+ (use Control-U to erase, Control-G to abort) Otherwise, no string is
+ offered in the prompt for a database query. If the previous query is
+ submitted without modification, a message to use Control-R to resubmit
+ the same query is display (so that the search will not be repeated
+ inadvertantly). - FM
+09-12-94
+* Fixed failure to load the popped menu properly when a gopher search was
+ selected and a NULL string, Control-G, or arrow key is entered to cancel
+ the prompt for a query. - FM
+* Hit lists/documents returned by ISINDEX searches are now always displayed
+ at their tops. They no longer inherit, inappropriately, the page and link
+ numbers of the previous list/document. - FM
+09-11-94
+* Fixed redirection handling so that the hash tables are updated and the
+ history stack works properly, including with forms that have VALUE
+ fields in OPTION tags that return Location: URL's for searches (e.g.,
+ the CUSI forms at Nexor). Whew, that took some doing! - FM
+09-05-94
+* Fixed up remaining problems with OPTION VALUE="foo" handling and the
+ associated popup window positioning and scrolling. - FM
+* Fixed bugs and several inadequacies in the history structure and code
+ (still needs some redesigning to deal more effectively with all aspects
+ of documents returned by forms and/or redirection). - FM
+* Now deals properly with anchors in a single document returned by
+ a form. - FM
+* Command line file specs on VMS can now be any valid explicit, wildcarded,
+ partial, or relative VMS specification, and will be converted to a valid
+ file://localhost/ URL, so that partial or relative URL's within the file
+ also will be interpretted properly. - FM
+* Now trims trailing white space and won't get tripped up by '=' characters
+ when reading configuration files. - FM
+* Miscellaneous bug fixes and enhancements. - FM
+* Tracked down and eliminated more memory leaks. - FM
+--- RELEASE of 2.3.1 BETA ---
+7-08-94
+* Correction handling of OPTION VALUE="" implemented.
+* Miscellaneous bugs corrected.
+6-17-94
+* Option to log memory leaks at exit by defining LY_FIND_LEAKS at compilation.
+6-17-94
+* Check amount of allocated memory, rather than just number of documents
+ cached, before deciding to remove the oldest document (implemented for
+ VMS with VAXC, not yet for Unix or VMS with DECC).
+6-16-94
+* VMS bookmark file version numbers are reset on additions of bookmarks.
+6-16-94
+* Gopher URL's with /hGET%20/ are converted to http URL's, as in the UMN
+ Unix/VMS gopher+ client.
+6-16-94
+* Added DIRECT_WAIS support for VMS
+6-16-94
+* Added build support for VMS TCPWare TCP/IP
+5-28-94
+* Increased nesting of HTML elements from 40 to 400. Hopefully this will limit
+ won't be encountered often.
+5-28-94
+* Modified for handling of Telnet URLs with spaces/other characters in the
+ username.
+5-26-94
+* Began terminating memory leaks with extreme predjudice.
+5-24-94
+* WAIS searches will now work when they are of type "www/present" as opposed
+ to only viewing the source.
+5-23-94
+* Added VMS CMU TCP/IP support, thanks to Andy Harper.
+--- RELEASE of 2.3 (19-May-1994, see CHANGES2-3) ---
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.5 b/gnu/usr.bin/lynx/docs/CHANGES2.5
new file mode 100644
index 00000000000..38621df6c2f
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.5
@@ -0,0 +1,1696 @@
+--- Rename of Lynx2-4-FM and release as Lynx2-5 (02-May-1996) ---
+==============================================================================
+05-02-96 ---- Release of Lynx2-5 ----
+* Modified documentation, help, and example files based on feedback for
+ yesterday's Lynx2-5 pre-release. - FM
+* Include ";q=0.001" whenever "iso8859-1" or "us-ascii" are autoappended
+ to Accept-charset headers. - FM
+* Added SITE_LIBS symbol in Makefile for convenient linking to any
+ site-specific libraries associated with any site-specific patches. - FM
+* Fixed an unsigned char typecast in GridText.c - FM
+* Eliminated statusline and TRACE warnings about possibly strange formatting
+ when TABLEs are in a document. - FM
+05-01-96
+* Renamed Lynx2-4-FM for pre-release as Lynx2-5
+04-30-96
+* Modified the fatal error messages such that they direct the user to
+ the local system administrator to confirm a bug before reporting it
+ to lynx-dev, and started updated the help and about files for the
+ switch to lynx-dev@sig.net as the primary list server. - FM
+04-28-96
+* Made use of ordered versus unordered lists and inclusion of article dates
+ in listings for news groups compilation and configuration options in
+ userdefs.h and lynx.cfg. - FM
+04-27-96
+* Added -realm switch for restricting URLs to the realm of the startfile.
+ The bookmark and jumps files are always considered as part of the realm.
+ Any execution links or form ACTIONs are permitted if obtained from
+ documents in the realm, but any switches that restrict bookmark operations
+ will still apply. For example, -book -realm will use the bookmark file
+ as the startfile, and restrict URLs to files in the user's account. Adding
+ -restrictions=bookmark_exec will block execution links in the bookmark
+ file, but not in other files within the realm (i.e., in the user's
+ account). If the startfile is an http URL, the realm will be equivalent
+ to that in http authorization procedures. Can be used with -traversal
+ for restricting the traversal to documents within the starting realm
+ for an http server. - FM
+* Fixed bug in form structure which could cause POST to be treated as
+ GET. - FM
+04-25-96
+* Added code to send Host: headers as described in the 23-Apr-96 HTTP/1.1
+ draft. - FM
+04-23-96
+* Modified HTMIME.c to pass documents with an ISO-8859-3 through -9, EUC-KR,
+ or ISO-2022-KR charset specified in the Content-Type header, to set the
+ flag for not doing 8-bit reverse translations, and to issue a statusline
+ message about the charset instead of forcing a download offer. Will have
+ garbage in the displays of 8-bit characters if one doesn't have the
+ corresponding charset installed for the terminal, but no harm should be
+ done, and those who do can get the files displayed instead of just being
+ up the creek without a paddle. Korean escape sequences will still be
+ trashed, since be have no translation functions as for Japanese, and we
+ still force a download offer if there is a mismatch for the supported
+ character sets, so the user can cancel and then modify the terminal setup
+ and charset choice appropriately. - FM
+* Increased the maximum number of attributes for tags (was too small for
+ OBJECT), updated the DTD for SCRIPT, and added the STYLE attribute for
+ all tags which presently, or might someday, accept it. - FM
+04-21-96
+* Modified the news gateway to use an ordered list with the numbers and
+ dates of the articles indicated in newsgroup listings. - FM
+* Fixed the checking and passing of the mailto argument in LYMainLoop.c
+ to mailmsg() in LYMail.c. - FM
+04-20-96
+* Fixed bugs in parsing of nntp and snews partial HREFs, and in the
+ parsing of NNTP message headers for creation of mailto and newspost
+ or newsrepy links. - FM
+04-19-96
+* Added OBJECT and BODYTEXT to the DTD, based on the 12-Apr-96 W3C draft.
+ The code for INSERT is still there, and should be remove if OBJECT
+ becomes a stable replacement. Code to handle data URLs for OBJECTs
+ not yet attempted. - FM
+* More tweaks for Japanese character handling. - FM
+04-18-96
+* If LINKS_ARE_NUMBERED is on, include the list of references in the
+ outputs of 'p'rint menu options, analogously to the output with
+ -dump. - FM
+04-14-96
+* Mods to report the content of SCRIPT, STYLE and ALIAS blocks in trace
+ mode. - FM
+* Made &die;, &macr; and &trade; synonyms for &uml;, &hibar; and &reg;,
+ respectively. - FM
+* Fixed typo in second line link highlighting code for slang. - ES
+04-13-96
+* More tweaks of Japanese character handling. - FM
+* Reinitialize timeout values after select() calls in LYUtils.c. - ES
+04-12-96
+* More tweaks of Japanese character handling. - FM
+* Tweak of target line and link setting when toggling to image_links mode
+ in LYMainLoop.c. - FM
+* Tweaks of circular buffer handling based on analyses from Mike Castle
+ (mcastle@umr.edu) and Bryan T. Vold (btv@ldl.HealthPartners.COM). - FM
+* Fixed typo for NeXT in tcp.h, based on feedback from LWV - FM
+* Reinitialize timeout values after select() calls in HTTCP.c. - Erik
+ Sundkvist (ess@lysator.liu.se)
+04-11-96
+* More tweaks of Japanese character handling. - FM
+* Added code for handling charset mappings for file and ftp URLs. - FM
+ You can set the mappings via lynx.cfg (or mime.types), e.g.:
+ SUFFIX:.html8R:text/html; charset=KOI8-R
+ SUFFIX:.txt8R:text/plain; charset=KOI8-R
+* Tweak of charset handling in HTMIME.c - FM
+04-09-96
+* Modified news gateway to handle split header lines. - FM
+* Tweaks of authorization header handling to make failures due to bad
+ headers from the http server clear to the Lynx user. - FM
+04-08-96
+* Yet more tweaks of memory management. - FM
+04-07-96
+* Tweaks for handling Japanese received via gateways. - FM
+04-06-96
+* More memory management tweaks. - FM
+04-05-96
+* Updated lynx.man, lynx.hlp and the online help files. - FM
+* Tweaks of INPUT, TEXTAREA and SELECT popup OPTION handling when
+ Japanese character translations are on. - FM
+04-04-96
+* Created new zip. Yesterday's appears to have been bad. - FM
+04-03-96
+* More optimizations and bug fixes based on patches from JED. - FM
+* More mods for handling keyboard input via SLANG library functions,
+ based on patches from JED. Note that the code for IGNORE_CTRL_C
+ has been bypassed in those mods, as they presently stand. - FM
+04-02-96
+* Added "first pass" handling of P end tags. - FM
+* Mods of HTCheckForInterrupt() for SLANG, based on patches from JED.
+ Note that the for-SLANG code is not taking possible SOCKSification of
+ Lynx into account. - FM
+* Use 3 for ^C instead of 7 for ^G as the argument for the slang abort
+ key in calls to SLang_init_tty(). - JED
+* Tweaks of make for clix. - AM
+03-31-96
+* More tweaks of memory management. - FM
+03-30-96
+* Added support for Japanese translations of text/plain in addition to
+ text/html documents, and for ALTs and form fields (see 03-26-96 mods).
+ Needs checking. Also added an LYK_JPN_TOGGLE, mapped to '@' by default,
+ for toggling JAPANESE mode ON and OFF, and code to indicate the situation
+ in the 'o'ptions menu. - FM
+* Added make for ultrix-slang and decstation-slang, and tweaks of LYCgi.c
+ for ultrix. - Alvian Tam (atm@newt.phys.unsw.edu.au)
+* Found and fixed some typos in yesterday's mods. - FM
+03-29-96
+* Added build-slang.com for building Lynx with the SLANG library instead
+ of curses on VMS. - FM
+* Mod to treat an EOF with errno of EINTR when GetChar() is defined as
+ getchar() in LYgetch() as due to a Ctrl-Z suspend, and invoke another
+ character fetch instead of exit on error. Based on patch from Gregory
+ Neil Shapiro (gshapiro@WPI.EDU). - FM
+* Numerous optimizations and bug fixes based on patches from JED. - FM
+03-28-96
+* More tweaks of SLANG support. - FM
+* Yet more tweaks of the HTList functions and macros, and their associated
+ memory management. - FM
+03-27-96
+* Fixed bug which could cause a crash if links are numbered and you
+ activate a link via a number when there are no links on the currently
+ displayed page. - FM
+* Tweaks of Content-Encoding header handling, and more detailed messages
+ about it in trace mode. - FM
+03-26-96
+* Added code in HTMIME.c for taking into account Content-Encoding headers,
+ so that compressed text/html or text/plain files are not displayed
+ inappropriately based on their Content-Type. - FM
+* Added "first pass" support for Japanese character translations, based on
+ patches for Lynx2-4-1 by Takuya Asada (asada@icsd6.tj.chiba-u.ac.jp). Is
+ to be checked out by Nelson Henry Eric (nelsonhe@ews07.nara.kindai.ac.jp)
+ because I have no way to check it here. Translations can be made the
+ default behavior by setting JAPANESE to TRUE in userdefs.h and/or
+ lynx.cfg. The default can be toggled via a "-jpn" command line switch.
+ If made TRUE by any means, the value of KANJI_CODE set in userdefs.h
+ and or lynx.cfg (EUC, SJIS, or NONE) will be applied, and can be changed
+ via "-euc", "-sjis" or "-ascii" command line switches, for setting Kanji
+ code translations to EUC, Shift JIS, or disabling it, respectively. Note
+ that Japanese translations are not yet performed in the line editor
+ (LYgetstr() of LYStrings.c and form_getstr() of LYForms.c), for form
+ field values, or for gateways (let's first see if what I've done so far
+ works right 8-) - FM
+* Added "LY" prefix for pop(), pop_num() and push() function names to
+ avoid possible conflicts with the ncurses library functions, and fixed
+ continuation line typo in solaris2 make, based on feedback from PN. - FM
+03-23-96
+* Tweaks of memory management in the CSO/PH gateway. - FM
+* Tweaks of wait() versus waitpid() handling for NeXT, aix4 and mips,
+ based on feedback from PN. - FM
+03-22-96
+* Tweaks of SLANG support for Unix, and finished up code support for it on
+ VMS (but tested only with OpenVMS/AXP). Haven't yet decided how to add
+ VMS build support for it in the COM and MMS files. Get the SLANG library
+ code from ftp://space.mit.edu/pub/davis and then add USE_SLANG in the
+ DEFINE list and the path to it's headers in the INCLUDE list for the
+ compilation, and [path]slang.olb/lib in the link list immediately before
+ the OPT file. We still need the curses library in the OPT file, because
+ that's not just curses functions on VMS and we're using ones not replaced
+ by the SLANG library (Try it, you'll like it! 8-). - FM
+* Tweaks for NeXT, based on feedback from Paul Nevai
+ (nevai@ops.mps.ohio-state.edu). - FM
+03-20-96
+* Tweaks of code for sorting directory listings by date (take into account
+ the 6-month-old time versus year rule on Unix). - FM
+* Tweaks of memory management for HTList-based buffers (use internal
+ allocations, instead of the libwww macros). - FM
+* Added solaris2-slang to Makefile, and tweaks of the sun4 makes. - LWV
+03-19-96
+* Tweak of MAP handling so that the ordered lists are displayed exactly
+ in the order of the resolved AREA tags.
+03-18-96
+* Added SLANG support (for colorized Lynx) based on patches from JED.
+ The make support is for linux and sun4, but it should be portable to
+ other Unix flavors. I have it working on VMS, but the SLANG interrupt
+ and exit handlers are incompatible with the current ones for VMS in
+ Lynx (and with the VMS debugger), so I haven't yet included SLANG
+ support in build.com or the MMS files. - FM
+03-17-96
+* Tweaks of 'd'ownload menu handling on returns to it from a DOWNLOADER
+ action. - FM
+* Added various anti-crash protections and cleaner code from John E. Davis
+ (davis@space.mit.edu) for trimming trailing white space and finding
+ unescaped colons in LYReadCFG.c, and cleaned up and more fully commented
+ the functions and subfunctions in that and the LYMainLoop.c modules. - FM
+03-16-96
+* Fixed routine which sorts directory listings by date (based on 'o'ptions
+ menu setting) to do it accurately and in reverse chronological order. - FM
+03-15-96
+* Added code to create links for likely URLs in results returned by
+ the CSO/PH and finger gateways. Try:
+ gopher://ns.bradley.edu:105/2 or:
+ cso://ns.bradley.edu/ and search for David Henderson.
+ Also try:
+ gopher://cegt201.bradley.edu:79/0/w%20davidh or:
+ finger://cegt201.bradley.edu/w/davidh as URL.s - FM
+* Added LYK_INTERRUPT handling for the CSO/PH and finger gateways, and
+ made their memory management more efficient. - FM
+* Made the my_spawn() function in LYLocal.c more portable by using
+ waitpid() instead of wait(). - FM
+* Restored the Lynx2-3 behavior of seeking the current position and link
+ on return from 'e'dit. May be wrong if the file was modified, but it
+ might be in the right ball park, and nothing really bad will happen if
+ it's far off. - FM
+03-14-96
+* Added -reload switch for instructing Lynx to send "Pragma: no-cache" and
+ "Cache-Control: no-cache" headers when requesting the startfile from an
+ http server (doesn't apply to subsequent fetches, or to non-http startfile
+ URLs). - Peter Ekberg (peda@lysator.liu.se)
+* Put the correct LYMain.c, which declares no_change_exec_perms, in the zip
+ (second try, hope I really did 8-). - FM
+03-13-96
+* Yet more tweaks of the CSO/PH gateway. - FM
+* Yet more tweaks of the finger gateway. - FM
+03-12-96
+* Made the URL and command buffering in the finger gateway secure from stack
+ modifications, beautified the HTLoadFinger() and response() functions, and
+ added support for the following URL formats for sending a "", "/w",
+ "username", or "/w username" command to the finger server:
+ finger://host finger://@host
+ finger://host/ finger://@host/
+ finger://host/%2fw finger://@host/w
+ finger://host/w finger://host/w/
+ finger://host/username[@host] finger://username@host
+ finger://host/username[@host]/ finger://username@host/
+ finger://host/w/username[@host] finger://username@host/w
+ finger://host/%2fw%20username[@host] finger://host/username[@host]/w
+* Replaced the _tolower macro in the CSO/PH gateway with TOLOWER. - FM
+* Tweaks of DIRED_SUPPORT. Added NO_CHANGE_EXECUTE_PERMS compilation
+ symbol and change_exec_perms restrictions switch for restricting
+ changes of the eXecute permissions to directories, and not files,
+ when OK_PERMIT has been set. - Earl Fogel (fogel@duke.usask.ca) & FM
+* Added make support for Intergraph CLIX (note that some online help files
+ must be edited and renamed to meet this Unix flavor's 14 character file
+ name limit). - Alex Matulich (matuli_a@marlin.navsea.navy.mil)
+03-11-96
+* Added support for using finger://host/w/username to send "/w username"
+ to finger (port 79) servers. - FM
+* Tweaks of alignment handling to deal with (illegally) embedded CENTER
+ containers (typically due to omission of an end tag for the first
+ CENTER of the pair; ugh!). - FM
+03-10-96
+* Added form-based CSO/PH (port 105) gateway. Can be invoked via a
+ cso://host[:port]/ or gopher://host[:port]/2 URL. If the gopher
+ format is used and a query token is appended (?[query]), the old
+ ISINDEX-based gateway will be used. - FM
+03-07-96
+* Added NO_FROM_HEADER configuration symbol in lynx.cfg, and -nofrom
+ command line switch, for blocking all transmissions of From headers
+ by Lynx. - FM
+* Added NO_REFERER_HEADER configuration symbol in lynx.cfg, and -noreferer
+ command line switch, for blocking all transmissions of Referer headers
+ by Lynx. - FM
+* Enhancements of the 'o'ptions menu. - FM
+03-06-96
+* Restored the Lynx2-3 behavior of seeking the current document position
+ and link on (^R)eloads. Will be wrong if the document is actually a
+ changing script output, or SSI with changes in the sizes of inserts,
+ and any form entries will be lost with no warning about that if no
+ form links are in the currently displayed page (and there may be other
+ glitches I don't remember any more). However, it's correct, and more
+ convenient, most of the time, and nothing really bad will happen if
+ it's wrong. - FM
+03-05-96
+* Added SAVE_SPACE configuration symbol in lynx.cfg, and LYNX_SAVE_SPACE
+ environment variable (Unix) or logical (VMS) for setting a default path
+ prefix in suggested filenames in Save to Disk operations of the 'p'rint
+ and 'd'ownload menus. If not set, only a filename will be suggested,
+ for saving in the current default directory. See the INSTALLATION file
+ and lynx.cfg for more information. - FM
+03-02-96
+* If an IMG tag has both ISMAP and USEMAP attributes, create links for
+ both, and use the ALT string, if present, for the USEMAP link. The
+ server-side script might have a content-rich default set up for non-GUI
+ clients, so we may as well be able to try it, and still have our own
+ USEMAP listing available if it's a site unconcerned about text and
+ braille clients, or GUI clients with image loading turned off. - FM
+* Tweaks of MAP code to maximize efficiency of fetching and processing
+ MAPs from a different document. - FM
+* Make sure the traversal code doesn't get tripped up by any HREFs
+ which contain newline characters due to misparsing (e.g., because a
+ close-double-quote wasn't present where required, and soft_dquotes
+ wasn't toggled ON, or invalid comments were present, and mimimal or
+ historical comment parsing weren't toggled ON). - FM
+* Renamed LYK_RESUBMIT ('x' or 'X') to LYK_NOCACHE and modified it's code
+ so that it applies to normal links as well as form submit buttons. If
+ used instead of LYK_ACTIVATE, any HText cache from a previous submission
+ or request will be dumped, and the submission or request will be made
+ with the "Pragma: no-cache" and "Cache-Control: no-cache" headers
+ included, to ensure that a proxy/cache server also will not return a
+ cached copy (assuming it respects either of those headers). - FM
+03-01-96
+* Converted the client-side image MAP code to a protocol which returns
+ a stream, rather than using a temporary file. This allows saving
+ the link as a bookmark, for fetching the MAP and creating a listing
+ without need to fetch and render the original document. Also enabled
+ direct downloading of the MAP listing. - FM
+02-29-96
+* Added handling of client-side image MAPs. If both USEMAP and ISMAP
+ attributes are present, the client-side MAP is used instead of the
+ the server-side script. The MAPs can be in the same or different
+ documents. The HREFs of the AREA tags are presented as a list,
+ with their ALTs (if present, otherwise their HREFs) as the link names
+ in the list. Added a TITLE attribute for MAPs, which will be ignored
+ by GUI clients, but if present will be used by Lynx as an H1 for the
+ list (MAP NAME="welcomemap" TITLE="Welcome Map"). Otherwise, the
+ IMG's ALT (if present, otherwise "[USEMAP]") will be used as an H1
+ in the list. The MAP's resolved URL also is shown in the list, since
+ the URL for the list is a temporary file. - FM
+02-25-96
+* Added a MINIMAL_COMMENTS configuration symbol, which if set TRUE in
+ lynx.cfg will emulate the Netscape v2.0 comment parsing bug of seeking
+ only a '-->' terminator, and not interpreting '--' pairs as serial
+ comments within the overall comment element. The compilation default
+ is FALSE, but we'll set it TRUE in lynx.cfg until Netscape gets its
+ comment parsing right, and "decorative" dashes in comment elements
+ cease to be so common in "Enhance for Netscape" pages. Also added
+ a '-minimal' command line switch for toggling the Mininal or Valid
+ configuration setting, and an LYK_MINIMAL command key toggle (mapped
+ by default to backquote). Note that setting Historical comments on
+ will override the Minimal or Valid setting (i.e., any '>' will be
+ treated as the terminator of a comment element). A statusline
+ message indicates whether Historical, Minimal or Valid comment
+ parsing has gone into effect when the LYK_MINIMAL or LYK_HISTORICAL
+ command key toggles are used (i.e., those two toggles in effect are
+ a "troggle"). - FM
+02-22-96
+* Tweak of HTList manipulations. - FM
+* Additions to the online help. - FM
+* Unescape any hex escaped username and/or password in ftp URLs. - FM
+02-20-96
+* Handle timeout disconnects of cached NNTP connections. - FM
+* Allow head or tail match specifications (e.g., comp.infosystems.*
+ or *.unix) in news, nntp and snews URLs (That's illegal, so don't
+ use it in public documents.). - FM
+* Tweak of bookmark handling. - Ismael Cordeiro (ismael@CAM.ORG)
+02-16-96
+* Tweak of the new code for setting a default CHECKED radio button. - FM
+02-15-96
+* Issue a sensible exit message if a non-http URL is used as the startfile
+ with -traversal. - FM
+* Tweaks of bookmark handling. - FM
+* Tweaks of Home_Dir() type casting. - FM
+02-14-96 Happy Valentine's Day!!!
+* Tweaks of charset conversions. - FM
+02-12-96
+* Made inclusion of Unix DIRED_SUPPORT the compilation default, and
+ its refinement easier to understand and set in the Makefile. - Will
+ Mengarini (seldon@eskimo.com) & FM
+* Changed (X) and ( ) to [X] and [ ] for indicating checked or unchecked
+ checkboxes. For radio buttons, we still use (*) and ( ). - FM
+02-11-96
+* Distinguish checkboxes from radio buttons in the Lynx display by using
+ (X) versus (*), respectively, when they are checked or selected. - FM
+* Make the first radio button in a series with the same NAME checked by
+ default if none of them had CHECKED specified. - FM
+02-09-96
+* Added LYK_HISTORICAL and LYK_SOFT_DQUOTES, mapped by default to the
+ the single- and double-quote keys, respectively, for toggling valid
+ versus "historical" comment parsing, and valid versus "old Mosaic-
+ and Netscape-like" double-quote parsing. - FM
+* Added SCRIPT to the DTD and code to ensure that bad comments in its
+ content don't generate garbage in the display. - FM
+* Added -DSVR4 to the make for solaris2. - KH
+* Use copy instead of rename in descrip.mms for putting lynx.exe in the
+ top directory, as in build.com. - FM
+* Added TITLE attribute to FORM, and code to use it for the Subject in
+ mailto ACTIONs. It's not in the spec, but better to offer it than
+ to settle into Netscape's ?subject=foo tack-on kludge which breaks
+ mailto for clients which haven't added code to cope with it. - FM
+02-08-96
+* Added -book switch for using the bookmark page as the startfile. The
+ default or command line startfile will still be set for the 'm'ain screen
+ command, and be used as the startfile if the bookmark page is unavailable
+ or blank. - FM
+* Fixed glitch for Unix in yesterday's LYMail.c mods. - FM
+* Try graceful alternatives if getenv("HOME") returns NULL. - Kenneth Herron
+ (kherron@campus.mci.net) & FM
+02-07-96
+* Added support for the ?subject=foo tack-on kludge to specify the Subject
+ in mailto ACTIONs and HREFs. - FM
+* Convert Explorer's semi-colon Internet address separators to commas
+ before acting on mailto address lists on Unix or VMS. - FM
+* Made EMBED empty again (the W3C container version has been replaced
+ by INSERT, and Netscape still has it empty). - FM
+02-06-96
+* Tweaks of descrip.mms files for VMS. - FM
+02-04-96
+* Fixed caching of news/nntp connections so that we access the correct host
+ when more than one has been specified. - FM
+02-03-96
+* Added ndash and mdash to the entities conversion tables. The W3C's
+ DTD specifies those, whereas the text descriptions say endash and
+ emdash, so we'll cover all the bases by supporting all four. - FM
+* Reduced the "en" metric for TAB to 2 per column. Was 12, to be
+ compatible with UdiWWW, but that's pixels. You can change the enval
+ initialization in HTML.c from 2 to 12 if you want the old behavior. - FM
+* Force use of DECC in build.com if that compiler is installed on VMS,
+ and make sure external logicals don't defeat a choice of DECC via
+ descrip.mms. - FM
+02-02-96
+* Mods to handle lone CRs as newlines when dislaying text/plain files
+ from MAC servers. Note that they'll stay CRs when downloading, or
+ fetching with -source, but be handled as newlines when the '\' source
+ toggle is used for text/html files and their source is displayed as
+ text/plain. - FM
+01-31-96
+* Added dummy initializers in LYCharSets.c and LYEditmap.c to ensure the
+ modules are linked if the external model is common block and they are
+ placed in a library. - FM
+01-30-96
+* For submissions of forms with a mailto ACTION, allow the user to edit
+ the default Subject string (the TITLE of the document containing the
+ form) via a statusline prompt, or to cancel the submission via Ctrl-G
+ at the prompt, analogously to 'c'omments or for anchors with a mailto
+ HREF. - FM
+01-29-96
+* Typo fixes in HTML.c, LYJump.c and LYGetFile.c. - PM
+01-28-96
+* Tweaks of redirection handling. - FM
+01-27-96
+* Support use of the TITLE attribute for setting the Subject in LINKs with
+ REV="made" or REV="owner" and a mailto HREF, equivalently to its use
+ with anchors in the BODY. - FM
+* Always use the parent document's URL for X-URL in mailto anchors, but
+ still use mailto:address if it was entered as a 'g'oto. - FM
+* Improvements of the code in LYMainLoop.c for checking the types of
+ links (first make sure that there are links to check 8-). - FM
+01-26-96
+* Made LYCharSets.c an object module instead of header for HTML.c, and
+ created LYCharUtils.c with character-related functions from HTML.c,
+ to reduce the size of HTML.c (got a report of memory exhaustion when
+ trying to compile HTML.c). - FM
+* Added BGSOUND to the DTD and code for creating a link to the source
+ when clickable_images is set. - FM
+01-24-96
+* Tweak of URL resolving when http servers return the obsolete file URL
+ format for what are actually ftp URLs (as DEC's servers are doing). - FM
+* Added LYE_LOWER and LYE_UPPER for lower or upper casing lines with the
+ line editor. Default bindings are Ctrl-K and Ctrl-T, respectively (not
+ "intuitive" but they're the only "safe" non-printing keys left 8-). - FM
+01-23-96
+* Yet more tweaks aimed at getting Lynx to compile across versions of
+ MultiNet through v3.5A and DECC through v5.2 or VAXC. Pat Rankin
+ is trying to cope with this mess for compilations with MultiNet and
+ his VMS port of GNUC (cross your fingers 8-). - FM
+* Updates of the help and about files. - FM
+* Tweak of sendmail path for BSDI. - Bennett Todd (bet@ritz.mordor.com)
+01-22-96
+* More tweaks for dealing with header conflicts in MultiNet v3.5A with
+ DECC v5.2. - FM
+* Tweak of our kludge to append a 0,0 coordinate pair for ISMAP URLs. - FM
+* Tweaks of base handling in HTML.c. - FM
+01-20-96
+* Mods for builds with NetBSD, or MultiNet v3.5A with DECC v5.2 (they
+ have conficting headers). FM & PR
+01-18-96
+* Improved and corrected the fatal error messages. - FM
+01-17-96
+* Added ability to set the NNTPSERVER environment variable via lynx.cfg if
+ it has not been set externally (analogously to the proxy variables). - FM
+* Tweaks of proxy handling. - FM
+* Modifed the "Accept-Language: " header handling so that is uses the
+ "perferred document lang(G)uage" string without any modifications.
+ This allows the user to specify a comma-separated string with quality
+ values included, exactly to his/her requirements. - FM
+01-16-96
+* Modified the traversal code so that it always outputs to an error file if
+ requests fail or unknown statuses are received from the http server. - FM
+* Added target "sun4-ncurses" to the Makefile. - Bennett E. Todd
+ (bet@nyc.fcmc.com)
+* Tweaks of "preferred document lan(G)uage" and "preferred document c(H)arset"
+ 'o'ptions handling. Send only the preferrence or comma-separated list of
+ preferrences in the "Accept-Language: " and "Accept-Charset: " headers.
+ Append ", en" if "en" isn't present, and ", ISO-8859-1" and/or ", US-ASCII"
+ if those aren't present, rather than relying on servers to honor defaults,
+ but still don't send an "Accept-Charset: " header at all if no preference
+ has been specified by the user. - FM
+* Fixed typos in the about and help files. - FM
+01-15-96
+* Tweaks of bold and underline setting in split_line() of GritText.c. - FM
+* Fixed handling of FORM start tags with no ACTION specified. - FM
+* Tweaks of "IBM PC character set" and added "IBM PC codepage 850"
+ (ISO8859-1, see IBMPC-charsets.announce). - Mike Brown (mike@hyperreal.com)
+* Check in userdefs.h whether LYNX_CGF_FILE has been defined via the
+ Makefile, build.com or descrip.mms. - PG
+* Created CHANGES2-3 with changes through release of Lynx2-3 on 04-19-94,
+ and CHANGES2-4 with subsequent changes through the rename of lynx2-3-FM
+ to Lynx2-4 and its release on 06-18-95, and deleted those sections from
+ this file. - FM
+* Added the new Copyright and links to it in about_lynx.html. - FM
+01-11-96
+* Tweaks of HTWAIS.c for compatibility across versions of FreeWAIS. - FM
+* Unescape any hex escaped percents in mailto URLs and ACTIONs. - FM
+01-10-96
+* Added an LYCheckForProxyURL() function, and a PROXY_URL_TYPE return value
+ for is_url(), so that Lynx can proxy URLs with an unknown scheme if a
+ proxy for the scheme has been set, e.g., if "foo_proxy" has been set
+ to "http://host/", then "foo:blah", where "blah" may or may not begin
+ with a slash, will be handled as "http://host/foo:blah". Components of
+ "blah" will be checked versus "no_proxy", if set, but since we don't
+ know the default port for scheme "foo", the checks for any ports
+ associated with the no_proxy values may not be reliable (but if we
+ don't proxy, nor know the scheme, nor find "foo:blah" as a local file,
+ the URL would fail, anyway) - FM
+* Fixed typo in VMSPrint.com. - Paul Farnham (farnham@pasco.wednet.edu)
+01-06-96
+* Tweak of traversal code. - FM
+01-04-96
+* Tweak of dynamic SOCKS mods. - TZ
+01-03-96
+* Added circular recall buffers for JUMP shortcuts. If multiple jumps
+ files are installed, each has it's own recall buffer. If Lynx was built
+ with PERMIT_GOTO_FROM_JUMP defined, any random URLs accessed via the JUMP
+ command are placed in the goto circular buffer, not that for shortcuts,
+ and a JUMP entry of the single character ':' for the target is treated
+ as a command to invoke the circular buffer of previously resolved goto
+ URLs (as if 'g'oto followed by Up-Arrow were used). - FM
+* Added GOTOBUFFER, homologous to JUMPBUFFER, for specifying via userdefs.h
+ and/or lynx.cfg whether to offer the previous goto URL, if any, for
+ reuse or editing whenever the 'g'oto command is entered, or simply rely
+ on invoking the circular buffer via the Up-Arrow and Down-Arrow keys for
+ accessing previously resolved goto URLs. - FM
+* Tweak of 'g'oto recall buffering loop in LYMainLoop.c. - AH
+01-02-96
+* Added circular recall buffering for 'g'oto URLs. Is invoked (if previous
+ URLs have been entered) via Up-Arrow or Down-Arrow after entering the
+ 'g'oto command. - FM
+* Added circular recall buffering for WHEREIS queries. Buffer is shared with
+ that for ISINDEX queries, and invoked via Up-Arrow or Down-Arrow following
+ the WHEREIS ('/') command. The 'n'ext command still uses the last WHEREIS
+ query, not necessarily the last entry in the recall buffer, which might
+ have been entered via a 's'earch command for an ISINDEX document. - FM
+* Extended treatment of FORMs which have only one INPUT (TYPE="text") field
+ for user entries as SUBMITting on press of RETURN in that field, so that
+ this behavior is retained if INPUT TYPE="hidden" fields are present. - FM
+* Tweaks of bookmark deletion sanity checks. - DT
+01-01-96 (Happy New Year!!!!)
+* Added circular recall buffer for ISINDEX queries. Up-Arrow will cylce
+ you from the most current query in the list to previous ones, and roll
+ from the oldest to the most current. Down-Arrow will cycle from the
+ oldest query to subsequent ones, and roll from the most current to the
+ oldest. If a previous query is reused, it is removed from the recall
+ buffer and reinserted as the most current.- FM
+* Plugged memory leaks in LYUtils.c and LYJump.c. - FM
+12-30-95
+* Added LOCALHOST_ALIAS symbols for lynx.cfg which can be set to local
+ host aliases or to trusted hosts at other sites which will be accepted
+ as "local" when the -localhost switch is set. - FM
+* Added the endash and emdash entities. - FM
+12-29-95
+* Use exit(0) versus exit(-1) more consistently for normal versus abnormal
+ exits, respectively. - FM
+12-26-95
+* Tweak of RELOAD handling for lynxcgi URLs. - FM
+* More anti-crash protections for bad HTML. - FM
+* Tweak of dynamic SOCKS mods. - TZ
+12-23-95
+* Tweaks of directory building on VMS. - FM
+* Tweaks of log file declarations for direct wais builds. - FM
+* Tweak of DIRED_SUPPORT mods so that non-TAG entries don't show up when
+ there are tagged files. - DT
+12-22-95
+* Added HTMake_VMS_name() to HTFTP.c for use by Unix as well as VMS with
+ VMS ftp servers. - FM
+* Added INSERT and ALIAS to the DTD, updated PARAM and OVERLAY, and made
+ FIG a paragraphing block, all as described in the 12-21-95 W3C working
+ draft for INSERT. In contrast to FIG, the INSERT and "heritage" EMBED
+ and APPLET elements invoke paragraphing only if their content displayed
+ by Lynx dictates it. The rules for resolving the sources for INSERTs or
+ for handling its ISMAP attribute are extremely complicated, and are not
+ implemented. Let's wait to see how people in the "real world" try to
+ make sense of them and actually use INSERT (if they do 8-). We still
+ create source links in "clickable_image" mode for the "heritage" versions
+ of FIG, OVERLAY, EMBED and APPLET markup, and send a 0,0 cooridinate pair
+ for IMG with the ISMAP attribute. See comments in HTML.c - FM
+12-21-95
+* Fixed bug in yesterday's ftp password-handling mods that could cause a
+ crash, and handle ftp://user:@host/path as specified in RFC 1738. - FM
+* Added protection against crashes for SELECT tags without the (required)
+ NAME attribute. - FM
+* Added code in HTFTP.c for recognizing MS Windows (Chameleon NEWT) servers
+ and parsing their LIST output (tested on ftp://emoryi.jpl.nasa.gov/) - FM
+* Another typo fix for VMS GNUC in HTFinger.c. - FM
+* Modified HTFTP.c to use personal_mail_address, if available, for the
+ password with anoymous FTP. It will still use "user@" (trim off the
+ host) if the host does not contain a dot and thus could not be a fully
+ qualified domain name, so it will work with Unix servers such as
+ ftp.uu.net (see get_connection() in HTFTP.c), but this will cause it
+ to fail with MS Windows servers. - FM
+* Added lots more info to the trace output for the ftp gateway. - FM
+12-20-95
+* Modified HTFTP.c to handle a hex escaped slash (%2F) following the
+ "punctuation" slash according to the strict provisions of RFC 1738
+ when connected to VMS ftp servers, so that a device can be in the
+ path and not be mishandled as a subdirectory, e.g., the URL
+ ftp://user:password@host/%2Fsys$common/syshlp
+ will create a directory listing for sys$common:[syshlp]. - FM
+* Fixed typo for VMS GNUC in HTFinger.c. - FM
+12-19-95
+* Enhancements of Unix DIRED_SUPPORT (see header of LYLocal.c). - DT
+12-18-95
+* Tweaks of element and entity structure alignments. - FM
+12-17-95
+* Tweaks of APPLET CODEBASE attribute resolving. - FM
+* Added support for a -nosocks command line switch to turn off SOCKS proxy
+ usage if Lynx was SOCKSified. - Thomas Zerucha (tz@execpc.com)
+12-16-95
+* Added the APPLET element and attributes to the DTD, and code for
+ creating links to the Applet code via image_links - FM
+* Added code to handle password fields in telnet URLs. - FM
+* Expanded EMBED as an "attribute soup" (for compatibility with
+ old versions of Netscape). - FM
+12-15-95
+* Added PARAM, and its attributes in the W3C draft for EMBED, to the DTD,
+ and code in HTML.c to minimize the possiblity of an INPUT belonging to
+ an EMBED being misassociated with a standard FORM container. - FM
+* Added "first pass" EMBED handling. Should be OK with both the W3C
+ container version and the Netscape "attribute soup" version (we'll
+ see 8-). The clickable_image switch and toggle ('*') are now misnomers.
+ They will cause creation of links to the EMBED SRCs whether they are
+ images or not. - FM
+* Enhancements of Unix uploading (see header of LYUpload.c). - GL
+12-14-95
+* Modified LYUnEscapeEntities() and LYExpandString() in HTML.c to make
+ it more likely that they'll be handled correctly across flavors of
+ compilers. - FM
+* Changed NETSCAPE_QUOTES and -netscape_quotes to SOFT_DQUOTES and
+ -soft_dquotes. - FM
+* Added '&' to the exclusion list for VMS suggested file names. - FM
+12-13-95
+* Added CAN_ANONYMOUS_GOTO_TELNET_PORT symbol which if set TRUE in
+ userdefs.h will allow anonymous users to specify a port in 'g'oto
+ commands for telnet URLs. - FM
+* Added NETSCAPE_QUOTES symbol which if set TRUE in lynx.cfg will cause
+ Lynx to emulate the Netscape bug of treating '>' as a co-terminator
+ of a double-quoted attribute value and the tag which contains it. - FM
+* Forgot to define FORM_LINK_RESUBMIT_MESSAGE in the distribution's
+ userdefs.h for yesterday's mods. - FM
+* Forgot to put the HTFile.c with the LIST_FORMAT mods into the
+ distribution (maybe I should just concentrate on Christmas 8-). - FM
+12-12-95
+* Changed handling of the no-cache META directive so that it applies to
+ the document which contains the META tag, rather than to any form submit
+ buttons within it. The form's CGI script should return a stream which
+ contains the directive to force resubmissions, and any (e.g., ISINDEX)
+ script or (e.g., foo.shtml) document can include the directive to
+ force reloading by Lynx. - FM
+* Added ALWAYS_RESUBMIT_FORMS symbol in userdefs.h and lynx.cfg for setting
+ forced resubmissions of forms, and a -resubmit_forms command line switch
+ for toggling the default. - FM
+12-11-95
+* Moved values of LYStrings.h function key definitions from 0x80 - 0x8D to
+ 0x100 - 0x10D and modified all the structures and functions in LYKeymap.c
+ and LYEditmap.c accordingly. - FM
+* Added the KOI8-R (Russian) character set. - Andrey A. Chernov
+ (ache@astral.msk.su).
+* Replace gets() with fgets() for the Unix setup() in LYCurses.c - AAC
+* Tweaks for building with FreeBSD. - AAC & FM
+* Added handling of META directives for ISO-8859-2 and KOI8-R if the
+ document is text/html and a server header didn't already set the
+ charset. - AAC & FM
+12-10-95
+* Tweaks of memory management. - FM
+* Made the LONG_LIST parameters for Unix local directory listings
+ configurable via userdefs.h and lynx.cfg - DT
+12-09-95
+* Added code for re-computing and retaining the current link if it is still
+ on the page when using the LYK_UP_TWO and LYK_DOWN_TWO commands. - FM
+* Added support for nested emphasis tags (they're all still displayed as
+ HT_UNDERLINE, but no longer terminated prematurely). - FM
+12-08-95
+* Added more suffix maps in HTInit.c. - FM
+* Tweak of META attribute definitions. - FM
+12-06-95
+* Don't reject LYNXKEYMAP and lynxcgi URLs with the -localhost switch. - FM
+12-05-95
+* Made the loaded_texts list in GridText.c functionally "circular", so
+ that returning to a cached document causes it to be treated as the most
+ current, and dumps of cache, when necessary to load a new document, are
+ done for the least recently viewed rather than least recently fetched
+ document. - FM
+* Show the METHOD and ACTION in showinfo() of LYShowInfo.c if invoked when
+ the cursor is positioned on a submit button. - FM
+* If the user mode is advanced, keep showing the URL in the statusline
+ when Lynx is in forms mode but the link is not a form field. - FM
+12-03-95
+* Tweaks of code for submissions of forms with only a single INPUT
+ (TYPE="text") field. - FM
+12-02-95
+* Treat any META directives with a NAME or HTTP-EQUIV value of "Pragma"
+ or "Cache-Control" and a CONTROL value of "no-cache" as an instruction
+ always to resubmit any form(s) in the document. - FM
+* Added parsing of META directives. Functions can be added where indicated
+ in HTML.c. - FM
+* Include the HTTP/1.1 "Cache-Control: no-cache" header together with the
+ HTTP/1.0 "Pragma: no-cache" header for reload or resubmit requests. - FM
+* Fixed bug in the check for an all-space ALT in IMG when creating a
+ link for its SRC. - FM
+* Fixed parsing of square-bracketted DOCTYPE fields. - FM
+12-01-95
+* Improvments of logic for indentations within lists. - FM
+11-30-95
+* For resiliency, treat upper case letters as equivalent to lower case in
+ scheme names (e.g., allow "HTTP" as well as "http"), by converting them
+ to the appropriate case before entering them into the anchor hash table
+ or otherwise acting on them. - FM
+* Added ability to change the default reply to the "really quit" prompt
+ from "[Y]" to "[N]" via a compilation symbol in userdefs.h. - DT
+11-29-95
+* Added ALIGN attribute for HR (default is "center"). - FM
+11-28-95
+* If a form has a single field, and it's INPUT TYPE="text", treat
+ RETURN as a submit command for it. - FM
+* Added START as a synonym for the SEQNUM attribute in OL. - FM
+11-27-95
+* Enhancements of the wais gateway. - FM
+11-26-95
+* Fixed up HREF, ACTION and SRC resolving to be conformant with RFC 1808
+ (except that we don't yet support a ";params" field). - FM
+11-25-95
+* Tweaks of yesterday's jumps file mods. - FM
+11-24-95
+* Enhancements of 'J'umps file handling, including ability to install
+ multiple jumps files mapped to different keys and associated with
+ different statusline prompts and recall buffers. - DT & FM
+* Deal with ALTs that have only spaces when in clickable_image mode. - FM
+* Worked in WM's mods to make the REVERSE_CLEAR_SCREEN_PROBLEM workaround
+ a configuration option via ENABLE_SCROLLBACK in lynx.cfg and a command
+ line toggle (-enable_scrollback), for use with comm programs which have
+ screen display buffers that can be accessed for review independently
+ of the Lynx commands (see comments in lynx.cfg). - FM
+11-23-95
+* Use the BASE, if present, instead of the original document URL, as the
+ default ACTION for forms. - FM
+* Tweaks of paragraph alignment handling. - FM
+* Make sure we don't realloc() a NULL env pointer in LYCgi.c. - DT
+* Cancel bookmark deletion if the line does not have a complete link or if
+ there is more than one link on the line. - DT
+11-21-95
+* Fixed bad logic in the setting of bold and/or underline starting points
+ in new lines created via split_line() of GridText.c. - FM
+* Added case KEY_BACKSPACE in LYgetch() of LYStrings.c. - GL
+11-19-95
+* Fixed problem of SELECT causing all immediately following white space
+ to be ignored. - FM
+* More tweaks of paragraphing, and handling of labeled blocks within
+ PRE blocks. - FM
+11-18-95
+* Added INFOSECS, MESSAGESECS and ALERTSECS symbols in userdefs.h and
+ lynx.cfg for setting the durations of statusline pauses (important when
+ using Lynx with a braille-based access). See comments in userdefs.h and
+ lynx.cfg for more information. - FM
+* More tweaks of paragraph handling. - FM
+* Include the Reference lists is crawl output files if the -number_links
+ switch was included and the -nolist switch wasn't. - FM
+11-17-95
+* Tweaks of finger and telnet gateways. - FM
+* Added handling of MARQUEE equivalently to BANNER. - FM
+* Various tweaks of 8-bit character and related HTML handling (OLs
+ or ULs without attributes or some wrong combinations were crashing
+ Lynx). - FM
+11-16-95
+* Implemented the ID attribute for TAB, and the TO and INDENT attributes
+ when its ALIGN attribute is "left" (the default) and the style's
+ alignment is HT_LEFT (the default). If these conditions don't apply,
+ or if the TAB target is outside the current margins or would overlap
+ prior text, a collapsible space is inserted instead of TABing. The
+ INDENT values are in "en" units, treated as 12 per column. Added
+ tabtest.html in the test subdirectory to illustrate TABing. - FM
+11-15-95
+* Added the HTML 3.0 DTD structures and definitions for SPOT, and fully
+ implemented it (use SPOT ID="foo" as SGML_EMPTY instead of named anchors
+ with no content). - FM
+* Added the HTML 3.0 DTD structures and definitions for TAB. For now, it
+ simply puts a collapsible space in the text stream if the TO attribute
+ is present. - FM
+* Added the top-level HTML 3.0 DTD structures and definitions for MATH, and
+ implemented it's ID attribute. The markup is captured as HTML_LITTERAL,
+ and until we have a processor, is output as is, in brackets to alert the
+ user about the situation. - FM
+11-14-95
+* Tweaks of LYK_UP_LINK and LYK_DOWN_LINK handling, and added them to the
+ default mapping as '<' and '>'. - FM
+* Tweaks of LYK_TOOLBAR handling. - FM
+11-13-95
+* Added LYK_TOOLBAR (mapped by default to '#') for jumping up to the pseudo
+ Toolbar or Banner if present in the current document. Using '#' instead
+ of Home to jump there allows you to Left-Arrow back to where you were in
+ the current document. Set up a BANNER in about_lynx-dev.html to serve
+ as an example of this feature. - FM
+* Added the HTML 3.0 DTD structures and definitions for BANNER, implemented
+ its ID attribute, and set it up to act as a pseudo Toolbar if one hasn't
+ been set up already via REL attributes of LINKs. - FM
+* Tweaks of paragraphing for CAPTION, CREDIT, FOOTNOTE, and NOTE. - FM
+11-12-95
+* Handle (i.e., ignore) any P that immediately follows an LI, DT or DD. - FM
+* Cancel any file fetch and viewer spawn or launch during traverals. - FM
+11-11-95
+* Added finger gateway (finger://host[/request]) based on patches from
+ Martin Hamilton (martin@mrrl.lut.ac.uk). - FM
+* Added LYE_TAB for mapping keys to act as LYE_ENTER, but return '\t' so
+ that the behavior of TAB is emulated in TEXTAREAs, and mapped Do to
+ LYE_TAB in the default binding. - FM
+* Fixed glitch in handling of DEC extended characters which contain two
+ digits (affected Do and Find). - FM
+* Better documented that disabling access to hidden (dot) files also
+ disables ability to create such files via Lynx. - FM
+11-10-95
+* Added handling of mailto as a form ACTION. See http://www.q-d.com/swc.htm
+ for software to extract and unescape the mailed content. - FM
+* Added lynxprog URL handling, which is identical to lynxexec URL handling
+ except that the user is not prompted to enter RETURN before returning
+ to Lynx. Use lynxprog for scripts or programs such as mail which do not
+ need an enforced pause to let the user read the screen output. - FM
+* Removed code in HTFile.c for treating ',' as a synomym of '.' for
+ hidden files (nobody seems to know why that was being done 8-). - FM
+* Moved inclusions from LYBookmark to tcp.h. - FM
+11-08-95
+* Extend optional hidden (dot) file/directory support to Unix, and embellished
+ it on VMS and Unix with regulation via a command line switch and 'o'ptions
+ menu setting. See userdefs.h and lynx.cfg for more information. - GL & FM
+* Added support on Unix for straight tar files and a compile time option that
+ disables the ability to extract files from an archive file (since there is
+ no control over the files extracted). - GL
+11-07-95
+* More tweaks of 8-bit character handling. - FM
+* Added "Macintosh (8 bit)" character set. - Neil K. Guy
+ (nkg@freenet.vancouver.bc.ca)
+* Added "Example Lynx Optimized User Home Page" to the online 'h'elp. - FM
+11-05-95
+* Fixed Cc: header handling for email on Unix. - FM
+11-04-95
+* Reference the current character set for any raw 8-bit characters in
+ text/plain streams (but don't translate named or decimal escaped
+ entities, since that's specific for text/html). - FM
+* Block any illegal control or escape characters in text/plain streams,
+ to avoid problems if a binary ftp or local file was mistyped and sent
+ to the screen as that Content-type. - FM
+* Eliminated mod in SGML.c which emulated Netscape's bug of treating '>'
+ as both a close-double-quote and close-tag (Netscape v2.0 fixed its
+ bug, so hopefully the bad HTML with it will go away. 8-). - FM
+11-02-95
+* Assume an ISO-8859-1 character set for all local files. If it's
+ actually ISO-8859-2 and the terminal is using that, set the Lynx
+ CharSet option to "ISO Latin 1" so that 8-bit characters will be
+ sent raw to the terminal. - FM
+* Added Martin Ramsch's iso8859-1.html to the test subdirectory.
+ Use it to complete the conversion tables in LYCharSets.c. - FM
+* Don't block insertion of a lead space for INPUTs in PRE blocks, so
+ alignments will be compatible with those of graphic clients. - FM
+* Don't block all access to the 'p'rint menu for the print restriction
+ (should still offer printer options which have the TRUE flag set;
+ all access is still blocked for -validate). - FM
+* Replaced the STDfoo_FILENO symbols in LYCgi.c with the more portable
+ fileno(stdfoo). - WM
+* Added NCURSESINCDIR compilation symbol for setting the path to the
+ NCURSES header file in LYCurses.h to that of the latest version. - GL
+* Tweaks of interrupt handling on VMS.
+10-31-95
+* Added more suffix maps in HTInit.c. - FM
+* Mods in LYCgi.c which hopefully makes the code more portable across
+ Unix flavors. - FM
+10-28-95
+* Tweaks of global flag initializations and resets in HTML.c. - FM
+* Added RESOLVLIB symbol in the top Makefile for including -lresolv
+ in the LIBS= list, if needed, for SUN 3 or 4 OS, and comments about
+ that in the Makefile, and INSTALLATION and PROBLEMS files based on an
+ explanation from Will Mengarini (seldon@eskimo.com). - FM
+10-27-95
+* Mods of top level Makefile: Added NOPORT compilation symbol for forcing
+ use of PASV in ftp URLs. Added NO_S_IFSOCK compilation symbol for Unix
+ flavors which lack an S_IFSOCK definition for lstat(). - FM
+* Reload the current document whenever the character set is changed. - FM
+* Don't reference entities for raw (or decimal escaped) 8-bit characters
+ if the document is not text/html, or for any local files if the charset
+ is Latin. - FM
+* Made Ctrl-H a synonym for DELETE instead of Left-Arrow in the line
+ editor. - FM
+10-25-95
+* Handle all characters in strings for the new line editor as unsigned
+ so they don't go negative if 8-bit. - DW
+* Restored proper handling of the MAXLENGTH attribute in INPUTs for
+ strings entered with the new line editor. - FM
+10-24-95
+* Deal with all non-printing characters when setting up the SELECT
+ pop-up window strings. - FM
+* Handle raw 8-bit characters via reference to the ISO-LATIN1 named
+ entities so they in turn can be referenced to the currently selected
+ character set. - FM
+* Yet more tweaks of non-breaking space handling. - FM
+10-22-95
+* Improved treatment of the startpage URL with -traversal so that it only
+ blocks traversals of links on other servers. Any links on the same
+ http server which shouldn't be traversed may be blocked via explicit
+ and/or wildcarded entries in REJECT.DAT. Updated CRAWL.announce to
+ make this more clear. - FM
+* Typo fixes in top-level Makefile. - Steve Jeske (jeske@pa.dec.com)
+10-21-95
+* Handle decimal escaped entities via reference to the ISO-LATIN1 named
+ entities so they in turn can be referenced to the currently selected
+ character set. - FM
+10-20-95
+* Tweaks of formatting for LONG_LIST directory lists and README file
+ inclusions in HTFile.c and HTVMSUtils.c. - FM
+* Tweaks of decimal escaped non-breaking space handling in HTML.c. - FM
+* Force unescaping of hidden VALUEs for INPUTs as ISO-LATIN1. - FM
+* Added ".shtml" and ".htmlx" as text/html extensions in HTInit.c. - FM
+10-18-95
+* Made parsing of the name and address out of the NNTP From: header more
+ reliable in HTNews.c. - FM
+* Added "LYNX_TEMP_SPACE" environment variable (Unix) or VMS logical,
+ which if present at run time will be used instead of the the TEMP_SPACE
+ definition in userdefs.h as the path prefix for temporary files. - FM
+10-17-95
+* Added TYPE attritute for OL, and coordinated it with the SEQNUM and
+ CONTINUE attributes. The default TYPE is "1" (Arabic numbers), and
+ SEQNUM values for it can range from -29997 to the system's maximum
+ integer. The Alphabetic TYPEs are "A" (upper case) and "a" (lower
+ case), and can range from 1 (" A." or " a.") to 18278 ("ZZZ." or
+ "zzz."). The Roman TYPES are "I" (upper case) and "i" (lower case),
+ and can range from 1 (" I." or " i.") to 3000 ("MMM." or "mmm.").
+ SEQNUM values should always be Arabic, and will be converted to
+ other types (e.g. SEQNUM="27" TYPE="a" will yield "aa." for the
+ next LI). The CONTINUE attribute will cause the sequence and TYPE
+ of the preceding OL to be continued for LIs in the current OL. - FM
+10-16-95
+* Treat a value of "*" for "no_proxy" as a global override of any
+ existing proxy variables. - FM
+10-15-95
+* Deal with raw or decimal escaped non-breaking space characters in
+ SGML_character() of SGML.c and LYUnEscapeEntities() of HTML.c. - FM
+10-14-95
+* Updated info about lynx-dev in lynx.man and lynx.hlp. - FM
+* Don't force LINKS_ARE_NUMBERED in dumps if -nolist was included. - FM
+* Output the References list for dumps with OL-style numbering. - FM
+* More tweaks of "anti-spoof" handling for telnet URLs. - FM
+10-13-95
+* Block direct access to the telnet prompt for telnet URLs entered without
+ a host field. - FM
+* Include the TRUSTED flag in spawns for OpenVMS/AXP v6.1 or greater. - FM
+10-12-95
+* Convert any strings in news articles that look like URLs into links. - FM
+* Use the Followup header in news articles, if present, for followups.
+ Otherwise, use the Newsgroups header. - FM
+* Ignore any invalid ISO 646 7-bit control characters or ISO 8859 8-bit
+ control characters in SGML_character() of SGML.c. - FM
+10-11-95
+* Typo fix in HTTCP.c for non-MULTINET VMS builds. - Gary Chow (garyc@mrs.com)
+10-09-95
+* Assume the root as path in HTParse() of HTParse.c if the access and host
+ but no path are given, and the access is http, https, or ftp. - FM
+10-05-95
+* Make sure the FREE(x) macro gets defined for HTTCP.c. - FM
+10-04-95
+* Mods in HTTCP.c to prevent string buffer overruns. - FM
+* Prevent possible string buffer underrun for terminal white space trims
+ in GridText.c. - Renato Buda (renato@peoplebank.co.uk)
+10-01-95
+* Updated the listserv and archive addresses in the about and help files. - FM
+09-30-95
+* Added support for Windows_NT FTP servers. - FM
+* Added ability to send a self copy of mail via a Cc: header on Unix
+ (sending of self copies is set via the mail software itself on VMS). - FM
+* Tweaks of SOCKET_ERRNO handling in HTTCP.C. - FM
+* Include unistd.h more consistently on Unix (via tcp.h) if NO_UNISTD_H
+ is not defined. - FM
+* Modified the FreeBSD and NetBSD libwww Makefiles to use the
+ CommonMakefile. - FM
+* Makefile addition (snake3) for the HP-UX purchased compiler. - Andy
+ Finkenstadt (genie@panix.com)
+09-29-95
+* Deal with HTAlert.c function calls to LYgetstr(), e.g., for a password,
+ when doing a -dump or -source non-interactive fetch. - FM
+* Output HTAlert() messages to both stderr and stdout in TRACE mode. - FM
+09-28-95
+* Added a description of the line editor's default key bindings to the
+ help file set. - FM
+* Tweaks of the line editor. - FM
+* Declare DCLspawn_exception() in LYCurses.c as unsigned int only for
+ DECC (otherwise as int, for VAXC and GNUC). - FM
+09-27-95
+* Added common line editor for forms and prompted queries, with configurable
+ line editor key bindings. See LYStrings.h and LYEditmap.c for the default
+ configuration. - DW & FM
+* Tweaks of build.com's symbol assignments when in batch mode. - MM
+09-22-95
+* Added ISO-8859-2 CharSet, and mods for Accept-Charsets handling based
+ on patches from Mark Martinec (Mark.Martinec@nsc.ijs.si). - FM
+09-19-95
+* Tweaks of OL attribute handling. Allow negative SEQNUM values. Keep
+ better track of CONTINUE versus non-CONTINUE OL sequences within nests.
+ Allow CONTINUE in the first OL of a new nest, set to the last LI count
+ of the previous nest (at any depth in that previous nest). - FM
+09-17-95
+* Tweak of LYUnEscapeEntities() in HTML.c. - DW & FM
+* Another tweak of groupid handling in LYShowInfo.c. - DW
+* More fixes of 7-bit character approximations. - DW
+* More help and about file tweaks. - DSL
+09-16-95
+* Added the HTML 3.0 DTD structures and definitions for DIV, and implemented
+ its ALIGN and ID attributes. I think I have it behaving rationally if it
+ is used together with CENTER, LEFT and/or RIGHT (Though they're all treated
+ as DIVs by Lynx, and shouldn't be embedded in each other, somebody will do
+ that anyway!. 8-). - FM
+* Added the HTML 3.0 DTD structures and definitions for FN (Footnote). It
+ should be handled as a popup window, but for now, it's implemented as a
+ labelled block and has the same style and behavior as a NOTE with an ID
+ attribute. - FM
+* Some compilers can't handle the continuation line in yesterday's
+ LYCurses.h. Made it one long line. - FM
+09-16-95
+* Further enhanced the online help and about files. - FM
+* Added -DNO_FILIO_H to Makefile for SCO. - FM
+* Worked in stuff from 14-Sep-95 lynx2-4-2 upgrade. - FM:
+--------------------------------------------------------
+ 09-06-95
+ * Added patch to compile Lynx on BSDI with Ncurses package. -RK
+ 09-06-95
+ * Ported Lynx to DG-UX. - RK
+--------------------------------------------------------
+09-12-95
+* Further modified HTNews.c so that it returns unmodified news messages
+ when the display is toggled to source ('\') or when downloading them,
+ so uuencoded messages always can be saved without corruption, and so
+ I also changed the SCAN_FOR_BURIED_NEWS_REFS compilation default to
+ TRUE. - FM
+* Simplified a compound if() in HTParse.c which may have been giving the
+ AIX v4.1 compiler a headache. - FM
+09-11-95
+* Eliminated distinct style sheets for CAPTION and CREDIT so their content
+ will inherit the current style, and added HTML_EnsureDoubleSpace() and
+ HTML_ResetParagraphAlignment() in HTML.c for coping with the absence of
+ distinct style sheets for those elements, and for FIG.
+09-10-95
+* Added SCAN_FOR_BURIED_NEWS_REFS configuration symbol in lynx.cfg, with
+ a compilation default of FALSE, and a -buried_news switch for toggling
+ the default. When TRUE, Lynx scans the bodies of news articles for
+ references and converts them to news links, but creates false news
+ links if any email addresses are enclosed in angle brackets, and can
+ trash uuencoded messages. - FM
+* Eliminated distinct style sheet for FIG so its content will inherit the
+ current style and display appropriately within lists. Should be OK if
+ people use valid HTML 3.0 in it's content for non-graphic clients. - FM
+* Added links for the W3C HTML 2.0 and 3.0 specifications and for the
+ HAL HTML validation service to the Lynx help file set.
+* Made the BOLD_NAME_ANCHORS compilation symbols FALSE by default. Most
+ documents now include emphasis tags for NAME (ID) anchors if it's desired,
+ because the most common graphic clients don't emphasize them by default,
+ so we should adjust to that in Lynx as well (IMHO 8-). Added emphasis
+ tags for the NAME anchors in the Lynx help files. - FM
+* Eliminated forced uppercasing of H1 headers. Most documents have mixed
+ casing and we should preserve it (IMHO 8-). Added a BOLD_H1 configuration
+ symbol, set FALSE by default, for making H1 headers bold even if BOLD_HEADERS
+ is FALSE. Modify the two configuration symbols in lynx.cfg for the pattern
+ or header emphasis which pleases you. - FM
+* Tweak of list paragraphing. Added HText_PeviousLineSize() in GridText.c
+ for determining if the previous line had only non-printing characters. - FM
+09-09-95
+* Impelemented true paragraphing and the P ALIGN attribute within lists (UL,
+ OL and DL blocks) and within ADDRESS blocks. Paragraphs within lists have
+ one blank line inserted. Within ADDRESS blocks, a newline will be created
+ if needed, but no blank lines are inserted. Use BR, not P, to force extra
+ newlines within blocks. Do not place a P immediately following the LI or
+ DD tags. Alignments of P blocks are done with respect to the "second line"
+ margins of LI or DD elements. - FM
+09-08-95
+* Convert '~' to getenv("HOME") in file URLs whether or not DIRED_SUPPORT
+ is defined. - FM
+* Tweak of TR and more tweaks of HR handling. Added HText_LastLineSize()
+ and HText_TrueLineSize() functions in GridText.c for determining if
+ lines have only non-printing characters in decisions on whether to
+ insert additional newlines. - FM
+09-07-95
+* Act on Page-Up, Page-Down, Home, End, Find and Select in the form_getstr()
+ editor (hoping they have their default mappings 8-). Also act on Remove
+ and Control-D as delete keys in that line editor (as in the LYgetstr()
+ line editor). - FM
+* Tweak of HR handling. - FM
+* Mods to prevent creating multiple copies of temporary printer files. - FM
+* More fixes for NeXT. Temporary files for VIEWER, DOWNLOADER or PRINTER
+ commands on NeXT all have the ".html" default suffix replaced with ones
+ indicative of the Content-type. - FM
+09-06-95
+* Mods to prevent creating multiple copies of temporary viewer or downloader
+ files. - FM
+* Fixes for NeXT. - FM
+09-05-95
+* Enabled the -help switch when no configuration file is available and
+ Lynx would otherwise exit (i.e., it now outputs the help message before
+ it exits). - FM
+* Documented the -child switch. - FM
+* Fixed and documented the -nolog switch. - FM
+* Changed the -linknums switch to -number_links, fixed the code to work,
+ and documented the switch. - FM
+* Made handling of escaped colons (\:) in VIEWER commands reliable. - FM
+09-04-95
+* Implemented the PLAIN attribute for UL, and the SEQNUM and CONTINUE
+ attributes for OL. - FM
+* Updated the DTD structures and definitions for DD, DL, DT, LI, OL and UL
+ to HTML 3.0, added LH, and implemented full HTML 3.0 ID handling for those,
+ and B, BLINK, BR, CENTER, CITE, CODE, DFN, DIR, EM, FORM, KBD, I, LEFT,
+ LISTING, MENU, PLAINTEXT, PRE, RIGHT, SAMP, STRONG, TT, U, VAR and XMP
+ (some of which are obsoleted in HTML 3.0, but what the heck 8-). - FM
+09-03-95
+* Made bolding of NAME (ID) anchor contents configurable in lynx.cfg. - FM
+09-02-95
+* Tweaks of FIG and OVERLAY handling: Only put up [FIGURE] (and +[OVERLAY])
+ links if clickable_images is set. Assume P ALIGN="left" if contained
+ text does not begin with an explicit tag that sets an alignment. - FM
+* Implemented full HTML 3.0 ID handling for IMG. - FM
+* Tweaks for FreeBSD. - Masafumi NAKANE (t94303mn@sfc.keio.ac.jp)
+08-31-95
+* Added support for using a TITLE attribute as the subject in anchors with a
+ mailto HREF (A HREF="mailto:address" TITLE="RE: subject"). - FM
+08-30-95
+* Implemented full HTML 3.0 ID handling for A, ADDRESS, BLOCKQUOTE, BQ,
+ CAPTION, CREDIT, FIG, H1 - H6, HR, INPUT, NOTE, OPTION, P, SELECT, TABLE,
+ TD, TEXTAREA, TH and TR. - FM
+* Updated the DTD structures and definitions for ADDRESS to HTML 3.0. - FM
+* Block insertion of any escape sequence characters or substitutes when
+ editing form INPUTs or TEXTAREAs. - FM
+08-29-95
+* Tweak of ALIGN attribute handling in paragraphs. - FM
+* Protect against hanging on escape sequences if received (illegally) in
+ documents typed as text/plain or text/html. - FM
+08-28-95
+* Declared DCLspawn_exception() as an unsigned int to keep DECC happy. - FM
+08-27-95
+* Give LYUpload() a return value (because LYLocal.c has been testing for
+ one all these years 8-). - FM
+* Force reload on return from 'o'ptions menu if HTfileSortMethod or
+ keypad_mode are changed. - FM
+* Force no cache of keymap display whenever vi_keys or emacs_keys are
+ changed. - FM
+* Added Remove and Control-D as Delete synonyms for removing characters to
+ the left of the cursor in the LYgetstr() line editor, and Control-F as
+ Right-arrow synonym for moving the cursor to the right. - FM
+08-24-95
+* Modified prompted string editing via LYgetstr() along lines in patch
+ from PM (editing of form INPUT and TEXTAREA strings is unchanged).
+ Here's how the prompted string editing works: Left-arrow and Backspace
+ (Control-H) move the cursor to the left, and Right-arrow to the right,
+ within the string. Characters are INSERTed at the cursor position.
+ Delete removes characters to the left of the cursor. Home, Find and
+ Control-A move the cursor to the beginning of the string. End, Select
+ and Control-E move the cursor to the end. Control-U erases the string.
+ Control-G cancels at any time. Return accepts if a string is present,
+ or cancels if it was fully erased or never entered. A right-curley
+ brace appears in the right-most column when the string has segment(s)
+ scrolled off screen, and if left scrolled, the cursor sits on it for
+ further editing with the above command keys (or acceptance via Return).
+ Long strings scroll both left and right between the prompt string and
+ right-curley brace. Had to modify 17 files to make this line editor
+ crash safe (I hope people like it! 8-). - FM
+08-22-95
+* Use a macro in parse_arg() of LYMain.c to ensure proper handling of
+ switches which take a value and might have a space instead of an '='
+ between the name and value. - DW
+* Insulate any system RTL's getline() from the one in HTInit.c. - DW
+* Enabled editing of titles when adding bookmarks. - FM
+08-21-95
+* Fixed the IBM PC character set in LYCharSets.c (Note: The PC-set has the
+ currency symbol but it is a control character - ^O - so there is a chance
+ that curses or the user's terminal may discard it. Did not fix the
+ Icelandic characters). - DW
+* Check whether getpwuid() and getgrid() have returned NULL pointers in
+ LYShowInfo.c. - DW
+* Break up the too elaborate, compound assignment statements in LYList.c
+ so no compilers get tripped up by evaluation order effects. - DW
+* Worked in mods from DW to cope with CR, CRLF or LF all as EOL in HTML.c
+ and GridText.c (not sure if they take into account all of the consequences
+ of Lou's "big cheat" in GridText.c, but they appear to, so far). - FM
+* Explicitly preserve the Lynx bookmark file mode on Unix. - DSL
+08-20-95
+* More documentation and help updates. - FM
+08-19-95
+* Updated INSTALLATION and comments in userdefs.h and lynx.cfg. - FM
+* If save to disk was done via the download menu, and a VMS rename() attempt
+ succeeded so we don't spawn a COPY, we no longer can access the file via
+ the download menu, so pop in that situation. - FM
+* Worked in stuff from 16-Aug-95 lynx2-4-2 upgrade. Most had already been
+ added to lynx2-4-FM. This is the new stuff. - FM:
+---------------------------------------------------
+ 08-16-95
+ * Applied patch from Peter van Heusden (pch@ucthpx.uct.ac.za) to fix
+ a bug when lynx encounters an OPTION tag before the style is
+ ever updated. - CL
+ 08-09-95
+ * Added some tweaks to Makefile and LYCurses.h to get lynx to properly
+ compile on ISC. Thanks to Robert Salter (salter1@master.nsbf.nasa.gov).
+---------------------------------------------------
+08-18-95
+* Added a -validate switch for turning off everything except http URLs,
+ helpfiles, and secure menus in Lynx. Can be used with -dump in CGI
+ scripts, but is intended for use with anonymous telnet logins. In the
+ latter case, the user can start with his/her server's or userdir homepage,
+ and validate everything, while able to manipulate the display features
+ (e.g., whether or not links are numbered) and turn on trace (Control-T,
+ then Control-R to reload) when a "Bad HTML" document is encountered. The
+ telnet approach is particularly useful when used with the 'l'ist feature.
+ When used with -dump, compare it with versus without -nolist. - FM
+* Added a missing curley brace in EF's (08-16-95) patches. - FM
+08-17-95
+* Added HISTORICAL_COMMENTS symbol which if set TRUE in lynx.cfg will cause
+ Lynx to revert to the "historical" behavior of treating any '>' as a
+ comment terminator instead of (a valid) '-->', and a -historical switch
+ for toggling the default behavior. - FM
+* Added a -nolist switch for turning off the link list feature in dumps. - FM
+* Modified SGML.c so that it still substitutes the expected end tag if a
+ different one is encountered (e.g, due to a document having interdigitated
+ instead of validly embedded tags), but doesn't do a wind down of the
+ element stack. This gives it a better chance of recovering from bad
+ HTML, and the sanity checks I've added thus far in HTML.c appear to still
+ be adequate for avoiding crashes (we'll see 8-). - FM
+08-16-95
+* Mods to support within-document anchors in documents returned via
+ lynxcgi scripts. - FM
+* Worked in EF's patches to handle changes of keymaps under DIRED_SUPPORT
+ with OK_OVERRIDE, and to give the user some feedback during an Install
+ command. - FM
+08-15-95
+* Don't include a Referer header for 'g'oto URLs. - FM
+* Added patches from PR for compilations with VMS port of GNUC: Modified
+ several prototypes to avoid GNUC warnings about conflicts with ones in
+ lib$routines.h, and added code in HTVMS_WaisUI.c to deal with an obscure
+ glitch for GNUC v2.6.[123] and v2.7.0 (not present in v2.6.0 or earlier,
+ and fixed in v2.7.1). - FM
+* Worked in code from PR as LYVMS_FixedLengthRecords() in HTFWriter.c to
+ change attributes of binary files on VMS from Stream_LF to FIXED 512,
+ no implied carriage control, best try contiguous. Replaces the spawn
+ to execute FIXED512.COM. - FM
+08-14-95
+* Modified TEXTAREA handling to succeed or fail on bad HTML equivalently
+ to Netscape. - FM
+08-12-95
+* Mods to avoid crashes and to do something reasonable with OPTION strings
+ that are wider than the available popup window width. Truncation is
+ indicated by omission of a terminating ']' in the window link, and the
+ window, when popped up, is made equal to the screen width (but we can't
+ wrap the strings within the window, so they're truncated if they still
+ don't fit). - FM
+* Mods to handle INPUT fields that are packaged in PRE and would extend past
+ the wrap column. No way to make that perfect without a major redesign,
+ but it's better now. - FM
+08-10-95
+* Handle 'g'oto entries equivalently to STARTFILE and HOMEPAGE, i.e., if
+ the user's entry isn't a URL, convert it to a file URL if it's a file
+ or directory on the local system, otherwise convert it to an http URL.
+ For example, "~/" will be converted to a file URL for listing the HOME
+ directory (on both Unix and VMS), and "www.netscape.com" will become
+ "http://www.netscape.com". - FM
+* Fix LYCurses.h to deal with definitions of TRUE and FALSE in cursesX.h
+ on ultrix. - Brian Exelbierd (bex@ncsu.edu)
+* Made SYSTEM_MAIL, and MAIL_ADRS on VMS, configurable in lynx.cfg. - FM
+08-08-95
+* Fixed two initialization problems that could account for reports of
+ inappropriate HEAD requests in pops of cached documents. - FM
+* More tweaks for coping with bad HTML. - FM
+* Fixed bug in code for bypassing bad SUFFIX: or VIEWER: entries. - FM
+08-06-95
+* Added code in GridText.c to deal with syntactically OK but symantically
+ nonsensical uses of ALT="" in IMG tags (i.e., when the IMG is structured
+ to provide the anchor for a link, and so the anchor ends up with nothing
+ but nonprinting characters for bolding), and removed the forcing of an
+ "[ISMAP]" pseudo-ALT in HTML.c. The show_anchor element in TextAnchor
+ structures is now set to NO whenever an anchor does not have any
+ printing characters. - FM
+* Modified HTML.c to issue only one "Bad HTML" statusline message per
+ document (unless it's one of those unbelievably bad CGI script outputs
+ that are functionally multiple, concatenated documents 8-), and similarly
+ for "Table in Form" and "Form in Table" informational messages. - FM
+* Don't bother prompting whether to send a HEAD request for the current
+ document if there are no links on the page (but still prompt if the user
+ makes a HEAD request when positioned on an inappropriate form link). - FM
+08-05-95
+* Added code in SGML.c for storing Identfiers (e.g., !DOCTYPE) and Comments
+ (i.e., tags beginning with !--) and for reporting them in trace mode.
+ Serves as a model for actually using them someday (i.e, functions for
+ analyzing them could be called where we presently just invoke a trace
+ output to stderr). - FM
+08-03-95
+* Modified SGML.c to handle comments as in the current specs, and put
+ Paul Gilmartin's (pg@sweng.stortek.com) TestComment.html in the
+ test subdirectory. - FM
+* Added binary extensions in HTInit.c that were giving people problems
+ on FTP servers. - FM
+08-02-95
+* Added explicit check for CMU in telnet support with SOCKETSHR-built
+ images. - SB
+* Added -link switch for setting the count in lnk#.dat files with -crawl
+ (needed if you interrupt a traversal and want to pick up again where
+ you left off). - DM
+* More tweaks of -traversal code and Makefile. All known bugs appear to
+ have been dealt with at this point. Updated lynx.man, lynx.hlp and
+ help files to include the -traversal and -crawl switches. - FM
+08-01-95
+* Changed the SEQUENT compilation sympbol to PTX2 and added a ptx2 procedure
+ to the Makefile for Sequent Symmetry DYNIX/ptx v2, because more current
+ versions reportedly have solved the problems which the conditional
+ compilation attempted to address. - FM
+* Force in the "[ISMAP]" pseudo-ALT if someone uses ALT="" for an IMG tag
+ that has ISMAP specified. - FM
+* Tweaks of the -traversal code (still experimental). - DM & FM
+07-31-95
+* Worked in code from David Mathog (mathog@seqaxp.bio.caltech.edu) for
+ implementing the TRAVERSAL function from old versions of Lynx, but via
+ a command line switch (-traversal) instead of in a separately compiled
+ executable, and for a CRAWL function, invoked via a command line switch
+ (-crawl), which allows Lynx to be used as the front end for a Web Crawler.
+ See CRAWL.announce for more information. - FM
+* More tweaks of LYCurses.c and LYCgi.c for GNUC on VMS. - SB
+* More tweaks of src/Makefile. - DSL
+07-30-95
+* Tweaks of yesterday's Makefile and descrip.mms files. - FM
+07-29-95
+* Tweak in HTFTP.c to ensure that Lynx doesn't sit around waiting for an
+ FTP server's good-bye message if the server closes the connection itself
+ and doesn't send one. - FM
+* Added GNUC support to the VMS descrip.mms files. - FM
+* Tweaks of HTWAIS.c socket handling on VMS (I can't reproduce a reported
+ problem with SOCKETSHR/NetLIB, but these tweaks might help). - FM
+* Added my guesses at code for HTTelnet.c to implement telnet, tn3270 and
+ rlogin support, if available, when building with SOCKETSHR/NetLIB on
+ VMS. - FM
+07-28-95
+* Mods for Sequent Symmetry DYNIX/ptx - Mark Kolmar (mkolmar@ccs.nslsilus.org)
+* Added GL's lynxcgi patches posted to lynx-dev, plus some tweaks. - FM
+* Worked in GL's lynxcgi mods as in Lynx2-4-2:
+ --------------------------------------------
+ Added George Lindholm's LYNXCGI feature. This allows lynx to bypass
+ http daemons to run local CGI scripts using a URL of the form
+ "lynxcgi:/path/cgi-script". To implement in Lynx, LYNXCGI_LINKS
+ must be uncommented in userdefs.h and TRUSTED_LYNXCGI must be fixed
+ in lynx.cfg. It doesn't handle redirection or mime-types and
+ scripts should probably generate partial URLs when referring back to
+ itself. If the file you're going after isn't an executable then it
+ will be loaded as regular file. This makes it possible to go back
+ and forth between cgi-scripts and .html files.
+ I changed the way TRUSTED_LYNXCGIs are recorded because they don't
+ work quite the same as TRUSTED_EXECs do. Also, George says it works
+ fine on SunOS and Solaris, and it seems to work fine on Linux. - CL
+ --------------------------------------------
+* Don't block access to the download menu when both no_download and
+ no_disk_save are set if any of the download commands have always_enabled
+ set (ie. present a reduced menu, with those still available). - FM
+* More tweaks of help and html files. - DSL
+07-26-95
+* Added support for GNUC in the VMS .com files. Should now compile and link
+ automatically for GNUC via build.com, but that needs testing. - FM
+* Reorganized VMS option files into ones for the transport and ones for the
+ compiler, with corresponding updates of the .com and .mms files. - FM
+* Tweaks of mods for GNUC on VMS, based on further discussions with
+ SB. - FM
+* Tweaks of -help output. - Daniel S. Lewart (d-lewart@uiuc.edu)
+07-25-95
+* Ugh!! Blew it for Unix when setting up the GLOBALDEF/GLOBALREF definitions
+ in tcp.h for VAXC vs. DECC vs. GNUC on VMS this morning (I'm a night
+ person 8-). - FM
+* Worked in code for compiling with the VMS port of GNUC, based on patches
+ from Sterling Bjorndahl (bjorndahl@augustana.ab.ca) and advice from
+ Pat Rankin (rankin@eql.caltech.edu). Needs testing, and the linking
+ procedure still needs to be addressed explicitly. - FM
+* Prevent possibility of a null pointer dereference if an ISMAP anchor
+ fetch fails. - David Trueman (david@cs.dal.ca)
+07-21-95
+* Added LYK_HEAD (mapped by default to ']') to send HEAD requests for the
+ current document or link (always sent with LYforce_no_cache). - FM
+* More lynx.man, lynx.hlp, help file and documentation updates. - FM
+07-19-95
+* Put back "-mime_headers" with mods like those in lynx2-4-2, i.e., so that
+ a source dump is forced. Both "-mine_headers" and "-head" show the status
+ line as well as the MIME headers. - FM
+* Modified "-error_file" to show the complete status line, as well as the
+ URL and METHOD, and to concatenate entries instead of creating separate
+ files for each request. - FM
+* Updated the lynx.man, lynx.hlp and lynx_help files. - FM
+07-18-95
+* Changed "-mime_headers" to "-head" and implemented it as a HEAD request
+ for fetching the MIME headers as text/plain. - FM
+07-17-95
+* Removed 00DIFFERENT from this distribution. - FM
+* Made use of _underline_ format in dumps optional via SUBSTITUTE_UNDERSCORES
+ definitions in userdefs.h and/or lynx.cfg, and added a "-underscore"
+ command line switch for toggling the default on or off. - FM
+* Use system("exec $SHELL") for spawning the default shell on Unix. - Paul
+ Gilmartin (pg@sweng.stortek.com)
+* Fixed typo in check for news vs. nntp URLs in HTNews.c. - Wilson Cheung
+ (wcheung@netcom.com)
+* Added code to the VMS setup() for dealing with curses conficts if someone
+ used -post_data or -get_data without specifying -dump under conditions
+ which require it, so it's not forced in LYMain.c as on Unix. If fact,
+ -get_data and -post_data are very useful in interactive invokations. - FM
+* Fixed memory leak in the -post_data and -get_data handling. - FM
+* Added LYNX_HOST_NAME in userdefs.h and lynx.cfg for defining an alias
+ which will be treated equivalently to "localhost" and HTHostName (the
+ fully qualified domain name of the system running Lynx) in checks for
+ URLs on the local host (e.g., when the -localhost switch is set). - FM
+* Added in or improved descriptions for the new switches in the Lynx
+ command line help and Lynx_users_guide.html. - FM
+07-16-95
+* Tweaks of yesterday's startfile and -homepage mods, and added treatment
+ of '~' as SYS$LOGIN when used as the lead character on VMS (e.g., on
+ VMS as on Unix, lynx ~/ will create a listing of the login directory
+ for the account running lynx). - FM
+* Worked in stuff from 13-Jul-95 lynx2-4-1 upgrade. Most had already been
+ added to lynx2-4-FM. This is the new stuff. - FM:
+---------------------------------------------------
+ 07-13-95
+* Added some command line patches from Peter Brooks - CL:
+ (pbrooks@micromind.com). The new command lines are:
+ -post_data, -get_data = send form data from stdin and dumps results.
+ -auth=ID:PASSWD = sets authorization stuff at startup.
+ -mime_header = prints mime header with -source.
+ -noredir = prevents automatic redirection
+ -error_file=file = prints HTTP status code to file. (Not sure of
+ his motivation on this one, something to do with SlipKnot,
+ I think.)
+ (Replaced Peter's strdup()'s with more portable code. - FM)
+ 07-11-95
+* Added Erik Olson's (olson@phys.washngton.edu) patch to use the
+ _underline_ format when using the -dump option. - CL
+ (Kept the old code, #ifdef'ed out, to make this optional someday. - FM)
+ 07-07-95
+* Fixed a bug in local_dired. Specifically, a pointer to a fixed array
+ was being fed into StrAllocCopy as the destination. Linux was choking
+ on this although OSF/1 and AIX seemed to handle it better. - CL
+---------------------------------------------------
+07-15-95
+* If a command line "startfile" and/or -homepage is not a URL, and can't
+ be located as a file or directory on the local system, treat it as an
+ http URL, e.g., www.wfeb.edu will be treated as http://www.wfeb.edu - FM
+07-13-95
+* Added nntp URL handling (nntp://news_host[:port]/path). Made it read
+ access only (use news URLs for both read and post access). - FM
+07-12-95
+* Added code for proxying https and snews URLs. The Netsite proxy server
+ can proxy them without need for SSL code in the clients themselves, i.e.,
+ for Lynx as publically distributed (need client-resident SSL code and
+ tunneling for the CERN proxy server, sorry). - FM
+* Added the CONNECT protocol to our local code, so that SSL URLs can be
+ tunneled through proxy servers, and reorganized some code so that patches
+ for the SSL hooks can be applied easily if NSA regulations are relaxed. - FM
+07-11-95
+* More tweaks of alignment code. - FM
+* Fixed bad code for removing trailing white space in GridText.c, LYrcFile.c,
+ LYReadCFG.c and LYUtils.c. - FM
+* Added snews and nttp protocols, which simply inform the user that they
+ aren't implemented. - FM
+* The claim is that even mere hooks to the RSA and SSL libraries are
+ objectionable to the NSA, so I removed then from the public distribution,
+ but left in the https protocol, which simply informs the user that it
+ isn't implemented. - FM
+07-08-95
+* Worked in Lou Montulli's (montulli@netscape.com) code for https URL
+ handling into the Common Library. To actually use it, you have to
+ get the RSA and SSL libraries, which are restricted to US citizens
+ (it works if you are and do 8-). I can't include those in this
+ distribution, because by US law that would in turn restrict it to
+ US citizens. - FM
+* Tweaks of paragraph alignment code. - FM
+07-07-95
+* If we are not allowed to change the status of the "lynxexec
+ execution of links" from the option screen then we shouldn't be
+ allowed to change it from the .lynxrc file either. - GL
+* Added George Lindholm's patch to add uudecode support to Lynx's file
+ manager. Unfortunately, uudecode puts the uudecoded file in the
+ current working directory, namely the directory where lynx is started.
+ I haven't thought of a workaround yet, so I made lynx print a
+ statusline message informing the user. - CL
+07-06-95
+* Modified redirection-handling code in HTTP.c to ensure that we get all of
+ the headers before trying to track down the Location: header. - FM
+* For move's or rename's in the local DIRED code, don't write the new file
+ name into the same buffer as the old. - Earl Fogel (fogel@duke.usask.ca)
+07-05-95
+* Added GL's mods to use a stream-based procedure for displaying the
+ current Lynx keymap. Faster and more efficient than the temporary
+ file-based procedure. - FM
+07-04-95 (Enjoy the fireworks!!! 8-)
+* More mods of SGML/HTML parsing to help recover from bad HTML. - FM
+* Fixed some cryptic initialization problems in the Common Library's
+ centering and right alignment code, that we're now using, by changing
+ the malloc's in HTChunk.c to calloc's. - FM
+* Secured some unsafe code in the LYstrncpy() function. - FM
+* Increased the connect() and select() while()-looping limit in HTTCP.c
+ to 30,000 tries. - FM
+* Tweak of HR WIDTH attribute handling. - FM
+07-03-95
+* Updated the DTD structures and definitions for HR to HTML 3.0, plus
+ its Netscape WIDTH and SIZE attributes, and implemented WIDTH, e.g.,
+ HR WIDTH="50%" yields a centered horizontal rule half the width
+ between the current left and right margins. - FM
+* Fixed problem of header end tags not yielding line breaks when embedded
+ in CENTER, LEFT or RIGHT tags. - FM
+07-02-95
+* Added MAKE_PSEUDO_ALTS_FOR_INLINES in userdefs.h and lynx.cfg which can
+ be defined FALSE to treat inlines without an ALT string as having ALT=""
+ instead of inserting the pseudo-ALT string "[INLINE]" into the document.
+ The configuration file default can be toggled via a -pseudo_inlines
+ command line switch, and the user can toggle the inclusion of pseudo-ALT
+ strings on or off at run time via LYK_INLINE_TOGGLE (mapped by default
+ to '['). - FM
+* Made the -image_links command line switch a toggle for the configuration
+ file default setting. - FM
+* Enabled processing of forms that use TABLE for formatting. I don't see any
+ risk of crashes, and they might end up usable. Messages warn the user that
+ the display of the form may be strange. - FM
+* Relaxed anti-crash protections for forms with bad HTML (usually due
+ to interdigitated instead of embedded tags, written by providers with
+ Netscape or Mosaic clients, which are insensitive to such fundamentally
+ bad HTML). I got the code to still work with several bad forms on the
+ Net, and if a crash should occur, the user has been tipped off via the
+ statusline or trace message about the nature of the problem. - FM
+07-01-95
+* Restored the meaning of the P element to be the beginning of a paragraph,
+ updated its structures and definitions in the DTD to HTML 3.0, and
+ implemented its ALIGN attribute (left, center, right). Note that it
+ no longer forces double spacing (you'll get the spacing defined in
+ the stylesheet for the current element, which may or may not be
+ double) and empty paragraphs (serial Ps) will not yield additional
+ newlines (use serial BRs for that). - FM
+* If both download options and disk saves are restricted, don't fetch
+ binary files with a download offer when their links are activated
+ (just issue a statusline message that the file can't be displayed),
+ and issue a "disabled" statusline message for any overt 'd'ownload
+ attemps. - FM
+* For disk saves in LYDownload.c, on VMS attempt a rename() first, and then
+ a spawned DCL copy if that fails. - FM
+* Added memory exhaustion checks for all mallocs, reallocs and callocs in
+ the LYfoo modules. - FM
+* Added CL's realloc() substitute for AIX and ultrix in GridText.c. - FM
+* Map extensions .html3 and .ht3 to text/html in HTInit.c. - FM
+06-29-95
+* Added code to enable creation of links for all images. Can be made the
+ default by setting MAKE_LINKS_FOR_ALL_IMAGES to TRUE in userdefs.h and/or
+ lynx.cfg (not advised). Can be implemented for the session via a command
+ line switch, -image_links, e.g., use lynx -dump -image_links to get links
+ for all images, as well as standard links, listed in the output. Can be
+ toggled on and off at run time via LYK_IMAGE_TOGGLE (mapped by default to
+ '*'). Use that in conjuction with the LYK_LIST command to get a list of
+ links that includes all images, e.g., for adding them as bookmarks. The
+ toggle also invokes a reload, so that the change will be implemented for
+ the current and any future documents, but if you return to cached
+ documents, those will need to be reloaded explicitly. See comments in
+ userdefs.h and lynx.cfg for more information. - FM
+* Don't restrict use of Control-T for toggling trace mode to advanced
+ usermode (i.e., make it available in all usermodes, so people might
+ follow the instructions in "BAD HTML" statusline messages to check
+ the document in trace mode). - FM
+* Modified LYList.c to indicate the anchor NAME/ID, if present, following
+ the TITLE, if known, in interactive 'l'ists.
+* Modified SGML.c to treat '>' as both a close-double-quote and close-tag.
+ Now Lynx acts like Netscape, in that respect, so all that bad HTML
+ Netscape users are generating will not bother Lynx. - FM
+06-28-95
+* Oops, missed an initialization in this morning's centering and right
+ alignment mods. - FM
+* Fixed up HTML.c to bypass HTML 3.0 attribute checks for start tags generated
+ by the Common Library's non-http access types (gopher, ftp, news, wais)
+ Could crash, otherwise. - FM
+* Fixed up GridText.c code to take non-printing control characters properly
+ into account when formatting centered or right-aligned text. - FM
+* Mods to improve appropriate carryover or cancelling of alignment attributes
+ across successive elements. - FM
+* Implemented Netscape LEFT and RIGHT extensions, homologously to CENTER. - FM
+* Implemented Netscape BLINK extension as HT_UNDERLINE. - FM
+06-26-95
+* Updated the DTD structures and definitions for H1 - H6 to HTML 3.0 and
+ implemented their ALIGN attribute (left, right and center). - FM
+* Implemented the Netscape CENTER extension. - FM
+06-25-95
+* Updated the DTD structures and definitions for FORM, INPUT, TEXTAREA,
+ SELECT and OPTION to HTML 3.0. - FM
+* Implemented the HTML 3.0 DISABLED attribute for FORM elements. - FM
+* INPUT type "scribble" implemented as "text" according to the HTML 3.0
+ recommendation for non-GUI clients. - FM
+* Added protections against problems with INPUT types "range" and "file"
+ until they're implemented (will be tricky, but do-able 8-). - FM
+06-23-95
+* Added all ISO8859-1 entities to the DTD. - FM
+06-22-95
+* Updated the DTD structures and definitions for A and IMG to HTML 3.0, and
+ implemented their ID attribute. - FM
+* Tweaks of FIG handling. - FM
+* It is somehow inappropriate to teach our users to write correct HTML and
+ to tell them to always check it before publishing, when Lynx's on-line
+ help gives such a bad example :-} (not to mention versions from a couple
+ of months back). Better now. - Mark Martinec (Mark.Martinec@nsc.ijs.si)
+06-20-95
+* Made the DTD structures and definitions for the HTML 3.0 elements
+ BQ, CAPTION, CREDIT, FIG, NOTE and OVERLAY complete, and added
+ those for STYLE, TABLE, TD, TH and TR.
+* Tweaks of yesterday's HTML 3.0 additions (still just "first pass"). - FM
+* Added code for avoiding potential problems with stylesheets and tables
+ in HTML 3.0 documents. - FM
+06-19-95
+* Added "first pass" handling of HTML 3.0 elements BQ, CAPTION, CREDIT,
+ FIG, NOTE and OVERLAY. - FM
+06-17-95
+* Close the configuration file on completion of the big while() in
+ LYReadCFG.c. - PM
+* Added 00DIFFERENT to keep track of files in this code set which
+ presently differ from those in the latest development code set
+ at UKans (currently, lynx2-4-1.zip of 15-Jun-95). - FM
+* Tweak of the pseudo-toolbar code. The 'l'ist command now displays the
+ TITLE (or RelValue, if TITLE is defaulted) of those links if they have
+ never been accessed, or their actual HTML titles if accessed, at the
+ top of the links list, so you can use that command instead of LYK_HOME
+ to reach the toolbar links at any time, and then left-arrow to where
+ you were in the current document instead of having to page back down
+ to that location. - FM
+06-16-95
+* Added LINK REL="RelValue" HREF="foo" TITLE="TitleValue" HTML 3.0
+ handling (as in http://www.hpl.hp.co.uk/people/dsr/html3/dochead.html
+ of 28-Mar-95). The HREF and REL values are required (the LINK will be
+ ignored if either is missing or has a zero-length value). TITLE is
+ optional, i.e., the RelValue will be used as the link name if TITLE
+ is omitted. Currently registered toolbar RelValues are: Home, ToC,
+ Index, Glossary, Copyright, Up, Next, Previous, Help, and Bookmark.
+ The Bookmark links are intended to have TITLEs (e.g., "Order Form").
+ The others have RelValues that yield self-evident link names. The LINKs
+ should be placed in the HEAD section, so they'll be displayed in a manner
+ simulating a toolbar (but not a real one, since we don't have Windows and
+ mouse support; use your LYK_HOME command to access it at any time 8-).
+ The BODY should have a line-breaking element (e.g, H1) to set them off.
+ For now, the Banner RelValue is treated like another toolbar element.
+ The StyleSheet RelValue is ignored, since we don't yet have loadable
+ stylesheet handling. - FM
+* Fixed up the 06-13-95 NO_ANONYMOUS_EMAIL patch to be appropriate for
+ VMS - FM.
+06-14-95
+* Added LYK_LIST command ('l' or 'L'; must be uppercase if VI keys are on)
+ for creating an ACTIVATEable list of references (links) in the current
+ document. If LINKS_ARE_NUMBERED is on, it's a UL, otherwise it's an
+ OL. Visited links have the TITLE displayed, otherwise the HREF is
+ displayed. - FM
+* Added code to append a list of references (links), if present in the
+ document, when -dump is used. Dumps are done with LINKS_ARE_NUMBERED
+ turned on. The reference list is numbered, and always shows the HREFs,
+ so that they can be referenced to the links in the document. - FM
+* Updated help files. - FM
+--- lynx2-4-1 on ftp2.cc.ukans.edu (added to lynx2-4-FM on 06-16-95)
+06-13-95
+* Added George Lindholm's patch to add -r (recurse) to the zip call in DIRED.
+ - JP
+06-12-95
+* Added George Lindholm's new file permission patch. Here's his description:
+ "Here is a rewamped version of my earlier file permission patch. This version
+ uses a html page to prompt for user input (rather than having the user
+ enter a obscure unix chmod string) using checkboxes." - JP
+* Added George Lindholm's addition of a compiler flag (NO_ANONYMOUS_EMAIL).
+ If NO_ANONYMOUS_EMAIL is set the user will not be able to add their own
+ from header. This will only work if the mail package being used will
+ add this information. - JP
+--- lynx2-4-1 on ftp2.cc.ukans.edu
+06-09-95
+* Replaced info.cern.ch with www.w3.org in html and make files. Designated
+ this code as 2.4-FM, for local use. - FM
+--- STARTING 2.4-FM ---
+--- Rename of Lynx2-3-FM and release as Lynx2-4 (08-June-1995) ---
+ (see CHANGES2-4 and CHANGES2-3)
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.6 b/gnu/usr.bin/lynx/docs/CHANGES2.6
new file mode 100644
index 00000000000..73c158ab13f
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.6
@@ -0,0 +1,732 @@
+--- Rename of Lynx2-5FM and release as Lynx2-6 (02-Sep-1996) ---
+==============================================================================
+09-02-96 ---- Release of Lynx2-6 ----
+* More expansions of the online 'h'elp files. - FM
+* Updated the PROBLEMS file. - FM
+09-01-96
+* More expansions of the online 'h'elp files. - FM
+* Tweaks of list handling. - FM
+* Miscellaneous code cleanups and annotations. - FM
+08-31-96
+* Further updates and expansions of the online 'h'elp files. - FM
+* Tweaks of alignment handling with bad HTML. - FM
+* Added JIS X 0201 Japanese Kana string support. - TA & FM
+08-30-96
+* Further updates and expansions of the online 'h'elp files. - FM
+* Typo fixes in the help and doc files. - LWV
+* Tweaks of ENCTYPE handling for FORM submissions. - FM
+08-29-96
+* Today's distribution is a pre-release of v2.6. The projected official
+ release date is 09-02-96.
+* Tweaks of numeric character reference handling. - FM
+* Typo fix in LYShowInfo.c. - IC
+08-28-96
+* Added handling of ENCTYPE="application/sgml-form-urlencoded" in FORMs
+ as a directive to use semi-colons instead of ampersands as name=value
+ separators, and to indicate that as the Content-Type for POSTs. - FM
+* Convert ampersands in addresses and link names, and angle-brackets in
+ link names, to SGML entities when creating bookmarks and showinfo ('=')
+ link 'l'ist, client-side-image-map, and history list text/html streams
+ or temporary files. - FM
+* More SGML compliance mods for the handling of attribute values which
+ represent URLs or URL components. - FM
+* Tweaks of form INPUT, TEXTAREA, SELECT and OPTION handling. - FM
+* Check EAGAIN on socket connect or select attempts for all platforms and
+ flavors. - FM
+* Include both <time.h> and <sys/time.h> in tcp.h for AIX.
+* Adding warning and info in the INSTALLATION file and userdefs.h on how
+ to cope with telnetd environment variable spamming for anonymous accounts
+ running Lynx captively. - FM
+08-24-96
+* Enhancements of the History List handling. Show each link's actual address
+ in addition to the titles, since the actual addresses can't be determined
+ via showinfo or the 'l'ist display, and links in the History List derived
+ from searches can have the same titles but different searchparts or hidden
+ content appended. If a link in the History List is activated, is still
+ cached, has POST content, and ALWAYS_RESUBMIT_POSTS was configured off (as
+ recommended) and wasn't toggled on via -resubmit_posts, prompt the user
+ whether to resubmit the form (versus retrieve the cached rendition from
+ the previous submission). We don't bother prompting on PREV_DOC ("back")
+ fetches, and still resubmit forms with POST content whenever their submit
+ buttons are activated, i.e., regardless of whether ALWAYS_RESUBMIT_POSTS
+ has been configured or toggled on. - FM
+* If a user attempts to add a bookmark while viewing a document returned
+ via a form submission with POST content, and it contains links, offer
+ the current link with it's link name for editing. Otherwise, display
+ a statusline message that documents from forms with POST content cannot
+ be saved as bookmarks. - FM
+08-23-96
+* Added UP_HALF and DOWN_HALF commands, mapped by default to '(' and ')',
+ for going back or forward half a page in the document. These are
+ complementary to UP_TWO and DOWN_TWO, for going back or forward two
+ lines (remember to use the 'K'eymap command for a list of all of the
+ keystroke command bindings currently in effect, since they may have
+ been changed via lynx.cfg from the defaults described in the online
+ 'H'elp). - FM
+* Made the Control-A and Control-E keys default synonyms for HOME and END,
+ complementary to their use for going to the beginning or end of the line
+ when using the line editor. - FM
+* Don't lose track of source versus present mode on returns from temporary
+ menu files to documents derived from forms with method POST. - FM
+* Ugh, I had deleted one too many lines from HTTP.c when stripping out my
+ SSL hooks for the distribution copy (no wonder the Authorization mods
+ worked fine for me but nobody else 8-). - FM
+08-22-96
+* Added handling of named entities and numeric character references in
+ the values of most of the non-URL attributes (we don't waste overhead
+ doing that for the values of simple attributes, like ALIGN, which have
+ designated strings). - FM
+08-21-96
+* Safely handle named entities and numeric character references in the values
+ of BASE, LINK, HREF, SRC, ACTION, DATA, CODEBASE and CODE attributes, and
+ in the URL field for the CONTENT of META with a "Refresh" HTTP-EQUIV or
+ NAME. They are converted in relation to the "ISO Latin 1" Character Set
+ array regardless of the selected Character Set (except that nbsp and shy
+ remain 160 and 173), then 8-bit translations are hex escaped (as they
+ should have been in the markup 8-), and ESC is hex escaped or omitted
+ depending on whether a CJK character set has been selected. There's no
+ way to do it such that the resolved URL always will be valid no matter
+ what yoyos or CGI scripts put in document instances, but this strategy
+ maximizes the chances while making sure no "dangerous" characters, based
+ on the selected Character Set, are ever sent to the screen (it used to be
+ HyperText Markup Language, not HyperGraphic Markup Language 8-)- FM
+* Allow Control-G or a zero-length username or password to act as a cancel
+ of the request (and restoration of the current document) when an http
+ server invokes prompting for Authorization. - FM
+* When using a proxy server, report the target host instead of the proxy
+ in prompts for Authorization. - FM
+* Show MIME types of files, if known, whenever a download offer is forced,
+ regardless of why it was forced (i.e, not only for mismatches between
+ the document's charset and the selected character set). - FM
+08-20-96
+* Yet more tweaks of MIME header parsing. - FM
+08-19-96
+* Enhancements of the news gateway. - FM
+* Tweaks of Content-Type and charset handling. - FM
+* Tweaks of MIME header parsing. - FM
+08-18-96
+* Tweaks of the news gateway and its documentation. - FM
+08-17-96
+* Added overt (rational 8-) handling of all status codes that might be
+ returned (appropriately or inappropriately 8-) from HTTP/1.1 http
+ servers, and massively annotated the code in HTTP.c. - FM
+* Added parsing in HTMIME.c, and at least trace mode reporting, for all
+ http server reply and entity headers as in the 08-12-96 HTTP/1.1 draft.
+ We should not get many of them, unless we declare ourselves as an HTTP/1.1
+ client and send the appropriate request headers, but they're all available
+ now for use as more HTTP/1.1 features are added. - FM
+08-16-96
+* Added handling of "Pragma: no-cache" or "Cache-Control: no-cache" headers
+ from http servers, and polished up the code for handling them via META
+ directives. - FM
+08-15-96
+* Modified form handling so that Lynx always resubmits forms if their method
+ is POST, even if their content was not changed, when their submit buttons
+ or submitting text input are activated. Changed the ALWAYS_RESUBMIT_FORMS
+ compilation and configuration definitions, and -resubmit_forms command
+ line toggle, to ALWAYS_RESUBMIT_POSTS, and -resubmit_posts. When FALSE,
+ you still get the previously returned document from a POSTed form if that
+ document had links which you activated, and then go back with the PREV_DOC
+ command or via the history list. If set TRUE, the form will be resubmitted
+ under those circumstances as well. Documents returned by forms with method
+ GET still require use of the RESUBMIT command to resubmit if the forms'
+ content was not changed, and forms with a mailto action still always mail
+ the content on activation of the submit button or submitting text input
+ (no document is returned, so the PREV_DOC command and history list behaviors
+ are irrelevant). - FM
+* Use space to plus conversions for values of submitted form content (Ugh,
+ Lynx has been using %20 all these years! It worked because they are
+ unescaped to space, anyway. 8-). - FM
+* Polished up and massively annotated the redirection handling code. If
+ a user approves redirection of a form with POST content, it will not be
+ freed and the submission will not be converted to a contentless GET request
+ unless the status was 303 (See Other). For 300 (Multiple Choices), the
+ returned document is offered, which should include links with descriptions
+ of their media types. The returned document (if any) is now displayed for
+ any redirection status code if no Location: header was present, and for
+ unknown 3xx codes (i.e., greater than 305). If Lynx gets an inappropriate
+ 304 (Not Modified), it switches to HEAD mode and displays the status line,
+ and anything else returned by the server, as text/plain. A 301 (Moved
+ Permanently) will be treated as 302 (Moved Temporarily) for form submissions
+ with POST content. Otherwise, Lynx will use the new URL for the remainder
+ of the current session (users will have to do a 'r'emove and 'a'dd for their
+ bookmarks themselves, for now). A 305 (Use Proxy) will not be honored if
+ Lynx is already using a proxy, and instead the returned document will be
+ displayed. The limit on serial redirections was dropped from the current
+ 10 to 5, as recommended in the August 10, 1996 HTTP/1.1 draft. - FM
+08-13-96
+* Mods to accommodate the HTTP/1.1 300 - 305 Redirection status codes, and
+ to require user confirmation for any redirection of POST content. - FM
+* Tweaks of OBJECT handling. - FM
+08-12-96
+* Implemented all aspects of OBJECT that make sense for a text client.
+ Will descend though nested OBJECTs. Can be used for presenting PRE
+ formatted character-cell versions of images, and appears to handle
+ all likely uses of the SHAPES and USEMAP attributes in OBJECTs. The
+ pseudo-ALTs for links to non-script DATA values (i.e, the for-GUI
+ sources) when offered as links (e.g., in clickable_images mode), if
+ not a markup-specified string (e.g., based on a TITLE attribute),
+ are (IMAGE) or (OBJECT), based on whether the nature of the source
+ can be inferred from the context, or an explicit TYPE attribute in
+ the OBJECT start tag. The use of parens instead of square-brackets
+ indicates that the links are for OBJECTs as opposed to IMGs. - FM
+* Tweaks of SELECT and OPTION handling. - FM
+08-09-96
+* Lots more stuff added to the online help files. - FM
+* Added state code in SGML.c to avoid getting tripped up by any single or
+ double quotes in CJK escape sequences that are within single or double
+ quoted attribute values. - TA
+* Restrict resetting the Kanji code flag on white space to Japanese
+ (i.e., not also Chinese, Taipai, or Korean). - TA
+* Added handling of EPLF lines (with local time) for the FTP gateway. -
+ D. J. Bernstein (djb@koobera.math.uic.edu)
+08-08-96
+* Added code for handling captured OBJECT content with the SHAPES
+ attribute equivalently to our handling of FIG, and with USEMAP and/or
+ ISMAP content equivalently to our handling of IMG.
+* Added code for capturing potentially nested container elements that
+ require pre-processing, e.g., OBJECT, and for passing the processed
+ markup back to the SGML parser to be inserted within the ongoing HTML
+ stream.
+* Added CHECK_EAGAIN Makefile definition for non-SVR4 Unix flavors which
+ might need it for socket connect() and select() calls. - FM
+* Tweaks of keyboard input with slang when LYCursesON is FALSE. - FM
+08-06-96
+* Terminate and start a new Accept: header line if the current one will
+ exceed 1 KB (shouldn't be necessary, but otherwise the long lines cause
+ an error for WebSitePro and crash Netscape servers, and perhaps have
+ adversed effects on some other http servers with ill designed code for
+ content negotiation). - FM
+* Give temporary files suffixes matched to the Content-Type for all flavors
+ of Unix and for VMS, not just for NeXT. - FM
+* Tweak of Location: header parsing in HTTP.c (trim all lead spaces). - FM
+08-05-96
+* More help and documentation updates. - FM
+08-04-96
+* Updated the online help files. - FM
+08-03-96
+* Mods of "user (A)gent" 'o'ption handling. Also added a "useragent"
+ -restriction, included in the defaults for anonymous accounts. See
+ the "Lynx options menu" section of the "Lynx Users Guide" via the
+ online 'h'elp for more information. - FM
+* Tweaks of messaging for unsupported URLs. - FM
+* Tweaks of interrupt handling on VMS. - FM
+08-02-96
+* Added handling of Refresh in META tags. The URL is presented as a link
+ pointed to by a "REFRESH(n sec):" label, where "n" is the seconds
+ parameter from the META tag, and you must activate it yourself, which
+ should enable people using Lynx via a braille interface to examine
+ the initial document before it is refreshed. The META format is:
+ <META HTTP-EQUIV=refresh CONTENT="n; URL=url"> where "n" can be "0" or
+ a positive integer, and the "; URL=url" field is optional, defaulting
+ to the document's own address. Netscape's docs say that "url" should
+ be a complete URL, but their client doesn't require it, and so it's
+ users don't reliably use complete URLs. Lynx therefore resolves "url"
+ versus the document's own address if it is not complete. - FM
+08-01-96
+* Added handling of ENCTYPE="text/plain" for FORMs with a mailto ACTION.
+ The name=value pairs are not hex escaped, and physical newlines instead
+ of '&' separate the pairs, so that the content is readable directly. - FM
+* Added SUBJECT attribute as synonym for TITLE in FORMs (Some clients
+ are using it instead of TITLE for mailto ACTIONs, ugh!). - FM
+* Tweaks of DEL, S, STRIKE, and INS handling. - FM
+* Handle any newline characters in quoted INPUT values. - FM
+* Added news-ncurses and news-slang Makefile targets, and tweaks of headers
+ for sony_news. - Makoto MATSUSHITA (matusita@ics.es.osaka-u.ac.jp)
+07-30-96
+* Finished and incorporated lynx_url_support.html in the online help,
+ and updated lynx_help_main.html. - FM
+* Tweaks of ID attribute handling. - FM
+* Tweaks of the gopher gateway. - FM
+* Updated IBMPC-charsets.announce. - MB
+07-26-96
+* Set the default anonymous account restrictions if Lynx is invoked in
+ the account pointed to by ANONYMOUS_USER, or with the -anonymous switch,
+ before processing any additional command line restrictions, so that any
+ greater restrictions will not drop back to the compilation defaults.
+ Note that the full set of -validate restrictions always are enforced for
+ that switch, i.e., no matter what other switches or compilation options
+ are used, and whether or not the account is anonymous. - FM
+* Implemented handling of the ANONYMOUS_USER definition on VMS (equivalently
+ to it's implementation on Unix). - FM
+* Tweaks of mailto URL handling and setting of the default subject via
+ TITLE attributes. - FM
+* Tweak of the news gateway's handling of the author (From:) field. - FM
+07-25-96
+* If a server returns redirection without a complete URL indicated, resolve
+ it relative to the original request instead of issuing an error message
+ (this is incorrect behavior, but that's another trashed standard, and
+ Lynx may as well handle the situation as standard-less clients do). - FM
+* Move the NO_JUMPFILE and JUMP_PROMPT definitions to LYMessages_en.h - FM
+* Added code for selective disabling of goto by scheme in anonymous accounts,
+ along lines of patch from Doug Lawson (dlawson@epfl2.epflbalto.org). - FM
+* Ignore any viewer mappings for text/html or text/plain in mailcap
+ files. - FM
+07-22-96
+* Updated ptx target and added ptx-slang. - Alan Coopersmith
+ (alanc@CSUA.Berkeley.EDU)
+* Added all the new elements and attributes from the July 12 HTML 3.2/Cougar
+ DTD, and implemented the new IMG TITLE attribute for use with USEMAP.
+* Added a -startfile_ok switch for allowing a non-http startfile or homepage
+ with -validate, and restored the behavior of not allowing *any* non-http
+ URLs by default.
+07-19-96
+* Treat PLAIN and TYPE="plain" as equivalent in UL tags. - FM
+* Fixed the mispositioning of thinsp in HTMLDTD.c. - FM
+07-18-96
+* Moved the statusline prompt, message, and warning string definitions
+ out of userdefs.h into an LYMessages_en.h header. See the comments
+ in userdefs.h and LYMessages_en.h for more information. - FM
+* Removed the -lc from the LIBS= list of the snake3 and snake3-slang
+ targets, added a description of the HP/UX 10.10 select() problems
+ and reported (but not yet satisfactory) workarounds in the PROBLEMS
+ file, and a note in the Makefile to read the PROBLEMS file. - FM
+07-17-96
+* Numerous typecasts added for optimized compilations. - FM
+* Tweaks for ISC. - WS
+* Changed make to $(MAKE) and -g to -O for Unix targets (may need
+ tweaking for some flavors 8-). - FM
+* Added news target for SONY NEWS-OS 4.2.1R based on patch from
+ Kazuya 'Sharl' Masuda (masuda@sp.hudson.co.jp) and TA. - FM
+* Fixed typo in LYList.c from yesterday's mods. - FM
+07-16-96
+* Plugged memory leaks associated with temporary file names. - FM
+* Finally figured out what was creating orphan child anchors, and plugged
+ that memory leak in HTAnchor_delete(). - FM
+* Replace <sys/select.h> with <sys/timeb.h> for SCO in tcp.h. - BL
+* Mods to avoid warning about redefinition of signal when building on
+ VMS with old versions of SOCKETSHR (irrelevant, but might worry
+ people who don't know that the warning can be ignored). - FM
+07-15-96
+* Plugged various memory leaks in FORM handling code. - FM
+07-13-96
+* Add the startfile, and homepage if different, to the 'g'oto recall
+ buffer so that they are available for editing in addition to any
+ overtly entered 'g'oto URLs. - FM
+* Changed TRUSTED_URL to ALWAYS_TRUSTED_EXEC for clarity, and plugged
+ memory leaks and some security holes in that code. - FM
+* Fixed typo in code for handling Z compressed files. - FM
+07-12-96
+* Added handling of &thinsp; (&#8201;), and handling of &#8194; as &ensp;,
+ &#8195; as &emsp;, &#8211; as &ndash; or &endash;, &#8212; as &mdash; or
+ &emdash;, and &#8482; as &trade; (treated as &reg; &#174;), based on the
+ Cougar DTD. - FM
+* Increased the line buffer size in HTLoadHTTP() and limited the deflt string
+ length in HTPrompt() to avoid possibilities of buffer overruns. - FM
+07-11-96
+* Block access to file: URLs via network served files or bookmarks in
+ addition to 'g'oto entries when -restrictions=file_url is set (one of
+ the default restrictions for -anonymous). - FM
+* Extended compressed file handling to the ftp gateway and local files.
+ If you ACTIVATE the link instead of overtly invoking a 'd'ownload, and
+ the path with the gz or Z stripped maps to a displayable Content-Type or
+ one for which you have a viewer or helper app, the file will be treated
+ as if it had a Content-Encoding: header indicating the compression (i.e.,
+ uncompressed and displayed or passed to the viewer or helper app). - FM
+* Mods to send http servers an Accept-Encoding: header indicating gzip and
+ compress, and to block inclusion of our new, internal www/compressed MIME
+ type in the Accept: header list. - FM
+* Changed the names of the lex_buffer and lex_lines globals to HTlex_buffer
+ and HTlex_lines in case name conflicts are causing segmentation faults on
+ linux for long usernames in authorization requests, and changed all
+ malloc()'s to calloc()'s in that code in case there's an initialization
+ glitch I don't yet see. - FM
+07-09-96
+* Use the username and password of an -auth= command line argument only
+ for the first realm that requests authorization, so they don't preclude
+ access to other realms later in any interactive session that might have
+ a different username and/or password, and handle inclusion of only a
+ username or only a password in the -auth= argument. - FM
+* Tweaks of memory leak plugs in authorization handling functions (hopefully
+ now avoiding segmentation faults on linux 8-). - FM
+* Include -lc in the first position of the LIBS= list for snake3 targets.
+ - Donald S. Teiser <dsteis01@homer.louisville.edu)
+* Enhancements of Makefile. - LWV
+07-07-96
+* Tweaks of code for uncompressing on the fly. Will now force a download
+ offer without uncompressing if there is no presentation mapping for the
+ Content-Type. - FM
+* Retain blank lines within TEXTAREA content (but not trailing blanks). - DT
+07-07-96
+* Added functions for uncompressing and handling documents which have
+ Content-Encoding headers that indicate "x-gzip", "gzip", "x-compress",
+ or "compress" (instead of forcing a download offer). The files are
+ not uncompressed if they were fetched via the 'd'ownload command.
+ Note, however, that if you activate a link for a compressed image or
+ other binary file, and don't have a viewer or helper app mapped for it,
+ it will already have been uncompressed before a D)ownload or C)ancel
+ offer can be made, so use the 'd'ownload command directly if it is
+ your intention to download such files. Note also that on VMS "gzip -d"
+ is used for both gz and Z uncompression. See the INSTALLATION file for
+ info on getting the VMS port of gzip. - FM
+07-06-96
+* Allow any startfile and homepage in -validate mode even if they are not
+ http URLs. - FM
+* Made all the 'o'ptions menu statusline prompts and informational messages
+ strings that can be defined in userdefs.h for different languages. - FM
+* Mods to send one Accept header as a comma-separated list instead of a
+ series of individual Accept header statements. - FM
+07-05-96
+* Added NO_FILE_REFERER configuration symbol and -nofilereferer switch
+ for disabling transmissions of Referer headers for any file URLs (is
+ a subset of what NO_REFERER_HEADER and -noreferer disable). - FM
+* Tweaks to facilitate additions of security-related patches. - FM
+07-04-96
+* Added NEWS_CHUNK_SIZE and NEWS_MAX_CHUNK configuration symbols and
+ -newschunksize and -newsmaxchunk switches for regulating the chunking
+ of news article listings. See comments in lynx.cfg for explanation. - FM
+07-02-96
+* Tweaks of URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES handling (was
+ doing double scheme prefixing under some circumstances). - FM
+* Fixed problem of potential crashes with bad HTML which lacks any
+ OPTION tags in SELECT containers (Yes, HTML that bad is really out
+ there! 8-). - FM
+* Fixed problem of potential infinite loop in HText_endAppend() for documents
+ that contain nothing but SCRIPTs and empty OBJECT containers (as in the
+ Microsoft ActiveX demos). -FM
+07-01-96
+* Added circular recall buffer for paths used as the second argument in
+ 'd'ownload and 'p'rint menu commands. Use the up- and down-arrow keys
+ to access then at the statusline prompt, equivalently to the recalls for
+ previous 'g'oto URLs, 'j'ump shortcuts, and ISINDEX or WHEREIS search
+ queries. - FM
+* Modified the LYMail.c functions to work as intended with both curses
+ and slang (through v0.9-33) on both Unix and VMS. - FM
+06-30-96
+* Changed yesterday's symbols to URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES
+ and added code to guess the scheme based on the first field of the domain
+ name (e.g., gopher.wfbr.edu will become gopher://gopher.wfbr.edu instead
+ an http://host URL). Note also that a partial host string can contain a
+ dot within it and still be tested with prefixes and suffixes if the DNS
+ lookup fails with the host string as entered (e.g., cc.ukans will become
+ http://www.cc.ukans.edu), and only dots at the end or beginning of the
+ partial host string will block prepending or appending, respectively, of
+ items from the prefix or suffix lists (e.g., ftp.foo. will block use of
+ items from the prefix list, but permit tests from the suffix list, and
+ will become ftp://ftp.foo.dom if the ftp.foo.dom lookup succeeds). - FM
+06-29-96
+* Added HTTP_DOMAIN_PREFIXES and HTTP_DOMAIN_SUFFIXES in userdefs.h and
+ lynx.cfg for defining lists and setting the order of domain name prefixes
+ and suffixes to use when creating http:// URLs from command line and
+ 'g'oto arguments which are not already URLs and cannot be opened via a
+ file://localhost URL (see 05-30-96 entry). - FM
+06-28-96
+* Tweaks of MIME header handling. - FM
+06-27-96
+* Do not send a referer header for links obtained from the history list,
+ bookmark file, or jumps file. - FM
+* Made sorts by name case-sensitive in ftp and file listings. - FM
+* Added osf-slang make target. - FM
+* Enable ^C (SIGINT) interrupts during spawns on Unix (^C and ^Y interrupts
+ were already being enabled for VMS ). - FM
+* Fixed glitch in WHEREIS search handling. - Michael Barabanov
+ (baraban@luz.cs.nmt.edu)
+06-26-96
+* Tweaks of ftp gateway for VM/CMS servers based on feedback from PG. - FM
+* More tweaks of 'o'ptions menu and DISPLAY handling. - FM
+* Tweaks for builds with WIN_TCP on VMS. - FM
+06-24-96
+* Modified 'o'ptions menu handling to allow NULLing of strings which were
+ set at startup. Note that if you NULL (or set) the DISPLAY variable,
+ Lynx configured itself for X/Motif or not based on whether it was set
+ (or NULL) at startup, and you need to restart Lynx to really change the
+ configuration for 'd'ownload forces versus X/Motif viewer spawns. - FM
+* More tweaks of language code, to make the HTCJK enum checks more
+ portable. - FM
+06-23-96
+* Set up handling of nested DIV tags with ALIGN attributes (and CENTER,
+ which is treated as DIV ALIGN="center"). - FM
+* Removed INSERT, ALIAS and MH from the DTD, and their associated code
+ from HTML.c and GridText.c. - FM
+06-22-96
+* Tweaks of character set handling. - FM
+* Added function for graphic boxing of popups with curses on VMS. - FM
+06-21-96
+* Mods to translate CJK escape sequences and take Kanji into account when
+ handling statusline() messages. That's in effect if a CJK character set
+ is selected, and regardless of the raw or CJK mode setting, because the
+ strings are coming from definitions in userdefs.h, not the document that
+ is being rendered or displayed. - FM
+* Added more statusline() string definitions in userdefs.h. - FM
+* Ignore a server's Content-Encoding header if it inappropriately indicates
+ "8bit" or "7bit" (should be indicated a compression scheme). - FM
+* Mods to use charset strings as in the 07-Jun-1996 HTTP/1.1 draft, and to
+ check for those as well as their common synonyms. - FM
+* Mods to revive clearok() functionality with the slang 0.99-33 library
+ (need it for Kanji handling and for VMS), and to deal with the definition
+ conflicts for the (poorly added) TRUE and FALSE definitions in the new
+ slang library's SLcurses.h. - FM
+06-20-96
+* Added handling of the SFS file system on VM ftp servers, tested on
+ ftp://ubvm.cc.buffalo.edu/ (be sure to escape the colons if you use SFS
+ paths, e.g., ftp://ubvm.cc.buffalo.edu/vmsysu%3alistserv.webshare) - FM
+* More memory management enhancements and leak plugs. - FM
+* Added -DUNIX and -DSCO to the sco and sco5 libwww targets. - BL
+06-17-96
+* Added handling of &shy;, &#173;, and 8-bit 173 for ISO-Latin-1 documents,
+ as a soft hyphen for all of the character sets. - FM
+* Polished up and massively annotated the new character set handling
+ code. - FM
+* Made all the dummy libwww headers in WWW/Library/Implementation
+ compatible with the new, actually used, headers in /src. - FM
+* Fixed some bad ifdef-ing for statusline string definitions which
+ were added to userdefs.h. - FM
+06-15-96
+* Added many more userdefs.h definitions for statusline() and HTAlert()
+ messages. - FM
+* Tweaks of ALT string handling when they are used as forced link names
+ for USEMAP, AREA, IMG, EMBED or APPLET sources. - FM
+* Oops, hadn't put the new HTML.h in the zip. - FM
+* Fixed casing typo for HTCJK.h inclusion in HTMIME.c. - LWV
+06-14-96
+* Updated the help files, lynx.man and lynx.hlp concerning the character
+ set handling. - FM
+* Changed the -jpn switch to a generic -raw switch, and the LYK_JPN_TOGGLE
+ ('@') to a generic LYK_RAW_TOGGLE. The toggling also can be done via
+ the 'o'ptions menu, in conjunction with selecting character sets. See
+ the comments about CHARACTER_SET in userdefs.h and lynx.cfg for more
+ information. The toggle determines whether raw 8-bit characters in the
+ document are assumed to be ISO-8859-1, and therefore translated for the
+ non-"ISO Latin 1" character sets based on their LYCharSets.c arrays, or
+ are assumed to match the character set (e.g, 8-bit ISO-8859-2 when the
+ "ISO Latin 2" set is selected, or Kanji when a CJK set is selected) and
+ therefore processed raw. Use raw or CJK mode when you know the charset
+ of the document is a match to your selected character set, but no header
+ or suffix has indicated that the charset is not ISO-8859-1. Be careful
+ about this when "Other ISO Latin" is selected, since the document could
+ be, e.g., ISO-8859-3, but you are using, e.g., ISO-8859-5. - FM
+* Added "Other ISO Latin", "Chinese", "Japanese (EUC)", "Japanese (SJIS)",
+ "Korean", and "Taipei (Big5)", character sets, which presently translate
+ 8-bit ISO-8859-1 named and numeric entities to 7-bit approximations, and
+ added a default "CHARACTER_SET" definition in userdefs.h, complementary
+ to that in lynx.cfg. - FM
+* Worked in the expanded CJK (Chinese, Japanese, Korean) escape sequence and
+ Kanji handling from Takuya ASADA's June 11, 1996 Lynx2-5CJK (available in
+ ftp://ftp.three-a.co.jp/pub/www/lynx). - FM
+06-11-96
+* Tweak of the ftp gateway to handle Reflection Unix emulation servers. - FM
+* Made lynx_version_putenv_command a global so we can free it at exit
+ via free_lynx_globals() in LYMain.c. - FM
+06-10-96
+* Convert a 0xFFFF value from slang in LYgetch() to 7 (^G) to cancel
+ whatever called it, instead of exiting on error. - FM
+* Tweaks of Makefile to use symbolic, $(include) and $(lib) paths with
+ ncurses for convex, NeXT and sun4, and for SOCKSLIB. - LWV
+* Tweaks of mail editor handling based on patch from Arne Riiber
+ (riiber@systek.no). - FM
+06-09-96
+* Had overdone it plugging memory leaks and was freeing the proxy, news
+ server, and lynx version variables too soon. - FM
+06-07-96
+* Moved the Kanji handling variables into HText structure elements to make
+ the GridText.c functions reentrant for them, and added code for regulating
+ them via charset parameters in server headers or META tags. The recognized
+ parameters are EUC-JP, Shift-JIS, ISO-2022-JP, ISO-2022-JP-2, and EUC-KR.
+ E.g., a META with:
+ HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=Shift-JIS"
+ will set up handling of the document as Shift-JIS. - FM
+* Made handling of Kanji more reliable when SJIS is the default, based
+ on the strategy in Takuya ASADA's Japanized Lynx2-4-2. - FM
+* K&Rized the Ichikawa ISO-2022-JP MIME header handling functions and added
+ them to HTMIME.c, together with Takuya ASADA's (asada@three-a.co.jp)
+ function for guessing whether an escape has been lost and filling it in,
+ and use them for checking news headers. - FM
+* Retry DCL spawns without the TRUSTED flag if it was included and we
+ got back an INVARG status. - Robert C. Gray (gray@cyberodyssey.com)
+06-06-96
+* Plugged lots of memory leaks. - FM
+* Handle colons in code for expanding host names and prepending http://
+ (e.g., wfbr:8002 will become http://www.wfbr.edu:8002/). - FM
+* More tweaks of character conversions. - FM
+* Block crashes if illegal markup such as Anchors are present in the
+ OPTION strings for SELECT. - FM
+06-04-96
+* Mods of entity and end tag handling in SGML.c and LYCharUtils.c. - FM
+* Tweaks of make target for sun4-slang. - NHE
+06-03-96
+* More tweaks of the ftp gateway. - FM
+* More anti-crash protections for bad HTML. - FM
+* Tweaks of LYCharUtils.c and SGML.c. - KW
+* Enclose the username for rlogin URLs in double-quotes on VMS to preserve
+ mixed casing if present. - Robert C. Gray (gray@cyberodyssey.com)
+06-02-96
+* Made DEFAULT_CACHE_SIZE and DEFAULT_VIRTUAL_MEMORY_SIZE configurable via
+ lynx.cfg. - FM
+* Added comments in HTFTP.c to make more clear some of the counterintuitive
+ things being done, and why. - FM
+* Oops, had left my ISSPACE() debugging macro in HTFTP.c yesterday. Is
+ now back to isspace(). - FM
+06-01-96
+* Added support for ;type=I (or A or D) to specify Image or ASCII transfer
+ modes, or a Directory, in ftp URLs. - FM
+* Added support for VM/CMS ftp servers. Note that 'd'ownloaded text files
+ will have CRLF as line terminators, due to their use of ASCII records
+ (tested on ftp://pucc.princeton.edu/anonymou.376). - FM
+* Added support for use of a tilde on Unix ftp servers to indicate that you
+ want a listing of the user's login directory instead of the root (i.e.,
+ ftp://user@host/~ or ftp://user@host/~username will cause Lynx to attempt
+ a listing of the translated ~ or ~username). Paths can be appended (e.g.,
+ ftp://user@host/~/subdirectory). This should not be used with anonymous
+ ftp, or in public documents. It yields the behavior on Unix or Unix-like
+ ftp servers which should occur without the tilde, based on RFC 1738. Note
+ that the valid behavior involving use of %2f is implemented for VMS (see
+ the 12-20-95 entry, below), but the behavior for Unix and Unix-like ftp
+ servers emulates Lynx's Unix DIRED_SUPPORT. - FM
+* Mods of CSO/PH gateway to deal with discontinuous field name tokens
+ (e.g., "NYU fax" instead of "NYU_fax"). - FM
+* More fixes for the putenv_command pointer in LYMain.c. - CC
+* Add curly braces to the current hack for mininizing reversals of
+ trace messages with slang. - KW
+05-30-96
+* Modified the http:// prepending code to try expanded host names if the
+ the first (or only) element does not contain a dot and is not a known
+ host name. Will first try it as www.host.com, then www.host.edu, then
+ www.host.net, then www.host.org, e.g., wfbr/dir/lynx will become an
+ http://www.wfbr.edu/dir/lynx URL. - FM
+* Added handling of MSDOS_SERVER ftp server type (tested on ftp.hayes.com)
+ and corrected WINDOWS_NT_SERVER handling (tested on ftp.boca.org). - FM
+* Reset any modified, non-HT-LEFT styles in HTML_free() if they were not
+ reset in HTML_end_element() due to missing end tags. - FM
+* Initialize the putenv_command pointer in LYMain.c. - Christophe Colle
+ (colle@krtkg1.rug.ac.be)
+* Include LYLocal.h in LYCgi.c. - Carl Hansen (hansen@best.com)
+05-28-96
+* Made all mainloop() statusline() message strings definitions in userdefs.h
+ for easier modification to other languages (we'll move them to a catalog
+ someday 8-). - FM
+* Added string definitions in userdefs.h for statusline messages identifying
+ active or DISABLED radio buttons. - FM
+* More tweaks of character conversions. Note that numeric entities with
+ values greater than 255 are displayed as text, until we are able to
+ handle them as Unicode. - FM
+* Implemented ID handling for BDO. - FM
+05-27-96
+* Added nested handling of Q, so that it alternates between double-quotes
+ and single-quotes, with directionality of start and end single-quotes
+ (should someday check the LANG and DIR attributes, and character set,
+ to use other quoting conventions if appropriate). - FM
+* Use [DEL: ... :DEL] labeling to indicate DEL content, and [INS: ... :INS]
+ labeling to indicate INS, S, and STRIKE content. - FM
+* Added ID handling for ABBREV, ACRONYM, AU, AUTHOR, BIG, DEL, INS, Q, S,
+ SMALL, SUB, SUP and SPAN. - FM
+* Added code to clear the screen of any trace messages directed to the
+ screen, once the full page has been created. - FM
+* Added code to minimize slang's casting of trace messages as reverse when
+ directed to the screen instead of a file. - FM
+05-26-96
+* More tweaks of character conversions. - FM
+* Added submit_enctype elements to the forms structures as will be needed to
+ implement INPUTS with TYPE="file" (someday 8-), and set disabled for FORM
+ fields if the ENCTYPE is multipart/form-data, until we can handle that
+ (someday 8-), so the user won't fill out the FORM pointlessly. - FM
+* Made the third argument of SLang_init_tty() 1 so that '\n' will be treated
+ as CRLF when trace messages are sent to the screen instead of to a file.
+ Might cause problems with the slang screen management functions, but
+ doesn't seem to according to KW. - FM
+05-25-96
+* Mods to pass 8-bit control characters entered via the line editor. They
+ should be assumed to be valid if the user entered them, and could indeed
+ be valid for Japanese and Russian. - FM
+* Check for a NULL return value from initscr() on Unix. - Geert Jan de Groot
+ (GeertJan.deGroot@ripe.net)
+* Tweaks of character conversions, and of 8-bit character handling with
+ slang. - Klaus Weide (kweide@tezcat.com)
+* Added TRUSTED_URL for specifying lynxexec and lynxprog URLs which always
+ are permitted, based on patches from David Drum (david@more.net). - FM
+05-21-96
+* Made the LOCAL_DOMAIN symbol configurable via lynx.cfg. - FM
+* Added descriptions of the quality (q=) and maxbytes (mxb=) parameters
+ in the sample mailcap file. - FM
+* Added a maxbytes element to the libwww presentation and converter
+ structures, and code for specifying a maximum for mailcap entries via
+ a semi-colon-separated mxb=value field, where "value" is a positive
+ integer (e.g., ; mxb=1000000). The default is 0, meaning no maximum.
+ If the value exceeds 0, a maxbytes parameter will be appended in the
+ Accept: header for the Content-Type. - FM
+05-20-96
+* Added code for specifying a quality parameter for mailcap entries via
+ a semi-colon-separated q=value field, where "value" is a floating point
+ number (e.g., ; q=0.002), and for appending the quality parameters in
+ Accept: headers if the values are less than 1.0. - FM
+* Treat screen width as 80 for the startup page when doing traversals with
+ a slang-build Lynx to prevent a crash. - FM
+05-19-96
+* Mods in HTML.c to make resolving of local file URLs more efficient. - FM
+* Tweaks of Makefile for slang. - Ed Doolittle (dolittle@math.toronto.edu)
+05-18-96
+* Added FRAME elements and attributes to the DTD, and code for creating
+ links to the SRCs. - FM
+* Added numerous sanity checks for valid but inappropriate combinations
+ of attributes based on the HTML 3.2 DTD.
+05-17-96
+* Added support for TYPE and VALUE attributes of LIs in OLs. TYPEs
+ are equivalent to those for OL, and VALUE is equivalent to START
+ or SEQNUM for OL. See the 11-28-95, 10-17-95, 09-19-95 and 09-04-95
+ entries in this file. If a TYPE is changed via an LI, the change
+ persists for subsequent LIs of that OL. The VALUE set for an LI
+ similarly increments for subsequent LIs in that OL. - FM
+05-16-96
+* Made SGML_character() in SGML.c fully reentrant. - FM
+* Set up capturing of marked sections, and DOCTYPE, ELEMENT, ATTLIST and
+ ENTITY declarations in SGML.c. Lynx doesn't do anything with them yet,
+ besides reporting them in trace mode, but they at least won't create
+ garbage in the display if they start being used for the "next generation"
+ of clients. - FM
+* Set up base code for CSIs (Client Side Includes, homologous to SSIs).
+ See the comments for LYDoCSI() in LYUtils.c. It should be moved to a
+ separate module if someone wants to work on CSIs seriously. LYDoCSI()
+ is called from SGML.c if the document was obtained via a file URL on
+ the local host and has comments that begin with "!--#". - FM
+05-15-96
+* Add a MIME charset parameter to POST Content-Type headers if it's not
+ ISO-8859-1 or US-ASCII and the server included the parameter when it
+ sent the form (but don't do it simply on the basis of the user's current
+ character set, because if the server didn't include the parameter, it's
+ CGI script probably won't parse the client header either, and will return
+ an error instead of processing the form submission). - FM
+05-14-96
+* Tweaks for Unixware and addition of a unixware-slang Makefile target based
+ on patches from Thanh Ma (tma@encore.com). - FM
+* Tweaks for SCO and addition of an sco5 Makefile target based on patches
+ from Bela Lubkin (filbo@armory.com). - FM
+* Include ;q=0.001 for the wildcard (*/*) Accept header. - FM
+05-13-96
+* Added support for a host field in news URLs, analogous to that for nntp
+ URLs. Though illegal according to the current RFCs, discussions with a
+ W3C member about this Netscapism indicate that Lynx may as well support
+ it now, rather than continue failing when it is encountered. - FM
+05-12-96
+* Added an explicit GetYX definition for slang in LYForms.c. - FM
+05-11-96
+* Eliminated the NCURSESINCDIR compilation symbol and added NCURSESHEADER,
+ so the default now is to seek ncurses/curses.h and -DNCURSESHEADER invokes
+ a seek for the (now obsolete 8-) ncurses.h. - FM
+* Added an explicit GetYX definition for slang in LYStrings.c (now avoids
+ reference to stdscr). - FM
+* Mods in tcp.h for TCPWARE builds on VMS with DECC. - FM
+05-08-96
+* Fixed typo in Makefile entry for linux. - LWV
+05-07-96
+* Added LYPassHighCTRL boolean for passing normally illegal 8-bit control
+ characters, and set it TRUE when the KOI8-R character set is selected
+ (note that they also are passed when Japanese character support is
+ toggled ON). - FM
+05-06-96
+* Mods in SGML.c to handle "<URL:" as text instead of an unknown tag. - FM
+05-05-96
+* Added typecasts of the third arguments for the getsockname() and
+ accept() calls in HTFTP.c to void pointers, to avoid conflicts with
+ their declarations as int versus unsigned int across platforms and
+ flavors. - FM
+* Renamed the for-VMS opendir(), readdir() and closedir() to HTVMSopendir(),
+ HTVMSreaddir() and HTVMSclosedir(), and the for-UCX ioctl() to HTioctl(),
+ to avoid possible conflicts with their additions to newer versions of
+ VMS and UCX. - FM
+05-04-96
+* Fixed typo which was placing a space instead of a slash between the
+ User-Agent name and version. - Tim Rowley (tor@cs.brown.edu)
+
+--- STARTING 2.5FM ---
+--- Rename of Lynx2-4-FM and release as Lynx2-5 (02-May-1996) ---
+ (see CHANGES2-5, CHANGES2-4 and CHANGES2-3)
+==============================================================================
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.7 b/gnu/usr.bin/lynx/docs/CHANGES2.7
new file mode 100644
index 00000000000..559ebd255a1
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.7
@@ -0,0 +1,831 @@
+=======================================================================
+--- Release of Lynx2-6FM as Lynx v2.7 (February 15, 1997) ---
+=======================================================================
+1997-02-15
+* Release of Lynx2-6FM as Lynx v2.7. - FM
+* Included -Ae when compiling the Implementation modules for the snake3
+ target. - FM
+1997-02-14
+* Mods to issue an alert about a BASE tag not having an absolute URL only
+ once per document. - FM
+* Added code for appending LYNX_SIG_FILE to email messages as well as to
+ news posts or followups, and updated the Users Guide accordingly. - FM
+* Updated build-slang.com. - FM
+1997-02-12
+* Fixed some problems in the code for using a hookless Lynx image with
+ snew_proxy, snewspost_proxy, and snewsreply_proxy set to
+ "nntp://host:port/" so that it uses Tom Zerucha's (tz@execpc.com)
+ daemon which handles the SSL communications on behalf of the Lynx
+ image. Also polished up all of the news gateway code, and added
+ comments for the benefit of new developers. - FM
+* Added an ECGOTO command mapped by default to 'G', complementary to the
+ GOTO command (default 'g'), to edit the current document's URL and then
+ go to it. Using case-sensitive letters with different command definitions
+ ensures that both will appear with their brief explanations in the 'k'eymap
+ listing. For ECGOTO, Control-G, failure to modify the URL, or complete
+ deletion of it, all act as a cancel. If the current document has POST
+ content associated with it, a warning will be issued before offering the
+ URL to edit. The POST content is retained if the modification merely
+ involves a change in fragment for the URL. Otherwise, the modified URL
+ (if it has an http scheme) will be submitted with method GET and no POST
+ content. If the ECGOTO command is not cancelled, or not simply a fragment
+ change, the modified URL will be added to the 'g'oto buffer, and can be
+ re-accessed, to edit further, via the GOTO command. See the updated online
+ 'h'elp for more information. - FM
+1997-02-10
+* Amplified the comments concerning deletion of prototypes for MultiNet
+ socket library functions as they get added to MultiNet's own headers
+ in newer versions of it's socket library. - FM
+* Added a missing fclose() in post_article() of HTNews.c, and added code
+ to delete the temporary file there, so it's gone as soon as we're done
+ with it. - FM
+02-09-97
+* Enhanced the Set-Cookie header parser to handle values that contain
+ spaces but were not enclosed in double-quotes, and to use such
+ quoting or not when sending Cookie headers, depending on whether
+ this was done in the Set-Cookie header. Also added anti-crash
+ checks should the parser's efforts to handle both historical (a.k.a.
+ original Netscape) cookies and Version 1 cookies go awry (does deal
+ successfully now with all the cookies which had been reported as
+ problematic). - FM
+* Mods of the screen handling in LYNews.c for cleaning up any screen
+ trash created by the external editor. - FM
+* Tracked down an uninitialized pointer in LYNews.c that probably was
+ behind reports of crashes when posting to newsgroups. - FM
+* Plugged a memory leak in LYMainLoop.c. - TJC
+* Added posting ability to the news gateway, in lieu of the previous,
+ variably reliable, use of a spawned news client for posting. The
+ news, nntp, and snews URLs now all return links for posting new
+ messages or followups (replies) to the server from which a newsgroup
+ listing or news article was retrieved, unless the server indicates
+ that it does not accept posts from the site at which Lynx is running.
+ See the updated INSTALLATION, userdefs.h, and lynx.cfg files, the
+ "USENET News posting" section of the Users Guide, and "Supported URLs"
+ page of the online 'h'elp for more information.
+* Fixed typo for e-dieresis in the KOI8-R charset. - AJF
+* Replaced an inappropriate _user_message() call in HTConfirmCookie()
+ of HTAlert.c with a _statusline() call. The original code could
+ cause crashes with some cookie values. - FM
+02-06-97
+* Added support for both hex escaped and unescaped white characters
+ in lynxexec and lynxprog URLs. Normally, Lynx strips out any white
+ characters that are not hex escaped in attribute values that are
+ to be resolved as URLs, on the assumption that they were derived
+ from wrapping in the markup. Any serial white characters in
+ lynxexec and lynxprog URLs are condensed to one space (' '), and
+ any lead or trailing white characters are trimmed. Note that we
+ still require hex escaping of spaces in mailto URLs, e.g,
+ HREF="mailto:lynx-dev@sig.net%20(I%20found%20a%20bug.)". - FM
+* Removed the 'e' switch from tar commands in LYLocal.c for greater
+ portability across all supported Unix flavors. - FM
+* Expanded the information in the PROBLEMS file on how to deal with
+ DECC and MultiNet header incompatibilites for different combinations
+ of the VMS compiler and socket library versions. - FM
+* Added TRACE message of the edit command created for the system()
+ call in LYEdit.c. - LWV
+* Fixed a typo in the userdefs.h comments. - NHE
+02-04-97
+* Mod in LYMainLoop.c to bypass mailing "not found" messages when
+ MAIL_SYSTEM_ERROR_LOGGING was set TRUE (which it should NOT be,
+ indescriminately) if the document's owner is the lynx-dev list. - FM
+* Added crash protection checks for the actual presence of anchors
+ in all HText structure anchor scans in GridText.c, based on a crash
+ report and suggested fix for one of them from Jonathan Sergent
+ (sergent@hillres55-129.cc.purdue.edu). - FM
+* Eliminated the typecast for ttytype (apparently varies across flavors,
+ and each flavor should know it's own typing; we'll see) in LYCurses.c,
+ and moved VMS system definitions with non-ANSI conformant tokens to a
+ separate header for VMS (LYVMSdef.h). - BL
+* Made the description of HISTORY in the 'k'eymap page more clear that
+ it invokes a list of the "suspended" documents currently held in the
+ history stack. - DC
+* Typo fixes in the help files and lynx.cfg. - LWV
+02-03-97
+* Today's distribution is a pre-release of v2.7. The projected official
+ release date is 02-15-97. All header, help and documentation files,
+ and the top directory name, have been updated for v2.7. - FM
+* Made xli, which is freeware, the default XLOADIMAGE_COMMAND for Unix
+ in userdefs.h (still xv on VMS, since its port is freeware), and
+ expanded the "self-documentation" to indicate where to get this
+ freeware. Added XLOADIMAGE_COMMAND as a configuration symbol in
+ lynx.cfg, so that the compilation default can be overridden on
+ systems which have and prefer xv (all users can override the default
+ mappings for image helper apps via their mailcap files) - FM
+* Added a -base command line switch which can be used with -source or
+ -mime_header to prepend the request URL as a comment, and a BASE tag
+ (which may or may not be the same as the request URL, depending on
+ HTTP/1.1 headers) for text/html documents, equivalent to the prepend
+ kludge for 'd'ownloads (see 09-20-96 mods). - FM
+* Added a check for an "ORGANIZATION" environment variable for inclusion
+ as a news post header on Unix (all system logicals intended for news
+ post headers automatically are included on VMS), and a sleep() before
+ restoring curses mode after the post, to allow reading of any error
+ messages from the news software. - FM
+* Fixed bug which yielded a "[LINK]" instead of "[INLINE]" pseduo-ALT
+ for ALT-less IMG tags used as the content for NAME-ed Anchors without
+ an HREF. - FM
+* Portability tweaks for the mini inews utility. - FM
+* Fixed an old and irrelevant typo in HTWriter.c. - JS
+01-29-97
+* Added more REL tokens that are acceptible for banner links. - FM
+* Ifdef'ed the standard foo_PATH definitions for FreeBSD at the bottom of
+ userdefs.h, based on a patch from AAC, and assuming they also apply for
+ NetBSD, BSDI, and Linux (we'll see 8-). - FM
+* Added make freebsd-slang target. - AAC
+01-28-97
+* Mods of LYSetCookie() to ensure setting of 443 as the default port for
+ https URLs, and force the secure flag on for https URLs whether or not
+ the Set-Cookie header had a secure parameter (too many Version 0
+ cookies don't, when they should). - FM
+* Removed -ltermcap from make for all ncurses targets. - FM
+* Tweaks of make for FreeBSD. - AAC
+* Use SLtt_get_screen_size() instead of the apparently less portable
+ code for slang in size_change() of LYUtils.c. - JED
+01-27-97
+* Made ALT a synonym for VALUE in INPUTs with TYPE="image" to cooperate
+ with well-intentioned (though misinformed) providers who use ALT instead
+ of VALUE for the benefit of text clients or GUIs with image handling
+ turned off. - FM
+* Modified the code for submission of form content with TYPE="image" NAME-ed
+ INPUTs that have a VALUE (or ALT) to "fake" a 0,0 coordinate pair, as when
+ a VALUE (or ALT) is absent, instead of sending a single name=value pair.
+ Requests that using a name=value pair in such cases to indicate that the
+ submission was from a text client or GUI with image handling turned off
+ be included in the HTML specifications keep falling on deaf ears, so we
+ may as well "fake" something closer to what the CGI scripts are expecting,
+ and hope that the script interprets 0,0 as an indicator that the user did
+ not see the image and make a conscious choice within it.
+* Added code to offer a link for the SRC of the image in INPUTs with
+ TYPE="image", distinct from the submit button, when clickable images
+ is on. - FM
+* Updated the "HTML Forms" section of the Users Guide. - FM
+* Fixed a typo in the parsing of Cache-Control MIME headers and META
+ directives. - FM
+01-25-97
+* Updated lynx_help_main.html, about_lynx.html and about_lynx-dev.html. - FM
+* Mods to indicate a toolbar by a '#' preceding its first link when the
+ toolbar is being displayed, and to indicate the availability of a toolbar
+ by a '#' in the top, left-hand corner of the screen when the toolbar is
+ not being displayed. Added explanation of this in the online 'h'elp. - FM
+* Indicate the 'allow' setting (always, never, or via prompt) for each
+ domain in the Cookie Jar Page. - AK
+* Don't delete cookie-less domains silently during garbage collections if
+ they have their 'allow' set to always or never. - AK & FM
+* Added ability to change the 'allow' settings for domains via the Cookie
+ Jar Page. - FM
+* Added basic protection against "denial of service attacks" by limiting
+ a domain to 50 cookies, the total number of stored cookies to 500, and
+ the maximum processed size of a cookie to 4096 bytes. - FM
+* SGML escape any ampersands or angle brackets in the cookie names, values,
+ parameters, and comments when creating the HTML stream for the Cookie
+ Jar Page, and only include entries for comments if they were present in
+ the servers' Set-Cookie headers. - FM
+* Updated the online 'h'elp for cookies. - FM
+* Removed -DNO_KEYPAD from all ncurses targets in the Makefile. - FM
+01-23-97
+* Added a "Lynx State Management (Me want cookie!)" section to the Lynx
+ Users Guide, and a cross-linked cookie_help.html file for the Cookie
+ Jar Page. - FM
+* Added prompting for whether to show the body of a 401 status reply or
+ simply return to the current document when an activated link requires
+ authentication via a username and password, and the user has none for
+ that realm, or forgot them. - FM
+01-22-97
+* Added handling of expires attribute values in Version 0 (a.k.a. Netscape)
+ Set-Cookie MIME headers or META tags, and added "Maximum Gobble Date"
+ entries in the Cookie Jar Page which indicate the maximum intended age
+ for each cookie based on the Version 0 expires or Version 1 max-age
+ attribute values. - FM
+* Added an LYmktime() function in LYUtils.c which accepts strings in the
+ format "Day, dd-Mon-yy hh:mm:ss GMT" or "Day, dd Mon yyyy hh:mm:ss GMT",
+ parses and converts them to time_t format (seconds since 00:00:00 Jan 1
+ 1970), and returns the time_t value, or zero if the date is in the
+ past. It is used for handling Expires headers or attribute values. - FM
+* Added parsing of Cache-Control and Expires MIME headers and META tags
+ sufficient to determine whether the no_cache element should be set in
+ the document's structures. - FM
+* Eliminated the "; $Path=foo; $Domain=blah" attr=value pairs when sending
+ Version 0 (a.k.a. Netscape) cookies in request headers, because too may
+ CGI scripts in the real world have brain-dead parsers and fail when they
+ are included. - FM
+* Added handling of Set-Cookie directives in META tags. - AK
+01-20-97
+* Added confirmation prompts for deletions from the Cookie Jar, expanded
+ the garbage collecting for expired cookies, debugged and implemented the
+ code for security checks based on lead and embedded dots in domain values
+ and host prefixes as described in Section 4.3.2 of the -05 State Management
+ draft, added requirement for https URLs (direct, or via proxy) to include
+ cookies which have the secure flag set in request headers, and extensively
+ annotated the cookie support code for ease of further development. - FM
+* Added ability to set SHOW_CURSOR in lynx.cfg, to override the compilation
+ setting in userdefs.h, and made the -show_cursor command line switch a
+ toggle for the compilation or configuration default. - FM
+01-18-97
+* Bug fixes and memory leak plugs for the cookie support. Added ability
+ to delete individual cookies or entire domains via the Cookie Jar Page
+ (Ctrl-K). The domains and cookies are displayed as DL/DT/DD blocks,
+ with links for each domain and cookies name. The deletions are done
+ by activating those links, which can be numbered, so it should be OK
+ for blind users. - FM
+* Tweaks of the news/nntp/snews gateway. - FM
+* Tweaks of paragraphing if ADDRESS, BANNER, BLOCKQUOTE, BQ, FN, MARQUEE
+ or NOTE blocks are nested (note that nesting does not yield progressive
+ indentations of these blocks). - FM
+01-16-97
+* Added "first pass" cookie support based on patches from Andrew Kuchling
+ (amk@magnet.com). Still needs work (see comments at top of LYCookie.c).
+ A SET_COOKIE symbol in userdefs.h and lynx.cfg determines whether cookie
+ support will be on or off by default, and the default can be toggled
+ via a -cookies command line switch. When on, Set-Cookie headers invoke
+ confirmations with possible replies of 'Y'es or 'N'o for that cookie,
+ 'A'lways, to accept all cookies from that domain, or ne'V'er to never
+ accept cookies from that domain. The Cookie Jar can be examined via
+ the COOKIE_JAR keystroke command, mapped by default to Ctrl-K. The
+ Cookie Jar, and any 'A'lways or ne'V'er settings, do not presently
+ outlast the Lynx session. - FM
+01-14-97
+* Added use of DEFAULT_INDEX_FILE or the URL from an -index=URL command
+ line switch as the the HREF for a banner LINK with REL="Index" and no
+ HREF of its own (see the 01-01-97 mods and the HTML Banners section of
+ the Lynx Users Guide). - FM
+01-13-97
+* Tweaks of the news gateway. - FM
+* Added "Negotiate: trans" header for GET and HEAD requests. Shouldn't
+ be necessary to get 300 instead of 406 replies when nothing matches
+ the Accept and Accept-foo request headers, but some HTTP/1.1 servers
+ apparently want it when the UA declares itself as HTTP/1.0, as Lynx
+ still does. - FM
+01-12-97
+* More updates of the online 'h'elp files. - FM
+* Simplified the code for checking whether a startfile is a bookmark file
+ entered as a URL instead of invoked via the -book switch. The previous
+ code was tripping up some versions of the osf and linux compilers. - FM
+01-10-97
+* Replaced the realloc() in split_line() of GridText.c with a calloc(),
+ memcpy(), FREE() sequence for all systems, not just AIX and ultrix,
+ based on analysis of memory wastage by Hans Reiser
+ (dl9rdz@cip.e-technik.uni-erlangen.de). - FM
+* Tweaks of the body= handling in mailto URLs. - FM
+* Tweaks of the ftp gateway. - FM
+* Restored inheritence when resolving versus a base with the same scheme,
+ because the RFC1808 and Fielding Draft behavior of not doing so yields
+ too many failures in the real world (sigh...). - FM
+01-09-97
+* Ugh! The distribution zip still had the Nov 4, 1996 HTTCP.c instead of
+ the one I modified on Christmas. No wonder people were still reporting
+ the wrong messaging with -DNSL_FORK. The right HTTCP.c is in there
+ now. - FM
+* Mods to resolve the HREFs for LINKs with REV="made" or REV="owner"
+ versus the base (a many, many year old bug finally caught 8-). - FM
+* Added HTAlert messages about BASE HREF vaules, Location header values,
+ and Refresh URL values that were not received as absolute URLs. We
+ still resolve them versus the RequestURI, since that's invariably
+ what is intended, and thus the optimum "error recovery" strategy. - FM
+* Added handling of cc= and body= fields in ?searchpart strings of mailto
+ URLs. They are described in draft-hoffman-mailto-url-00.txt recently
+ posted to the URI-WG list. This draft ignores the objections which have
+ been filed about changing the semantics of mailto and breaking clients
+ which are fully conformant with the mailto specs in RFC1738, instead of
+ using a new scheme name (e.g., smtp:) for URLs with mail headers, and it
+ extends the ill-advised use of '&' as puctuation in URLs instead of
+ honoring the previous IETF effort to seek it's replacement by ';' as the
+ URL name=value separator and, in effect, treating them as parameters
+ without need to worry about confusions with entities when the URLs are
+ attribute values in text/html. However, the chairman of the URI-WG is
+ a co-author of this draft, so, sigh... As far as this Lynx code is
+ concerned, the mods are more "error recovery" to cope with the sad things
+ which have afflicted the Web during the past 2-3 years, and use of a
+ ?searchpart in mailto URLs is still DISadvised. Lynx uses only subject=,
+ cc=, and body= fields from a ?searchpart, using it's own "safe" rules for
+ other mail headers, and ignoring ones other than those three in the
+ ?searchpart as "unsafe". The cc= values in a ?searchpart are added to
+ the primary address as a comma-separated list for the mail agent, and
+ Lynx's own Cc: is that entered, optionally, by the user. Any body= field
+ is passed to the external editor, if one has been defined, for review and
+ possible modification. Otherwise, it is scrolled for review. The mailing
+ can be cancelled at any time (via Ctrl-G), and via a statusline prompt
+ after everything has been reviewed, if the user judges the body and/or
+ addresses to be unsafe or inappropriate. - FM
+* Moved information and prompt strings in LYMail.c to installer-modifiable
+ symbols in LYMessages_en.h. - FM
+01-07-97
+* Eliminated forced exits for keyboard input buffer overruns on VMS.
+ There's no perfect way to deal with it, but Lynx should recover
+ gracefully most of the time now, and do nothing bad if ungraceful. - FM
+* Added handling of Content-Base and Content-Location MIME headers when
+ 'd'ownloading, 'p'rinting, or mailing HTML source. For this, as
+ for rendered HTML streams (see 01-06-97 mods) the base is determined
+ according to HTTP/1.1 rules: If a Content-Base header was received,
+ that's the base. Otherwise, if a Content-Location header was received
+ and it's an absolute URL, that's the base. Otherwise, the URL used
+ to retrieve the document is the base. When actually rendering, any
+ BASE tag in the document overrides the base derived from headers.
+ When 'd'ownloading, or outputting HTML source for a 'p'rint option,
+ an X-URL comment with the URL used to retrieve the document and a
+ BASE tag with the header or URL-derived base are inserted at the top
+ of the document. These should be moved down into the actual HEAD
+ section to make the HTML fully legal, but will work as is if the
+ output is used in conjunction with automatic invocation of Lynx or
+ Netscape as a text/html helper application. When mailing with an
+ SMTP-conformant mailer, the actual URL used to retrieve the document
+ is indicated via an X-URL header, and for HTML source, a Content-Base
+ and a Content-Location header are included, set to what was actually
+ received by Lynx via MIME headers, or to the retrieval URL. - FM
+01-06-97
+* More updates of the online 'h'elp. The Visited Links Page ('V'),
+ multi-bookmark file support, REL/REV and META enhancements, and new
+ switches are now all fully documented in the 'h'elp. - FM
+* Added handling of Content-Base and Content-Location MIME headers for
+ rendered HTML streams (still using the document's URL in the 'd'ownload
+ and 'p'rint (and mailing) BASE prepending kludge). - FM
+* Added code to avoid getting tripped up by double-quoted header values
+ in HTMIME.c. We still need more sophisticated parsing of possibly
+ compound HTTP/1.1 headers, but we don't yet use any of those. - FM
+* Tweak of the efficiency mods for command line parsing in LYMain.c. - FM
+* Simplified some code in LYMainLoop.c that was tripping up the AIX32
+ compiler. - FM
+01-04-97
+* More updates of the online 'h'elp. - FM
+* Added DIRED_MENU support for .tgz files as for .tar.gz files. - FM
+01-03-97
+* Made the command line parsing in LYMain.c more efficient. - FM
+* Added -nopause switch for setting InfoSecs, MessageSecs, and AlertSecs
+ to zero. Can be used to eliminate forced statusline pauses during
+ traversals. - FM
+* Mods to allow absolute zero quality values for Accept headers, so that
+ in mailcap files users can do things like map image/* to a helper app
+ but exclude particular image subtypes which the app can't handle by
+ assigning q=0 for that subtype. HTTP/1.1 still specifies 4 significant
+ figures for quality values, so if the value is non-zero, Lynx still
+ forces a minimum of q=0.001. - FM
+* Typo fixes in lynx.cfg. - LWV
+01-02-97
+* Updates of the online 'h'elp files. - FM
+* Made the parsing of lynx.cfg in LYReadCFG.c more efficient. - FM
+01-01-97 -- Happy New Year!
+* More partial/relative HREF resolving enhancements. Everything is now
+ handled as recommended in Larry Masinter's -03 revision of Roy Fielding's
+ -02 URL ID, except file and ftp URLs (which Lynx handles as described
+ in the online 'h'elp ). Note, though, that Lynx handles known schemes
+ on a scheme-by-scheme basis, and for schemes that involve substitutions
+ of "/" for a NULL/zero-length path, Lynx inserts the "/" at the resolving
+ stage, so those slashes are present where the Fielding test suite doesn't
+ indicate them, but the actual requests sent to servers (or bad URL message
+ if it's a scheme that requires a host field and doesn't have a default)
+ will be the same. Note, also, that Lynx sends only the path<?searchpart>
+ ("absolute path") in it's direct http requests and indicates the host of
+ the URL in the Host: header, i.e., sends the absolute URL only to proxies.
+ Note, as well, that Lynx treats a zero-length attribute value for an HREF,
+ SRC, etc. as a reference to the currently displayed document, but still
+ uses the base (which might not be the current document's address) as the
+ default for FORMs without an ACTION specified, or ISINDEX tags without
+ an HREF or ACTION specified. - FM
+* Expanded REL/REV handling. All of the REL values in the (expired) Maloney
+ and Quin draft-ietf-relrev-00.txt ID which make sense for banner links in
+ Lynx have been added. For REL="Help" without an HREF in the LINK, Lynx
+ uses its helpfile URL. For REL="Home" without an HREF in the LINK, it
+ uses the configuration startfile or WWW_HOME URL (i.e., not a startfile
+ specified on the command line), or the command line homepage, if it was
+ specified. - FM
+* Added handling of fragments in conjunction with URL expansion guessing for
+ startfile, homepage and 'g'oto strings. Note that any '#' that is not a
+ fragment delimiter should be hex escaped (%23), and ideally all reserved
+ or unsafe characters will be hex escaped in the user-entered string, though
+ you can get away with not using the hex codes for most others, depending on
+ their positions in the string. Also note that on VMS if you include the
+ version for local files it must precede the fragment (e.g., foo.html;3#frag)
+ as for parameters. - FM
+12-26-96
+* Mods of HREF resolving to be more consistent with the latest IETF draft
+ (http://www.ics.uci.edu/pub/ietf/uri/draft-fielding-url-syntax-02.txt).
+ Most importantly, lone fragments (HREF="#fragment") are resolved versus
+ the current document's URL, and no longer versus the BASE, if present.
+ There are a few things in the draft which are at odds with what virtually
+ all currently deployed browsers do, and so I stuck with the "deployed"
+ behavior. Try the tests in http://www.ics.uci.edu/~fielding/url/ to
+ see where Lynx still differs from the draft. - FM
+* Tweaks of 'z'ap handling. - FM
+12-24-96
+* Tweaks of DIRED_SUPPORT and make for osf. - FM
+12-23-96
+* Added code to check if the startfile has BOOKMARK_TITLE as its title,
+ and if so, and it's in the bookmark file list, add the bookmark element
+ and reload to have it treated as if it were invoked with -book. - FM
+12-21-96
+* Added code for the DIRED_MENU command ('f' and 'F' by default) to invoke
+ CSwing on VMS if CSWING_PATH is defined, as explained in userdefs.h and
+ lynx.cfg . - FM
+12-20-96
+* More improvements in the fatal error and memory exhaustion handling, and
+ plugging of memory leaks. - FM
+* Changed "newline" to "Newline" in LYMainLoop.c to deal with another
+ reported, ill-advised, macro in the AIX 4.2 curses.h. - FM
+* More tweaks of lynx.cfg. - FM
+12-19-96
+* Improvements in the messaging and cleanups for aborts on fatal errors
+ and exits on memory exhaustion. - FM
+* Worked v2.1 of lpansi.c into the distribution. - FM
+* Modified lynx.cfg to reflect the compilation defaults consistently, and
+ changed the compilation default for SUBSTITUTE_UNDERSCORES to FALSE. - FM
+* Changed the "lines" element to "Lines" in the HText structure and the
+ "tab" structure name to "Tab" to cope with some unwise employee reportedly
+ using all lower case "lines" and "tab" strings as macros in the AIX 4.2
+ curses.h. - FM
+12-17-96
+* Restored use of the -l format in the parent links of local Unix directory
+ listings if LONG_LIST is defined, without the v2.6 bug of creating strange,
+ trailing relative or escaped strings. As far as I can tell from exercizing
+ them, the DIRED_SUPPORT and LONG_LIST handling are now fully debugged
+ (famous last words... 8-). - FM
+12-16-96
+* Don't reiterate parent links in local directory listings. They are
+ offered only in the top, up to parent link if NO_PARENT_DIR_REFERENCE
+ is not defined. - FM
+* Moved more HTML.c functions to LYCharUtils.c. - FM
+* Tweak of META handling, which was causing crashes (due to freeing an
+ anchor structure prematurely in the 12-13-96 mods for moving HTML.c
+ code to LYCharUtils.c). - FM
+* Block Unix relative path strings in lynxexec and lynxprog URLs. - DT
+12-14-96
+* Added a COLLAPSE_BR_TAGS compilation and configuration symbol for
+ determinining whether Lynx collapses serial BR tags. Note that the
+ valid way to create extra blank lines in HTML is with PRE blocks that
+ contain only newlines. - FM
+* Fixed a longstanding glitch in the alignment handling which could
+ cause a Paragraph's ALIGN value to cross embebbed blocks, rather than
+ restoring the appropriate alignment for the outer division or block
+ on close of the embedded block. - FM
+* Modified HR handling so that it inserts the same before and after
+ spacing regardless of whether P end and/or start tags are present
+ before and/or after the HR. - FM
+* Don't insert the bookmark file description and filepath if multiple
+ bookmark file support has been turned off, and this is the default
+ bookmark file (but they will still be inserted if it's not the default,
+ e.g., if it's another bookmark file viewed before the support was
+ turned off, and retrieved as a previous document). - FM
+12-13-96
+* Added parsing of Content-Disposition in META tags and setting the
+ suggested file name if file; filename=name.suffix is in the value
+ of the Content attribute and we don't already have that via a server
+ header. - FM
+* Incorporated almost all globals related to stream parsing and page
+ display in HTML.c and GridText.c into the HTML object structure and
+ HText structure to make the parsing and display functions more nearly
+ re-entrant, and moved several functions from HTML.c to LYCharUtils.c
+ to reduce the size of HTML.c. - FM
+* Added -cckr to the libwww Makefile compiler options for SGI. - Carl
+ Buxbaum (crb@world.std.com)
+* Fixed typo in LYMainLoop.c that affected the 'd'ownload command when
+ DIRED_SUPPORT is enabled. - FM
+12-10-96
+* Implemented Safe header handling and prompting about resubmissions of
+ forms with method POST along the lines described in the 24-Nov-96 IETF
+ ID: http://gewis.win.tue.nl/~koen/draft-holtman-http-safe-01.txt
+ Lynx prompts for confirmation whenever it detects that a resubmission
+ would occur, unless the previous reply included "Safe: yes". Prompts
+ always will occur if the -resubmit_post toggle is on (since resubmission
+ always would occur; not advised). If not toggled on, resubmissions
+ would occur when no_cache is set or the previous reply has been dumped
+ from the cache. When using the PREV_DOC command or History Page, if
+ confirmation is not obtained, Lynx will skip to the yet earlier document,
+ or cancel, as appropriate. - FM
+* Added parsing of the Safe header in HTMIME.c, and added a safe element
+ to the anchor and document structures. Will be FALSE unless a Safe
+ header is received that specifies "YES" or "TRUE" (case-insensitive,
+ only "YES" is in the specs), and applies only to replies from form
+ submissions with the POST method. - FM
+* Cleanup of code in HTAccess.c. May correct problem of crashes for
+ ISINDEX searches on some systems, though I couldn't reproduce that
+ problem here. - FM
+12-09-96
+* Added an HTSetPresentation() for image/x-xbitmap in HTInit.c when DISPLAY
+ is set. - FM
+* Added an LYOutOfMemory boolean that is set by the outofmem() macro, and
+ code in the Unix FatalProblem() and VMS exit handler for reporting the
+ memory exhaustion instead of the misleading "bug" message when they are
+ invoked due to memory exhaustion. May not be reported reliably for
+ linux, because for some reason I don't understand, the SIGBUS trapping
+ is ifdef'ed out for linux in LYMain.c. - FM
+* Fixed typo in the new LYAddVisitedLink() in LYHistory.c of yesterday's
+ mods. - KW
+12-08-96
+* Added a VLINKS command, mapped by default to upper case 'V', and code
+ for creating a list of all links 'V'isited during the current Lynx session
+ in order of recency (most recent highest in the list). Lower case 'v' is
+ still mapped to VIEW_BOOKMARKS. The VLINKS listing is complementary to
+ the History Page listing, and formatted similarly. It excludes POST
+ replies, and bookmark, menu and list files (use the History Page or
+ direct keystroke commands for those). It includes any links that were
+ downloaded, or passed to a helper app (except mailto and newsreply or
+ newsfollowup links, since those require activation in the original
+ document for proper inclusion of it in the email message or news
+ post). You can print the Visited Links Page, or 'd'ownload it via
+ the History Page. - FM
+* Added reporting of the Charset parameter, if present in a server reply
+ header, META tag, or by virtue of a suffix map, to the showinfo ('=')
+ display. - FM
+12-07-96
+* Added 'p'rint menu support for the History Page. - FM
+* Added a content_length element to the anchor structure and use that,
+ if a Content-Length header has been received, to indicate the total
+ bytes in the statusline when receiving the stream. - FM
+* Include HTTP_ACCEPT_LANGUAGE in the lynxcgi environment. - David Trueman
+ (david@cs.dal.ca).
+12-06-96
+* Many more cleanups and commenting of the code for the benefit of new
+ developers. - FM
+* Tweaks of URL parsing and path simplifications. Added simplification
+ of the file://localhost paths from startup and 'g'oto guesses. - FM
+* More anti-crash protections for bad HTML in SELECT blocks. - FM
+* Usability enhancement for DIRED's 'F' menu: list number and names of
+ (some of) the tagged items, and provide a way to untag all items. - KW
+* Force screen refresh after a DIRED system command has failed. - KW
+* Modified HTFile.c to handle relative and "Up to parent" links more
+ effectively. - KW
+* Added KEYGEN to the DTD (but no code to do anything with it yet). - FM
+12-05-96
+* Fixed typo in the for-Unix section of LYAddPathToHome() that was added
+ yesterday in LYUtils.c. - James Troup (J.J.Troup@comp.brad.ac.uk)
+12-04-96
+* Numerous cleanups and commenting of the LYfoo.c and LYfoo.h modules,
+ for the benefit of new Lynx developers. - FM
+* More security-related enhancements and polishing up of the multiple
+ bookmark file support. - FM
+* Increased the sizes of MAXHIST and MAXLINKS, added statusline messages
+ should they ever be exceeded (not likely now 8-), and code for freeing
+ all excess pointers on each page draw instead of letting them grow and
+ freeing them on exit (should help for memory-limited systems 8-). - FM
+* Tweaks of DIRED_SUPPORT. - KW
+12-02-96
+* Show nntp server status messages in group listings when not 221 (normal
+ reply to HEAD request), so the user will know that the articles are
+ not available from the server, rather than a bug in Lynx. - FM
+* Tweaks of BASE resolving. - FM
+* Added "trick" to send hostname guesses to stdout when the startfile or
+ homepage are not URLs, as we send to the statusline for 'g'oto guesses
+ (but don't use stdout if we are not interactive and the desired output
+ is going to stdout). If the DNS lookup stalls, one thus can Control-C
+ out, instead of wondering why Lynx is taking so long to start up. - FM
+* Cleaned up the read_rc() and save_rc() functions in LYrcFile.c. - FM
+* Eliminated all printw() calls to avoid problems with non-ASCII and/or
+ multibyte/CJK characters. - FM
+* Numerous additional bug fixes and enhancements of the multiple bookmark
+ file support. - FM
+* Got rid of the ADVANCED_MULTI_BOOKMARKS symbol now that the choice can
+ be made in the 'o'ptions menu and saved in the .lynxrc file. - FM
+11-30-96
+* Added the ability to set the advanced mode for multiple bookmarks from
+ the options menu and save the defaults in the .lynxrc file - HL
+* Various typo corrections including one which kept LYMainLoop.c from
+ compiling under Unix when DIRED_SUPPORT was defined. - HL
+11-29-96
+* Numerous additional refinements and enhancements of the multiple bookmark
+ support. Added support for REFRESH and PREV_DOC in the options and bookmark
+ menus, and NEXT_PAGE, PREV_PAGE, and ACTIVATE in the bookmark menus or
+ prompts. Expanded the anchor and document structures to keep track of
+ different bookmark files in conjunction with VIEW_BOOKMARK, ADD_BOOKMARK,
+ and DEL_BOOKMARK commands, to restore the proper bookmark files on reloads
+ (overt, or because the cache was dumped for subsequent documents accessed
+ via bookmark links), and in conjunction with security-related restrictions.
+ Multiple bookmark support can be regulated via MULTI_BOOKMARK_SUPPORT,
+ BLOCK_MULTI_BOOKMARKS and ADVANCED_MULTI_BOOKMARKS symbols in userdefs.h
+ (or as SITE_DEFS in the Makefile) and lynx.cfg. The multiple bookmark
+ support can be blocked via a -restrictions=multibook command line switch,
+ which is also set for -anonymous and -validate. Prompting or display of
+ the bookmark file selection menu occurs only if bookmark files in addition
+ to the startup default have been defined (via the B)ookmark command in the
+ 'o'ptions menu, if mu(L)ti bookmarks has been turned on; the setting and
+ definitions can be saved in the .lynxrc file). Plugged memory leaks in
+ the previous implementation of multiple bookmark support. Added code for
+ inserting the current description and filepath for each bookmark file
+ dynamically during rendering. - FM
+* Another tweak of attribute order in HTMLDTD.c. - KW
+11-28-96
+* Tweaked multiple bookmark support to fix an error which was causing a
+ crash on some systems and incorrect behavior on others - HL
+* Tweaked editing of multiple bookmark filenames to correct shifting of
+ screen between multiple pages - HL
+11-26-96
+* Added support for setting the rendering of SELECT OPTIONs as popup menus
+ versus radio button lists via the 'o'ptions menu, and saving the default
+ in the RC file. Changed NO_SELECT_POPUPS to USE_SELECT_POPUPS in lynx.cfg
+ and userdefs.h. The -popup switch still overrides everything. - FM
+* Added multiple bookmark support along the lines of the patch from Filip M.
+ Gieszczykiewicz (filipg@paranoia.com), plus numerous enhancements of the
+ 'o'ptions menu and bookmark handling. - FM
+* Tweaks of attribute orders in HTMLDTD.h and HTMLDTD.c. - KW
+11-25-96
+* Updated the "Lynx Enhanced Pages" links to the new "Lynx links"
+ (http://www.crl.com/~subir/lynx.html) throughout the help, docs,
+ and code. - FM
+11-24-96
+* Modified the ENCTYPE="multipart/form-data" handling to indicate the
+ Content-Type with charset parameter, when known, within each part
+ rather than in the main Content-Type header. - FM
+* Corrected typo in HTNews.c. - FM
+* Added support for setting the suggested filename in 'd'ownload and
+ 'p'rint options based on the Content-Disposition header if it included
+ the string file; filename=name.suffix in its value. Can be used by
+ CGI scripts to set the suggested filename for saves to disk, downloads
+ or mailings of the script's reply body, so it won't be the last symbolic
+ element in the path field of the form's ACTION (which is normally the
+ the script, itself, or a PATH_INFO element, and thus misleading). - FM
+* Tweaks of change_sug_filename() in LYUtils.c for better handling of
+ gzipped files on VMS. - FM
+11-23-96
+* Added reporting of the Server, Date and Last-Modified headers, if present
+ in server replies, to the showinfo ('=') display. - FM
+* Added the ability to store the NO_SELECT_POPUPS in the .lynxrc, but the
+ .lynxrc must be edited manually until the options handling is converted
+ to a form-like interface that accommodates more options. For now, select
+ 'O'ptions and write out the options with '>' to create a block in .lynxrc
+ with an explanation of the switch. The switch is "select_popups" and
+ can have the values of "on", "off", or nothing. If nothing, the default
+ set in userdefs.h or lynx.cfg will persist. Otherwise, "on" will set use
+ of popups and "off" will set use of radio buttons as the default. The
+ startup default always can be toggled via the -popup switch. - HL & FM
+* Corrected a couple of typos in the help files. - HL
+11-22-96
+* Added support for WHEREIS ('/') and 'n'ext searches within SELECT popups.
+ The buffering for 'n'ext is separate from that in the main loop (i.e.,
+ for non-form field document searches), but all previously entered search
+ strings are still combined into a circular buffer and can be accessed via
+ the up-arrow or down-arrow keys at the prompt for a search string. The
+ searches within popup menus do not yield highlighting of the search string,
+ but simply positioning of the cursor on successive options which contain
+ the search string. - FM
+* Added support for all of the navigation commands within SELECT popup
+ windows, including HOME, END, UP_TWO, DOWN_TWO, UP_HALF and DOWN_HALF,
+ in addition to the single line and paging navigation commands. - FM
+* Added support for the REFRESH command within SELECT popup windows. - FM
+* Tweak of hookless snews handling. - FM
+11-21-96
+* Added handling of forms with ENCTYPE="multipart/form-data". Note that
+ we still don't support INPUTs with TYPE="file" or TYPE="range", and
+ thus still set the DISABLED attribute for all fields in the form if
+ either of those two TYPEs are present in it. - FM
+* Tweak of -mime_header handling. - FM
+* Typo fixes of comments in HTML.c. - Albert S Woodhull
+ (aswNS@hamp.hampshire.edu)
+11-20-96
+* Added a NO_SELECT_POPUPS compilation (userdefs.h) and configuration
+ (lynx.cfg) definition, normally set FALSE. If set TRUE, single-choice
+ SELECT blocks (i.e., ones without the MULTIPLE attribute) will be handled
+ as a list of radio buttons instead of via a popup window. Also added a
+ -popup command line switch for toggling the compilation or configuration
+ setting. - FM
+11-18-96
+* Tweak of LYFindEndOfComment() in LYCharUtils.c. - Brian Borowski
+ (brianb@braille.uwo.ca)
+11-17-96
+* Added links to the lynx-dev hypertext archive at FLORA in the online
+ 'h'elp. - FM
+* Tweaks of my_spawn() in LYLocal.c. - KW
+11-16-96
+* Added support for use of the 'd'ownload command on TYPE="submit" and
+ TYPE="image" submit buttons. You still must use the History Page for
+ TYPE="text" INPUT fields that also act as submit buttons by virtue of
+ being the only non-hidden field, because the 'd'ownload command key
+ could be a text entry into the field, and thus must be treated as
+ such. - FM
+11-15-96
+* Mods of HTFormat.c and HTTP.c for better handling of unexpected server
+ disconnects. - FM
+11-13-96
+* Wind down the element stack on EOF if any unclosed tags were received. - FM
+* Fixed typos in the HTMLDTD.c BODYTEXT definitions. - FM
+11-10-96
+* More tweaks of hook-less snews handling. - FM
+* Changed the default STARTFILE to http://lynx.browser.org/ and the default
+ HELPFILE to the v2.6 set at NYU in userdefs.h and lynx.cfg. - FM
+* New function HTUnEscapeSome() in HTParse.c for unescaping selected
+ characters in a string.. - KW
+* Numerous changes to make DIRED_SUPPORT work as intended, to use the
+ library's HTList functions and macros for managing the list of tagged
+ file URLs, and to keep track of proper levels of URL escaping so that
+ unusual filenames which contain #% etc. are handled properly. Can now
+ edit, move, etc. Abc%25252525def.html, #xy#~, etc. - KW
+11-09-96
+* Treat 301 or 302 redirection of a POST as 303 when the Lynx process is
+ non-interactive, rather than rejecting the redirection, since 303 is
+ still most likely what the CGI script actually intends (will still
+ prompt if the process is interactive). - FM
+* Added parsing and trace mode reporting of Content-Disposition headers
+ in HTMIME.c (should be used, someday, to set the suggested file name
+ for disk saves and downloads based on any filename=foo.blah field). - FM
+* Further mods of HTNews.c to facilitate use of Lynx without SSL-hooks
+ in conjunction with an SSL-capable daemon/proxy for snews URLs that
+ returns NNTP streams for Lynx itself to convert into HTML, instead
+ of already converted streams as from a standard proxy. - TZ & FM
+11-08-96
+* Changed information returned by "-version" in LYMain.c to point to
+ lynx.browser.org and added a date to the copyright info. - HL
+11-07-96
+* Mods of HTNews.c to facilitate use of Lynx without SSL-hooks in
+ conjunction with an SSL-capable daemon/proxy for snews URLs. - TZ
+11-05-96
+* Typo fixes in HTMIME.c. - KW
+* Tweak of NSL_FORK mods. - FM
+11-04-96
+* Tweaks of host parsing when a password and/or username is present
+ in override_proxy() of HTAccess.c. - FM
+* Tweaks of the UNDERSCORES and STARS macro setup and useage to avoid
+ possible crashes for FORMs with long values. - FM
+* Worked in Tom Zerucha's (tz@execpc.com) code for fork-based name
+ server lookups that can be 'z'apped. May not yet be portable to
+ all flavors of Unix. Add -DNSL_FORK to your SITE_LYDEFS to try
+ it. - FM
+11-02-96
+* Fixed typo in HTAlert.h. - FM
+* Cleaned up HTTCP.c code, simplified some of its spaghetti
+ ifdef'ing, and worked in mods to bypass connection confirmations
+ when Lynx is SOCKSified and the socks_flag is set. - FM
+* Added recognition and acceptance of text/x-sgml and text/sgml
+ MIME types (all that I've encountered thus far work fine with
+ Lynx, though it doesn't yet interpret marked sections). - FM
+* Added socket function prototypes for MultiNet in tcp.h. - FM
+* Mods to facilitate application of the SSL patches (after some
+ corrections in the patches to keep HTLoadHTTP re-entrant, make
+ CONNECT work as intended again, and eliminate memory leaks in
+ the SSLeay adaption) - FM
+* Adding info about -DNO_TTYTYPE in top level Makefile. - FM
+* Use clrtoeol() in LYOptions.c to ensure that no terminals which use
+ reverse video for standout() will have trailing reverse fields on
+ edits of option vaules. - DK
+* Offer user@host instead of WebMaster@host for the 'c'omment command
+ if the path for the URL begins with a tilde and there is no
+ LINK REV="made" present. - FM
+* Tweaks of inews Makefile and clientlib.c. - Christopher R. Maden
+ (crm@ebt.com)
+* Check nhist before attempting a DIRED_SUPPORT directory listing in
+ LYShowInfo.c. - KW
+10-21-96
+* Offer WebMaster@host for the 'c'omment command if no LINK REV="made"
+ was present in a text/html document, and save a known owner URL when
+ toggling to source ('\') so that the 'c'omment command can still be
+ used with that owner's (mailto or homepage) URL, but the source can
+ be included in the comment, as would be desireable (instead of a bad
+ rendering) when sending a comment about bad HTML in the document. - FM
+10-20-96
+* Added code for traversing the pseudo-documents created for client-side
+ image MAPs. See the updated CRAWL.announce for more information. - FM
+10-19-96
+* Added definitions in LYCurses.h relating curses function calls to slang
+ functions or emulations for compatibility with new versions of slang,
+ based on patch from John E. Davis (davis@space.mit.edu). - FM
+* Added unescaping of the full address fields in mailto URLs or ACTIONs,
+ and improved the reliability of the parsing of the subject header from
+ the ?searchpart Netscapism when present. - FM
+* Give user option to use 303-like coversion of POST to GET in confirmation
+ requests for redirection of POSTs, base on patches from Drazen Kacar
+ (dave@fly.cc.fer.hr). - FM
+* Tweaks of POST content submissions in HTTP.c, based on patch from
+ KW. - FM
+* Fixed EOF checks in HTAAFile.c, HTGroup.c and HTPasswd.c, and improved
+ host address parsing in HTTCP.c, based on patches from Larry Schwimmer
+ (schwim@cyclone.stanford.edu) and Klaus Weide (kweide@tezcat.com). - FM
+* Added targets for umaxv and umaxv-slang for Encore's UMAXV - Thanh Ma
+ (tma@encore.com)
+10-16-96
+* Send the rendering of decompressed files to stdout with -dump, don't
+ spawn a viewer under any circumstances if -dump was used instead of
+ -source for Content-Types that are not text/html, and remove the
+ temporary decompressed files before exiting with -dump or -source. - FM
+* Properly handle TYPE="radio" versus TYPE="checkbox" INPUTs with NULL
+ or zero-length VALUEs. - FM
+* Added a continuation line token for the netbsd-ncurses target - HL
+* Fixed a typo in HTMIME.c in the trace output - HL
+* Block predictable buffer overrun in GridText.c if a page has more
+ than MAXLINKS links in it. - FM
+10-01-96
+* Add a Mime-Version header to the other headers in LYPrint.c so that the
+ 09-20-96 mods for mailing source do what they were intended to do. :) -
+ Hamish MacEwan (macewanh@diatp.dia.govt.nz)
+09-20-96
+* Add a BASE tag to the tops of HTML source files, a la Netscape, when
+ mailing or downloading, and don't worry, for now, if that creates
+ technically invalid HTML (since Lynx copes with it as of the 09-15-96
+ mods 8-). - FM
+* Include Content-Type, Content-Location and Content-Base headers when
+ mailing HTML source on Unix. - FM
+* Use .txt versus .html suffixes when submitting rendered versus HTML source
+ temporary files to VMS MAIL, so that transports such as PMDF will indicate
+ the appropriate Content-Type. - FM
+09-17-96
+* Handle illegally positioned BASE tags. - FM
+* Tweak of Q nesting level checks. - Pawel Wiecek
+ (coven@i17linuxb.ists.pwr.wroc.pl)
+* Fixed typo in HTMIME.c for parsing of Pragma header. - Wilson Cheung
+ (wcheung@netcom.com)
+* Added parsing of Set-Cookie header in HTMIME.c (see IETF ID
+ http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-mgmt-03.txt
+ for info on how to implement it's use). - FM
+* Fixed typo in LYMainLoop.c for display of error message when up arrow is
+ pressed at the top of a document. - Hiram Lester, Jr. (hwlester@pobox.com)
+09-16-96
+* Use standard ls -l parsing of LIST output for Windows_NT ftp servers in
+ Lynx v2.6 as in v2.5. - FM
+
+--- Rename of Lynx2-5FM and release as Lynx2-6 (02-Sep-1996) ---
+ (see CHANGES2-6, CHANGES2-5, CHANGES2-4 and CHANGES2-3)
+==============================================================================
diff --git a/gnu/usr.bin/lynx/docs/CHANGES2.8 b/gnu/usr.bin/lynx/docs/CHANGES2.8
new file mode 100644
index 00000000000..6d6fb7f3a3c
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CHANGES2.8
@@ -0,0 +1,3403 @@
+=======================================================================
+--- Release of Lynx v2.8 (March 10, 1998) ---
+=======================================================================
+
+1998-03-10
+* omit platform-specifics about release (recommended by HN). - TD
+* drop samples/lynx.cfg since it is redundant (recommended by HN). - TD
+* modify makefile.in so that "make install-cfg" does not edit lynx.cfg
+ to point at local helpfiles, while "make install-help" will now do
+ that (reported by LP). - TD
+* one more patch to UPPER8 function. - LP
+1998-03-07
+* move ifdef's for EXP_8BIT_TOUPPER inside UPPER8 function to allow
+ check for DOS/WINDOWS display charsets. - LP
+1998-03-06
+* clarify relationship between the configure script and userdefs.h with
+ respect to the LYNX_CFG_FILE definition. - TD
+* newer CF_FIND_LIBRARY autoconf macro, to allow ncurses library in /lib
+ only, needed for SUSE Linux. - TD
+* add casts to UPPER8 function's comparison for equality of parameters, and
+ to TOUPPER macro to guard against sign-extension due to prototype. - AC
+* correct spelling of -lcur_colr library in aclocal.m4, change order of
+ tests to put -lHcurses second on HP-UX (patch by Jonathan Sergent).
+* restore simple zmodem downloader script, displaced by recent undocumented
+ change (there are some concerns about security or permissions with the
+ alternate script). - DK
+* DOSPATH localfile patch: corrected display of file://localhost/c:/,
+ which was displayed as file://localhost/c%3A/ (tweak LYConvertToUrl() in
+ LYUtils.c). Now we may start "lynx c:" or 'go' c: and not see these
+ strange letters. On the other hand, if % and # symbols found in local
+ path it will be escaped as before (note that #fragment is not supposed here
+ to be used from command line...) - LP
+* workaround error in vendor's terminfo description of 'dtterm' by ensuring
+ we limit color pair-number accordingly. - TD
+1998-03-04
+* strip -g compiler option if not otherwise specified, for debugging (note
+ that autoconf 2.12 does not try to use -O option due to concerns about
+ compiler optimization). - TD
+* correct value of $host_os used in CF_CURSES_LIBS for special-case of
+ HP's -lHcurses (Jonathan Sergent <sergent@ecn.purdue.edu>).
+* correct def7_uni.tbl for Greek letters, note about UPPER8 assumption
+ added to chrtrans/README.format. - LP
+* few comments corrected. - LP
+1998-02-28
+* create new PRCS revision (2.8pre) for pre-release testing of Lynx 2.8
+* remove RELEASE_STATEMENT, merging it into README as per HN's
+ recommendation - TD
+* comments/minor changes to HTDOS.c, HTDOS.h, LYUtils.c - LP
+* document recent fix for RAW_DOS_KEY_HACK in lynx.cfg - DK
+* rename CHANGES.new to docs/CHANGES2.8 - TD
+* undo last minor change to UPPER8 - LP
+1998-02-27
+* add RELEASE_STATEMENT file. - TD
+* modify slang configuration to add fake 'scrollok()' - JED
+* modify LYmktime() so that 2-digit years must be greater/equal to 70 to be in
+ 1900's (patch by Bela Lubkin). Also adjust parse_windows_nt_dir_entry() and
+ parse_cms_dir_entry() as noted by Bela - TD
+* comment-out entries in cp1252_uni.tbl which correspond to nonprinting
+ control-characters - LP
+* add logic in SGML.c to correspond with 2.7.2 logic for codes used by
+ Microsoft FrontPage. - LP
+* remove unneeded code for nbsp, ensp, emsp, thinsp and shy from handle_entity()
+ in SGML.c - LP
+* ifdef UPPER8 function with EXP_8BIT_TOUPPER,
+ add configure option --enable-8bit-toupper to allow testing. - TD
+* case-insensitive search and 8bit letters: It was realized that
+ information about upper/lower mapping got from TOUPPER which depends on
+ locale in its 8bit and usually fails on non-UNIX systems. We introduce
+ UPPER8 and strcasecomp8 to implement 8-bit aware case-independent search
+ using one simple assumption: 8bit upper/lower case letters have their
+ "7bit approximation" images in def7_uni.tbl matched case-insensitively
+ (7bit). The cost of this assumption is that several differently accented
+ letters may be interpreted as equal but this is negligible if the search
+ string is more than one character long. (LYStrings.c, also HTString.c
+ and LYMainLoop.c). - LP & TD
+* add SunOS 4.x-specific ifdef to quiet redefinition warnings for sys/ioctl.h
+ vs sys/termios.h - TD
+* convert usage/options messages into arrays to simplify maintenance. - TD
+* add "-useragent" command-line option to set "User-Agent" (request by Merlin
+ Mathesius <merlin_mathesius@swissbank.com>). - LP
+* tweak HTML in LYDownload.c, LYPrint.c to restore some double-spacing effects
+ altered in 'collapsible spaces' change 1998-01-25 (reported by James Elkinton
+ <zio@blueneptune.com>). - LP
+* use strncasecomp/strcasecomp consistently throughout to avoid library
+ dependency on strncasecmp/strcasecmp. - TD
+* correct lengths in several strncasecmp calls for command-line options
+ (though -w is still an abbreviation for -width). - TD
+* test-build with BSD curses on OS/2 EMX (does not display properly), and
+ with ncurses.
+* add configure check CF_FUNC_LSTAT.
+* modify CF_CHECK_ERRNO so that configure script on OS/2 EMX finds sys_errlist.
+* reset styles[] and styleSheet list in DefaultStyle.c, HTML.c so that when
+ a user reloads a page with ^R, we undo changes to those data structures
+ (reported by Larry Virden). - TD
+* remove extra copy of HTML.h from Implementation directory. - TD
+* add CF_GCC_ATTRIBUTES to configure script, to use in flushing out unused
+ parameter warnings (and later, to support prototypes for logging). - TD
+* rename 'extra_entities' to 'unicode_entities' (recommended by LP) - TD
+* add configure option --use-default-colors, to allow background color to use
+ default value (request by SUNAGAWA Keiki <Keiki_Sunagawa@yokogawa.co.jp>) -
+ TD
+* change default for --disable-internal-links so it is normally-off - TD
+1998-02-19
+* add configure test CF_FIONBIO, some ifdef's (e.g., S_IFLNK) to support
+ build on OS/2 EMX. - TD
+* add configure option --disable-extended-dtd, for testing - TD
+* split-out entities.h from HTMLDTD.c - TD
+* remove obsolete mapping in "private" e000 area of mnem_suni.tbl,
+ mnem2_suni.tbl, rfc_suni.tbl - LP
+* remove unused function HTMLGetLatinOneValue() - LP
+* remove logic that would attempt lookup of Unicode entities by index into the
+ unicode_entities.put_entity method (e.g., of HTML_dtd), in HTML.c
+ (HTML_put_entity) and HTMLGen.c (HTMLGen_put_entity) - LP
+* tweaks to HTPlain.c, LYCharUtils.c and SGML.c, remove extra checks for
+ Unicode mdash, ndash, trade, as well as "iso-8859-2", "koi8-r", since they
+ are done in the chartrans tables - LP
+* add an alias 'H' for F1 when using RAWDOSKEYHACK (LYStrings.c) - DK
+* restore -DRAWDOSKEYHACK to src/makefile.dos, reported by DK - TD
+* correct a typo in CF_CURSES_LIBS configure macro, which caused the configure
+ script to not add termcap library to the list - TD
+* correct --disable-internal-links, by adding DONT_TRACK_INTERNAL_LINKS to
+ config.hin - TD
+1998-02-13
+* use size_t in SGML_dtd. - TD
+* remove extra trademark symbol and quotes from chrtrans/*.tbl, since
+ they are in the default def7_uni.tbl - LP
+* New item to lynx.cfg added: PREPEND_CHARSET_TO_SOURCE (similar to BASE), we
+ need it to resolve charset for downloaded/printed HTML sources which became
+ local. This is really useful because downloaded and printed texts may
+ happened to have different charsets so assume_local_charset fails. For
+ downloaded source meta charset added from HTTP charset header (if and only if
+ present). For printed source meta charset added from display_charset (real
+ charset after chrtrans). If the original source has its own meta charset
+ and we add the second on top - Lynx currently use those on top and ignore
+ others (old) value (that is correct, although non standard like BASE on top).
+ The compilation default is FALSE (compatibility). - LP
+* modify ncurses mouse behavior to match slang (use button 3 rather than
+ button 2 for "previous document" (reported by Michael Ritzert) - TD
+* use case-independent comparison for tail-only comparison in override_proxy
+ (patch by pg@sweng.stortek.com) - TD
+* remove unneeded definitions of ALT_CHAR_SET, NCURSES_VERSION in
+ src/makefile.dos - DK
+* correct syntax for the RAW_DOS_KEY_HACK in lynx.cfg, add a little information
+ on how to compile this. Also patched makefile.dos to make compilation of the
+ raw dos key hack the default when compiling in DOS. - DK
+* change back to boolean since the logic was unused: UCCanTranslateFromTo(),
+ UCCanTranslateUniTo(), and UCCanUniTranslateFrom(). - TD
+* Mods of SGML.c and LYCharUtils.c to improve handling of entities,
+ obsolete stuff removed (not all yet). - LP
+* -localhost mode: disable interpreting BASE HREF= if local_host_only
+ to resolve local html files with BASE (Lynx add base to downloaded
+ sources and this may affect links if looking them with -localhost).
+ (tweak in html.c). - LP
+* Modify HTMLGetEntityUCValue in LYCharSets.c:
+ we begin to move from old style entities[] to unicode-based. - LP
+* added a few comments. - LP
+1998-02-07
+* Fixed a bug in HTTP.c which could cause trashing of authorization info
+ for an origin HTTP(s) server if the request is being proxied. - FM
+* Tweak in HTTP.c so that the reloading variable is not reset until
+ after any resubmissions due to authorization challenges. - FM
+* Tweaks of userdefs.h, lynx.cfg, LYMessages_en.h, LYMain.c, LYMainLoop.c,
+ LYClean.c, LYReadCFG.c, and LYGlobalDefs.h so that the QUIT_DEFAULT_YES
+ compilation symbol can be overridden in lynx.cfg, in keeping with
+ the principle that only strict security-related compilation symbols
+ cannot be overridden at run time. - FM
+1998-02-05
+* adjust formatting, comments & some messages in WWW files to simplify
+ comparison with 2.7.2 version. (I have preserved some chunks of difference,
+ ifdef'd NOTUSED_FOTEMODS or NOTDEFINED for ease of comparison -- these may be
+ removed at a later time, when we are done absorbing changes from 2.7.2) - TD
+* Update SGML entity to Unicode table in HTMLDTD.c from ftp.unicode.org -
+ lots of new entities, iso-latin-1 now included there.
+ See also new files in test/ directory: sgml.html and unicode.html.
+ Tweak a few typos in test/*.html according to sgml.html.
+ Add a few new entries in def7_uni.tbl according to sgml.html - LP
+* Cleanup iso01-iso09, cp866 tables against ones found at ftp.unicode.org
+* Strip the fat from LYCharSets.c - unnecessary obsoleted tables removed
+ and redirected to SevenBitApproximation table (ones which have unicode tables
+ override it anyway, those for CJK had exactly the same tables as
+ SevenBit..). - LP
+* Remove obsolete "Other ISO Latin" charset, which works _exactly_ the same
+ as "7 bit approximation" (See the note on 06-14-96 where it comes from).
+* Sort the list of charsets in Options according to 2.7.2 for 1997-10-15,
+ see the comments in UCinit at the bottom of UCDomap.c - LP
+* add ifdef to HTFile.c to workaround conflicting S_IFIFO vs S_IFSOCK
+ (e.g., on Apollo, from a report by Dave Eaton <dwe@arde.com>) - TD
+* updated INSTALLATION (patch by HN) - TD
+* modify DOS handling of CTL-C and CTL-BREAK handling for DOS to allow
+ exiting via SIGINT when pressing CTL-C or CTL-BREAK regardless of the
+ BREAK setting in DOS. This leaves the BREAK setting unchanged unless
+ CTL-C or CTL-BREAK is actually pressed (in which case it leaves BREAK
+ ON) - DK
+* add note about Lynx vs frames to User's Guide (from Al Gilman) - TD
+1998-01-27
+* correct lynx.man to reference section "1" (one), not "l", since it is
+ not installed in the latter (reported by Jason Castonguay
+ <jcast@ntplx.net>) - TD
+* fix for VMS declarations of mainloop() and from_hex() (reported by FM) - TD
+* add to include-paths in libmake.com, build.com (reported by FM, citing
+ Brian Tillman) - TD
+* revert HTML.c to use LYHandleSELECT() - TD
+* align cases for function keys in LYStrings.c with 2.7.2 - TD
+* remove EXP_CHARTRANS ifdef's - TD
+* remove symbol USE_SIZECHANGEHACK
+* adjust formatting, comments & some messages in most remaining ./src files to
+ simplify comparison with 2.7.2 version. - TD
+1998-01-25
+* Changed the utf-8 Display Character Set string to "UNICODE UTF-8"
+ (i.e., added the hyphen between UTF and 8), and fixed typos in
+ the comments about iso-8859-5. LP & FM
+* Modified HTML.c to add collapsible spaces before and after IMG ALT
+ strings or pseudo-ALTs whether or not the IMG element is within
+ Anchor content. The occasional absence of such spaces due to poor
+ HTML was problematic for blind users. Note that markup which uses
+ an image for a fancy letter with the ASCII letter as an ALT will
+ have that letter separated from the rest of the word. Also note
+ that these spaces will not be collapsed in PRE blocks, but IMG is
+ invalid in PRE blocks. The spaces could be omitted when IMG is
+ used invalidly in PRE blocks, but that would revive the problem
+ for blind users that they might not be present at all, so it seems
+ better to suffer extra spaces in such cases. - FM
+1998-01-24
+* Tweak in HTAccess.c to reset the title element in anchors on forced
+ reloads. - FM
+1998-01-22
+* Tweaks in HTML.c to prevent collapsing of blank lines within TEXTAREA
+ default values. Note that we still strip any leading or trailing
+ blank lines (reported by Edward S. Marshall <emarshal@xnet.com>). - FM
+* Tweaks of LYCurses.c, LYMain.c, LYOptions.c, LYReadCFG.c, LYUtils.c
+ and LYAuto.c to ensure properly setting, with internal buffering, and
+ avoid memory leaks for the display and homedir values (reported by
+ pg@sweng.stortek.com). - FM
+* include userdefs.h in LYCurses.h to address redefinition warnings for
+ curses-related configuration. - TD
+* adjust formatting, comments & some messages in recently-modified files to
+ simplify comparison with 2.7.2 version. - TD
+* remove obsolete logic from UCCanTranslateFromTo, (recommended by LP). - TD
+* make character set names (e.g., cp437, cp850, next) consistent in lynx.cfg,
+ userdefs.h (reported by LP). - TD
+* change configure script to check for termcap library before curses, in case
+ it is dependent. - TD
+* More corrections in the Russian Cyrillic area of def7_uni.tbl. - LP
+1998-01-17
+* correct logic for no_color_video by ensuring that if not defined, it
+ doesn't disable underline with color. - TD
+* remove NSL_CLONE - didn't build. - TD
+1998-01-16
+* eliminate gcc "shadowed variable", "nested declaration", "no previous
+ prototype" warnings. - TD
+* add --disable-internal-links configure option. - TD
+* remove W3C gateway (patch by DK, based on email from Gerald Oskoboiny
+ <gerald@w3.org>). - TD
+* documentation updates (patch by JS). - TD
+* add CONTENT_TYPE to environment of lynxcgi POST documents (reported by
+ Ty Sarna <tsarna@endicor.com> & FM). - TD
+* add NSL_CLONE ifdef that enables use of the Linux clone() call instead of
+ fork() for the gethostbyname() calls in HTTCP.c. (patch by Ryan Nielsen
+ <ran@haxor.com>). - TD
+from the lynx code. I think the following patch does this.
+1998-01-15
+* Tweak of the NSL_FORK code in HTTCP.c to prevent zombie processes from
+ being created when gethostbyname() is interrupted. - RN
+* Corrected the Russian Cyrillic area of the def7_uni.tbl Unicode to
+ 7-bit approximations conversion table. - LP
+* Mods of UCAux.c, LYCharUtils.c, SGML.c and HTPlain.c to use 7-bit
+ approximations instead of 8th bit stripping when the document charset
+ is koi8-r and the Display Character Set does not have the corresponding
+ characters. - FM
+* Tweaks in HTML.c to ignore a newline character immediately following
+ a PRE start tag more consistently. When PRE blocks are used to create
+ blank lines, you should get only as many as are actually included in
+ the PRE block, unless you include less than the number specified for
+ "before" the block to which you return, in which case you'll get the
+ latter number of blank lines. - FM
+1998-01-13
+* Fixed a typo in the HTParse() code of HTParse.c for checking whether
+ a colon in the host field indeed delimits a port number. - FM
+* Changed the internal MIME names for all Microsoft Windows codepages
+ from cp#### to windows-####, since the latter is used more commonly
+ as the charset value in META elements and/or Content-Type headers,
+ and most of them have been registered that way with IANA. Note,
+ however, that Microsoft uses cp instead of windows- prefixes in the
+ charset names for the Unicode conversion tables submitted to the
+ Unicode Consortium. Also note that we still treat cp, cp-, and ibm
+ prefixes as synonyms for the windows- prefix. - FM
+1998-01-06
+* work around for 'keypad()' function w/o corresponding key defines
+ (reported by Francisco A. Tomei Torres for NeXTstep 4.0). - TD
+* quote message in install rule, just in case (from HN). - TD
+* correct expression to supply default value of .cfg file's pathname
+ (reported by LE & Ambrose Li <acli@acli.interlog.com>). - TD
+* correct dependency of .cfg files upon $(libdir) in makefile.in - TD
+1998-01-04
+* correct temporary filename for -traversal -crawl (patch by Doug Kaufman). - TD
+* correct redefinition of SYSTEM_MAIL_FLAGS. (reported by Doug Kaufman). - TD
+* uncache current document when character set may have changed (patch
+ by Andrey A. Chernov) - TD
+* modify Linux setfont code to restore the original font on exit - TD
+* correct missing backslash (again) in makefile.in
+ (reported by Mark Mentovai - again) - TD
+1998-01-02
+* workaround for sed expression when rerunning configure with config.cache
+ for slang libraries (reported by Hynek Med). - TD
+* fix indicated by Laura Eaves (LE) for LYUCFullyTranslateString_1() - TD
+* modify SPAWNING_MSG for DOSPATH configuration, avoid unnecessary use
+ of clear-screen in shell (patch by Doug Kaufman). - TD
+* remove install-help from list for install rule, adding message to
+ indicate how to install it. - TD
+* install lynx.lss only if color-style is configured. - TD
+* correct filemode for DJGPP when processing config-file, patch by
+ Doug Kaufman). - TD
+* add LYNX_LSS_FILE to config.hin, reported by Ambrose Li
+ <acli@acli.interlog.com>. - TD
+* new copy of INSTALLATION file from HN. - TD
+* add COPY* to install rule. - TD
+* simplify includes in UCdomap.c by using include-path in makefiles. - TD
+* build configure script with patched autoconf to workaround limited
+ environment space on CLIX 3.1 - TD
+* rename mnemonic_suni.tbl to mnem2_suni.tbl to accommodate 'make' on
+ older system with 14-character name-limit. - TD
+* sorted some lists (e.g., character sets) which were unreadable. - TD
+* incorporate most of FM's changes from 971124 to 971230 (see below). - TD
+ (Note: don't try to use fflush(stdin) -- it's an FAQ -- nonstandard,
+ dumps core on some platforms).
+1997-12-30
+* Added Unicode translation support for "DosBaltRim (cp775)" and
+ "WinBaltRim (cp1257)". - FM
+1997-12-29
+* Fixed bug in the order of re-initializations for the 1997-12-22
+ get_connection() mods. - FM
+* Fixed typos in some LYCharUtils.c comment. - FM
+* Fixed typo in LYrcFile.c comments concerning the NO_FROM_HEADER
+ symbol. - DK
+1997-12-24
+* resolve conflict between autoconf $INSTALL and lynx's INSTALL_PATH
+ (reported by Scott McGee). - TD
+* modify CF_CHECK_FUNCDECL to work with non-gcc compilers. - TD
+* add <stdio.h> to prototype test for getgrgid getgrnam, needed on SVr3. - TD
+* add install-lss to makefile.in. - TD
+* modify order of includes in LYKeymap.c so that USE_EXTERNALS is defined
+ if it comes from userdefs.h (inferred from a report by Larry Virden). - TD
+* correct spelling of USE_EXTERNALS which prevented --enable-externs from
+ working. - TD
+* move assignment to stderr from VMSexit to cleanup function (reported
+ by Brian Tillman & FM). - TD
+* modify UCChangeTerminalCodepage() to not use stderr, disentangling it
+ from stderr/logfile hack. - TD
+* rename docs/CHANGES2-* files to docs/CHANGES2.* (reported by
+ Doug Kaufman). - TD
+* add start_color() call to DOSPATH version of start_curses() to
+ fix problem reported by Doug Kaufman - TD
+* correct typo in ColorCode() function (reported by Doug Kaufman) - TD
+* modify comments in makefile.in (patch by HN) - TD
+* minor fixes for CF_CHECK_ERRNO, CF_SIZECHANGE, CF_SLANG_CPPFLAGS
+ macros. - TD
+* add configure option --enable-nsl-fork to turn on code defined by
+ NSL_FORK. - TD
+* add configure option --enable-links to turn on code defined by
+ UNDERLINE_LINKS. - TD
+* add configure option --enable-font-switch, to turn on code defined by
+ EXP_CHARTRANS_AUTOSWITCH. - TD
+* modify configure CF_CURSES_LIBS test to look also for ncurses,
+ since some systems do not have a "curses" library (reported by
+ Michael Ritzert). - TD
+1997-12-22
+* Reworked -width=NUMBER command line switch for specifying the screen
+ width for formatting of dumps (default is 80; forced wraps occur at one
+ column less than the screen width, i.e., at 79 by default). - FM
+* Tweak of get_connection() in HTFTP.c to re-initialize the elements of
+ the connection structure when using a previously allocated connection
+ object. - DW & FM
+* Mods of LYexit.c, LYClean.c, LYMain.c and LYMainLoop.c to fflush() all
+ standard file descriptors in conjunction with all fopen() and fclose()
+ operations on the TRACE log and redirections of stderr via equality
+ statements (see 1997-12-16, 1997-12-13 and 1997-07-18 mods). - FM
+1997-12-18
+* forgotten last } UN-inserted (John Line) - WB
+* few commented messages corrected according to RFC2068 (HTTP1.1)
+ (Leonid Pauzner) - WB
+1997-12-17
+* Changed all %i tokens to %d or %ld in functions that always get decimal
+ values in their arguments. - FM
+1997-12-17 (all patches by Leonid Pauzner)
+* open text mode while writing lynx.rc and bookmarks files
+ LYrcFile.c and LYBookmark.c (forgotten last } inserted). - WB
+* add a comment about binary mode in LYMain.c and pile them
+ in one ifdef - WB
+* few misprinted characters (in comments) corrected in
+ \chrtrans\cp850_uni.tbl - WB
+1997-12-16
+* Further mods in LYClean.c (see 1997-12-13 mods) do block the
+ *stderr = LYOrigStderr; statement in cleanup() for VMS with VAXC. - FM
+* Added an ELGOTO keystroke command, mapped by default to upper case 'E'
+ (lower case 'e' still invokes the editor for the current document, if
+ it is a local file), for passing the URL (or ACTION) of the current
+ link to the line editor for editing as a goto URL. Works like the
+ ECGOTO ('G') keystroke command for editing the URL of the current
+ document as a goto URL, i.e., if the URL is not modified, is set to
+ a zero-length string, or ^G is entered, the command is cancelled. - FM
+* Mods of LYMainLoop.c to disallow ECGOTO or ELGOTO commands for File
+ Management (DIRED_SUPPORT) menu URLs. - FM
+1997-12-15
+* Added reporting of the Discard value (YES or NO), in the Cookie Jar Page
+ (note that until we have code for storing cookies beyond the current
+ session, Lynx behaves as if Discard were set, whether or not it was set
+ by the server, but we still report the server's instructions, as we do
+ for the Maximum Gobble Date). - FM
+1997-12-14
+* added a lynx.cfg switch to turn on/off extended dos translations for keys.
+ -WB
+* added minor DOS tweaks by Doug Kaufman and myself. - WB
+* fixed windows binary mode piping. - WB
+1997-12-13
+* Tweaks in LYList.c to make the link numbers correspond with those in
+ the current document when LINKS_AND_FORM_FIELDS_ARE_NUMBERED in on,
+ and to show the current document's URL in the display. - FM
+* Mods in HTTP.c to show the body of a 305 return status instead of ever
+ acting on it. A number of security/privacy problems with this status
+ are being discussed in the HTTP-WG, and it's likely to be dropped or
+ deprecated in the next revision of the HTTP/1.1 specs. - FM
+* Restored the v2.7.1 HTmmdecode() that's specific for iso-2022-jp in
+ HTMIME.c. We still only call it when HTCJK == JAPANESE, and the
+ generalized version reportedly has problems. - FM
+* Removed the *stderr = LYOrigStderr; statement from VMSexit() in LYCurses.c
+ and added it to the if() claused section which closes the TRACE log file,
+ if opened, in cleanup() of LYClean.c. This is just a stab in the dark
+ for dealing with reported problems on exit with VAXC on VAXen. We may
+ need to use freopen() for redirecting TRACE messages to a file for VAXC
+ or VAXen (there's no apparent problem with the current code with DECC
+ on VMS/AXP). - FM
+* Added more function key cases to the keypad() mode switch() in LYgetch()
+ of LYStrings.c. We don't need them with this code set, but they may as
+ well be there for completeness. - FM
+* check for and use ncurses default-color extension, use to make the
+ color-style configuration usable on xterm with white background. - TD
+* add cases in LYgetch() for remaining VT220-compatible codes, reported
+ by Michael Ritzert and FM. - TD
+* add configure test to see if slang can be linked without curses or
+ termcap libraries, request by John Davis. - TD
+* set umask in mkdirs.sh script to work around users who have set root's
+ umask to 077. - TD
+* split up install rule to install-bin, install-cfg, install-man and
+ install-help. - TD
+* suppress suffixes in top-level makefile so 'make' won't try to create
+ a file named "install" from install.sh - TD
+* make $(CPPFLAGS) inherit consistently from top-level makefile. - TD
+ (reported by Mark Mentovai)
+* add configure option --enable-externs, to turn on USE_EXTERNS. - TD
+* use explicit comparison for enum values, fix compile problem with VAX C
+ for UCAux functions (reported by Brian Tillman). - TD
+1997-12-03
+* Remove CHANGES.configure, since it is redundant. - TD
+* Make -g3 option check for OSF/1 3.2 consistent with -Olimit check. - TD
+* Use 'result' rather than 'time' in mktime.c to avoid shadowing. - TD
+* Use wborder only if configure finds it, not ifdef FANCY_CURSES. - PHDM
+* List of systems having strerror replaced by configure test. - PHDM
+* Beautifying of mktime.c (`now' was misleading). - PHDM
+1997-12-02
+* Mods in LYCookie.c to prompt whether to accept (or reject) cookies with
+ an invalid domain value which yields a hostname prefix with a dot (as
+ specified in section 4.3.2 of the IETF cookie drafts and RFC), rather
+ than rejecting it silently. Note that it is rejected in non-interactive
+ (-dump or -source) mode, because the user can't be prompted. - FM
+1997-11-27
+* Added a PREPEND_BASE_TO_SOURCE configuration symbol in lynx.cfg which
+ can be set FALSE to suppress prepending of a Request URL comment and
+ BASE element to text/html sources retrieved for 'd'ownloading or passed
+ to 'p'rint functions. Note that this prepending is not done for -source
+ dumps unless the -base switch also was included on the command line, and
+ the latter switch overrides the setting of the PREPEND_BASE_TO_SOURCE
+ configuration variable. - FM
+1997-11-25
+* Mods in LYMail.c and LYPrint.c to handle to=address(es), cc=address(es),
+ subject=string, keywords=word_list, and body=message fields in the
+ ?searchpart of mailto URLs as specified in the 1997-11-16 draft:
+ ftp://ftp.isi.edu/internet-drafts/draft-hoffman-mailto-url-03.txt
+ The cc=address(es) values are now handled as a Cc: header, and a self
+ copy, if confirmed on prompt, is added to the Cc: header. Note that
+ the draft now allows mailto:?to=address(es)[&foo=blah] as a format,
+ i.e., without an address before the ?searchpart. The Netscape
+ ?searchpart tack-on broke all pre-existing implementations of mailto,
+ and this breaks Lynx's support through v2.7.1. Though it's now
+ supported in this code set, don't use it. Complaints and formal
+ requests to provide this functionality via a new scheme (e.g.,
+ mail: or smtp:) without breaking existing implementation of mailto:,
+ including from TimBL (HimSelf :), thus far have fallen on deaf ears.
+ You can send email to those deaf ears via:
+ mailto:masinter@parc.xerox.com%20(Larry%20Masinter)
+ Don't allow the IETF backward compatibility principle to go down
+ the drain. - FM
+* Mods to support use of the PMDF SEND command on VMS in conjunction with
+ a temporary header file, so that all headers specified in the ?searchpart
+ of mailto URLs can be included in the mailing, and made that the compilation
+ default in userdefs.h to go with the default MAIL_ADRS mask for PMDF (If
+ the "generic" VMS MAIL utility is used, not all of the headers can be
+ specified on the command line, as it requires). Look at the code in
+ LYMail.c and LYPrint.c that is used when isPMDF is TRUE as a model of how
+ to do this with other header-file-capable VMS mailers (but I don't have
+ any besides PMDF, and can't do it for you :). - FM
+* Tweak of the 1997-11-17 URL parsing mods so that relative symbolic
+ elements immediately preceding a ?searchpart are handled identically
+ to when a ?searchpart is not present. - FM
+* Added support for setting both SYSTEM_MAIL and SYSTEM_MAIL_FLAGS in
+ both userdefs.h and lynx.cfg. - FM
+1997-11-23
+* integrate PHDM's patch. - TD
+* Check for existence of sys/wait.h. - PHDM
+* Do not include sys/stat.h twice. - PHDM
+* New autoconf-macros to check if a function is declared after including a
+ specific set of files. - PHDM
+* Declare strstr if it is not declared by string.h. - PHDM
+* Declare getgrgid and getgrnam if not declared by grp.h. - PHDM
+* Provide strstr and mktime implementations, and use them if needed. - PHDM
+* Always include sys/types.h in HTUtils.h. - PHDM
+* define NO_GROUPS if we do not have getgroups. - PHDM
+* define NEED_REMOVE also if test yields unknown. - PHDM
+* define mode_t if not done by system include files. - PHDM (phdm@macqel.be)
+* change CF_UNION_WAIT to use compile+link rather than compile, to ensure
+ that we pick up the wait-macros rather than an implied function, which
+ should fix configure problems on NeXT for Francisco A. Tomei Torres
+ <fatomei2@mail.unm.edu>. - TD
+* spelling nit from Larry Virden. - TD
+* add osf3.0 to special case compiler options using -g3 in place of
+ -O -g, from Harsh Kumar <harsh@krcl.ernet.in>. - TD
+* remove redundant "-c" option from $(installbin) in makefile.in, reported
+ by Michael Warner <warner@wsu.edu>, for OSF/1 4.0. - TD
+* if configure --srcdir is not used, comment-out rmdir's in "make distclean"
+ rule. - TD
+* modify recent erase/clear change so that it applies only to FANCY_CURSES,
+ since BSD curses does not otherwise clear the screen when restoring after
+ popup. - TD
+* modify change for boxes so this builds with BSD curses, which has no
+ wborder() function. - TD
+* reverse ifdef for NO_SIZECHANGEHACK to USE_SIZECHANGEHACK, which is
+ normally off, since this code did not work with BSD 4.4 curses, SVr4
+ curses, or ncurses 4.1 with xterm. (Will make a configure test if anyone
+ can identify a configuration that works). - TD.
+1997-11-21
+* Changed LYE_LINKN to LYE_LKCMD (still mapped by default to Ctrl-V; may
+ need to be entered twice for some systems) for invoking a prompt to
+ enter any Lynx keystroke command when in form text fields. - FM
+1997-11-20
+* Added an LYK_CLEAR_AUTH command, mapped to underscore ('_') by default,
+ which clears all authorization info for the current session. This is
+ recommended for the situation when one leaves one's terminal but doesn't
+ want to end the browser session, nor want others to be able to retrieve
+ protected documents with previously entered username and password info.
+ Note that we don't yet have a way to block access to any protected
+ documents which are still in cache. - FM
+1997-11-19
+* Tweak of HTTP.c to ensure closing of the connection when interrupted
+ ('z'apped) on the first socket read. - FM
+1997-11-18
+* Mods to use the explicit label "Bad HTML:" in trace messages corresponding
+ to BAD_HTML_USE_TRACE messages. - FM & KW
+* Tweak of the restored TABLE-in-PRE block handling to deal with the
+ case when it's encased in a CENTER or DIV with ALIGN="center". - FM
+* Changed docs/README.defines to refer to INSTALLATION file - HN
+1997-11-17
+* Changed the default ASCII BOXVERT and BOXHORI definitions from '*' to
+ to '|' and '-', and new function LYbox() for non-VMS (n)curses. - FM
+* Use explicitly specified characters for drawing the corners of popup
+ boxes with non-VMS (n)curses if we have also specified characters for
+ vertical and horizontal lines. - KW
+* Mods in HTTP.c to trim any "LYNXIMGMAP:" leader from Referer header
+ values and strip the #fragment when making http(s) requests via links
+ in the pseudo-documents constructed for MAP elements. - FM & KW
+* Mods of SGML parsing to better handle SELECT blocks with invalid markup,
+ in effect for both TagSoup and SortaSGML parsing (for the latter just
+ in case it doesn't already prevent invalid markup from being passed on).
+ Only OPTION elements are accepted in SELECT blocks.
+ Otherwise, if the element is a form-related start tag, the
+ SELECT block is closed and the new form-related element is started.
+ All other elements are ignored. A FORM end or start tag ends any open
+ SELECT block and the current FORM (before starting another FORM if
+ it is a start tag). Note that we now support SELECT blocks outside
+ of FORM blocks, which some providers are using for "informational"
+ popups, but no Lynx user would do anything that awful, right? - FM
+* Tweak in LYMainLoop.c to override an LYresubmit_posts flag if we are
+ reloading a popped document due to a NOT_FOUND or NULLFILE return
+ value from getfile(). - FM
+ (But if the document that would be loaded after such a failure has POST
+ data and is not in memory, still jump to the PREV_DOC code, see enttry
+ for 1997-11-03. - KW)
+* Worked in a variant of AJL's suggestion of setting LINES and COLUMNS
+ artificially high before the initscr() call with Unix curses, then
+ using a dummy call to size_change() for setting LYlines and LYcols
+ to the actual screen dimensions, so that increases in the screen size
+ during the Lynx session, and not just decreases, can be handled.
+ Note that one still needs to do a RELOAD (^R) overtly to create a
+ new HText structure based on the current screen size. - FM
+ (The new code can be disabled by defining NO_SIZECHANGEHACK, in case
+ some curses version or terminal cannot deal with it. - KW)
+* Tweaks of the chartrans code. - FM & KW
+* Change in HTNews.c to ignore very long bogus newsgroup names when listing
+ available groups. - KW
+* Tweaks in code for highlighting search text in anchors, to better deal with
+ terminals in UTF-8 mode. - KW
+* Mods to ignore anything past a '?' character when simplifying URL paths,
+ as is now more clearly specified in the Fielding URL draft. Note that
+ we still assume a ';' is not in fact a parameter delimiter, or won't
+ have a value with characters that could be misinterpreted as relative
+ path specs. - FM
+* Increased the redirection limit to the original Lynx's value of 10,
+ because the HTTP/1.1 draft no longer will restrict it to 5, but instead
+ will leave it to the discretion of the browser (and I like 10, as a
+ reminder of the "good old days" :). - FM
+1997-11-15
+* Mods of parsing in HTML.c to restore support for the TABLE-in-PRE-block
+ HTML kludge described in http://ppewww.ph.gla.ac.uk/~flavell/tablejob.html,
+ which stopped working in conjunction with the 1997-05-21 mods (see below)
+ for treating TABLEs as DIVisions to support ALIGNment attributes in TABLE
+ markup. The PRE-in-TABLE-block HTML kludge was not affected by those mods
+ but works only with the TagSoup parsing mode. - FM & KW
+1997-11-12
+* Made handling of the 'x' in hexadecimal character references (&#xH;)
+ case insensitive, as for the "alphabetic digits" (a-f, A-F). - FM
+* Added a LINKN command key in the line editor, mapped to Ctrl-V, for
+ invoking the F_LINK_NUM prompt when in form text fields. Ctrl-V is
+ still a dead key under other circumstances in the line editor. - FM
+* remove options --with-lss-file and --with-cfg-file, since the corresponding
+ files will always be installed under $(libdir), reported by Henry Eric
+ Nelson (HN). - TD
+* modify configure script and makefile templates to permit builds with the
+ --srcdir option, noted by Philippe De Muyter. - TD
+1997-11-08
+* Added Unicode support for "DosArabic (cp864)", "WinArabic (cp1256)",
+ "DosGreek (cp737)", "DosGreek2 (cp869)", "WinGreek (cp1253)",
+ "DosHebrew (cp862)", and "WinHebrew (cp1255)". Note that we still
+ have no code for taking DIR attributes, or directionality in general,
+ into account. - FM
+* Mods to handle "cp-#" charset names as synonyms for "cp#", and some
+ cp# names as synonyms for "windows-#". FM & KW
+1997-11-07
+* Change of LY_SLrefresh() in LYCurses.c as suggested by JED - FM
+* add logic to make install-directories as needed. - TD
+* remove --disable-char-trans option (ifdef's still remain). - TD
+* correct type used in first compile-test for union wait. - TD
+* correct order of deletions in "make distclean" rule. - TD
+* new versions of macros used to check for ncurses version. - TD
+* don't suppress -I/usr/local/include when checking -I/usr/local/include/*,
+ to accommodate older versions of gcc. - TD
+1997-11-06
+* Use erase() instead of clear() in some places, to avoid unnecessary full
+ screen repainting even for UNIX (and similar) curses. Renamed LY_SLclear
+ to LY_SLerase, but it is used for erase() and clear() now, so there should
+ be no change in behavior for slang introduced by this. - KW
+* Added new format for lines in chartrans .tbl files: U+NNNN "a string" where
+ the string can have C backslash-escaped characters. This allows to write
+ replacement strings with 8-bit characters that won't be garbled when the
+ .tbl files are transferred in some non-binary way. Note there is no ':'
+ between the Unicode value and the beginning quote character. - KW
+* Changes to HTMLDTD.c (for SortaSGML parsing) and HTML.c (second line of
+ defense) for dealing with invalid SELECT tags. Also tolerate SELECT
+ outside of forms. - KW
+* Change in HTLocalName for DOSPATH so that it doesn't depend on whether
+ HTDOS_name returns a pointer to static memory or not. - KW
+* Started new file docs/README.defines. Renamed CHANGES to CHANGES2-7,
+ removed duplicate 2-7-1 entries. Minor changes to INSTALLATION, other
+ files. CHANGES.chartrans is gone. - KW
+* Tweaked color style stuff again. Statusline may behave better. - KW
+* Don't use memmove for HEAD in HTNews.c. - KW
+* For UNIX, use normal umask permissions, instead of the extra-cautious temp
+ file permissions, for files saved to disk by the default actions for PRINT
+ and DOWNLOAD. - KW
+* Changes (untested) in the code dealing with reading of compressed files in
+ HTFile.c, in parallel to the code for other systems. - KW
+* Mods to avoid va_start redefinition warnings when building with slang. - FM
+1997-11-05
+* Change in LYForms.c to avoid full screen repaint after popup is retracted
+ for slang. - KW & FM
+1997-11-03
+* Internal links code revised. Some details follow, but first a summary
+ of the basic premises. Links in a document given as href="#fragment" or
+ href="" (empty, but href attribute is present) mean something different
+ from href="url#fragment" or href="url" (where url is a non-empty absolute
+ or relative URL not including a fragment), they are internal links pointing
+ to an element or a location within the same copy of the document (or to the
+ document itself, for href=""). In contrast, a URL-Reference with a non-
+ empty URL refers to a (generally...) external resource. If the "url"
+ happens to coincide with (or, if it is relative, resolve to) the URL from
+ which the current document was retrieved, the current document is a
+ representation of the resource, but not the same thing. In most such cases
+ we can treat href="#fragment" and href="url#fragment" the same way, i.e.
+ activating such a link is interpreted as a request to reposition within
+ the current document; we are using the current document as a cache copy
+ of the resource (like we would other documents in the memory cache). But
+ if we have marked our copy as no-cache, it seems more consistent to treat
+ activation of a href="url#fragment" link as a request for retrieving a
+ new copy and _then_ locating #fragment in it, as we do for "any-other-url
+ #fragment" if we have cached a document which represents "any-other-url"
+ and which is marked no-cache. Following a href="" link should just result
+ in repositioning to the start of the document, not in a new retrieval for
+ no-cache documents.
+ If the current document is the result of a POST submission, there is in
+ general no way to refer to its underlying resource with a URL, since there
+ is no URL notation for "url+post_data". Internal links can be used within
+ the context of this document, but there is no way to hyperlink to it or
+ parts of it from "outside". A link to a href="url" or href="url#fragment"
+ target should always imply a GET retrieval, whether it occurs within a
+ document from a POST submission or not, for consistency.
+ This understanding also applies to other than <A href=..> uses of URL-
+ References in documents, for example the link implied between a USEMAP
+ attribute and a MAP element; but not to all uses, for example a FORM's
+ ACTION requires an external resource and not an internal reference, so
+ ACTION="" is resolved to an absolute URL (using a base URL if one is
+ given).
+ The semantics for URL-less URL-References are given in Internet Draft
+ <http://www.ics.uci.edu/~fielding/url/draft-fielding-url-syntax-09.txt>,
+ including that "Traversal of such a reference should not result in an
+ additional retrieval action." No comparable prescriptions are made for
+ references which have a URL, in particular it is not stated that they
+ should be treated as equivalent when the URL coincides with or resolves
+ to the current document's retrieval URL.
+ The changes to the Lynx code attempt to implement what is outlined above,
+ by keeping track of how a link destination was originally specified. href=
+ "#fragment" and href="" links are still "resolved" into a "url#fragment"
+ and "url" form, for use internally, and if an explicit NOCACHE action is
+ requested, and for generating lists of links etc., and in general for use
+ outside of the context of the current document.
+ To the best of my knowledge they do not lead to unwanted (or misdirected)
+ resubmission of POST content without prompting the user for confirmation
+ (although the prompt texts probably need improvement). - KW
+* The notion of the context of the "current document" is extended, so that
+ auxiliary LYNXIMGMAP documents generated by Lynx are within the scope of
+ the underlying document, i.e. the document containing the MAP and AREA
+ elements. Although they are treated as separate documents for display
+ and internal handling, following links between the underlying document
+ and its LYNXIMGMAP documents will result in display from cached data
+ (if available) even for no-cache documents, if a fragment-only (or empty)
+ URL-Reference was used in the HTML. This includes the link generated for
+ pointing from the IMG to the LYNXIMGMAP if the USEMAP attribute value was
+ was fragment-only; the LYNXIMGMAP is normally regenerated from the list
+ of MAP and AREA elements kept internally when a link to it is activated.
+ (Note that a LYNXIMGMAP screen is still not reloaded from external sources
+ even when RELOAD or NOCACHE keys are used, if data for the MAP is found
+ in the internal list; but that reloading the underlying document will
+ refresh the internal lists.) - KW
+* List Page screens are also in the context of the underlying document, so
+ that internal links in the underlying document can be listed and activated
+ from the List Page. When following an internal link from a List Page, it
+ is not pushed on the history stack (similar to the History List Page), to
+ reduce the chance of confusion when walking back through history. - KW
+* LYNXIMGMAP and List Page auxiliary documents can now be associated with
+ POST data. This does not mean that the data is posted to a "LYNXIMGMAP:"
+ or "file:" URL, which is impossible; but that the underlying document is
+ associated with the POST data. This way these aux documents can still
+ have links regarded as "internal" pointing to the document of which they
+ are logically a part, keeping track of what POST data are applicable if
+ several form submissions have occurred. Normally the underlying document
+ should be in the document cache when such a link is activated, so that
+ resubmission of the POST can be overridden. If it is not found,
+ resubmission may happen after user confirmation. Although the POST data
+ content is not shown on such aux pages, it can be inspected with the INFO
+ ('=') command. Note that the association of LYNXIMGMAPs and List Pages
+ with POST data automatically excludes them from various operations which
+ may otherwise be possible, such as bookmarking or inclusion in the
+ 'V'isited Links Page. Note also that such aux pages are treated internally
+ as different documents from their POST-free counterparts with the same
+ address, which might be generated for example after typing the address
+ at a 'g'oto prompt while viewing a different text. It may be possible to
+ generate confusing situations, but regenerating the displayed data (by
+ invoking 'L'IST again, or by following a LYNXIMGMAP: link) will always
+ show the currently applicable information.
+ For image maps, the change implements link-following capabilities which
+ come naturally to graphical UAs, which can handle IMG USEMAP and the
+ corresponding MAP elements from the same data stream as objects within
+ the same document instance. - KW
+* To implement the above, MAP and AREA information from a POST response is
+ not kept in the global list shared by all other documents, but in a separate
+ list specific to the underlying (containing) document and the POST data.
+ The specific lists are managed with the underlying document's anchor
+ structure so that they can automatically expire after the anchor is removed
+ from memory and will not stay around and accumulate until session end. - KW
+* POST data is kept in mainloop when following an internal link, but is now
+ always dropped for links that were given with a URL. This removes the
+ limitation by which a link in a POST response to the URL of the POST
+ submission script would be inappropriately converted to a resubmission of
+ the POST data. (example: search form from <http://www.marshall.edu/htbin/
+ calendar>) - KW
+* Changes to the PREV_DOC handling in mainloop. When encountering documents
+ that may need to be reloaded while walking back in history, because they
+ have POST data associated and are not marked "safe" and are either not found
+ in the memory cache or -resubmit_posts has been set, the user is prompted
+ for confirmation as before; if the reply is 'n' the document will be skipped
+ but if the user cancels with ^G the walkback operation is cancelled and the
+ currently viewed document remains loaded. Some of the aux documents which
+ can new be associated with POST data may be automatically skipped if their
+ document structures are not any more in memory. - KW
+* When following a link marked internal from a List Page and confirmation is
+ required, ^G may also have the different effect of cancelling the operation
+ while responding 'n' may attempt to follow the link as a GET request (i.e.
+ with POST data dropped). - KW
+* In some situations, automatic popping from the history stack in mainloop
+ after getfile fails to load a new document could lead to resubmission of
+ a previous POST request without prompting. This is now avoided by jumping
+ to the code handling PREV_DOC. - KW
+* Use new LYinternal_flag variable for propagating info to HTAccess, rather
+ than overloading LYoverride_no_cache. - KW
+* Tweaks for bad form tag soup with crashes on unclosed SELECT. Changes in
+ HTML.c and GridText.c to prevent memory leaks resulting from insanely
+ placed or unclosed form field tags, hopefully not introducing other
+ problems... - KW
+1997-11-02
+* Changes in HTParse's scan to leave additional '#' characters alone after
+ the first has been found when scanning (from left) for fragments, and
+ to apply the "don't treat '#' as start of a fragment for some kinds of
+ URLs" hack only when the '#' will become part of what has been scanned
+ as a path. NNTP articles with more than '#' in the message-id are now
+ accessible with the "news:" or "nntp:" schemes. We should actually always
+ escape when generating URLs and unescape when parsing them instead. - KW
+* Changed HTUnEscape to leave '%' alone if not followed by two valid hex
+ digits. - KW
+* Allow the HEAD key and -head and -mime_header flags for "lynxcgi:" URLs
+ and for "news:" and "nntp:" URLs that specify a single news article. - KW
+* Change to writing of POST data in LYCgi.c, to close file descriptor after
+ done writing and before reading as suggested by mhw@bcs.org.uk (Mark
+ H. Wilkinson), and to check status from the write() call and retry if
+ needed. Note that the code is not appropriate for handling large
+ amounts of POST data, since it still first does all the writing and
+ then all the reading. - KW
+1997-11-01
+* Added support for presentation of text/plain files in SOURCE ('\') mode,
+ homologously to text/html files, rather than treating the command as a
+ synonym for 'd'ownload when viewing a text/plain file. Note that if the
+ text/plain file has no long lines, the display of it will not change,
+ but otherwise, the long lines will not be wrapped in SOURCE mode, and
+ thus can be 'p'rinted without line wrapping. One still should use
+ 'd'ownload for a faithful copy of the file, i.e., without charset
+ conversions and expansions of TABs. - FM
+1997-10-30
+* Get numbering of links on List Page right, by faking hidden links for
+ form fields which get counted but are not selectable. - KW
+* Allow LYNXHIST: links in List Page since the History Page may get
+ 'L'isted... - KW
+* Mods of HTML.c parsing to close any open Anchor or emphasis elements
+ at the starts of TABLE elements, as the Big Two's TABLE handlers appear
+ to do now. - FM
+* Tweaks of charset handling via META elements and CHARSET attributes. - FM
+1997-10-29
+* Tweak of SortaSGML DTD for insane HTML with FORM start before HEAD. - KW
+* Prevent memory leaks from HTChunks for option and textarea with very
+ bad markup, added TRACE and BAD_HTML_USE_TRACE warnings for those. - KW
+* Don't call tigetnum("ncv") for _WINDOWS - BD
+* Added Unicode tables for the "DEC Multinational", "Macintosh (8 bit)",
+ and "NeXT character set" display character sets. - FM
+1997-10-28
+* Disable setting of the `reloading' flag in HTLoadDocument which would
+ generate no-cache headers for request where this is not appropriate. - KW
+* Memory leak for first OPTION in SELECT removed. - KW
+* Changed HTDOS_name to not return pointer to static area. - Binh Do
+ <bdo@mailman.epnet.com>
+* Changes to INSTALLATION file. - HN
+* Fix in HTMIME.c to recognize Content-location. - KW
+1997-10-27
+* Don't disable FORMs that have INPUTs with TYPE="file" or TYPE="range"
+ since those fields may be optional and the rest of the FORM may be
+ valid to submit. - FM
+* Updated links to www.w3.org in help files. - KW
+* Some changes for DOS compilation. - DK
+* Changes to INSTALLATION file. - HN
+* Tweaks of internal links stuff. - KW
+* Allow HEAD on URLs starting with LYNXIMGMAP:http by stripping the
+ prefix. - KW
+* Reverted LYCheckForCSI() to previous incarnation. - KW
+1997-10-26
+* If compiled with -DDONT_TRACK_INTERNAL_LINKS, behavior with respect to
+ internal links as in FM's code. - KW
+* Some chartrans tweaks. - KW
+1997-10-25
+* Changes to INSTALLATION file. - HN
+* Make temp file names conform to 8+3 naming convention for DOS, and
+ give LYNX_TEMP_SPACE priority over TEMP and TMP for DOS. - DK
+* Create temp file names with '-' char as separator between pid and
+ sequential number for non-8+3 systems, to prevent (unlikely)
+ collision. - KW
+1997-10-24
+* Change in HTML.c to use the base (rather than current document, if the
+ base differs) in all cases for form ACTIONs (i.e., if the ACTION is
+ empty, or has a lone fragment, or an ACTION attribute is not included)
+ as specified in the -07 to -09 Fielding URL drafts. - FM
+1997-10-23
+* Fixed a few typos and glued together a few URLs to make it easier for
+ folk to cut and paste them, in the new INSTALLATION file. - LVW
+1997-10-22
+* Many locations of files changed, about_lynx/ directory and references to
+ aboutfilepath removed, userdefs.h reorganized, changed README, new
+ INSTALLATION file, doc changes, some doc files removed. - HN
+ (Removed paragraph in README which doesn't apply yet, some files still
+ not done - KW)
+* Patch to WWW/Library/djgpp/makefile - WS
+* Added entity names from HTML 4.0 draft to extra entities in HTMLDTD.c - KW
+* Understand lists in ACCEPT-CHARSET attributes. Added a list of forms
+ to GridText structure (currently underused). - KW
+* Don't try to use box drawing chars in UTF-8 display mode. - KW
+* Changed chartrans mechanism (UCdomap.c, makeuctb.c) so that the "default"
+ translation table is now used as a fallback for other translation tables.
+ This also applies to display character sets which do not have a chartrans
+ table file but are listed in LYCharSets.c. Changed syntax of table files
+ (see src/chrtrans/README.format), added a keyword to disable using the
+ fallback. Currently def7_uni (corresponding to "7 bit approximations"
+ and the MIME charset "us-ascii") is used as default table, as before;
+ but previously the default table didn't have any real meaning.
+ Conceptually every translation table (unless it disables fallback) is
+ extended as if it included all the replacements from the default table.
+ Note that mappings for some characters in the default table file still
+ differ from the old mappings given in LYCharSets.c, and what is displayed
+ e.g. for umlaut characters may not be consistent, this still has to be
+ sorted out. It may just have become more visible now. - KW
+* Tweaks to some replacement strings in def7_uni.tbl; contributions of
+ more useful strings would be welcome... - KW
+* Removed mappings for invalid chars from some chartrans files, removed
+ Ethiopic chars from iso01_uni.tbl. - KW
+* Some other corrections and tweaks for chartrans mechanisms. - KW
+1997-11-21
+* Fixed handling of Control-D (delete character under the cursor) in the
+ line editor when the cursor is at the end of the line instead of on a
+ character in the string being edited. - FM
+* revised tests for wait/waitpid/union-wait. - TD
+* correct/update handling of default prefix in CF_WITH_PATH macro, used for
+ parsing --with-cfg-file and --with-lss-file options. - TD
+* add uninstall target to top-level makefile. - TD
+* remove redundant install options from $(INSTALL_DATA). - TD
+* add configure --with-lss-file option.
+* minor cleanup of gcc warnings, ifdefs. - TD
+1997-10-20
+* Mods in the CSO/PH gateway to set the anchor's safe flag to TRUE so the
+ user need not be bothered with confirmation prompts on resubmissions of
+ the search form. - FM
+* Tweaked the break point setting code in GridText.c for CJK di-bytes
+ so that one is set after a recognized "ESC(" ISO 2022 escape sequence
+ has been found. - FM
+1997-10-16
+* Tweaks to recognition of Japanese (better recognize x-euc-*), and to
+ the mechanism in GridText.c keeping track of which encoding is used for
+ Japanese. The state for this is now reset on explicit '\n' and '\r'
+ received by the HText object in addition to space chars. - KW
+* Tweaks in HTTP.c to avoid access to uninitialized memory and pacify
+ paranoid dbx. - KW
+* Try to more consistently remember the charset in effect for a document
+ when going to SOURCE view, using new LYUC{Push,Pop}Assumed functions.
+ Note that this is only in effect immediately when switching to SOURCE
+ view; any later reloading while within SOURCE view (including those
+ caused by RELOAD, RAW_TOGGLE and other keys, or by Options Screen changes)
+ may still revert to the usual assumption about charset, which means a
+ charset specified in a META tag may be forgotten at that point; this may
+ be considered a feature... - KW
+* Refer to TagSoup and SortaSGML parsing (coined by FM), rather than "old"
+ and "new" DTD. - KW
+* Made some of the changes concerning and removal and location changes of
+ files proposed by HN. - KW
+* Restored LYCheckForCSI example function to its previous form, with a check
+ added and comments added. - KW
+1997-10-15
+* Changed the order of display character set entries for the options menu
+ popup. "ISO Latin 1" and its "DosLatin1 (cp850)" and "WinLatin1 (cp1252)"
+ equivalents come first, then the system-based charsets (note that I
+ changed "IBM PC character set" to "DosLatinUS (cp437)"), then the CJK
+ and Vietnamese charsets, then "Other ISO Latin" (probably don't need
+ that one any more), then the known ISO 8859-# charsets with their
+ homologs (e.g, Dos and Win Cyrillic and KOI8-R) in groups, then
+ "UNICODE UTF 8" and the Unicode mnemonic charsets. - FM
+* Various fixes for color style code, should prevent memory corruption. - KW
+* Some LYCharUtils.c cleanup. - KW
+* Added some of the changes from fotemods to SGML.c, especially handling of
+ &zwnj; as allowing a line break, and conversion to UNICODE UTF-8. - KW
+* Mods in code handling mailcap lines, to avoid access to invalid memory. - KW
+1997-10-12
+* Added LYLeakSACopy and LYLeakSACat to LYLeaks.c. Running Lynx compiled
+ with LY_FIND_LEAKS defined will now give the source locations where
+ StrAllocCopy and StrAllocCat are used, if those create leaks. Added
+ missing include of LYLeaks.h in LYCookie.c. - KW
+* More heavy tweaks in LYCharUtils.c. Associated changes in HTChunk.c
+ (new functions), small change for -raw (in connection with attribute
+ values) in SGML_character. LYCharUtils.c is still a work in
+ progress... - KW
+* Tweaks to allow some chars as data input (0x97, 0x9b, 0xa0) if the
+ current display character set seems to have those values as printable
+ characters (by testing LYlowest_eightbit[]). - KW
+1997-10-11
+* Mods in HTFTP.c to recognize NetPresenz server (variation of AppleShare
+ claiming to be Peter Lewis server?, try current ftp://www.unicode.org/),
+ and to show server's identification from initial greeting on info
+ screen for FTP URLs. Other cosmetic changes in HTFTP.c. - KW
+* Fixed various memory leaks. - KW
+* Some more minor cleanup tweaks for color style code. - KW
+* Avoid unnecessary pauses if TRACE is on and a Trace Log file is in use. - KW
+1997-10-10
+* Renamed lynx_help/keystroke_commands/ directory to lynx_help/keystrokes/
+ for the benefit of DOS, and changed references accordingly. - KW
+* Changed parsing of command line options for -lss file, it should now
+ be used and override the default from userdefs.h or environment variables
+ as advertised. - KW
+* More tweaks and cleanup in HText_SubmitForm. - KW
+* Code to recover from memory exhaustion, sometimes. The requests for
+ dynamic memory which heuristically most often fail for lack of memory
+ when rendering large documents are the calloc() calls in split_line.
+ They are replaced by LY_check_calloc() which has the same calling
+ conventions as calloc() but additionally checks if "enough" memory is
+ available for the requested amount plus some margin and tries some
+ remedial action if this is not the case. The additional safety margins
+ are required to make it likely that other allocation requests in other
+ places of the program won't fail before the next check. The actions
+ which may be taken in order to avoid exiting if low memory is detected:
+ (1) Try to unload cached documents (other than the one currently being
+ loaded), until we seem to have enough memory. (2) If that fails (or
+ there are no other documents cached in memory), try to fake a 'Z' key
+ interruption; this will have the same effect as if the user had pressed
+ 'Z' so it will only detected if some other part of the program tests
+ HTCheckForInterrupt() and acts on it. (3) If this seems not to be
+ sufficient to stop loading, halt appending of normal text data to the
+ document structure (A warning *** MEMORY EXHAUSTED *** is appended
+ instead). - KW
+* A tweak of color style memory allocation. - KW
+1997-10-09
+* Some more tweaks from FM for VMS build - KW
+* For DJGPP compilation, src/chrtrans/makefile.dos - WS (Bill Schiavo
+ <Wschiavo@concentric.net>)
+* Some cleanup in Hext_SubmitForm (needs more). Start using ACCEPT-CHARSET
+ (doesn't recognize list yet, only recognized if on the INPUT field that
+ causes submission). - KW
+* Added two test files for iso-8859-2 charset. - KW
+* Tweaks in LYMainLoop.c for various keys that page up, to better preserve
+ keep the current link selected if possible and to correct a glitch with
+ UP_LINK. - KW
+* Reorder text/html and text/plain to the beginning of HTPresentations list,
+ so they will be found more quickly and will appear at the beginning of
+ Accept request header fields. - KW
+1997-10-08
+* add logic to implement mouse button 2 "previous document" for
+ ncurses configuration. - TD
+* add dependencies on 'lynx' to top-level 'all' and 'install' rules
+ in makefile.in - TD
+* add osf4.0 to special case compiler options using -g3 in place of
+ -O -g, for Heikki Kantola <hezu@iki.fi>. - TD
+* correct some of the uninitialized-variable warnings. - TD
+* Removed the compilation of the old libwww-FM HTAlert.c module for VMS,
+ as previously removed for Unix. - FM
+* Added comments and tweaks of build.com, build-slang.com and libmake.com,
+ (and a complementary tweak of tcp.h) to make more clear how compiler
+ definitions and compiler and linker options can be added. - FM
+1997-10-07
+* Changed PROBLEMS file for ^Z and for "forgetting emphasis of link text"
+ problem (which shouldn't occur any more). - KW
+1997-10-05
+* Changed SGML.c parsing of unrecognized and invalid start tags. If the
+ '<' character in HTML is followed by a 7-bit letter character, we now
+ do tag parsing even if the element name is not recognized, instead of
+ going to 'S_junk_tag' mode, so that a '>' embedded in an attribute value
+ (which may also be part of a CJK character's encoding) will not
+ prematurely end the tag. (But "soft double-quotes parsing" mode is
+ recognized.) Treat a '<' followed by most other 7-bit chars as data,
+ i.e. recover it and the following char. - KW
+1997-10-04
+* Corrected check for empty string at beginning of LYUnEscapeEntities. - KW
+* Squeezed option for "Assume charset if unknown:" into Options screen.
+ It is selected with a control char (^A), is only available in Advanced User
+ mode, and the value is currently not saved into .lynxrc with '>', i.e.
+ for a persistent change lynx.cfg has to be modified (or use an alias or,
+ for DOS, a batch file to call lynx with -assume_charset=...). The
+ interaction with the Raw M(O)de setting may be confusing (or confused :) ),
+ and it is possible to set nonsensical values that have no effect. - KW
+* Changed order and criteria of transformation attempts in HTPlain.c to
+ be more like SGML.c. For plain text KOI8-R would use 8-bit stripping
+ to early. HTPlain_write still is too different from SGML_character... - KW
+* Reinstate the slash after special interpretation of /~ at beginning of
+ file URL path for DOSPATH - DK
+* Changed SGML_character to not try to convert attribute values to UTF-8
+ if HTCJK is in effect (arrggh!) - KW
+* Changed effect of -raw / '@' for CJK display character sets: it now toggles
+ the effective charset assumption between that specified with ASSUME_CHARSET
+ or -assume_charset (or iso-8859-1 if none given) and the charset that
+ corresponds to the selected display character set, as for non-CJK. An
+ exception is made if both charsets are CJK charsets, so that the toggle
+ will still have the function of toggling CJK mode on and off. Explicitly
+ specifying a CJK charset as assumed is currently not very useful, since we
+ cannot translate from that to other character sets. - KW
+* Oh, by the way: compilation without defining EXP_CHARTRANS won't work any
+ more. Regard #ifdef EXP_CHARTRANS as some strange kind of comment for
+ now, until it goes away. - KW
+* Write comment at top of .lynxrc file to make clear that it is different
+ from lynx.cfg, suggested by LWV. - KW
+1997-09-30
+* Changed order of display character sets on options screen a bit, and
+ corrected charset listings in lynx.cfg and userdefs.h files - KW
+* Added comment on lynx.lss in userdefs.h, moved it. - KW
+1997-09-27
+* Made TRACE messages which correspond to BAD_HTML_USE_TRACE warnings stand
+ out more by decorating them with ***** characters, so that users who
+ follow the BAD_HTML_USE_TRACE advice can more easily find the relevant
+ messages. - KW
+* Reworked LYUnEscapeEntities() while loop into a (hopefully) more
+ understandable and consistent state-based switch, and integrated
+ LYUnEscapeToLatinOne functionality. - KW
+* Non-ASCII characters in URLs and similar strings encountered in the HTML.c
+ processing (previously handled by LYUnEscapeToLatinOne) are now generally
+ URL-encoded, instead of doing this just for 8-bit characters which are
+ the result of entity expansion. There is no clear standard definition what
+ non-ASCII characters in URLs in HTML attributes (HREF etc.) actually mean,
+ especially if the transmission character encoding is something else than
+ iso-8859-1. Leaving them as the raw byte values as received runs against
+ the HTML i18n view that the transmission encoding is distinct from the
+ document character set and has to be (conceptually at least) decoded before
+ SGML parsing. It also won't work in general for entities that expand to
+ to Unicode characters which cannot be expressed at all in the currently
+ effective (or assumed) charset, and would lead to problems with displaying
+ URLs on the statusline or representing them in auxiliary screens or bookmark
+ files. So now we try to first transform to the document charset "as usual"
+ (undo the transmission encoding), then translate the Unicode value into a
+ sequence of (one or more) byte values which are then URL-encoded. Since
+ character values > 255 cannot be expressed in a byte, always use UTF-8
+ for them. It may not be what the author intended, but should be at least
+ consistent between internal (fragment) HREFs and NAME (or ID) attributes
+ in the same document or set of documents. Since this is dealing with
+ bytes currently disallowed in URLs, it falls under error recovery. But
+ the handling should be roughly in line with current Internet Drafts
+ (draft-masinter-url-i18n-00.txt, draft-duerst-query-i18n-00.txt,
+ draft-ietf-ftpext-intl-ftp-02.txt).
+ For character values < 256 (but > 127) this isn't currently consistently
+ done, we may still be URL-escaping the byte value without UTF-8 encoding.
+ - KW
+1997-09-25
+* Integrated the attribute and form field translation stuff from separate
+ code line. This is still a rough attempt. Needs testing and refinement,
+ for various character set situations, expect glitches and bugs. - KW
+1997-09-24
+* Removed the compilations of the old libwww-FM HTInit.c and HTFWriter.c
+ modules for VMS, as previously removed for Unix. - FM
+* Added other changes from FM's feedback for VMS. - KW
+* Fixed a bug in the SGML unescaping of OPTION values. - FM
+* Fixed a bug in the SGML unescaping of TEXTAREA text. - KW
+1997-09-23
+* Fixed file 'E'dit command from dired directory listing, which I had
+ broken in 2.7.1ac-0.69. - KW
+* Added -width=NUMBER option to specify line width for non-interactive
+ formatting (-dump output). Also used by -preparsed source mode. - KW
+* Changed suffix mapping mechanism to deal with "real" content-encoding
+ parameters (gzip, compress) in addition to 7bit, 8bit, and binary. Added
+ a new field for brief descriptive text, so that the MIME type doesn't have
+ to be abused for this purpose, but left most settings in HTInit.c unchanged
+ for now. - KW
+* Changes in HTFWriter.c and HTFile.c so that we don't forget the file type
+ and encoding information we already have for a compressed file when passing
+ control to HTLoadFile (possibly after uncompression). - KW
+* Introduced FNAMES_8_3 symbol (for DOS 8+3 file system), and HTML_SUFFIX
+ which should be defined as ".htm" for DOS and ".html" otherwise. Various
+ tweaks to deal with systems with 8+3 restricted filenames, in general and
+ in connection with uncompression. - KW
+* Applied diffs from FM for VMS, compared with recent fotemods. - KW
+1997-09-21
+* Use 0.01 rather than 0.001 as the q value for inserted iso-8859-1 and
+ us-ascii charset parameters in Accept-Charset headers. - FM
+* Added internal buffering of I.value elements in HTML_start_element()
+ of HTML.c. - FM
+1997-09-20
+* Show HTTP header for all 2xx status codes (including 204-206) if requested
+ with HEAD or -head. - KW
+1997-09-19
+* Modified the Unix "strange character" filter in exec_ok() of LYGetFile.c
+ to allow '+', '&' and '=' characters. - FM
+* minor ifdef/declaration fixes required to build on IRIX 6.2,
+ SunOS (K&R) and VAX C. - TD
+1997-09-18
+* Try again after interrupted waitpid() in LYLoadCGI(), as in LYExecv() - KW
+* Tweak in LYKeymap.c to bypass the isalpha() test for non-ASCII values,
+ including values > 255 mapped to arrow keys, etc., when generating the
+ 'k'eymap display. - KW
+* Changes to prevent many (but not all) compiler warnings about `const'.
+ Not that this is different from TD's recent changes. Also some other minor
+ tweaks relating to (gcc) compiler warnings. - KW
+1997-09-17
+* Mods in GridText.c to use HTEscapeSP() for space-to-plus conversions of
+ name fields, and not just value fields, in submitted form content. Note
+ that some CGI scripts may still be doing plus-to-space restorations only
+ for value fields, and only hex unescaping for name fields, while others
+ may not be hex unescaping the name fields, so we may as well follow the
+ specs fully (and cross our fingers :). - KW & FM
+* merge symbols 'has_color' and 'lynx_has_color' to simplify ifdef's,
+ and correct a problem building color-style configuration. - TD
+* add configure symbol for ifdef'ing presence of waitpid, which
+ was stopping build on HP-UX. - TD
+* correct the symbol that is defined by CF_SIZECHANGE test, noted
+ by failure to build SCO version after making an include for
+ <sys/ioctl.h> ifdef'd according to configure test. - TD
+* corrected check for broken (pre-1.9.9g) ncurses versions so that
+ they can build with color support. - TD
+* cache state of CF_NETLIBS so that rerunning configure will yield
+ the same results for network libraries. - TD
+* Add configure test for HP-UX -lHcurses library. - TD
+* Minor adjustments to names of configure-script variables, to make
+ them the same as other programs (e.g., tin-unoff). - TD
+1997-09-16
+* Added code to JKT's and KW's mods in LYPrint.c to also handle VMS:
+ set the document's title as a logical on VMS (can be accessed via
+ f$trnlnm("LYNX_PRINT_TITLE") in scripts). - FM
+* Smaller cleanups here and there - FM & KW
+97-09-15
+* Recover from bad sequence "<=" in SGML.c by outputting those characters
+ literally. - KW
+* Try again after interrupted waitpid() in LYExecv(). - JED
+* Some tweaks in new DTD, some doc typo corrections. - KW
+97-09-13
+* Changes in LYConvertToURL() for better handling of the case when the
+ pathname of the current directory (when Lynx is invoked) contains
+ unusual, URL-reserved characters (especially '#') and we test for
+ a relative but URL-encoded path. (no change for VMS) - KW
+97-09-13
+* Changes in LYStrings.c to enable keypad() processing for non-NCURSES
+ if HAVE_KEYPAD is defined. - KW
+97-09-12
+* Correct mismatch/omission of HAVE_TYPE_UNIONWAIT symbol from
+ change for wait vs waitpid. - TD
+97-09-11
+* Tweaks in HTMLGen.c for display of special characters and line breaking
+ with -preparsed. - KW
+* Got rid of use of underlining together with reverse for non-current
+ links for (n)curses if color is not used. - KW
+* Small HTMLDTD.c changes for new parsing. - KW
+* Change in SGML.c to always recognize SOFT HYPHEN when given as &#173. - KW
+97-09-10
+* Modify CF_WITH_PATH to allow substitution of --libdir and other
+ configure options pathnames, e.g., for --with-cfg-file. - TD
+* Include lynx_cfg.h in userdefs.h to resolve redefinition reported by
+ AC. - TD
+* Remove Ultrix/sony_news -specific ifdef's for curses headers,
+ replace with configure-tests. - TD
+* Remove AIX/NeXT/sony_news -specific ifdef's for wait vs waitpid,
+ replace with configure-tests. - TD
+* Add/use CF_HELP_MESSAGE macro to visually break down the very long
+ help message into sections. - TD
+* Move the development options to the beginning of the configure script,
+ to facilitate adjustment of compiler options (especially for Ultrix)
+ to reduce the number of spurious warnings from miscombining -g/-O
+ options. - TD
+* Correct misplaced assignment to cf_cv_ncurses_header in configure.in,
+ which caused misconfigure against vendor curses, reported by Hynek Med
+ (Ultrix) and Roger Hill (HP-UX 10.x). - TD
+1997-09-09
+* Added arguments to the multinet_htons() and multinet_ntohs() declarations
+ in tcp.h. - FM
+* Tweak of the this_MIMEcharset[] and this_LYNXcharset[] checks in
+ makeuctb.c. - FM
+* Replaced the index() and bcopy() with strchr() and memcpy() in the
+ putenv() for NeXT in LYUtils.c. - FM
+1997-09-08
+* Added a -preparsed flag, to be used with -source or with SOURCE view.
+ When invoked with this flag, show HTML text as it is output from the SGML
+ parsing stage, regenerated via HTMLGen.c functions, rather than the usual
+ more raw rendering (in SOURCE view) or the original byte stream (as with
+ the -source flag, possibly with BASE information prepended). Lynx will
+ attempt to wrap the text to screen width (or 80 cols for the -source flag),
+ but will not always succeed. Unrecognized tags and attributes as well as
+ comments are dropped, attributes reordered, missing end tags supplied,
+ abd other changes made, showing how Lynx internally treats the document's
+ structure. This is probably most useful for debugging (of either Lynx's
+ parsing or of HTML documents, although a real validator should be used for
+ the latter!). It can also be instructive to switch the DTD parsing mode
+ (with the ^V key) while viewing preparsed source.
+ Note that this doesn't work so well now with character translations and
+ entity expansion don't work well now, showing some of the same problems
+ which appear for rendered documents and dropping some characters. Making
+ those problems of parsing more directly visible was one of the motivations
+ for this flag. Also note that META tags which may contain charset info
+ are never interpreted when using -source (with or without the -preparsed
+ flag), but when interactively switching to SOURCE view, Lynx MAY remember
+ that charset info from the previous non-SOURCE full parsing (again this
+ applies with or without -preparsed); the INFO screen should always show
+ the assumption currently in effect. - KW
+* Updated some HTMLGenerator functions to use line wrapping logic found in
+ newer libwww versions, and further mods in HTMLGen.c. - KW
+* Tweaks to use of chartrans stages, should now better preserve charset
+ info from META tags even in compressed HTML files. - KW
+* Fixed a problem with LYCheckForCSI which could lead to crashes. - KW
+1997-09-06
+* Modifications to allow the Lynx lynxcgi feature to process
+ PATH_INFO in addition to QUERY_STRINGS in URLs. DOCUMENT_ROOT
+ may be set by the user in lynx.cfg and is then passed as well.
+ If DOCUMENT_ROOT is set, then PATH_TRANSLATED is calculated and
+ passed as well. - J. Kevin Ternes <jkternes@mindspring.com>
+* Changes to LYPrint.c to put the variable LYNX_PRINT_TITLE
+ into the system()'ed environment for use by post-Lynx, pre-lp
+ formatting scripts. LYNX_PRINT_TITLE is simply generated by
+ calling HText_GetTitle(). - JKT
+* Corrections to JKT's mods (to avoid memory leaks etc.). Avoid
+ unnecessary stat() calls. Other fixes in LYCgi.c. Make
+ setting of HTTP_ACCEPT_CHARSET actually work. Now URL-unescape
+ the path in lynxcgi URLs before doing anything with it.
+ Better logic for when to check for restrictions, the previous checking
+ for !reloading could be easily circumvented. Also check whether
+ the full path including a possible PATH_INFO passes the restrictions
+ test by exec_ok(), to catch "../" segments. Don't try to handle
+ a non-executable lynxcgi URL as a file URL if there was a PATH_INFO
+ part, it gets too confusing. Strip '#' fragments from the lynxcgi
+ path, but leave the interpretation of '#' characters after a '?' as
+ before so that they are still regarded as part of the query or search
+ string. If PATHINFO is present, unescaped '#' characters in it will
+ still be rejected by exec_ok(). - KW
+* added a bit of text about running ./configure to INSTALLATION file.
+ - David Combs <dkcombs@netcom.com> & KW
+* Added a translation table for Vietnamese (VISCII), and associated code
+ changes. See the file viscii_uni.tbl. - KW
+1997-09-05
+* Mods in LYGetFile.c to retain a fragment on redirection if the redirection
+ URL does not include a fragment. - FM
+97-09-04
+* Correct ifdef'ing for getbkgd function calls. - TD
+* Correct ifdef'ing for remaining inline chmod calls. - TD
+* Consolidate various logic for opening secure files into utility
+ functions, correcting portability problems as well. - TD
+* Add configure option --with-cfg-file to override default location of
+ Lynx configuration file (requested by Laura Eaves). - TD
+* Strip -g option from CFLAGS for the non-debug version of Ultrix
+ configuration (requested by Hynek Med). - TD
+* Add configure test for HP "color" curses (noting that this cannot
+ possibly comply with XPG4 due to naming conventions, we'll expect
+ other problems with it). - TD
+* Add checks to configure test for COLOR_CURSES to work around bug
+ report for HP-UX. - TD
+* Don't cache configure options except where essential (e.g., the
+ setting of 'screen'). - TD
+* Change some configure options to disable/enable for consistency. - TD
+1997-09-03
+* Tweaks in HTML_put_string() and LYUnEscapeEntities() to deal with line-
+ breaks within attributes more consistently, and more independently of
+ which convention is used (CRLF, CR, or LF). - KW
+* Tweaks to prevent a few compiler warnings. - KW
+* Tweaks of the iso06_uni.tbl and iso08_uni.tbl files now compiled in.
+ Note that a replacement character or string to replace invalid or
+ unrecognized characters can be defined by mapping the Unicode value
+ U+FFFD, which is done here (for testing, and because these two charsets
+ have a lot of undefined code points). Also some mods in default 7-bit
+ table for some Hebrew characters and points. - KW
+1997-09-02
+* Mods to include "ISO 8859-6 Arabic" and "ISO 8859-8 Hebrew" in the display
+ character set options (Note, though, that Lynx presently has no code to
+ deal overtly with non-Latin directionalities.). - DK & FM
+1997-08-31
+* Mod of HTMIME.c to ignore any Content-Encoding header with a value of
+ "identity" (case insensitive). Shouldn't happen, but better safe than
+ sorry. - FM
+1997-08-28
+* Correct a quoting error in CF_RECHECK_FUNC macro. - TD
+1997-08-27
+* Further refine/correct configure macros for finding network and curses
+ libraries, adding CF_RECHECK_FUNC to simplify CF_NETLIBS. - TD
+* Rename #define for NCURSESHEADER to HAVE_NCURSES_H, for consistency. - TD
+* Add-back test for -lm to support slang shared libraries. - TD
+* Modify test for disentangling ncurses library from mytinfo on FreeBSD
+ to workaround linker limitation. - AC
+1997-08-22
+* Fixed typo in LYReadCFG.c when checking for a NOVICE mode default. - JN
+ (Note that this and other lynx.cfg defaults which have 'o'ptions settings
+ are overridden when the 'o'ptions are saved to the RC file. - FM)
+1997-08-21
+* Tweak to LYHistory.c to better remember last position on page. - KW
+* Eliminated two more MIME types (application/html and text/x-sgml) from
+ the Accept header generated by default by setting the q-value to 2.0,
+ since there are more standard alternatives for these names. - KW
+* Lower maximum length for generated Accept header lines from 1000 to 252,
+ to accommodate an incompetent Windows HTTP server. - KW
+* Changed order of some functions in LYCharUtils.c (no other change there
+ yet). - KW
+1997-08-20
+* Modify top-level install rule to depend on 'all'. - TD
+* Suppress check for ANSI compiler when we are using gcc. - TD
+* Use -g3 option in place of -O -g for Ultrix compiler --debug configuration
+ (request by Hynek Med). - TD
+* Drop "-lm" library from slang configuration, since it does not seem to
+ be used. - TD
+* Add configure --includedir and --oldincludedir values to header search
+ path for ncurses and slang. - TD
+* Modify configure checks for ncurses and slang libraries to generate
+ -L options as required, using new macros CF_FIND_LIBRARY and
+ CF_LIBRARY_PATH. - TD
+* Add substitution for CPP in src/makefile.in so that .c.i rule works. - TD
+* Add configure test for lint program. - TD
+* Add "make depend" target to generated makefiles. This is intended only
+ for use in editing/developing, since many of the header dependencies in
+ chrtrans are generated during the build process and cannot be determined
+ by makedepend in advance. - TD
+* Add configure option --with-zlib. - TD
+1997-08-19
+* Tweak of highlight() in LYUtils.c to ensure that split link names with a
+ soft hyphen are handled identically for slang, VMS curses and Unix curses
+ when such links are made current. - FM
+1997-08-17
+* Use 0.01 rather than 0.001 as the q value for the global wildcard in
+ Accept headers. - FM
+* Put up correct makefile for dos port (oops) - WB
+1997-08-16
+* Mini tweaks for the win-dos ports. One fix for the pull down boxes
+ and the rest mostly maintenance. - WB
+* Fixed a bug in LYNews.c which caused overwriting of the first three
+ characters in the Subject for a followup. - FM
+1997-08-15
+* Hack in highlight() to preserve a '-' character at the end of line
+ within anchor text, which can result from splitting at the position
+ of a &shy; or <SHY> or SOFT HYPHEN character. - KW
+* Tweaks in print_wwwfile_to_fd print_crawl_to_fd to output a soft hyphen
+ character if it is present at the end of a line. For -dump, a raw
+ ISO 8859 SOFT HYPHEN character may be written if the Display Character
+ Set (default from lynx.cfg or saved value in .lynxrc) is an ISO 8859
+ character set, but this may be overridden with the -raw toggle.
+ Otherwise represent soft hyphen with '-' as usual. - KW
+* Modified the news gateway to try XGTITLE for wildcarded lists of
+ available newsgroups (e.g., news:bionet.* for the bionet hierarchy,
+ or news:* for all of its served newsgroups). If that fails, Lynx
+ retries with the old behavior of using LIST NEWSGROUPS and parsing
+ the reply itself for the desired groups. Note that LIST NEWSGROUPS
+ can take a wildcarded argument for some nntp servers, but not all,
+ so we don't risk it. - FM
+* Fixed a bug in HTHandleAuthInfo() of yesterday's HTNews.c which could
+ yield an infinite while() loop. - FM
+* Various tweaks in HTNews.c to HTHandleAuthInfo() and elsewhere, to
+ keep connections open more often in some common cases of non-fatal
+ errors, and also avoid trying to use the network socket after some
+ recognized case of closing by the server. Only based on some testing
+ with INN's nnrpd, not on any written specs. - KW
+1997-08-14
+* Added nntp authorization (AUTHINFO) handling to the news gateway. - FM
+* Added a "Loading cfg file '%s'." trace message in LYMain.c to indicate
+ the absolute path of the configuration (lynx.cfg) file which was used
+ at startup (if Lynx is invoked with the -trace command line switch). - FM
+* Added code in HTFWriter.c to avoid calling HTLoadFile() on the temporary
+ file which results from decompression of a temporary file created by
+ HTCompressed(), if this would just result in making a copy of the file
+ and then invoking an external viewer. Instead the viewer command is
+ now invoked directly from the HTFWriter_free of the HTCompressed()
+ stream after decompression. - KW
+* Added code in HTFWriter.c, HTFile.c, and HTFormat.c to support reading
+ of gzipped local files directly, using functions from the zlib library.
+ Note that gzipped files from remote servers are still first copied to
+ a temporary file before lynx can process them further, and an external
+ GZIP_PATH command is still needed at least for passing such files to an
+ external viewer, as well as for various DIRED_SUPPORT File menu functions.
+ To activate this code, the symbol USE_ZLIB has to be defined, it is
+ currently not set by the auto-config script. The zlib library may be
+ already installed on your system (probably called libz.a or libz.so.1
+ or similar, the required header files are zlib.h and zconf.h), otherwise
+ it is available through <http://www.cdrom.com/pub/infozip/zlib/>, it
+ appears to support all platforms for which lynx is available (including
+ VMS, DOS, MS Win32). Note that this library would probably also be
+ needed if in the future support for the HTTP/1.1 "deflate" content-coding
+ is added. - KW
+* Don't send MIME types in Accept headers whose q values are outside of the
+ allowed range 0.0 <= q <= 1.0 - KW
+* Tweaks in HTInit.c to use the official names for image/png and image/tiff,
+ but still support the image/x-* forms. - KW
+1997-08-13
+* Tweaks of LYConvertToURL() in LYUtils.c and HTParseInet() in HTTCP.c
+ to deal more coherently with 'z'ap attempts during gethostbyname()
+ calls. - FM
+* Tweaks of split_line() and HText_endAppend() in GridText.c to handle
+ trimming of spaces from the tails of link names more effectively. - FM
+* Expanded the OL nesting depth and type counters to track up to 12 list
+ depths before punting to the lowest negative number. Note that the
+ indentations still are limited to 6 nested depths, so use the TYPE
+ attribute to distinguish OLs with deeper nestings. - FM
+1997-08-12
+* Mods of LYMainLoop.c to maintain treatment of a local startfile as
+ text/html source when it does not have a suffix mapped to that MIME
+ type and the -force_html switch was used. - FM
+* Added .phtml to the default suffix mappings for text/html. - FM
+* Mods of LYCurses.c to avoid using /dev/tty arbitrarily for stdin on
+ Unix when compiling with slang versions greater than 0.99-35, based
+ on JED's suggestion to lynx-dev. - FM
+* Tweaks of HTCheckFnameForCompression() in GridText.c to avoid warnings
+ from some compilers. - FM
+1997-08-09
+* Changed the code of 1997-08-06 which modifies suggested filenames for a
+ 'D'ownload to be more cautious: don't remove a '.gz', '.Z' etc. suffix
+ if there is no header indication that we have a compressed file. Not
+ all servers and gateways (including the internal FTP gateway) detect
+ and label compressed content reliably. - KW
+1997-08-08
+* Mods of HTTP.c so that download requests are converted to presentation
+ requests for interactive users, and traversal requests are converted to
+ cancels, when servers return non-success statuses with bodies which
+ should be displayed to interactive users. - FM
+* Added the "DosCyrillic (cp866)" display character set to the chartrans
+ support, and tweaked the other Cyrillic charset tables. - AAC & KW
+* Tweaked MULTI_SUFFIX support in HTFile.c, so that it now somewhat
+ works. Dunno whether it's useful for anybody. - KW
+1997-08-07
+* Tweaks of yesterdays mods in GridText.c. - FM
+* Correct storage class of variables in UCMap.h, from -warn-common linker
+ option. - TD
+* Refine configure tests for acs_map, ttytype to accommodate broken linker
+ on FreeBSD 2.1.5 - TD
+* Modify README.configure to indicate the associated definitions for
+ each configure option, as suggested by Klaus Weide. - TD
+* Correct duplicate declaration of Current_Attr, which Linux linker ignores
+ (reported by Hynek Med). - TD
+* Add -G7 option to Ultrix compiler options (request by Hynek Med
+ <xmedh02@lada.vse.cz>). - TD
+* Add include for <sys/types.h> to utmp configure test (reported by Andrey
+ A. Chernov). - TD
+* Add check for FreeBSD library mytinfo (reported by Andrey A. Chernov
+ <ache@null.net>). - TD
+* Modify ./makefile.in so that 'all', the default target, will build the
+ Lynx executable. The old 'all' target is retained as "make help". - TD
+* Modify src/makefile.in to allow development compiles within the src
+ directory. - TD
+* Mask spaces in the bkgd (background attribute) calls for color curses to
+ make the color-style code work better with SVr4 curses. - TD
+* Change workaround for 8-bit acs characters by adding to the initialization
+ a loop forcing the entries of acs_map[] to 8-bits. - TD
+* Many minor tweaks for the DJGPP version by DK - WB
+* A rename of about_lynx_dev.html to lynx_dev.html for 8.3 systems - WB
+1997-08-06
+* Modified HTMIME.c and LYCharUtils.c so that setting of suggested filenames
+ via a filename=value pair in Content-Disposition headers and META elements
+ is not restricted to the file disposition type. - FM
+* Mods in GridText.c, LYGetFile.c and HTAnchor.c so that suggested filenames
+ will have appropriate suffixes when 'd'ownloading, based on whether or not
+ the file is gzipped or Unix compressed. - FM
+1997-08-05
+* Mods of the lead relative symbolic element stripping for http/https
+ URLs in cases for which they would persist when resolved to an
+ absolute URL. The latest URL draft is ambiguous about whether this
+ should be considered an error, and leaves the handling of it up to the
+ UA. So we now get rid of all lead relative symbolic elements from the
+ resolved http/https URLs, but no others, and still issue a Bad Partial
+ Reference statusline message. - FM
+* Tweaks of title handling in LYMainLoop.c and LYShowInfo.c so that the
+ known title, or link name associated with ACTIVATE-ion, form submission,
+ or a HEAD request, will be used in the INFO ('=') display. - FM & KW
+1997-08-04
+* Fixed header parsing in HTMIME.c so that "Safe:" is recognized. - KW
+* Changed confirmation prompts for HEAD (']') commands acting on a POST
+ document, to reflect the fact that the POST request body will not
+ actually be submitted in a HEAD request. - KW
+* Reset LYCancelDownload to FALSE at top of getfile(), to prevent delayed
+ effect which can otherwise occur. - KW
+* Block URLs with port numbers outside the range of valid numbers in
+ getfile(). - KW
+1997-08-03
+* Changed the NSL_FORK code in HTTCP.c so that the gethostbyname() call
+ is retried without forking if the child process exits without returning
+ enough data. Also added trace output, to show whether something
+ unusual has happened to the child process. - KW
+* The IETF has indicated intent to adopt KW's "status 307" proposal for
+ dealing with the status 302 problems, so HTTP.c and HTAlert.c implement
+ that now. The 302 status is "General (temporary) Redirection" which
+ can be handled as 303 at the UA's discretion, so we do that in all cases,
+ rather than prompting the user whether to do that when the 302 is for
+ a POST submission. The 307 (and 305) for POST submissions invokes a
+ prompt whether to P)roceed or C)ancel, without the Use G)ET option.
+ The 301 is treated as permanent, normally, but for POST submissions
+ still is treated as temporary and invokes a prompt which includes the
+ Use G)ET option, because scripts written to empirical behavior may
+ still be expecting that (it's virtually never encountered in redirections
+ of POSTs, though, because the document containing the form typically
+ is redirected, so the user only sees the form if a local copy has been
+ made, and it would be best to C)ancel and get a new local copy of the
+ document from the correct http/https URL, to serve as a BASE for the
+ form's ACTION). - FM
+* Changed the typedef for HTCoord in HTStyle.h from float to int, for
+ significant speedup of rendering on machines without floating-point
+ hardware based on DW's, KW's, BL's analyses. Note that this should
+ be taken into account when/if external style sheet support is added
+ for page formatting (e.g., for optimum handling by speech synthesizers
+ and braille interfaces), beyond the current emphasis on colorizing. - FM
+1997-08-02
+* The cookie pre-draft has been adopted as an IETF ID:
+ ftp://ds.internic.net/internet-drafts/draft-ietf-http-state-man-mec-03.txt
+ so the code for combining Set-Cookie and Set-Cookie2 headers has been
+ eliminated in LYCookie.c (see mods for 1997-07-31). - FM
+1997-08-01
+* Fixed typos in LYCookie.c. - FM
+1997-07-31
+* Mods of the cookie handling based on the latest pre-draft. Add a
+ Cookie2: $Version="1" header in any requests that use historical
+ cookies in the Cookie: request header, so that modern servers will
+ use Set-Cookie2 headers with modern cookies in their subsequent
+ replies. Limit the scheme for commentURLs to http or https, not
+ just to network servers (e.g., gopher is now barred too). Include
+ a $Port attribute in modern Cookie request headers if it was set
+ via a server's reply header. The pre-draft indicates intention
+ to drop the requirement to combine Set-Cookie2 and Set-Cookie
+ headers if both types were received. We're still combining them,
+ but based on bona fide one-to-one correspondence checks (which were
+ not specified in the earlier draft), so that's OK, and we'll get
+ rid of that needless overhead if the current pre-draft holds up
+ and becomes an official IETF draft. - FM
+* Added a -nocc command line switch for disabling the Cc: prompt
+ for self copies of mailings. Note that this does not disable
+ any CCs that have been incorporated within a mailto URL or form
+ ACTION. - FM
+* Added a NO_FORCED_CORE_DUMP compilation (userdefs.h) and configuration
+ (lynx.cfg) symbol, normally set FALSE, which if changed to TRUE will
+ block forced core dumps on Unix via abort() calls on fatal errors or
+ assert() calls on potentially fatal error checks. Also added a -core
+ command line switch for toggling the default. - FM
+* Updated the documentation and 'h'elp concerning the new symbol and
+ switches. - FM
+1997-07-30
+* Added workaround for curses with broken handling of 8-bit acs characters
+ (which may be used for drawing of popup boxes) to LYCurses.h. This fixes
+ box characters and attributes/colors for solaris curses used with linux
+ console as terminal. Currently it is not automatically enabled or
+ configured, but can be enabled by -DBROKEN_CURSES_8BIT_ACS. - KW
+* Mod in HTFWriter.c to change the statusline appropriately when an
+ uncompression has completed. - FM
+* Fixed code in LYOptions.c for the case when NEVER_ALLOW_REMOTE_EXEC was
+ not defined and ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS was defined. - KW
+1997-07-28
+* Avoid traversing the full list of anchors each time when HText_endAnchor()
+ is called with a non-zero anchor number, if that number corresponds to
+ the last anchor added to the HText structure. It is is the most common case
+ that HText_endAnchor() refers to the last anchor, and the only case that
+ could be handled correctly before FM's changes of 1997-05-13. Avoiding
+ the loop over the list of anchor can improve loading time significantly,
+ especially for large files with thousands of anchors. - KW
+* Add progress display and 'z'appability for loading of local files.
+ They are activated only after a few hundred k bytes have been read.
+ Added define for HT_PARTIAL_CONTENT to HTUtils.h, used in above.
+ (The WWW Library 5.x uses HTTP-ish status codes like this throughout.
+ I find it much less confusing than -29998 and so on, and there's no
+ conflict in this case. - KW
+* Minor LYUtils.c tweaks. - KW
+1997-07-27
+* Changed code for checks in LYGetFile.c for URL schemes which should
+ be rejected when received as redirections, added checks for more
+ schemes. - FM
+* Rename top-level Makefile to Makefile.old (it's obsolete) - TD
+* Reduce top-level targets to one, 'lynx' - TD
+* Move comments describing DirEd to README.configure from makefile.in,
+ leaving only the definitions that haven't been integrated yet. - TD
+* Add configure options to enable/disable DirEd and its associated modes. - TD
+* Add configure option to enable/disable char-trans support. - TD
+* Correct sense of autoconf'd symbol for size-change. - TD
+* Accommodate systems with obsolete ncurses.h in configure tests. - TD
+1997-07-26
+* Changed the variable hline in LYUtils.c to hLine, so as not to conflict
+ with a curses function or macro. - FM
+* Fixed an esoteric glitch in highlight() of LYUtils.c which could cause
+ the last character of a current link to receive WHEREIS search target
+ emphasis if it happened to be the first character of the target (though
+ perfection is unattainable, we should strive to achieve it :). - FM
+* Changed the default value for STRIP_DOTDOT_URLS (lynx.cfg) to TRUE. - KW
+* Made some of the additional checks introduced yesterday in LYMainLoop.c
+ for invalid links to internal dired URLs more strict, as they probably
+ were intended. - KW
+* Added checks for some internal URL types, which should be rejected
+ if received in a server redirection, to LYGetFile.c. Maybe more types
+ should be added to the list. - KW
+1997-07-25
+* Map charsets of the form "ibmNNN<...>" to "cpNNN<...>" in UCdomap.c
+ if not already recognized. Also recognize "windows-1252". - KW
+* Compared the handling of 4-way "show color (&)" in the 'o'ptions menu
+ against FM's implementation, and made some changes (mostly in formatting,
+ variable and constant names and usage, ordering of statements) to aid
+ further comparison. The logic is still messy and needs further cleanup
+ and simplification, but seems to do what it should. Note that this
+ also handles color-curses, in a (hopefully) reasonable way. Command
+ line flags -nocolor and (if using slang) -color override a preference
+ found in the RC file. See updated "Lynx Users Guide" file and the
+ comments written to the RC file.
+ Documentation changes adapted from FM's changes. - KW
+* Mods of the DIRED_SUPPORT to check the actual URLs of temporary files
+ rather than just their titles when filtering for spoofing attempts via
+ external files with internal URLs. Also recast the PRIVATE my_spawn()
+ to a PUBLIC LYExecv(), so that it can be used by any module (though
+ presently it's still used only by LYLocal.c functions). - FM
+* Tweaks of LYCharUtils.c to handle Set-Cookie HTTP-EQUIVs in META elements
+ without risking crashes in LYCookie.c or HTParse.c. - FM
+1997-07-24
+* Made "show color" option a 4-way choice, if compiled with color support
+ and if saving of options to a .lynxrc file is allowed. - KW
+* Made changing file permissions with DIRED_SUPPORT work again; one of
+ the recently added checks in LYMainLoop.c was too restrictive.
+ Added protection to permit_location in LYLocal.c, similar to the changes
+ of 1997-06-24 to LYDownload.c. - KW
+* Generate CANCELLED message when editing of a string value on the Options
+ Screen has been cancelled (typically with ^G), instead of an
+ inappropriate VALUE_ACCEPTED statusline. - KW
+1997-07-23
+* Tweaks of the strtok() calls for textarea values in HTML.c, so that they
+ will never be repeated after NULL has been returned, and thus won't cause
+ linux-alpha to crash. - FM
+* Make -nocolor command line flag work if compiled with slang. Note that
+ -nocolor is strong, it overrides all other reasons that might otherwise
+ turn color on. - KW
+* Tweaks in LYCurses.c to ensure that slang library and Lynx flags for
+ whether color support is on stay in register. - FM
+* Change the default in userdefs.h for SHOW_COLOR to FALSE for USE_SLANG.
+ Because of the different logic used for LYShowColor in the curses code
+ vs. slang code, setting SHOW_COLOR to TRUE makes it difficult to invoke
+ a binary compiled with slang so that color is not used on startup
+ (except by using -nocolor).
+ Note that reading show_color from .lynxrc is still commented out. - KW
+* There is now a "trailing comment" handler in LYReadCFG.c. It treats '#'
+ as a comment token only if it is somewhere after the last colon for the
+ lynx.cfg entry and is preceded by a space or tab. - FM
+* Added TT to the Utterly Tag and Attribute Soup group of HTML elements. - FM
+ (applies only to "old" DTD in this code set, as usual - KW)
+1997-07-22
+* Modify curses popups in LYForms.c and LYOptions.c to use background color
+ from main window - TD
+* Ifdef'd out the logic that saves "show color" to .lynxrc, since it is
+ deemed to be confusing to users - TD
+* Merged FM's changes to the "show color (&)" toggle to save to .lynxrc,
+ support slang, update online documentation - TD
+* Add error message to show actual context in error-checking for color
+ parsing suggested by Filip M Gieszczykiewicz - TD
+* Check for/suppress duplicate -lsocket in network library configure - TD
+* Remove HP-UX snake2/snake3 targets from makefile.in - TD
+* Add configure script case for 'sequent', drop ptx, ptx2 targets from
+ makefile.in - TD
+* Add logic to configure script handling of slang to suppress spurious
+ -Ipredefined when header location is given in $CFLAGS - TD
+1997-07-21
+* Check for lynx_uses_color and LYShowColor in lynx_start_status_color()
+ and lynx_stop_status_color() of LYCurses.c so that the statusline
+ will appear reverse (or otherwise highlighted if the terminal doesn't
+ support reverse), if color support is compiled in but not currently
+ used. - KW
+* Added comments on color usage to lynx.cfg. - KW
+1997-07-20
+* Added command-line option "-nocolor" to disable color on terminals that
+ would otherwise support it. Added options toggle for colors, tested
+ with ncurses. - TD
+* Remove option value from configure option "--with-color-styles". - TD
+* Correct background of popups in LYOptions.c - TD
+* Add configure check for compiler options to enable prototypes - TD
+* Remove IRIX "-cckr" compiler flags. - TD
+* Correct whitespace as per LPS: LYCurses.c, LYOptions.c - TD
+* Tweaks of LYMainLoop.c in the code controlling how the document is reloaded
+ due to any changes in the 'o'ption menu which require a new rendering of
+ the document (but still without forcing a proxy cache refresh when that is
+ inappropriate; see the 1997-05-26 mods). - FM
+1997-07-18
+* Mods in LYexit.c and LYCurses.c to ensure restoration of stderr (if it
+ was changed for output to the trace log) on all exits. - BRL & FM
+* Include an unsigned char typecast in the HASH_FUNCTION definition for
+ HTAtom.c - CK
+* Modified change to is_url() of 1997-07-13 to check for the slash after
+ stripping any lead space characters. - FM
+1997-07-16
+* Added the Windows Cyrillic display character set. - AAC
+ (Andrey A. Chernov <ache@null.net>)
+1997-07-15
+* Added support for a commentURL attribute in cookies. This attribute is
+ under discussion in the HTTP-WG and not presently in the draft (see the
+ 1997-07-09 mods for the draft's URL), but would be extremely advantageous
+ for multi-lingual and non-English-speaking sites because the comment
+ attribute can have only ASCII characters in its value, whereas a request
+ for the comment via a URL in turn allows use of charset and language
+ negotiation for what the server returns. The value of the commentURL is
+ resolved and retained only if it's scheme points to a server (i.e., file
+ and special lynx URLs are rejected), and if it is retained, is included
+ as a link in the Cookie Jar Page. If commentURL is not ultimately
+ included in the revised State Management RFC, sites which wish to use
+ it could do a User-Agent check for Lynx (and any other browsers which
+ implement it). - FM
+* Fixed a typo in HTCompressed() of HTFWriter.c so that the last dot in a
+ tentative temporary filename is sought via strrchr(), as is done for
+ HTSaveAndExecute() and HTSaveToFile(). - KW
+1997-07-14
+* Yet more tweaks of the cookie support. We include $PATH and/or $DOMAIN
+ attribute/value pairs in Cookie request headers only when their values
+ were set explicitly via a server's Set-Cookie and/or Set-Cookie2 reply
+ headers (and the cookies are $VERSION="1" or greater). - FM
+* Added support for IFRAME homologous (but not identical) to that for FRAME.
+ It is handled as a block with a blank line before and after style, and
+ with margins and default alignment inherited from the containing block,
+ division, or span. The IFRAME rendition always begins with an emphasized
+ "IFRAME: " label followed by the NAME attribute's value, if present, or
+ the URL for the SRC attribute, serving as a link for the SRC, followed
+ on a new line by any rendered IFRAME content. - FM
+* Added handling of LEGEND elements. The content is rendered in place,
+ as for CAPTION elements, since we don't have multiple pass inlining
+ capabilities. Hopefully, if the LEGEND is intended to be ALIGN-ed at
+ the "top" or "bottom" of the associated insert, the author will place
+ the LEGEND element above or below it, respectively. Note that LABEL
+ elements similarly are rendered in place, and will be displayed
+ interpretably only if the INPUT to which the LABEL's "for" attribute
+ refers, immediately follows the LABEL element. - FM
+* Added recognition of BUTTON elements, and handling of them (sorta :)
+ when they are TYPE="submit" or TYPE="reset" in forms. The default
+ "submit" or "reset" string, or the value of a VALUE attribute, if
+ present, is embedded in parentheses and used for the link, and the
+ content is simply rendered and displayed in place. Until we see what
+ kind of markup the real world puts in such elements, it's too risky
+ to try to use that rendition as the link. Also, the W3C's HTML 4.0
+ draft presently is very fuzzy about whether, and if so, when, an IMG
+ element in the BUTTON content should be treated as an image map, so
+ the present code doesn't try to cast any submitted BUTTON name/value
+ pairs into the format for INPUTs with TYPE="image". When the BUTTON
+ is a script control rather than submit or reset button, a "[BUTTON]"
+ pseudo-ALT is inserted to warn users of its presence, but the form
+ is not disabled. The W3C's HTML 4.0 draft makes scripting intrinsic,
+ with no SGML-based fallbacks if it is not available or is disabled by
+ security-conscious sites. Dave Raggett of the W3C replied to criticisms
+ of this in www-html@w3c.org by saying that he wished it have been
+ otherwise, but "market forces" prevailed (Sigh...) - FM
+1997-07-13
+* Changed is_url() to return immediately if the string to check starts with
+ a slash character. This prevents some false positives if the string
+ contains ':' characters. - KW
+* Added support for "MACOS AppleShare IP FTP Server" to HTFTP.c.
+ Only based on and tested with (the current incarnation of)
+ <ftp://www.unicode.org/>. - KW
+1997-07-12
+* Correct some build issues with the merge (ifdefs for the curses modules)
+ as well as minor fix for makefile distclean rule. - TD
+* More refinements of the cookie support in relation to recent discussions
+ in the HTTP-WG, and for more fully effective protection against denial
+ of service attacks. If the same attribute appears more than once for
+ the same cookie, ensure that the first instance will be used. Limit
+ the total number of cookies across Set-Cookie and Set-Cookie2 headers
+ to 50 per server reply, and each cookie to a maximum of 4096 bytes. - FM
+1997-07-11
+* Added support for hexadecimal character references (&#xH;) as proposed
+ in the W3C HTML 4.0 draft. - FM
+1997-07-10
+* Synchronized the development code against the fotemods patches up to
+ 1997-07-06 (relevant changes listed below, as usual). Note that FM
+ has now included the chartrans code, but has eliminated conditional
+ compilation of it; however, in this code set setting -DEXP_CHARTRANS
+ at compile time is still necessary (but compilation without it has not
+ been tested). - KW
+* Fixed character counting logic in display_line() for lines where
+ soft hyphens (&shy; or <SHY> or a soft-hyphen character) are used
+ for their intended purpose. - KW
+ NOTE: The W3C HTML 4.0 draft explicitly specifies handling of &shy;,
+ &#173; (and now also &#xAD;) in the manner long implemented by Lynx
+ (i.e., as a truly soft hyphen), and not in the brain-dead manner
+ implemented by Netscape and MSIE. - FM
+* Various tweaks of the cookie support to handle likely (based on past
+ experience in the real world :) abuses of Set-Cookie and Set-Cookie2
+ headers from servers. Most importantly, apply sanity checks to the
+ values of port attributes so that any unquoted port list will not be
+ misinterpreted as the start of a new cookie within the port list.
+ Also added code to fold (CR LF TAB) Cookie request headers if they
+ contain a long sequence of cookies which would exceed 1024 bytes on
+ one line, since some servers suffer buffer overruns and crash in such
+ cases. - FM
+* Modified HTNews.c to use HTmmdecode() and HTrjis() for the Subject and
+ Author strings in listings of news articles when using a Japanese display
+ character set. - HN
+1997-07-09
+* Massive updating and revamping of the cookie support in accordance with
+ http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-02.txt
+ which is scheduled to replace RFC 2109 on July 15, 1997. Noteworthy
+ changes are that (1) the blanket port restriction is now lifted, and
+ sharing of cookies among servers with matching domains but different
+ ports is blocked only if a port attribute was included in the
+ Set-Cookie2 header (or Set-Cookie header, though it's not expected
+ there), with a value which defaults to the request's port, but can
+ be a comma separated list of ports, and (2) the blanket restriction
+ on sharing of SSL-encrypted (https) cookies with http servers is
+ lifted, and normally depends on the Set-Cookie or Set-Cookie2 header
+ having included a secure attribute. However, a configuration option
+ (see lynx.cfg) to FORCE_SSL_COOKIES_SECURE is now available, and the
+ compilation or configuration default can be toggled via a -force_secure
+ command line switch. - FM
+* Make NOCACHE ('x' key) work as expected from history list for internal
+ links. - KW
+* Removed bogus checking for a config file in home directory which had
+ been introduced into the development code. - KW
+1997-07-08
+* Synchronized the development code against the fotemods patches up to
+ 1997-06-24 - TD & KW
+1997-07-06
+* Implemented popup windows for the 'o'ptions menu, homologous to those
+ for SELECT blocks in forms. They are implemented when select_popups
+ is on, and include WHEREIS search and 123[g,p] features (very useful
+ for navigating the choice list of 28 display character sets :). Use
+ the F_LINK_NUM command ('0') to invoke the prompt for a choice list
+ number when in NUMBERS_AS_ARROWS mode. The popups are not invoked for
+ the simple, binary choice options. Also modified the options menu so
+ that the cursor is positioned to the left of choices when show_curser
+ is on (but it is still positioned initially at the endings of strings
+ when the line editor is invoked for options that have user-entered
+ values). - FM
+1997-07-04 (KaBoom! :)
+* Mods of HTMIME.c and HTFile.c to ignore Content-Type parameters other
+ than charset when charset is not present, as we do when it is present
+ and we know we can handle it. - FM
+* Fixed bug in LYNews.c which could cause Lynx to crash when posting or
+ sending followups to news groups and the Organization header was
+ obtained from the /etc/organization file. - FM
+* Fixed bug in LYEdit.c which could cause Lynx to crash when an editor
+ to which a line number is passed as an argument is used and there are
+ no links on the current page of the document to be edited. - FM
+* Added information about the new $USER feature to the comments about
+ TEMP_SPACE in userdefs.h. - FM
+1997-07-03
+* Tweaks of change_sug_filename() in LYUtils.c to make protections against
+ buffer overruns explicit within the function. - FM
+* Tweaks of the #ifdef'ing in HTTCP.c. - FM
+1997-07-02
+* Mods in LYDownload.c and LYPrint.c to treat a suggested output file
+ entry of "/dev/null" on Unix, and "nl:" or "/nl/" paths on VMS (case
+ insensitive), as a cancel (^G). - FM
+* Mods in LYGetFile.c to include URLs with content from a form submission
+ with method GET in the group for which Referer headers are never sent,
+ because the content might include private (e.g., password or credit
+ card) information which should not be visible in Referer logs. - FM
+* Added -G 7 to the LYFLAGS and MCFLAGS for the ultrix and ultrix-slang
+ Makefile targets when using the native ultrix compiler. - HM
+* Added -DNSL_FORK to the LYFLAGS for all of the solaris2 and Linux
+ targets in Makefile. - FM
+* The above two changes don't affect the makefile used by auto-config - KW
+1997-06-30
+* Removed a redundant declaration in UCdomap.c which was causing some
+ compilers to balk. - FM
+* Fixed typos in SGML.c which could cause echoing of numeric character
+ references for some of the display character sets. - FM
+1997-06-29
+* Updated lynx.hlp, lynx.man and the online 'h'elp concerning the chartrans
+ support. - FM
+1997-06-26
+* Tweak of the "tag and attribute soup" parsing mods in HTML.c so that the
+ PLAIN attribute works for UL blocks again. - FM
+* More tweaks of LYMainLoop.c to issue informative statusline messages
+ about attempts to ACTIVATE, DOWNLOAD, or submit URLs or ACTIONs which
+ are disallowed in the current context and destined to fail, rather than
+ acting on them and generating actual failures. - FM
+* Mods of LYmktime() in LYUtils.c to support dd-mm-yyyy format for expires
+ headers and cookie attributes. - FM
+* Oops, hadn't included checks for whether there are links on the page
+ in this morning's LYMainLoop.c mods to ensure appropriate statusline
+ messages for attempts to bookmark special URLs that can't be bookmarked,
+ which could yield a crash it there aren't any. The checks are in there
+ now. - FM
+* Added ability to bookmark links from the Lynx List Page, as from the
+ Visited Links Page, but not for those pages, themselves, since they
+ are temporary files. Note that Lynx List Page links will not have
+ the documents' titles, as do those in the Visited Links Page, unless
+ you've visited them before invoking the Lynx List Page. - FM
+* Added explicit protections against buffer overruns in the LYDownload.c
+ handling of suggested filenames. - FM
+* Changes in LYCurses.c, GridText.c, HTML.c, and LYUtils.c, and smaller
+ changes to some other files, to fix problems with RP's style code.
+ Color leaking should now be at least much reduced, and some possible
+ crashes avoided. - KW
+1997-06-24
+* Mods in LYDownload.c to check whether the File= field in a LYNXDOWNLOAD
+ URL has the value that was inserted into the URL via the most recent
+ download options menu. This prevents spoofing with arbitrary LYNXDOWNLOAD
+ URLs entered via the 'g'oto or ECGOTO commands, or ACTIVATE-ed in a file
+ other than the most recent download options menu which was created by
+ Lynx internally. - FM
+* Mods in LYMainLoop.c to ignore LYNXCOOKIE, LYNXDIRED, LYNXDOWNLOAD, and
+ LYNXPRINT URLs if entered via a 'g'oto or ECGOTO command, and to issue
+ a statusline message explaining that the special URL is not allowed as a
+ goto. This is just for informational purposes, and the above anti-spoof
+ mod is not dependent on it. - FM
+1997-06-23
+* remove "Styles" identifier from Lynx version string in userdefs.h
+ since it causes "patch-o-matic" to choke. -- JES
+1997-06-20
+* Now that we add or subtract attributes for Unix FANCY_CURSES, as for VMS
+ curses and slang, the 1997-05-30 mods based on LE's patch for keeping track
+ of whether links occur in an underlining context, and if so, restoring it
+ when a current link is made non-current, should be extended to FANCY_CURSES
+ as well. So they are extended, now, in highlight() of LYUtils.c. - FM
+* Added code in LYNewsPost() of LYNews.c for converting any EUC or SJIS to
+ JIS (ISO-2022-JP) in posts or followups to Usenet news groups if the
+ display character set is "Japanese (EUC)" or "Japanese (SJIS)". The mods
+ need testing by Japanese users, because the TO_JIS() function I added
+ long ago in SGML.c has not actually been used before. - FM
+* Modified the hack in LYPrint.c for mailing HTML source so that it never
+ appends a charset parameter to the "text/html" value of the Content-Type
+ header if compiled without chartrans enabled. - FM & KW
+1997-06-18
+* Added a check for nonsense LINES and COLS values in setup() of LYCurses.c,
+ homologous to the check in size_change() of LYUtils.c, and set LYlines and
+ LYcols to the 80x24 default if they're nonsense. The slang library and
+ most curses implementations do the equivalent themselves, but we may as
+ well make sure it's done. - FM
+* Tweaks of the anti-spoof mods in HTFWriter.c for additional protection
+ against extra %s entries in viewer command mappings. - FM
+1997-06-17
+* Came up with a low overhead way to restore the emphasis for WHEREIS
+ search targets when links are made current or non-current and the
+ target string starts before and/or extends past the end of the link
+ name (hightext or hightext2) string (see 1997-06-14 mods), so the
+ restoration works in that case as well, now. - FM
+1997-06-14
+* Fixed a longstanding bug in highlight() of LYUtils.c which caused seeking
+ of a column position less than 0 and strange behavior when a link is made
+ current, if show_cursor is on and the link begins at column 0 (as can
+ happen in PRE blocks). We now position the cursor on the first character
+ of such links, so the current link will remain clear for those with speech
+ or braille interfaces. - FM
+* Added functions in LYCurses.c, along the lines of those in the development
+ code, so that the [w]start_foo() and [w]stop_foo() functions no longer
+ just replace character attributes for Unix FANCY_CURSES, but now add or
+ subtract them as for VMS curses and slang. - FM
+* More mods in GridText.c and LYUtils.c so that the handling of WHEREIS
+ search target emphasis when links are made current and non-current is the
+ full equivalent for Unix FANCY_CURSES of that for VMS curses and slang.
+ Note that the restoration of search target emphasis does not succeed if
+ the hit started before or extends beyond the link name (hightext or
+ hightext2 string). What it would take to succeed in that case as well
+ doesn't seem worth the overhead, but I'm still thinking about it. Also
+ note that we still do not emphasize search target hits, but only do link
+ or page re-positioning, for Unix curses when only standout() and standin()
+ are supported. In that case, standout() is being used for all links,
+ including the current (with the latter indicated via cursor position by
+ turning show_cursor on), so we don't want to create a totally confusing
+ situation by using standout() for search target hits as well. The code
+ is still designed to degrade gracefully when the terminal does not have
+ the capabilities of the curses or slang with which Lynx was built. - FM
+1997-06-13
+* Tweak of yesterday's LYGetFile.c mods. Lost a lynx_edit_mode = FALSE
+ statement that is still needed when DIRED_SUPPORT is defined. - FM
+* Mods in LYForms.c so that the cursor is positioned at the left of the
+ current option in select popup windows when show_cursor is on, as when
+ the cursor is used to indicate the current link in the main document.
+ This is important when Lynx is used with a speech or braille interface,
+ or a terminal which does not respond to the highlighting/color for the
+ current option. When show_cursor is off, the cursor is still positioned
+ to the right of the current option for curses, and is fully "hidden" in
+ the lower right corner for slang, so that the highlighting or color of
+ the current option can be used without the distraction of a blinking
+ cursor in the left-to-right reading field. - FM
+* Added ability to change the show_cursor setting via the 'o'ptions menu
+ and to save that as the default in the RC file (otherwise, the default
+ is still that set in userdefs.h or lynx.cfg). The -show_cursor command
+ line switch toggles the default, however obtained, homologously to the
+ -popup toggle. Updated the online 'h'elp accordingly (option_help.html
+ and Lynx_users_guide.html). - FM
+1997-06-12
+* Tweaks of the 1997-06-04 mods for restoring emphasis of WHEREIS search
+ targets in link names when they are changed to the current link or again
+ made non-current. When the link is made current, the first and last
+ characters of the link name never are emphasized, so they'll retain the
+ attributes/color for the current link, and the user can see (if sighted)
+ that the link was made current. With this change, the restoration of
+ emphasis also is interpretable with Unix FANCY_CURSES, so the block for
+ that is lifted. Note that I figured out why the bold+reverse+underline
+ combination doesn't work for that. The vanilla and this Lynx code are
+ not adding or subtracting attributes for their start_foo() and stop_foo()
+ functions (as is done for slang and VMS curses), but are replacing them,
+ so you always end up with the last attribute in a series of start_foo()
+ calls (underlining for the search target emphasis). I don't know if
+ ability to sum attributes applies to all Unix curses flavors for which
+ FANCY_CURSES is defined in the Makefile, so I left the Unix, non-slang
+ start_foo() and stop_foo() functions the way they are, for now. - FM
+* Mods in LYGetFile.c so that any '~' in file URLs is handled as when in
+ startfile, home page, or 'g'oto commands. Only the first '~' is converted
+ to Home_Dir(), and only for the first symbolic element in the URL, and if
+ it is followed by a username, that username is stripped (so that the
+ "~username" becomes a reference to the home of the account running Lynx,
+ as if only '~' had been used, and can't be used as a reference for an
+ arbitrary home). Note that we don't do this stripping for ftp URLs,
+ because the ftp server should decide, itself, whether to grant access to
+ arbitrary homes, based on the username and password that were used to
+ log in. Note, also, that if the account running Lynx is allowed access
+ to the root of the file system for its home, then access to any arbitrary
+ home in that file system can be gained from there. Access to the root
+ never is allowed for file URLs in the for-VMS code, but depends on the
+ root's protection in the for-Unix code. Also, any arbitrary path in file
+ URLs will be attempted if it is specified as an absolute path. The
+ stripping of the username from "~username" in most cases on Unix only
+ protects against probing for homes in other file systems, without the
+ user knowing the corresponding absolute path. - FM
+1997-06-11
+* Mods in HTAABrow.c, HTTP.c and HTAlert.c so that auth_proxy is no
+ longer a module wide global, and the structures which handle/create
+ authentication/authorization headers maintain separate setup trees
+ for proxy authentication/authorization versus for protected limbs of
+ http/https data trees (realms) on the same server. This ensures that
+ each proxy's template, which is the global '*' for all paths (that are
+ in fact full URLs) in its proxying requests, are kept distinct from
+ the templates for true paths of the protected limbs on the same saver,
+ even if the user fails to include that proxy in the no_proxy list, or
+ the server's WebMaster fails to do the equivalent configuration for
+ the server, and the realm names overlap. Also modified the prompt
+ strings for the username and password to be encrypted for protected
+ document requests versus for proxy access so that they indicate
+ explicitly whether the user's entries will be used for one or the
+ other. - FM
+* Added a -pauth=id:pw switch for proxy servers, homologous to the
+ -auth=id:pw switch for protected documents, along the lines of AJL's
+ patch. Note that the -pauth value is used only for authorization
+ headers to the first protected proxy server encountered, and the -auth
+ value is used only for the authorization headers in document requests
+ for the first protected limb encountered. Now that we have an explicit
+ switch for proxy authentication, it should be used explicitly for that,
+ instead of still allowing use of the -auth=id:pw switch for either
+ (IMHO). Also, there's no serious need to make inclusion of the code
+ for handling these switches a compilation option, because they are only
+ available to users with shell access. Updated the help files concerning
+ these switches, and included advice to make sure any script files which
+ use these switches have restricted access. - FM
+1997-06-09
+* More refinements of the code in GridText.c, HTML.c and LYCharUtils.c
+ for handling visible versus hidden links, blank lines, stripping of
+ the numbered brackets for links, and the interactions of these things
+ with soft hyphens. - FM
+1997-06-06
+* Fixed typos in LYrcFile.c which caused failure to start two comments
+ on new lines when writing to the RC file. - FM
+* Fixed a typo in the lead dot pair stripping code in LYLegitimizeHREF()
+ of LYCharUtils.c. - FM
+* Tweak of code in GridText.c for handling soft hyphens so that we don't
+ display a hyphen if it's the first character in the line, or is preceded
+ by a space, even if it is followed by a newline. - FM
+* Mods of the hidden link handling and numbered bracket stripping code in
+ GridText.c so that it succeeds no matter how many blank lines are in
+ the anchor content. - FM
+1997-06-04
+* Mods in LYLegitimizeHREF() of LYCharUtils.c for dealing more effectively
+ with fragments which have illegal characters, as is becoming common due
+ to authoring tools such as Microsoft's Frontpage and Netscape's HTML
+ editor. The actual URL-reference is still handled so as to yield a
+ fully legitimate absolute URL, without any unescaped spaces, but the
+ fragment is checked only for problem characters such as tab or newline,
+ and otherwise is unmodified. (Try the vanilla versus modified code with
+ the http://www.cnib.org/library/ww_flw96.htm atrocity, brought to you
+ discourtesy of Frontpage. :) - FM
+* Worked into the fotemods code use of bold+reverse+underline highlighting
+ of WHEREIS search hits for VMS curses, and slang on both VMS and Unix (with
+ or without the color mode on), and added code in highlight() of LYUtils.c
+ for restoring that highlighting when links are made current or non-current
+ if the string for the hit was contained within the string for the link (won't
+ be restored if the hit's string starts before or extends past the link's
+ string). Couldn't get any of this to work with curses and the solaris2
+ target, so for Unix curses the hit string still is just underlined and
+ not restored when links are made current or non-current. - FM
+* Fixed typo in the 1997-06-01 LYOptions.c mods. - FM
+1997-06-03
+* Mods in LYList.c to skip setting up a list block for visible links if
+ the document has only hidden links, and in HTML.c to include a notice
+ about this with a suggestion to use the 'l'ist command. Try it with
+ the http://www.sony.com/ atrocity. - FM
+* Tweak in LYMainLoop.c to fix a longstanding bug which would cause the
+ curdoc.line and curdoc.link numbers to be mishandled, and thus cause
+ the wrong page and current link to be restored on return to the document
+ via PREV_DOC or the History Page, if the document was fetched originally
+ with a fragment and a link on its first page had been activated. - FM
+* Tweaks in GridText.c so that returns from image map menus to parent
+ documents are not treated as if a different document is being sought,
+ and thus any no-cache directives associated with the parent will be
+ ignored unless another fetch is initiated within the parent or via
+ another, externally existing document. - FM
+* Added SEEK_FRAG_MAP_IN_CUR and SEEK_FRAG_AREA_IN_CUR configuration
+ (lynx.cfg) options for how to resolve USEMAP attribute values in
+ IMG or OBJECT tags and HREF attribute values in AREA tags when they
+ consist solely of a fragment (USEMAP="#frag" or HREF="#frag"). The
+ compilation default is TRUE, i.e., they are resolved with respect
+ to the current document's URL, even if the base is different, as is
+ being done for the HREF attribute values of Anchors and LINKs. The
+ compilation default seems to be working out, even though most of the
+ currently deployed browsers still use the base. - FM
+1997-06-02
+* Mods in LYMain.c so as not to require that a lone "-" argument for
+ invoking input of command line arguments from stdin be the only
+ argument on the actual command line. That requirement preluded use
+ of this feature when the command for invoking Lynx was aliased so
+ as to include arguments, because the lone "-" then could not be the
+ only argument. Also tweaked the code so that any stdin-derived
+ arguments which need to be processed early in main() are so processed.
+ The vanilla code had severely flawed logic in this respect. The
+ security considerations associated with switch handling have gotten
+ hairy beyond reasonable bounds, but I think I've thought it all through
+ (we'll see :), and have plugged some holes in the vanilla code for
+ this feature. Redirection of stdout and/or stderr to a file now also
+ works reliably in conjunction with this feature. - FM
+* Added an explanation in the PROBLEMS file of the bad getsockname() and
+ getpeername() functions within SOCKETSHR 0.9D which affect the ftp
+ gateway, and the URLs for Andy Harper's (A.HARPER@kcl.ac.uk) fixes of
+ the SOCKETSHR 0.9D sources. - FM
+* Cast LYLocal.c into the Lynx programming style. - FM
+1997-06-01
+* Added support for numbered form fields, and options in SELECT popups,
+ based on LE's patch. The LINKS_AND_FORM_FIELDS_ARE_NUMBERED keypad
+ mode can be defined in userdefs.h and via the 'o'ptions menu. When
+ in SELECT popups, the F_LINK_NUM ('0') command can be used in any mode
+ to invoke a "Select option (or page) number:" prompt, which can take
+ 'g' or 'p' suffixes, homologously to the
+ "Follow link (or goto link or page) number:"
+ prompt in the main document with popups retracted. Note that when in
+ the main document, the F_LINK_NUM command has an implied 'g' suffix
+ for form links (i.e., will position you on the form link, not, for
+ example, ACTIVATE a submit button), but *not* in popup windows (i.e.,
+ without a 'g' suffix, the option corresponding to the number will be
+ selected, and the popup will be retracted, as if you had pressed
+ ACTIVATE when positioned on that option). The 123p feature is quite
+ useful in popups with a very large number of options, and supplements
+ the HOME, END and WHEREIS functions for seeking positions in the list
+ (again, regardless of keypad mode, if F_LINK_NUM is used to invoke
+ the prompt). A "page" is defined as the number of lines within the
+ vertical dimension of the popup box. - FM
+* Mods in LYEdit.c to seek the current page and line when the editor
+ is sedt on VMS. - FM
+* Updated the online 'h'elp concerning the "Follow link (or page) number:"
+ and "Select option (or page) number:" features (Lynx_users_guide.html,
+ follow_help.html, keystroke_help.html and other_help.html). - FM
+* changes to help files to reflect the different prompt string. - KW
+1997-05-30
+* Worked in LE's patch for keeping track of whether links occur in an
+ underlining context, and if so, restore it when slang color is on and
+ a current link is made non-current, thereby actually dealing with the
+ longstanding bug discussed in the 1997-05-27 mods (This is just a hobby,
+ and I always reserve the right to change my mind! :). - FM
+* Mods of LYForms.c and LYStrings.c to deal with form field values too
+ long to fit in the line editor's buffer (such as long TEXTAREA values
+ which have no newlines in them). As much of the tail as fits in the
+ buffer is offered for editing, with statusline messages explaining the
+ situation. If the tail is modified, it is combined with the unmodified
+ head when the form field is made non-current. The result can be edited
+ further by making the form field current again. If the form has a
+ Reset button, it can be used to restore the original value. The
+ vanilla code would crash on buffer overflow (Ugh! A potential
+ security hole.). - FM
+1997-05-29
+* Restored underlining in conjunction with reversing for the current link
+ with slang when colors are being used, but not otherwise. - FM
+* The 1997-05-26 mods to bypass screen redraws on retractions of SELECT
+ popups when the selected OPTION was not changed worked properly only
+ for VMS curses. Tweaked the for-slang code so that it now works like
+ VMS curses (though not as efficiently). However, with Unix curses,
+ the delwin() - refresh() sequence does not restore what was there
+ before the popup was invoked, and none of the tweaks I tried got that
+ to work, so the poor Unix folks using Unix curses are now stuck again
+ with screen redraws for every popup retraction. - FM
+1997-05-27
+* Eliminated in the fotemods code underlining in conjunction with reversing
+ for the current link with slang, to avoid the longstanding bug of
+ underlining being lost (and distracting color changes occurring) when that
+ link ceases to be current and it was embedded in an underlined region of
+ text. The attributes of the current link can be better handled in the
+ development code based on configurable style sheets, so there's no
+ point letting this bug ride, nor trying to deal with it through
+ temporary internal mods, in the fotemods code set. - FM
+1997-05-26
+* Mods of display_title() in GridText.c to eliminate the "format"
+ mask as in KW's 1997-05-14 development code mods, and to make the
+ memory management more efficient. - FM
+* Mods of change_form_link() in LYForms.c to bypass the screen redraw
+ on retraction of a SELECT popup if the SELECT block is DISABLE-ed
+ or the selected OPTION was not changed. Note that the complete
+ elimination of the screen redraw in the 1997-05-20 development code
+ mods, i.e., even when the selected OPTION was changed, results in
+ the change not being made evident to the user in the retracted popup
+ unless the screen is redrawn fortuitously (e.g., due to subsequent
+ paging). - FM
+* Modified the caching-related changes of 1997-05-15 to LYMainLoop.c,
+ handling automatic reloading after a change of the User-Agent string
+ like after comparable other option changes.
+ We force a reload if "preferred document lan(G)uage"
+ or "preferred document c(H)arset" are changed via the 'o'ptions menu,
+ and to set the "reloading" flag for forcing a proxy cache refresh if
+ those or "user (A)gent" are changed and the current document has an
+ http, https or lynxcgi scheme, but not force a proxy cache refresh if
+ we're reloading due to an INLINE_TOGGLE, IMAGE_TOGGLE, or RAW_TOGGLE
+ command. - KW & FM
+1997-05-25
+* Mods in LYMain.c to convert $USER if present in the TEMP_SPACE
+ definition or LYNX_TEMP_SPACE environment variable to the string
+ returned by getenv("USER"). - FM
+* Fixed two typos for me->inFONT settings in HTML.c - TD
+* Added chmod(file, 0600) calls for most files created by Lynx. - FM
+1997-05-24
+* integrate patch JED's mods which support mouse for slang as well as add
+ new functions to encapsulate differences between slang/curses. - TD
+1997-05-21
+* Mods in HTML.c and LYCharUtils.c so that TABLE blocks are treated
+ as divisions in the DIV nest, with a default alignment of HT_LEFT
+ if the TABLE start tag lacks an ALIGN attribute, and otherwise,
+ that attribute's value. Nested TABLEs extend the DIV nest. This
+ avoids the problem in the vanilla code of TABLE content inheriting
+ the alignment of a containing CENTER or DIV which is intended for
+ alignment of the TABLE as a whole. Also added support for ALIGN
+ attributes in TR elements. If the TR has no ALIGN attribute, it
+ inherits that of the current division, which should be that of the
+ current TABLE. This, of course, still does not yield true TABLEs
+ for truly tabular content, but makes TABLEs used for formatting
+ more readable. - FM
+1997-05-20
+* correct 2 occurrences of "me->inFONT == TRUE;" in HTML.c - TD
+* add configure --with-color-style option to merge RP's alpha changes for
+ color styles (this works only with ncurses, since it does not initialize
+ the window background, leaving it null, thereby exploiting a bug in
+ ncurses which sets null backgrounds to a space). Also some whitespace
+ (and renamed CS to make this build w/o ncurses) - TD
+* test-built with ncurses 1.8.7, 1.9.4, 1.9.9e and 4.0, as well as bsd 4.4
+ curses and slang - TD
+* Tweak of HTFWriter.c so that it does the anti-spoof tests normally
+ done by tempname() (see the 1997-05-19 mods) in all cases for which
+ it changes the temporary file suffix from any of those checked by
+ tempname() itself. At this point, every way I've thought of for
+ trying to spoof Lynx via links for temporary files is blocked, but
+ people should beat on today's code to see if there's any spoofing
+ strategy I haven't yet blocked. - FM
+* Modified the Lynx Trace Log handling so that it doesn't use actual
+ redirection of stderr via freopen() calls, and restores the original
+ value of stderr during any escape to shell. This avoids the problem
+ on Unix that sh and ksh send their prompt strings to stderr, and that
+ bash sends both its prompt and command line echo to stderr, so they
+ end up in the log instead of being visible. I had tested the initial
+ design on VMS and with csh on Unix, and thus didn't notice this
+ foolishness for the other Unix shells. Anyway, it's OK for all of
+ them now. - FM
+* Tweaked SIGTSTP interrupt handler in the USE_SLANG for-unix code, so
+ that it gets set to SIG_DFL when stop_curses() is called, to prevent
+ strange interferences experienced when ^Z is used while a helper
+ process is in the foreground. - KW
+* Change in LYForms.c to prevent forced screen refresh after selection
+ from a popup box. - KW
+1997-05-19
+* Recognize Linux console F1 key in LYgetch() (applies if -DNO_KEYPAD
+ is in effect, as for all binaries built with slang). - KW
+* Protect LYgetch() against returning raw values of keypad() symbols
+ which are invalid when used later as an index into keymap[],
+ override[], etc. - KW
+* in the USE_SLANG for-unix start_curses(), honor the no_suspend flag
+ if set. This implements -restrictions=suspend handling for slang
+ (although it was intended for curses implementations which have
+ problems with ^Z within Lynx; see the PROBLEMS file).
+ Note that the no_suspend flag cannot be suspected to have
+ the desired effect if lynx is executed from a shell script, unless
+ the shell process forked for the script also ignores the SIGTSTP
+ signal generated (usually) by the ^Z key. Also if the user is
+ allowed to execute any helper process (VIEWER, PRINTER, etc.) which
+ does allow suspending while no_suspend is in effect for the Lynx
+ parent process (by overriding the SIG_IGN setting done by Lynx or by
+ other means), then suspending may still be possible, in addition to
+ strange effects either immediately or when the process or process group
+ is continued (wrong tty and screen state, zombie processes, total
+ hang of the session without any way to interrupt - you get the idea...).
+ Trying to use the suspend restriction in order to prevent users from
+ getting a shell prompt doesn't make much sense anyway when they are
+ allowed access to execute commands which may be interrupted or allow
+ escaping to a shell... - KW
+* Tweak of HTFile.c so that we no longer lose an LYforce_HTML_mode
+ directive if the file is gzipped or compressed and the uncompressed
+ suffix is not mapped to text/html. - FM
+* Modified tempname() in LYUtils.c so that it checks whether files
+ with the current PID and target count already exist, and if so,
+ increments the count until a name for a non-existing file has been
+ created. - FM
+1997-05-18
+* Mods in LYMainLoop.c and LYClean.c so that Control-G is treated as
+ a synonym for 'n'o in quit confirmation prompts. - FM
+* Mods in LYPrint.c to strip any gzip or compress suffix from the
+ suggested filename, on the assumption that we're deal with a text/html
+ or text/plain file that had a corresponding Content-Encoding and no
+ Content-Disposition: file; filename=name.suffix header indicating
+ the appropriate filename after uncompression. This assumption does
+ apply for our current ftp gateway, and for most present-day http
+ servers. This mod in turn ensures that text/html files which are
+ not being printed as source will have their uncompressed suffixes
+ converted to .txt, indicated that they are rendered. - FM
+1997-05-17
+* Fixed long-standing bug in display_page() of GridText.c. When it
+ was updating the links structures, it wasn't re-initializing the
+ form element if the links structure is not for a form field. - FM
+* Mods in HTML.c to deal more effectively with H# headers used instead
+ of LH in lists. We now, in effect, treat them fully as if they were
+ LH, so that their left indentations are in register with the current
+ list nesting depth, and we apply better error recovery in cases where
+ the author is mis-using H# for a FONT change rather than as an actual
+ header. - FM
+1997-05-16
+* Changed the line where a WHEREIS search target should preferably be
+ displayed to the 4th line (not counting the title line). This can
+ be changed by redefining SEARCH_GOAL_LINE in userdefs.h.
+ SEARCH_GOAL_LINE can also be a simple expression in terms of the
+ variable display_lines, e.g. `#define SEARCH_GOAL_LINE (display_lines/3)',
+ this should then automatically adapt to screen size changes (provided the
+ display system can deal with that...)
+ Note that this this goal line will normally not be used if the next
+ target, according to the algorithm Lynx uses, is already on the displayed
+ screen. Also, when the displayed page changes to show a search result,
+ there is no guarantee that it will end up on the line set by
+ SEARCH_GOAL_LINE. It should rather be regarded as a maximum.
+ For example the presence of anchors on the line with the target or on
+ the preceding lines will change the positioning. - KW
+* The SEARCH_GOAL_LINE line will also be used for "going to" a link with
+ 'g' suffix at the "Follow link ..." prompt, although the algorithm is
+ quite different. As for a search target, this only applies when Lynx
+ has to position to a different page of the document, and then is only
+ a maximum. - KW
+* Enabled the no-cache setting for the pseudo document Lynx creates for
+ a client-side image map in LYMap.c, for now. - KW
+* Minor typo fix for the proxy authentication mods. - FM
+* Tweak of PRE block handling in HTML.c to ensure an implied paragraph
+ after the block if it is in a list and not followed by an LI. - FM
+* Tweaks of SGML.c and LYCharUtils.c to allow any non-digit to terminate
+ a numeric character reference once at least one digit has been found in
+ the reference. - FM
+* Change in LYUnEscapeToLatinOne() to use isdigit() instead of isalnum()
+ for recognizing numeric character references like LYUnEscapeEntities()
+ does. - KW
+1997-05-15
+* Worked in JED's mods for taking a suspend into account during select()
+ calls. - FM
+* Mods in LYMainLoop.c to not force a cache refresh on a proxy any more
+ when INLINE_TOGGLE, IMAGE_TOGGLE, RAW_TOGGLE are used. On the other
+ hand, do force a proxy cache refresh after one of the variables relevant
+ for content negotiation `language' or `pref_charset' has been changed
+ from the Options screen, if the current document is from a http, https, or
+ lynxcgi resource. - KW
+* Set HTTP_ACCEPT_CHARSET environment variable for the child process in
+ LYCgi.c if pref_charset is not NULL. - KW
+* (chartrans) Write a META tag with the current display character sets to
+ the files generated for Bookmarks, List, Info, History, and Visited Links
+ pages, so title strings contained in those files will (hopefully) not
+ get erroneously translated again. Use new function LYaddMETAcharsetToFD()
+ in LUCharUtils for this purpose. - KW
+* (chartrans) makeuctb now sets RawUni to UCT_ENC_8BIT if not otherwise set
+ and if there are char values above 127. - KW
+* (chartrans) Change in HTuncache_current_document() to prevent caching of
+ UCStages info which should be discarded. Still allow caching for this
+ in the node_anchor for source display, so that a META tag in the parsed
+ HTML can influence the display after using the SOURCE '\' key. - KW
+1997-05-14
+* Don't use title in showlist() if it is empty, to prevent "hidden links"
+ on the List Page itself caused by documents with <TITLE></TITLE>. - KW
+* Changed display_title() in GridText.c to not rely on sprintf() to get
+ the number of blanks right. - KW
+* (chartrans) Added new lynx.cfg symbols ASSUME_CHARSET,
+ ASSUME_LOCAL_CHARSET, and ASSUME_UNREC_CHARSET. They are only
+ recognized if compiled with -DEXP_CHARTRANS. They correspond to the
+ command line options -assume_charset, -assume_local_charset, and
+ -assume_unrec_charset.
+ The default for ASSUME_CHARSET is iso-8859-1 (corresponding to display
+ character set "ISO Latin 1"). If no ASSUME_LOCAL_CHARSET is set,
+ the explicit or default value for ASSUME_CHARSET will also be used for
+ local files. ASSUME_UNREC_CHARSET has no default. See added text
+ in lynx.cfg. - KW
+* (chartrans) Changes in LYCharSets.c to HTMLSetCharacterHandling() and
+ HTMLSetUseDefaultRawMode() to support (hopefully) more consistent
+ and user-friendly handling of raw mode and its default.
+ Note that the following description does not apply if the display
+ character set is one of the CJK settings. In that case, -raw and
+ the corresponding Options setting is used as a CJK toggle as before.
+ Note that the -raw flag is a toggle. It changes the "raw mode"
+ setting from the default. The current setting of "raw mode" can be
+ seen on the Options screen, and is also shown in a statusline message
+ when the RAW_TOGGLE key (normally '@') is used.
+ The default depends on the display character set (as previously)
+ but now also on the ASSUME_CHARSET setting (as determined by a setting
+ in lynx.cfg, possibly overridden by -assume_charset on the command
+ line, or the default iso-8859-1). When the display character set
+ corresponds to the ASSUME_CHARSET, the default for "raw mode" is ON,
+ otherwise it is OFF.
+ The effect of "raw mode" on the interpretation of documents which have
+ no explicit charset label (from HTTP headers, a META tag, or otherwise)
+ is as follows. There is an internal "assume charset" which may differ
+ from the user-specified ASSUME_CHARSET value. When "raw mode" is set
+ ON, the internal variable is set to correspond to the display character
+ set. When "raw mode" is set OFF, the internal variable changes to
+ the user-specified ASSUME_CHARSET or, if that also corresponds to the
+ display character set (so that otherwise there would be no change),
+ reverts back to the iso-8859-1 Web default.
+ Raw mode doesn't imply total rawness. HTML character entities may
+ be expanded and translated with either setting, 8-bit characters which
+ are inappropriate for the display character set will not be sent to
+ the terminal. For a "more raw" setting, try the "Transparent" pseudo
+ display character set. - KW
+1997-05-13
+* Changed the compilation default in userdefs.h for USE_TRACE_LOG
+ to FALSE, for now. - KW
+* Code for "fixing" of relative http and https URLs which start with a
+ ../ segment from FM added, but it has to be enabled with the new
+ lynx.cfg symbol STRIP_DOTDOT_URLS (default currently set to FALSE).
+ See FM's description under 1997-04-23. - KW
+* Changed the test for dot segment fixing in LYLegitimizeHREF() so
+ that now (if enabled) it also applies when the http or https base URL
+ in effect does have a non-empty path but without any slashes in it
+ (beyond the initial one between host and path). The test was too narrow
+ before and did not recognize this case, so that an unmodified URL with
+ ../ in it would still be sent to the server and without generating a
+ statusline message. - KW
+* Tweak of case LYK_REFRESH: in LYMainLoop.c so that the REFRESH command
+ still invokes an obligatory, complete refresh of the screen for slang
+ on Unix with the new LY_SLclear() function (see 1997-05-09 mods),
+ by using scrollok() if USE_SLANG is defined. - FM
+* Changed the local variable name, lines, in follow_link_number() of
+ LYGetFile.c to nlines, to deal with the AIX 4.2 bug of treating lines
+ as a macro. Also changed the variable name, pages, to npages for
+ logical complementarity (they both refer to the total number). - FM
+* Mods in HTML.c, LYCharUtils.c and GridText.c to deal with links for
+ positioning, specified via NAME or ID attributes, when they are embedded
+ in Anchors which have an HREF, so that they now don't force premature
+ closing of those Anchors. Also tweaked the code for creating links for
+ the sources of images or other for-GUI embedded objects when clickable
+ images ('*') is toggled on, so they use those mods as well, when
+ possible. Note, however, that the clickable images feature is creating
+ Anchors with HREFs which aren't actually there, and still can create
+ technically invalid markup, on occasion, when the non-doctored markup
+ actually is valid. The latter mods still need some improvements in the
+ formatting, but are OK to use for now, and my brain hurts from trying
+ to think through all the possible markup we might encounter. - FM
+* Tweaks of the Lynx Trace Log handling to deal with reloads when the
+ HText structure for the log has been dumped. Made the first letter
+ of the filename uppercase (Lynx.trace), complementary to Lynx.leaks.
+ Eliminated the log from the Visited Links Page so it can't be sought
+ there as a forward link. Use the History Page if you want to 'd'ownload
+ the log, or use the 'p'rint option while viewing the log. Note that
+ suffix maps do tail matching, and thus the so-called suffixes need not
+ begin with a dot. If you want to use an external viewer for the log,
+ you can put:
+ SUFFIX:Lynx.trace:application/x-LynxTrace
+ VIEWER:application/x-LynxTrace:most +s %s
+ in your lynx.cfg, or their equivalents in your mime.types and mailcap
+ files. - FM
+* Tweaks in LYMainLoop.c to set newdoc.title for various special pages
+ generated by Lynx (History Page, Info Page, etc.) and when following
+ a link. - FM
+* Small change to the heuristics for New_DTD in start_element()
+ in SGML.c (try a bit more to close containing element if it's the
+ same tag) - KW
+1997-05-12
+* Added support for proxy authentication. - AJL & FM
+* Updated follow_help.html to indicate that 0 is the universal
+ F_LINK_NUM mapping for invoking the "Follow link (or ...) number:"
+ prompt. - FM
+1997-05-11
+* Tweaks in LYMainLoop.c to ensure that the LYforce_HTML_mode flag is
+ reset reliably, so it doesn't carry over to requests for text/plain
+ documents, as it was doing under some circumstances in the vanilla
+ code, e.g., when a bookmark file was used as the startfile via a
+ file://localhost/path URL rather than via the -book switch. - FM
+* Very minor change in Lynx_users_guide.html, added two words - KW
+1997-05-10
+* Fixed a typo in statusline() of LYUtils.c. The check for whether
+ the string is zero length before bothering to convert CJK multi-bytes
+ was checking a holding buffer instead of the string. - FM
+* Fixed a bug in LYHandleMETA() of LYCharUtils.c. The check for a
+ URL following the SECONDS value in REFRESH directives was not
+ taking into account that an EOL might follow the digits for the
+ SECONDS value. - FM
+* Changed the behavior of boolean_choice() in LYOptions.c so that the
+ cursor is positioned immediately at the option display line instead
+ of staying at the statusline instructions until an initial entry is
+ made, and modified the statusline instructions accordingly. - LE & FM
+* Added a check for a NULL pointer in the LYCookie.c code for blocking
+ sharing of SSL encrypted cookies with http servers, based on a patch
+ from RT, and added a comment on why code for a block based on the
+ scheme is there, despite its being redundant with the current blanket
+ restriction based of the ports. - FM
+* Mapped 0 to F_LINK_NUM (as suggested by KW), so that 0 invokes the
+ "Follow link (or goto link or page) number:" prompt under all
+ circumstances (but with the 0 not treated as the first digit of
+ the number entry). That's a better way
+ to do it, because then the F_LINK_NUM command and explanation always
+ appears in the "Current Key Map" display, and only the mappings of
+ numbers to functions drop out when going from NUMBERS_AS_ARROWS to
+ LINKS_ARE_NUMBERS mode (as they should, 'cuz the numbers no longer
+ are mapped to functions; though maybe they should stay mapped to
+ functions now that we have an explicit command key for invoking the
+ prompt; something to think about...). - FM
+* Updated the PROBLEMS file to indicate that you should try changing
+ -lresolve to -lbind if you have upgraded to the bind-8.1 or later
+ library on a Sun system and keep getting the message "Alert!: Unable
+ to connect to remote host". - FM
+1997-05-09
+* Typo fix in follow_help.html. - FM
+* Added an LY_SLclear() function in LYCurses.c as a more efficient
+ substitute for slang of the curses clear(), based on a patch from
+ JED. - FM
+* Added a USE_TRACE_LOG compilation (userdefs.h) symbol and -tlog command
+ line toggle of the compilation default (normally TRUE), for directing
+ syserr messages to a lynx.trace file in the user's home directory when
+ TRACE mode has been turned on (either via the -trace command line switch,
+ or the TOGGLE_TRACE (Control-T) command. Also added a TRACE_LOG command
+ (normally ';') for viewing the "Lynx Trace Log" (lynx.trace) at any time,
+ if one has been initiated during the current session. The trace log
+ feature is disabled automatically in anonymous or validation accounts,
+ and should not be used in any account which could have different users
+ simultaneously. The mods work well to the extent I've exercised them
+ thus far on VMS and for the solaris2 target, but possibly need more
+ refinements, depending on the behavior for other Unix flavors of
+ freopen(), which is used for redirecting stderr to the log. Updated
+ lynx.man, lynx.hlp, and the online 'h'elp to describe these new
+ features. - FM
+1997-05-08
+* Made the handling of hidden links dependent on a new command line
+ option. With -hiddenlinks=listonly hidden links are only shown on
+ 'l'ist screens and listings generated by -dump or from the 'p'rint
+ menu, but appear separately at the end of those lists.
+ With -hiddenlinks=ignore they don't appear even in listings.
+ With -hiddenlinks=merge hidden links are treated as before,
+ i.e. they show up as bracketed numbers if LINKS_ARE_NUMBERED is on,
+ and are numbered together with other links in the sequence of their
+ occurrence in the document. The default is -hiddenlinks=listonly.
+ Changed the new follow_help.html file accordingly.
+ This may help obviate an apparent need to call something a bug which
+ others regard as a feature... - KW
+* Function HText_AreDifferent() updated as in FM's code, but still
+ unused. - KW
+1997-05-07
+* Added another argument in follow_link_number() of LYGetFile.c for
+ returning the number entered at the "Follow link (or page) number:"
+ prompt to the mainloop(), and modified the statusline error messages
+ that may be issued from the mainloop() in conjunction the with 'g' or
+ 'p' suffixes so that they report that number when appropriate. - FM
+* Changed the prompt to "Follow link (or goto link or page) number:" - KW
+* Tweaked case HTML_DD: in HTML.c so that it checks whether a wrap
+ has just occurred naturally before imposing a newline for DD start
+ tags. Without that check, seemingly random, extra newlines could
+ occur in the DL/DT/DD blocks. - FM
+* Created a follow_help.html for the keystroke_commands subdirectory
+ of the online 'h'elp, describing the "Follow link (or page) number:"
+ features, and added links to it in Lynx_users_guide.html and
+ keystroke_help.html. - FM
+* Changed the help description according to what is implemented here - KW
+1997-05-06
+* Further tweaked KW's mainloop() tweak (see yesterday's entry), so that
+ newdoc.link is reinitialized properly when we're going to, but not
+ ACTIVATE-ing, a link in the current page due to a 'g' suffix for a
+ "Follow link (or page) number:" entry. Otherwise, if the number with
+ a 'g' suffix was used to make the last link on the current page the
+ current link, and then a NEXT_LINK command was used, one could end
+ up on a link beyond the first one in the next page. Also added a
+ statusline message if the 'g' suffix is used with a number which
+ corresponds to a link that already is current. - FM
+* Tweaked yesterday's LYList.c mods so that an OL with the CONTINUE
+ attribute is used when a "Hidden links:" list is appended to a
+ "Visible links:" list and NUMBERS_AS_ARROWS mode is on. This allows
+ you to see the number to enter at "Follow link (or page) number:"
+ prompts, as when LINKS_ARE_NUMBERED mode is on. - FM
+* Mods in HTML.c for LI and LH handling so that a pointless wrap will not
+ occur at the spacer following the bullet in UL blocks or the Arabic
+ number, Roman numeral, or upper- or lowercase letter in OL blocks if
+ the subsequent text has no spaces, itself, up to the right margin.
+ In such cases, that text now stays on the initial LI or LH line, and
+ wraps at the right margin to the left indentation for a second or
+ greater line in the LI or LH. - FM
+* Changes to avoid memory leaks in LYCookie.c - KW
+* Escape '<' and '>' characters (using the LYEntify functions) in URL
+ strings written to the temporary files for LIST and INFO screens, to
+ avoid invalid HTML and corrupted display as a result of URLs which
+ contain these characters (although they shouldn't) and have not been
+ escaped earlier. - KW
+* Changed the label for the currently selected link from "Filename:"
+ to "URL:", and fixed an alignment glitch for the 9th item on the
+ History and Visited Links pages. - KW
+* Changed an "8-bit" occurring in HtInit.c to "8bit", tweaked LYKeymap.c
+ comments. - KW
+1997-05-05
+* Added HText_AddHiddenLink(), HText_HiddenLinkCount(), and
+ HText_HiddenLinkAt() functions in GridText.c for keeping track of the
+ addresses (URL, plus fragment if present) for links that were converted
+ to hidden by HText_endAnchor() due to their having no visible link name,
+ and modified showlist() and printlist() in LYList.c so that if any hidden
+ links were create during the rendition, the "References in this document:"
+ menu for the 'l'ist command or appendix on dumps segregates and clearly
+ labels the visible versus hidden links. - FM
+* Plugged a memory leak in LYEntify() of LYCharUtils.c. - FM
+* Modified experimental DTD info to not close anchors when an invalid
+ P, H1-H6, or ADDRESS start tag is encountered, and to change error
+ recovery for P and MAP. - KW
+* Modified experimental DTD info and HTML.c to not close PRE when
+ an invalid FORM start tag is encountered, and to use the appropriate
+ handling for preformatted text if PRE is in effect but is not the top
+ element on HTML.c's stack. The HTStyle structure's freeFormat (which
+ wasn't used anywhere before) is now used as one test whether we are
+ within preformatted text, also corrected the style setting of freeFormat
+ for PRE in DefaultStyle.c. - KW
+* Changed internal gateways (in HTNews.c, HTFile.c, HTWAIS.c, HTWSRC.c)
+ to end LI, DT, and DD elements if they are not declared SGML_EMPTY,
+ so that HTML.c's stack won't get overloaded in this case. - KW
+* Tweaks in mainloop() handling of DO_GOTOLINK_STUFF and DO_GOTOPAGE_STUFF.
+ Going to a link with the 'g' suffix and then immediately ACTIVATing that
+ link could previously show the wrong page of the new document, since
+ newdoc.line was not being reset. - KW
+1997-05-03
+* (chartrans) Now always check for LYlowest_eightbit[current_char_set]
+ near the top of HText_appendCharacter(), to prevent writing C1 control
+ chars to the terminal if they are not valid as displayable characters
+ according to the selected "display character set" Option.
+ All this should be handled earlier in processing, and this check may
+ disappear again for testing, but somebody asked for it... - KW
+* (chartrans) Small changes to README files. - KW
+* In the section of HTUtils.h for non-autoconf builds, don't set
+ HAVE_KEYPAD or HAVE_TTYTYPE if USE_SLANG is defined. - KW
+* Modified HText_LinksInLines() to not count hidden form fields. - KW
+* Added support for setting an anchor's no_cache element based on a
+ comparison between Expires and Date headers if both were received
+ and we didn't set it based on a Cache-Control directive. Also
+ added equivalent support for a comparison between an Expires value
+ from a META tag and a Date header. We still compare Expires header
+ or META values versus the system time if no Date header was received,
+ and still do not accept Date values from META tags because they are
+ unlikely to be reliable. - FM
+1997-05-02
+* Fixed a bug in LYAddImageMap() of LYMap.c which could cause multiple
+ insertions of the same MAP into the LynxMaps structure, and crashes
+ on some systems due to the consequent multiple FREE()'s at exit. - FM
+1997-05-01
+* More mods in HTML.c, LYCharUtils.c and GridText.c for rational handling
+ of potentially wrapped form fields in PRE blocks. We now artificially
+ wrap the line if the form field would start within 6 columns from the
+ right margin. This makes sure that editing windows and the highlighted
+ segments of submit or reset buttons will not ever be ridiculously short,
+ and is homologous to our use of a collapsible space before input fields
+ and buttons when not in PRE blocks to promote a wrap there instead of
+ within the fields or buttons. - FM
+* Expanded the WHEREIS query support so that it also locates the values
+ of form fields within the current document and repositions or pages
+ accordingly, as for normal (Anchor) links and for text strings. Note
+ that if the hit was for an OPTION value in a retracted SELECT popup,
+ you are positioned on the retracted window, and must pop it up and
+ search again to be positioned on the OPTION value with the hit, unless
+ it already is the selected OPTION. The mods are hairy enough without
+ trying to do the latter automatically, at least for now. - FM
+1997-04-30
+* Quote the URL for external command (not for VMS or DOS or Windows)
+ to avoid dangerous chars and shell spoofing. - KW
+* Escape characters properly when constructing URLs from filenames
+ in LYConvertToURL. If a string given for startfile, home page, or
+ a goto command which does not already have the form of an absolute
+ URL starting with an URL scheme and which does not start with '~'
+ (but may start with '/') specifies an existing file or directory in
+ valid Unix-like format for the native filesystem, i.e. without using
+ escaping, it gets URL-escaped, otherwise it is assumed to already
+ be URL-escaped. - KW
+1997-04-29
+* Updated RP Styles 0.2 code, don't allow comma as separator between
+ fg and bg colors after all, fix the LYNX_VERSION string generation
+ in userdefs.h to have `-Styles' appended *within* the quoted string. - KW
+* Added support for a 'p' suffix, like the 'g' suffix for making a link
+ number the current link rather than ACTIVATE-ing it,
+ but for displaying the page indicated by the number preceding the
+ 'p' suffix entered at the "follow link (or goto link or page) number:"
+ prompt. [...] If the number
+ entered at the prompt is '1' or less followed by the 'p' suffix, or only
+ 'p' is entered, you get the same behavior as for the HOME command. If
+ the number is equal to or greater than the number of pages, you get the
+ last page displayed as you would if you had used successive PAGE_DOWN
+ commands from the HOME position to reach it. This differs from the END
+ command, which fills the screen with lines from the end of the document
+ if you are not already displaying the end of the document. Note that if
+ you enter a number without a suffix (to ACTIVATE the link with that number)
+ or with the 'g' suffix (to make the link with that number the current link)
+ it must correspond to a valid link number or an error statusline message
+ will be issued, in contrast to the 'p' suffix for which an out of range
+ number is treated as a request to display the first or last actual page in
+ the current document. - FM
+* Fixed some typos in lynx.man. - LWV
+* More modifications of the anchor counting code for HTGetLinkInfo() in
+ GridText.c so that it properly skips hidden form fields and anchors
+ without selectable text. - KW
+* More modifications in GridText.c and HTML.c so that it deals rationally
+ with submit or reset button values, and the underscore placeholders for
+ other form fields, when in versus not in PRE blocks. The entire submit
+ or reset button values are now always displayed, whether or not a portion
+ of it was wrapped, but we still can only highlight the portion before the
+ wrap to indicate a link for submission of the form or for resetting the
+ form field values. - FM
+* Undid some mysterious changes in SIGHUP setting (SIG_IGN vs. SIG_DFL)
+ which had sneaked in in connection with adding the NOSIGHUP
+ conditional. - KW
+* Tweaks to New DTD's extra info for CENTER and H1..H6 - KW
+* New function HText_AreDifferent() from FM added to GridText.c, but
+ not used yet. - KW
+* Tweaks to WB's additions for external command: use strncasecomp, add
+ LYExtern.o to src/makefile.in, changed test for empty command. - KW
+* Changed LYKeymap.h and LYKeymap.c so they agree about the symbols
+ assigned to the new keys (SWITCH_DTD, EXTERN). - KW
+* correct minor syntax err that caused SCO 3.x to fail make-include
+ autoconf test. also, eliminate whitespace before '#' that causes
+ compile-fail on K&R compilers. - TD
+1997-04-28
+* Updated lynx_url_support.html so as to make clear that the offer to
+ include the currently displayed document with right-angle-bracket
+ prefixing for mailto, newsreply, and snewsreply URLs is made only if
+ the user has defined an external editor via the Options Menu, and that
+ the user is expected to edit this inclusion so that it retains only
+ those passages relevant to the email or followup message which the
+ user will add. - FM
+* Tweak of INPUT handling in HTML.c so that we use nbsp instead of any
+ spaces when loading a submit or reset button's actual value instead
+ of a series of underscores into the HText structure, so that we
+ still promote a wrap, if needed, at the space we ensured would be
+ present before each INPUT. - FM
+* Made first_option a structure member rather than a static variable
+ in HTML.c - KW
+1997-04-27
+* Tweak of Control-C and Control-G handling for popup_options() in
+ LYForms.c. They were being sought improperly as command keys rather
+ than as raw keyboard entries. Note that only Control-G should be
+ used as "cancel" within popup windows on Unix, because Control-C
+ is not being trapped to a handler as on VMS. - LE & FM
+* Tweak of the anchor counting code for HTGetLinkInfo() in GridText.c
+ so that it takes form fields into account when making a link current
+ based on a "Follow link number" entry with the 'g' suffix.
+ Also added comments to that code. - KW
+1997-04-25
+* Added information in the "Lynx bookmarks" section of the Users Guide
+ about appropriate versus unsupported modifications when editing the
+ bookmark files. - FM
+* RP Styles 0.2 fixed a bit and brought up to current experimental code
+ level (no autoconfig or simple-curses, only older version of Wayne's
+ mods, maybe something else is missing, too). No documentation, no
+ detailed checking, no real cleanup. Makefile slightly adapted,
+ but still needs changing for new systems - see comments there. - KW
+1997-04-24
+* Tweaks for enhanced mouse support in Win32 and hooks for 386 which
+ doesn't have mouse support yet. - WB
+* External command added. See LYExtern.* in src and lynx.cfg.
+ You need to define USE_EXTERNALS to compile this in. - WB
+1997-04-23
+* Modified LYCharUtils.c, HTML.c and LYMessages_en.h so that if a
+ partial reference (HREF or SRC value) would be resolved to an http
+ or https URL which has only two dots as the first symbolic element in
+ the path (e.g., http://host/../foo.html), such that the server would
+ reject the request, that element is excluded from the resultant URL,
+ but a statusline message is issued (once per document) about a bad
+ partial reference, as immediate feedback which might lead to the
+ document provider correcting the bad partial reference(s). We still
+ retain that first symbolic element, in compliance with the IETF RFCs
+ and IDs for resolving URLs, with other URL schemes (e.g., ftp). - FM
+* Added a skip_stack int to the HTML.h struct _HTStructured, to use
+ for flagging that the next call to HTML_start_element or
+ HTML_end_element is an internal shortcut and should skip pushing
+ or popping the HTML.c paragraph style stack even for elements
+ that are not declared SGML_EMPTY. Added a SET_SKIP_STACK macro
+ to HTML.c to set the flag, use it. - KW
+* Changes to HTML.c to better deal with a number of elements which may
+ or may not have been declared SGML_EMPTY in HTMLDTD.c:
+ if the last stacked element is HTML_OPTION, treat text as for
+ HTML_SELECT in HTML_put_character and HTML_put_character and
+ HTML_put_string. Added handling code for </P> to HTML_end_element
+ (similar but not identical to that for P in HTML_start_element).
+ Added check whether a SELECT is still open to FORM handling in
+ HTML_end_element. Added check whether a FORM is open to SELECT
+ handling in HTML_end_element. Added cases for end tags of
+ TABLE-related elements (TR, THEAD, TFOOT, TBODY, COLGROUP, TH, TD)
+ and of DT, DD, LH, LI, FONT, OVERLAY to the switch in
+ HTML_end_element, currently just break from the switch. - KW
+* Some tweaks and corrections to the additional element info and
+ to the content types used with New_DTD, in HTMLDTD.c. Made
+ OPTION non-empty. - KW
+* Now changed the tags_old[] in HTMLDTD.c, which is used with the
+ switchable "old" SGML parsing, to follow the changes for A, B,
+ BLINK, CITE, EM, FONT, I, STRONG, and U mentioned in the entry
+ of 1997-04-15. These, together with FORM and P, are all declared
+ as SGML_EMPTY now when the "old" SGML parsing is in effect, but
+ not with new parsing. - KW
+* Changes to LYMail.c and LYPrint.c to send Content-Transfer-Encoding
+ headers and/or a charset parameter when mailing, based on idea from
+ Hynek Med. Don't use charset if we only have 7-bit characters
+ anyway. If compiled with EXP_CHARTRANS, use MIME name corresponding
+ to display character set if it looks valid (not "x-"), otherwise
+ only an explicitly given document charset. In the chartrans case,
+ don't send charset parameter for CJK since it may be wrong... - KW
+* Added TRACE output to UCAuto.c - HM
+1997-04-22
+* refined check for slang libraries/headers by checking if $CFLAGS has been
+ set so that slang.h is in the search path - TD
+* add check to allow use of broken ncurses 1.9.9e's color - TD
+* add check for NGROUPS, TRUE, FALSE macro definitions - TD
+* remove top-level makefile.in targets that can be combined with the generic
+ target (more work required on the remaining ones) - TD.
+* Plugged memory leak in deleteLinks() of HTAnchor.c. - KW
+* When dumping or outputting a rendered document via the 'p'rint menu,
+ Lynx would use the underscore placeholders for submit/image/reset
+ buttons as for other INPUT fields. We now load the values of
+ submit/image/reset buttons instead of placeholders into the HText
+ structure, so the values will be seen when dumping or outputting
+ via the 'p'rint menu. See the comments under case HTML_INPUT: in
+ HTML.c for the still less than optimal things that happen if a
+ wrap occurs within the INPUT value or placeholder strings, as might
+ happen in PRE blocks, or for strings wider than the screen. - LE & FM
+* SGML_abort() did not free memory used by the SGML.c parser stack.
+ Now it does, but still doesn't call HTML_end_element() for the
+ stacked elements (it's an abort after all...) - KW
+1997-04-21
+* Tweaks of the 1997-04-11 and 1997-04-09 mods in HText_endAnchor() of
+ GridText.c so as to take possible wrapping of Anchor content into
+ account when deciding whether or not to implement the Anchor as an
+ ACTIVATE-able link. - FM
+* New SGML.c parser, and new HTMLDTD.c with additional element info.
+ Extra content information for each tag is now included in the
+ HTTag structure, and given in an extended tags_new[] table in
+ HTMLDTD.c. Modified start_element() and end_element() in SGML.c
+ to perform some heuristic wind-downs of the parsing stack, based
+ on the extra element info. - KW
+* Revert treatment of some tags which were treated as SGML_EMPTY
+ before to their "natural" content model. No changes made to
+ HTML.c to accommodate this change, so results may differ where
+ HTML.c relies on previous hacks or has now handling code for
+ end tags of elements which were previously SGML_EMPTY. - KW
+* Made SGML parsing switchable between old and new HTMLDTD info
+ and SGML.c code, controlled by a New_DTD global variable and
+ LYK_SWITCH_DTD toggle key. Use (temporarily?) ^V for the toggle key.
+ This is not yet changeable via command line, lynx.cfg, etc., and the
+ default is New_DTD==YES (so that it gets tested :-) ). - KW
+* Made some of the error messages before exit in LYMainLoop.c and
+ LYMain.c go to stderr instead of stdout, but only for UNIX and,
+ in the case of the LYMainLoop.c messages, only if
+ dump_output_immediately was in effect. - KW
+1997-04-20
+* Tweaks in LYCharUtils.c to bind META CONTENT to a header value only
+ via an HTTP-EQUIV attribute (i.e., not via a NAME attribute). - FM
+* Mod in HTAccess.c to ignore the anchor's no_cache element if we're
+ seeking a position in the currently loaded document. - FM
+* Commented out the above change in HTAccess.c. There's a more complete
+ mechanism for it already in this code... - KW
+* Fixed a typo in the bookmark file lead text. - DK (Doug Kaufman
+ <dkaufman@rahul.net>)
+1997-04-19
+* Changed the inappropriate StrAllocCat() to StrAllocCopy() for
+ loading the XLOADIMAGE_COMMAND in LYReadCFG.c. - PC
+1997-04-18
+* Based on recent discussions in www-html@w3.org, added HY and SHY
+ to the DTD (treated as synonyms; one or the other is most likely
+ to be used in future HTML specs, so for now, we support both), as
+ markup equivalent to the named entity &shy; and numeric character
+ reference &#173; (soft hyphen). Note that Lynx implements soft
+ hyphens as specified in IETF RFC 2070 (link "HTML i18n" in the
+ Users Guide). Use of a tag instead of entity is preferable for
+ a soft hyphen because browsers which do not support soft hyphen
+ will ignore it as an "unknown tag" instead of inappropriately
+ inserting a hyphen or displaying the raw entity. Also added WBR,
+ which is handled like soft hyphen (indicating a permissible wrap
+ point), but does not insert a hyphen at the wrap. - FM
+1997-04-17
+* Mods in HTML.c, HTML.h, and LYMessages_en.h to issue an HTML stack
+ overrun message only once per document, and as a statusline message
+ if not in TRACE mode, and to check in HTML_end_element() for
+ correspondence between the SGML and HTML stacks if an overrun should
+ occur. - FM
+* Corrections in HTML.c for the bounds checks associated with DIV and
+ CENTER nesting levels, and for an HTML stack underrun. - KW
+* Plugged a memory leak under case HTML_IMG: of HTML_start_element() in
+ HTML.c, and removed an inappropriate if(){} in HText_endAnchor() of
+ GridText.c. - FM & KW
+* Modified the lead text created for bookmark files in LYBookmark.c so
+ that it indicates that an editor can be used to delete or reorder
+ the links, but that the format within lines should not be changed,
+ nor other HTML markup added. Note that the new lead text will be
+ used only when new bookmark files are created via the 'a'dd bookmark
+ link command. A new bookmark file is not created if the one being
+ sought already exists, so existing ones will still have the old
+ lead text. - FM
+1997-04-16
+* Extensive changes to try to keep track of whether a document (or
+ a location within it) was reached by an internal (fragment-only)
+ URL reference or not. The basic idea is to be serious about I-D
+ (currently) draft-fielding-url-syntax-04.txt.
+ URL references starting with '#' are always to the current
+ document (from which the reference is made). This leads to a
+ lot of hackery in HTML.c, LYMainLoop.c, LYHistory.c, etc. etc...
+ to distinguish a doc that was reached by an "internal" reference
+ from others. But it seems necessary to keep track of how the
+ reference to a fragment was specified, whether with a non-empty
+ "real" URL (possibly relative) preceding the '#' or without it,
+ all the way way from the HTML parsing to the mainloop. Only then
+ can the mainloop decide to not start a new retrieval for an internal
+ reference without skipping a new retrieval if a full URL reference
+ with fragment is made to a location in the same document (which
+ may be non-cachable or the result of a POST)...
+ This code prevents unnecessary/inappropriate POST form resubmissions
+ on following an internal link in a POST response, as they are
+ present for example in WebTechs validation results. - KW
+* A "Goto numbered link" feature. The user interface could be improved...
+ Start typing the link number, then add 'g' before hitting enter.
+* Some improvements to WHEREIS search. Will not always position
+ found string on first line (details depend on whether anchors are
+ present, usually will position in top third of screen), and avoid
+ some unnecessary screen updates. - KW
+1997-04-15
+* Miscellaneous additional tweaks in HTML.c for more robust error recovery
+ from bad HTML involving emphasis or style elements (B, BLINK, CITE, EM,
+ FONT, I, STRONG, and U), or HREF-less NAME-ed Anchors without matching
+ end tags. - FM
+* Modified the declarations in HTMLDTD.c and code in SGML.C, HTML.c, and
+ GridText.c to handle A, B, BLINK, CITE, EM, FONT, I, STRONG, and U
+ container elements homologously to the modified handling of FORM (see
+ 1997-04-05 mods) so that if they are invalidly interdigitated or have
+ spurious end tags in the markup, substitutions of the "expected" end
+ tags by the SGML.c stack-based parser will not be made, and without
+ messing up the HTML.c stack-based parser. Appears to work reliably
+ for all of the elements, and to be reasonably crash safe (hopefully
+ as safe as the vanilla v2.7.1), but there are no guarantees. - FM
+* Only *some* (most?) of the changes described in the above two
+ entries are used, as far as they change HTML.c. Not yet using the
+ changes to HTMLDTD.c and SGML.c. - KW
+* refined logic of SVr4 curses color support to test the no_color_video
+ attribute - TD
+* ifdef'd NCURSES_MOUSE_VERSION logic to allow build with ncurses 1.9.4 - TD
+* ifdef'd wgetbkgd misspelling to allow build with ncurses prior to 1.9.9g - TD
+* document USE_MOUSE configuration-option - TD
+* modify configure script and makefile.in templates to make BSDI_Makefile
+ obsolete - TD
+* rename config.h to lynx_cfg.h to minimize conflict when configuring against
+ ncurses or slang in nonstandard locations - TD
+* new autoconf macro CF_HEADER_PATH is used to make header-search for slang
+ the same as ncurses - TD
+* modify CF_CURSES_LIBS, CF_NCURSES_LIBS and CF_SLANG_LIBS to accommodate
+ predefinition of $LIBS variable - TD
+* corrected autoconf'd compiler flags for Ultrix - TD
+* add config.guess & config.sub to allow specialized host-type checks - TD
+* guard against redefinition of NO_FILIO_H - TD
+* use new autoconf macro CF_SYSTEM_MAIL_FLAGS /jes
+1997-04-14
+* Tweaked LYAddImageMap() in LYMap.c so that it removes all pre-existing
+ AREA element entries when updating MAP element content, and set the
+ no_cache anchor element in LYLoadIMGmap() so that the updated MAPs
+ always will be used when rendering. - FM
+* Not using the no_cache change from last entry, until further
+ investigation. - KW
+* Removed two spurious lines under case LYK_PRINT: in LYMainLoop.c
+ (from an old cut and paste from case LYK_HISTORY: done too late
+ at night 8-). - FM
+1997-04-13
+* Modified the handling of BASE for resolving HREFs in relation to MAP
+ and AREA elements, and USEMAPs in IMG and OBJECT elements. The
+ formally released code was treating such links equivalently to the
+ handling of fragments for positioning the display to ID-ed elements
+ or NAME-ed Anchors, and assuming they're in the same document if the
+ associated HREF value begins with a '#', rather than resolving versus
+ the BASE, and was always resolving versus the BASE for MAP ID or NAME
+ attributes, and for the AREA HREFs in MAP content. We now always
+ resolve the MAP ID or NAME attributes versus the current stream's
+ address (since the MAP must be in it or we wouldn't be handling it)
+ [...] According to the
+ original draft and the current HTML 3.2 Proposed Standard,
+ MAPs need not be in the same document as the IMG or OBJECT elements
+ which specify links to the MAPs. Because MAPs are "deferred objects",
+ they logically should be placed above any IMG or OBJECT elements which
+ reference them in the same document (as is done for SCRIPTs), but this
+ isn't stated in the specs, nor always done in practice. [...]
+ ([A]uthors who place the MAPs further down in the same document should be
+ informed about "deferred objects" and encouraged to move them up 8-). - FM
+* Use logical extension of the rules for HREF references also for
+ USEMAP references to MAPs: relative URL references are resolved with
+ respect to a BASE element if one is present in the document where they
+ occur, unless they are URL references without a URL, i.e. only a
+ fragment starting with '#'. In the latter case they are taken as
+ internal references referring to a MAP in the same document where
+ the USEMAP occurs, whether the MAP occurs before the USEMAP (as it
+ should, according to previous entry) or after the USEMAP.
+ HREF's in AREA elements follow the same rules. - KW
+* Fixed bug in HTML_free() for the case when LYMapsOnly is set. We
+ didn't create an HText structure for the stream (just scanned it for
+ MAPs and processed them into LYMap.c's LynxMaps structure), nor do
+ we want to create a blank one (as was being done) since we didn't
+ render the stream, nor would we have a me->target set. So we just
+ free any me elements that might still be allocated (though they
+ should have been freed already), and return rather than continuing
+ through the rest of the HTML_free() code. - FM
+1997-04-11
+* Fixed bugs in Gridtext.c and HTML.c which could cause mishandling
+ of anchors in LINKS_ARE_NUMBERS mode if a line wrap occurred in
+ the numbered bracket or the anchor content following the bracket,
+ and failures to suppress the numbered bracket if the anchor content
+ was empty due to ALT="" in an IMG tag, or if Lynx was configured or
+ toggled to suppress the link for the server-side image map if both
+ ISMAP and USEMAP attibutes were present in the IMG tag. - FM
+* Only using the number-removing code under additional conditions:
+ ISMAPs which appear together with USEMAPs and which are suppressed
+ with LYNoISMAPifUSEMAP in LINKS_ARE_NUMBERS mode. - KW
+* Extended the disk_save restriction to the print menu as well as
+ the download menu, and accordingly updated lynx.hlp, lynx.man, and
+ Lynx_users_guide.html. - HN & FM
+1997-04-09
+* Many changes to further the Win32 and 386 ports. An emulation of
+ the HTVMS_ calls was used to try and cover all the DOS'izms.
+ A specialized ifdef for pdcurses color mapping added. Some keypad
+ tweaks. More generalized process spawning. .lynxrc is lynx.rc for 386.
+ - WB
+* Tweak to ensure that a newline isn't inserted by virtue of a
+ FORM start tag if it's in the first line of a list element and
+ no text precedes it other than a UL's bullet or OL's number
+ on that line. - FM
+* Added pauses for the "Bad HTML" statusline messages under cases
+ HTML_HTML and HTML_BODY in HTML_end_element(), and eliminated
+ their checks for an unclosed FORM because we no longer expect
+ that to cause a serious problem. - LE & FM
+* Added a NO_ISMAP_IF_USEMAP configuration symbol and -ismap
+ command line toggle for suppressing inclusion of a link for the
+ server-side-image-map if an IMG or OBJECT element has both ISMAP
+ and USEMAP attributes such that a client-side-image-map link is
+ created. Updated lynx.man, lynx.hlp and Lynx_users_guide.html
+ accordingly. - FM
+* Fixed a glitch in HText_endAnchor() of Gridtext.c which could
+ cause dangling Anchors in LINKS_ARE_NUMBERED mode if the Anchor's
+ content was handled in a manner which caused it to become zero
+ length. - FM
+* Moved handling for NEWS_POSTING in LYReadCFG.c to the right place,
+ so that it can actually have an effect. - LWV
+* Typo fixes for the comment concerning NO_ANONYMOUS_EMAIL in
+ userdefs.h - HN & FM
+1997-04-08
+* New translation table koi8r_uni for KOI8-R charset. Lynx can now
+ translate between iso-8859-5 and KOI8-R, at least for the Cyrillic
+ characters present in both. - KW
+* New translation table def7_uni with default 7-bit mappings
+ (replacement representation). Based on RFC1345 and mnemonic,ds
+ from ftp://dkuug.dk/i18n/ and previous Lynx replacements
+ in LYCharSets.c and IPA FAQ convention and stuff for Ethiopic and
+ KOI8-R. It maps many of the accented Latin characters present in
+ Unicode to their unaccented counterparts. This table is now
+ used for the "7 bit approximations" display "character set". - KW
+* Entities for Latin2 characters added to HTMLDTD.c These also
+ include many entity names for ASCII characters, and characters
+ which are in both iso-8859-1 and iso-8859-2. - Hynek Med
+* Changes to the non-chartrans translation tables in LYCharSets.c
+ for &Dstrok;, &ETH;, and &eth;. Treat &Dstrok; more like
+ an entity for the (Latin-2) Unicode character U+0110, since
+ that seems to be SGML standard usage. - KW
+* Added mappings for some "smart quote" characters to several
+ translation tables. - KW
+* Make makeuctb slightly more flexible (accept unicode range for
+ mapping to single code point). - KW
+1997-04-07
+* Took out special-case handling in the curses-color code for underlining
+ when lynx is running under Linux using the linux console with color.
+ The code was introduced on 1997-03-12 and would ignore "smul" capability
+ info from terminfo or termcap under those circumstances, always using
+ bold instead of underline. - KW
+* Slightly modified the FORM handling patch of 1997-04-05, as follows:
+ Use a generic test for a non-SGML_EMPTY element for bypassing the
+ stack pop in HTML_end_element() of HTML.c instead of an explicit
+ test for HTML_FORM. - KW
+1997-04-06
+* Patch for IMG elements which have both ISMAP and USEMAP in effect.
+ In HTML_start_element() don't generate the "[ISMAP]-" string for
+ output in this case, unless clickable_images is set TRUE. - KW
+1997-04-05
+* Patch for Lynx v2.7.1 to handle invalidly interdigitated container
+ elements or spurious container end tags without substitutions of
+ "expected" FORM end tags by the SGML.c stack-based parser, and
+ without messing up the HTML.c stack-based parser. Reliably succeeds
+ in not closing FORMs before all of the FORM elements, including
+ submit buttons, have been processed. Should be reasonably crash
+ safe (hopefully as safe as the vanilla v2.7.1), but there are no
+ guarantees. - FM
+1997-04-04
+============================================================================
+--- Release of Lynx2-7 + BUGFIXES as Lynx v2.7.1 (April 4, 1997) by FM ---
+============================================================================
+* Note that 2.7.1 was not a release from this code set, but all 2.7 -> 2.7.1
+ bugfixes and other changes are also included in this code set, in either
+ identical or equivalent form. Therefore the entries below this point
+ comprise the 2.7 -> 2.7.1 changes, and additionally other changes made to
+ the development code set during that time. - KW
+1997-04-02
+* add Andrew Kuchling's patch to support mouse-clicks with ncurses. - TD
+* refine tests that address porting problems to SCO (detecting struct winsize,
+ workaround for misdefinition of 'remove')
+* refine CF_COLOR_CURSES test to avoid ncurses 1.9.9e bugs. - TD
+* refine CF_PATH_PROG to allow for machines that haven't the given programs,
+ by using only the program name and added configure option
+ --disable-full-paths to enforce this behavior. - TD
+* fixes for some gcc compiler warnings (missing prototypes, unused variables,
+ uninitialized variables, shadowed variables). - TD
+* Fixed typos in LYHistory.c, LYMail.c and LYMain.c which caused
+ failures of flag setting in the distributed code. - TD
+* correct cast in HTFWriter.c that may break if atoi() is not prototyped. - TD
+* add top-level makefile target 'maintainer-clean', use this to remove
+ Lynx.prj - TD
+1997-03-31
+* Added a missing check for whether the fragment token is NULL in
+ LYConvertToURL() of LYUtils.c. Without the check, the for-Unix code
+ could crash if a local file spec was entered as a startfile or goto
+ with escaped characters. - KW
+* Mod in HTML.c to retain "[INLINE]" as the default ALT string if an
+ IMG element has an ISMAP attribute but is not in Anchor content such
+ that it could not in fact function as a server-side image map. - FM
+1997-03-27
+* In mainloop(), after the call to HText_pageDisplay() following a change
+ of the document view, ensure that curdoc.link does not remain set to -1
+ if there are any links on the screen. This would otherwise happen if
+ a document is pushed to the history stack while there are no links, and
+ later popped (and refreshed) after one or more links have been created.
+ This change prevents segmentation faults which occurred after creation
+ of a new file in a previously empty directory via the DIRED menu. The
+ access to invalid memory only occurred if the screen showing the empty
+ directory did not have a parent dir reference link (which is always the
+ case if NO_PARENT_DIR_REFERENCE was specified at compilation time). - KW
+* In LYLocal.c, modified the code handling DIRED_MENU to do more careful
+ checking of the selected file. In addition to "TAG", "FILE", and "DIR",
+ DIRED_MENU definitions in lynx.cfg now also recognize LINK as a type.
+ DIRED_MENU definitions with a type field of "LINK" are only used if the
+ current selection is a symbolic link ("FILE" and "DIR" definitions are
+ not used in that case). The default menu definitions have been updated
+ to reflect this change, and to avoid the showing of menu items whose
+ action would always fail - KW
+* Some cleanup to eliminate compiler warnings, remove some unused
+ variables - KW
+* Fixed a typo and added comments for the code in LYMainLoop.c which
+ decides whether to load the URLs for homepage and/or startfile into
+ the goto buffer at startup. The typo in the distributed code caused
+ the startfile URL always to be added to the goto buffer, even if
+ it had POST content such that it could be resent inappropriately
+ as a GET request via the goto buffer. - FM
+* Added a bsdi-slang target to the Makefile. - Laura Eaves
+1997-03-26
+* Changed highlighting of strings found by a WHEREIS ('/') search.
+ Now uses Christmas tree attribute combination ("all bits are on"),
+ which with color support translates to COLOR:7. - KW
+* Modified the HTStream structure and associated code in src/HTFWriter.c
+ so that we save and use the relevant content of the associated
+ HTPresentation structure as two HTFormat elements rather than via a
+ pointer to the HTPresentation structure itself, because the latter
+ structure might not be valid under some circumstances when
+ HTFWriter_free() is called. The distributed code might indirectly
+ result in segmentation faults during downloading on Linux and some
+ other flavors of Unix (though they don't occur for most flavors, or
+ on VMS). - KW
+1997-03-23
+* Further reduction of top-level makefile.in by moving definitions out of
+ WWW/Implementation/*/Makefile, so only one is needed for autoconfigured
+ build (i.e., WWW/Implementation/unix/Makefile). This highlights the
+ remaining differences between the top-level targets - TD
+* Make configure script generate Unix makefiles in subdirectories, a step
+ toward being able to run make from any directory, for development - TD
+* Add autoconf tests for paths of programs, including sendmail vs mmdf - TD
+* Add configure script options for development (--disable-echo, --enable-debug,
+ --enable-find-leaks, --enable-warnings) - TD
+* Allow user to override search path for ncurses header by setting $CFLAGS or
+ $CPPFLAGS - TD
+* Correct array limit in LYCurses.c for SVr4 color support - TD
+* Use addstr rather than printw in popup-forms to address concern about 8-bit
+ characters - TD
+1997-03-21
+* Changes in auto config handling of ncurses header location, function
+ used for reading terminal input, some other system dependent tweaks
+ (including SCO broken remove, time.h) - TD
+* Fix for popup handling with late ncurses versions (uses wprintw
+ instead of waddstr in LYForms.c) - TD
+* Mods in LYPrint.c to use ".txt" as the output file extension for
+ all rendered text/html files regardless of their original extension.
+ The distributed code was doing this only for ones with an extension
+ of ".html". The original extension still is retained if the file
+ is being output as source. - FM
+* Added protection against passing a NULL pointer for path_url to
+ render_item() from dired_options() in LYLocal.c. - GN
+1997-03-20
+* Tweaked the protection against URLs directed to port 19 or port 25 so
+ that it can't be circumvented via lead zeros in the port numbers. - FM
+* Changed the compilation default so as not to send From MIME headers to
+ http or https servers. The default can still be changed via lynx.cfg.
+ Replaced the -nofrom disabling switch to a -from switch for toggling
+ the compilation or configuration default. Sending the From header
+ has become widely regarded as an invasion of privacy risk, particularly
+ in conjunction with cookie support. - FM
+* Corrected a typo in the lynx.cfg comments concerning TRUSTED_LYNXCGI
+ rules. - KW
+1997-03-17
+* Mods of LYNews.c and LYMail.c to prepend a "-- " separator before
+ appending the LYNX_SIG_FILE signature file to news and email
+ messages. - FM
+* Made the installation mode 755 in the top-level Makefile. The
+ distributed code used 555, and some install commands were unable
+ to do the strip. - LWV
+1997-03-14
+* Corrected typos and expanded the comments concerning lynxcgi symbols
+ in userdefs.h and lynx.cfg. - FM
+* Modified SGML.c to handle the numeric character reference &#8482; as
+ the named entity &trade; also in the non-chartrans case. The
+ trademark character (given by &#8482; or &trade;) will be shown as
+ "(TM)" as the ASCII substitution unless the current display character
+ has a code point for the trademark character or unless overridden by a
+ chartrans translation table. The code of 1997-02-25 prevented showing
+ the trademark sign as "(R)" but did not work in all non-chartrans
+ cases. - KW
+* Include time.h via tcp.h for SVR4 systems. The tcp.h header does include
+ sys/time.h for Unix systems, but this apparently doesn't get struct tm
+ and extern char * ctime() declared for SVR4. - FM
+1997-03-13
+* Added protection in LYGetFile.c against connections to the port 25
+ ESMTP service. - FM
+1997-03-12
+* (chartrans) Make compilation in src/chrtrans less verbose, no more
+ generating automatic *.h_old backup copies. - KW
+* Refinement to the SVr4 (ncurses) color support, allowing it
+ to more closely model the slang support. - TD
+1997-03-11
+* Tweak for command line parsing of files with no URL in LYUtils.c.
+ Also added ability to pass partial domain names in the DJGPP version. - WB
+* Added the closing function for Win32 TCP in LYExit.c (did anyone see a
+ difference?!). - WB
+* Altered LYCurses.c so that the DJGPP version could spawn other programs
+ without certain death. - WB
+* Ignoring the whole ~/lynx.cfg problem (expanding '~') entirely for the
+ Win32 version for now. - WB
+* Some other tweaks for Win32 and DJGPP - WB
+* Added protection in LYGetFile.c against denial of service attacks via
+ the port 19 CHARGEN service. The distributed code left Lynx or proxies
+ vulnerable to such attacks via direct or redirection URLs. - FM
+1997-03-10
+* Fixed error in the handling of numeric character references with values
+ greater than 255 in SGML.c. The distributed code was breaking after
+ substitutions instead of falling through to reset the string chunk and
+ recycle the terminator if not a semi-colon. - FM
+1997-03-09
+* Integrated (simple) color, auto-configure patches with 2.7 following
+ chrtrans patch - T.Dickey, J.Spath.
+1997-03-08
+* Fixed error in the switch positioning of checks for XLOADIMAGE_COMMAND
+ and wais_proxy in LYReadCFG.c. The distributed code had them reversed
+ under case 'W' versus case 'X'. - PDS
+* Expanded the copyright and licensing statements in the -version
+ output. - FM
+1997-03-04
+* Corrected the offset computation in textsearch() of LYSearch.c so that
+ WHEREIS searches repeated on a page with no links seek the target
+ starting at the line immediately following the last displayed. The
+ distributed code was setting a greater offset. - JS
+1997-03-02
+* Don't entify post content for the showinfo display, now that we are
+ making it an XMP block in that display to handle all of the supported
+ enctypes. - FM
+* Patches to fix mail and FTP for Win32 (LYMail.c, HTFile.c). - WB
+* Makefiles to compile chartrans code for Win32. - WB
+* (chartrans) Minor cleanups (makeuctb.c, chrtrans/Makefile, HTPlain.c)
+ to enable successful compilation on Win32. - KW
+1997-02-28
+* Changed all references to "image/*" to just "image" in the userdefs.h
+ and lynx.cfg comments about XLOADIMAGE_COMMAND. The "/*" within the
+ userdefs.h comments was generating warnings from some compilers. - FM
+* Added a snake-slang target to the Makefile, and added -DUNIX to the
+ LYFLAGS for the snake3 and snake3-slang targets (HP-UX apparently does
+ not define "unix" itself with the -Ae switch, and thus needs to have
+ that definition forced via -DUNIX). - HL
+* Merged with patches and makefiles from Wayne Buttles
+ (buttles@wsb.champlain.edu) to enable compilation in two new environments:
+ Win32 (95/NT) with Borland C++ 4.52 compiler, and 386 DOS with DJGPP
+ compiler. To add ports for Win32 (95/NT) and 386 DOS computers with a
+ packet driver, four new defines were created: _WINDOWS (Defined for Win32
+ specific code - Mostly TCP related), DJGPP (Defined for 386 specific code -
+ Mostly TCP related), DOSPATH (Defined for any DOS'ish computer), and
+ NOSIGHUP (Defined for computers not supporting sighup signal calls).
+ Separate utility programs needed for compiling and running Lynx on those
+ platforms are available from Wayne at
+ <http://www.fdisk.com/doslynx/wlynx/>. - WB, KW
+* Fixed Telnet for Win32 - WB
+* (chartrans) Small correction in SGML.c (set_chartrans_handling) - KW
+1997-02-26
+* Close both descriptors of the pipe() for the NSL_FORK enabled code
+ in HTTCP.c. The distributed code was closing only one of them on
+ completed gethostbyname() calls, and neither on 'z'aps. - FM
+* Changed the HREF for the "Lynx FAQ" link in the online 'h'elp to
+ its new URL (http://www.slcc.edu/lynx/faq.html). - FM
+1997-02-25
+* More reverse engineering to cope with Netscape's bogus cookie header
+ parsing. The parser must not require an '=' between the expires
+ attribute name and value, because Set-Cookie headers are being
+ transmitted without it (e.g., by http://law.agps.gov.au). So Lynx
+ now treats that as another special case. - FM
+* Cope with invalid use of expires attributes in Version 1 cookies.
+ An -06 State Management draft recommends that for "backward
+ compatibility", and has been severely criticized in the HTTP-WG,
+ but it would be foolish not to assume Netscape will do that. See the
+ expanded comments in LYSetCookie() of LYCookie.c for more information.
+ Note that "expires" thus cannot be used as a Version 1 cookie name, but
+ a provider would be foolish to use that, anyway. Note also that the
+ possibility of using different header names for Version 1 versus
+ Version 0 (a.k.a., "Netscape") cookies is being discussed in the
+ HTTP-WG, which might have been better to do in the first place, but
+ the -05 draft has been approved as RFC 2109:
+ http://info.internet.isi.edu/in-notes/rfc/files/rfc2109.txt
+ so it would be a while before that were done, if ever. - FM
+* chartrans code for translation of character sets, handling of Unicode,
+ and i18n updated for Lynx 2.7. Support for CHARSET attribute on A
+ tags. New directory src/chrtrans with table files. Compilation flags
+ -DEXP_CHARTRANS, -DEXP_CHARTRANS_AUTOSWITCH (for Linux),
+ -DSLANG_MBCS_HACK (for raw unicode console).
+ New command line options when compiled with -DEXP_CHARTRANS:
+ -assume_charset, -assume_local_charset, -assume_unrec_charset.
+ See README.chartrans and README files in src/chrtrans for more info.
+ INFO screen shows of effective charset even if not given explicitly.
+ Translation routines in LYCharUtils.c not chartrans-ified at this point.
+ - KW
+* No showing of &trade; or &#8482; as (R) any more, use (TM) instead. - KW
+* Prefer HTTP-EQUIV over NAME in META tags. - KW
+1997-02-22
+* Fixed a memory management glitch which could cause a crash if the
+ MIME type of a reply to a FORM submission with METHOD=POST caused a
+ download offer to be invoked. - FM
+* Don't simplify ftp URLs by trimming trailing slashes if the URL is
+ being proxied. The Netscape proxy server for some unknown reason
+ can return redirection for ftp URLs with the slash appended, and
+ trimming it can result in a redirection loop. Based on a posted
+ patch from KW. - FM
+* Fixed two typos in the checks for HTPassHighCtrlRaw in LYExpandString()
+ of LYCharUtils.c. - KW
+* Fixed typo in the equality check on line 1553 in HTGopher.c. - AM
+1997-02-19
+* Reset the host string after an '@', if present, when trimming default
+ ":port" fields in the new code aimed at compliance with the Masinter
+ and Fielding URL drafts, expected to replace RFCs 1738 and 1808. The
+ distributed code neglected to do that, and was ending up on a ":password"
+ field, if present, instead of on the ":port" field, causing the username
+ to be treated as the host name. - FM
+* Expand the default port trimming so as to include all of the registered
+ URL schemes which support a port field in the v2.7 release. - FM
+* Correctly uncache the current directory listing when invoking an 'u'pload,
+ so that it will be updated to include the uploaded file if placed in the
+ current directory. The released code attempted to do this in a manner
+ which prevented a pop, so that the directory listing couldn't be restored
+ on return from the uploader menu. - FM
+* Recognize a bookmark file used as the startfile, whether it resides in the
+ home directory or in a subdirectory off home. The released code failed if
+ the file was in home, and not in a subdirectory, unless the -book switch
+ was used instead of a startfile entry or WWW_HOME variable. - FM
diff --git a/gnu/usr.bin/lynx/docs/CMU.announce b/gnu/usr.bin/lynx/docs/CMU.announce
new file mode 100644
index 00000000000..a4cc6eadcf7
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CMU.announce
@@ -0,0 +1,31 @@
+This document describes the required steps to install Lynx on VMS systems
+which use the CMU TCP/IP package.
+
+The interface to CMU is implemented via Mike O'Malley's excellent LIBCMU socket
+library for VMS. It is not included in the Lynx distribution as it is quite
+large and freely available from:
+ ftp://kermit.columbia.edu/vms-libcmu/ckvlcmu.hex
+
+This is a hexified version of the LIBCMU.BCK saveset.
+
+All LIBCMU files (library and include files) are assumed to be in the
+CMUIP_ROOT:[SYSLIB] directory. Ensure the following LIBCMU files are
+placed appropriately on your system:
+
+ cmuip_root:[syslib]ioctl.h
+ cmuip_root:[syslib]libcmu.olb
+
+Beyond this, follow the same INSTALLATION procedures that you would for any
+VMS Lynx compilation.
+
+REMAINING PROBLEMS:
+ At this time, the FTP Lynx code does not appear to work; it is believed
+ that this problem is due to an as of yet unresolved problem with the
+ LIBCMU 1.2 library. The getsockname routine returns all zeros for the
+ local address portion and results in the system sending an invalid
+ PORT command to the remote end.
+
+ Telnet, tn3270 and rlogin support are not yet implemented.
+
+Andy Harper
+A.Harper@bay.cc.kcl.ac.uk
diff --git a/gnu/usr.bin/lynx/docs/CRAWL.announce b/gnu/usr.bin/lynx/docs/CRAWL.announce
new file mode 100644
index 00000000000..e734bcba44f
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/CRAWL.announce
@@ -0,0 +1,131 @@
+The TRAVERSAL code from old versions of Lynx has been upgraded by David
+Mathog (mathog@seqaxp.bio.caltech.edu) so that it works again, can be
+implemented via a command line switch (-traversal) instead of via a
+compilation symbol for creating a separate Lynx executable as in those
+previous versions, and can be used in conjunction with a -crawl switch
+to make Lynx a front end for a Web Crawler.
+
+
+Usage:
+
+ lynx [-traversal] [-realm] [-crawl] ["startpage"]
+
+
+Added switches are:
+
+ -traversal Follow all http links derived from startpage that are
+ on the same server as startpage. If startpage isn't
+ specified then the traversal begins with the default
+ startfile or WWW_HOME.
+
+ -realm Further restrict http links to ones in the same realm
+ (having a matching base URI) as the startpage (e.g.,
+ http://host/~user/ will restrict the traversal to that
+ user's public html tree).
+
+ -crawl With [-traversal] outputs each unique hypertext page
+ as an lnk###########.dat file in the format specified
+ below. With [-dump] outputs only the startpage, in
+ the same format, to stdout.
+
+
+Note on startpage:
+
+ If a startpage is specified and contains any uppercase
+ characters, on VMS it should be enclosed in double-quotes.
+ The code that extracts the access and host fields from
+ startpage for comparsions with links to ensure they are
+ not on another server, and the comparisons with already
+ traversed links, are case sensitive, and the startpage
+ will go to all lowercase on VMS if no double-quotes are
+ supplied, such that it might be treated as a new link if
+ encounted with uppercase letters.
+
+
+Files created and/or used with the -traversal switch, based on definitions
+in userdefs.h:
+
+TRAVERSE_FILE (traverse.dat):
+ Contains a list of all URLs that were traversed. Note
+ that if a URL appears in this file it will not be
+ traversed again (important if runs are started and
+ stopped). Placing an entry in this file BEFORE the
+ run will block traversal of that URL. Unlike reject.dat
+ a final * has no effect (see below). Note that Lynx
+ internal client-side image MAP URLs will be included in
+ this file (e.g., LYNXIMGMAP:http://server/foo.html#map1),
+ in addition to the "real" (external) http URLs.
+
+TRAVERSE_FOUND_FILE (traverse2.dat):
+ Contains a list of all URLs that were traversed, in the
+ order encountered or re-encountered (but not re-travered)
+ during a traversal run, and the TITLEs of the documents
+ (separated from the URLs by TABs) A URL and TITLE may be
+ present in this list many times. To simplify the list,
+ on VMS use: sort/nodups traverse2.dat;1 ;2
+ Note that the URLs and TITLEs of the Lynx internal
+ client-side image MAP pseudo-documents will not be
+ included in this file, though "traversed", but only the
+ http URLs and TITLEs derived from the MAP's AREA tag
+ HREFs that were traversed.
+
+TRAVERSE_REJECT_FILE (reject.dat):
+ Contains a list of URLs that have been rejected from the
+ traversal. Once a URL has been entered in this list, it
+ will not be traversed. URLs that end in a * will cause
+ rejection of all URLs that match up to the character before
+ the *. So for instance, to reject all htbin references on a
+ site put this line in the reject.dat file BEFORE starting
+ the run: http://www.site.wherever:8000/htbin*
+
+TRAVERSE_ERRORS (traverse.errors):
+ A list of links that could not be accessed or had an
+ unknown status returned by the http server. If the
+ owner of the document containing the link is know via
+ a LINK REV="made" HREF="mailto:foo" in it and the
+ MAIL_SYSTEM_ERROR_LOGGING was set true in userdefs.h
+ or lynx.cfg (not recommended!!!), a message about the
+ problem will be mailed to the owner as well.
+
+
+Files created during traversals if the -crawl switch is included with the
+-traversal switch:
+
+lnk########.dat Numbered output files containing the contents of traversed
+ hypertext documents in text format. All hypertext links
+ within the document have been stripped, and the URL and
+ TITLE of the document are recorded as the first two lines,
+ e.g., for the seqaxp.bio.caltech.edu home page the first
+ two lines will be:
+
+ THE_URL:http://seqaxp.bio.caltech.edu:8000/
+ THE_TITLE:SAF Web server home page
+
+ The VMSIndex software is being adapted to use this
+ information to extract the corresponding URL and TITLE
+ for use in indexing the lnk########.dat files, e.g.:
+
+ $ build_index -
+ /url=(text="THE_URL:") -
+ /topic=(text="THE_TITLE:",EXCLUDE) -
+ /output=INDEX_NAME -
+ lnk*.dat
+
+ A clever person should be able to figure out a way to
+ index the lnk########.dat files on Unix as well.
+
+ If you want the hypertext links in the document to be
+ numbered, include the -number_links switch. By default,
+ this will cause the list of References (URLs for the
+ numbered links) to be appended as well. If you want
+ numbered links but not the References list, include the
+ -nolist switch as well.
+
+ Note that any client-side image MAP pseudo documents
+ that were "traversed" will not have lnk########.dat
+ output files created for them, but output files will
+ be created for "real" documents that were traversed
+ based on the HREFs of the MAP's AREA tags.
+
+This functionality is still under development. Feedback and suggestions
+are welcome.
diff --git a/gnu/usr.bin/lynx/docs/FM.announce b/gnu/usr.bin/lynx/docs/FM.announce
new file mode 100644
index 00000000000..dc3530c46e6
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/FM.announce
@@ -0,0 +1,72 @@
+LYNX FILE MANAGEMENT SUPPORT
+
+New facilities have been added since Lynx 2-3 to provide support
+for managing files on the local filesystem. These facilities allow
+the user to delete, rename, and re-locate files and/or directories and
+to create and/or upload new files and directories. This will mainly
+be of interest to systems administrators who are interested in running
+lynx as a restricted shell in order to provide controlled access to a
+range of services (as in a freenet). It may also be of use at sites
+where some of the users are experiencing difficulty with the raw Unix
+interface.
+
+Support for the new facilities is enabled at compile time by defining
+the variable `DIRED_SUPPORT' in the `MCFLAGS' list in the Lynx
+Makefile, and in the WWW makefile `CommonMakefile'. Runtime support
+for disabling the facilities is provided by way of the restriction
+`dired_support' which can be set on the command line for a particular
+session.
+
+The Makefile also provides additional compile time flags for
+controlling the extent and application of the file management
+facilities; specifically, `OK_TAR' which enables support for creating
+and expanding tar archives, `OK_GZIP' which enables use of gzip to
+compress and decompress files, and `OK_OVERRIDE' which allows access
+to the file management facilities directly from the keyboard in
+addition to access by way of a file management menu.
+
+There are two possible modes of operation; the first in which a single
+file management menu is invoked via the `f', or `F' key; the second,
+in which the more often used facilities are made available directly
+from the keyboard in addition to access via the menu. The second
+method provides a much better user interface but requires re-mapping
+some of the keys from their standard lynx interpretation, temporarily
+when file management mode is in effect. For example, if OK_OVERRIDE is
+defined at compile-time, then the line at the bottom of the screen, in
+novice mode, will be
+
+ C)reate D)ownload E)dit F)ull menu M)odify R)emove T)ag U)pload
+
+rather than the standard second noviceline,
+
+ H)elp O)ptions P)rint G)o M)ain screen Q)uit /=search [delete]=history list
+
+when the user is browsing part of the file system. If OK_OVERRIDE is not
+defined then all access to file management functionality must be by way
+of the menu. The only exception is that the facility to tag files for
+subsequent removal and/or re-location is always available directly from
+the keyboard using `t', and `T'.
+
+This is a first release of the file management enhancements and suggestions
+for improvements are welcome. Among the enhancements which are currently
+being considered are facilities for changing file access attributes, and
+a facility for listing and extracting part of an archive.
+
+In order to use the file management facilities you may either point
+the program at a directory on the command line or point the program at
+an html file which contains a link of the following form:
+
+ <a href="file://localhost/~/"> Manage Personal Directory ? </a>
+
+where the anchor `file://localhost/~/' implies a reference to
+/home/username. Because the `~/' in a file URL is converted to
+`/home/username' regardless of origin, these facilities also work when
+the anchor shown above is served from an http server as well. In
+either case the reference is to files on the local system and not
+files in the domain of the server.
+
+By default the file listing is in standard Unix mixed format, but you
+may use the Options menu to select WWW `directories first' format, or
+`files first' format if you prefer.
+
+Rick Mallett, Carleton University, Ottawa Canada. (rmallett@ccs.carleton.ca)
diff --git a/gnu/usr.bin/lynx/docs/IBMPC-charsets.announce b/gnu/usr.bin/lynx/docs/IBMPC-charsets.announce
new file mode 100644
index 00000000000..870abe5bf13
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/IBMPC-charsets.announce
@@ -0,0 +1,73 @@
+
+Summary
+=======
+This document is primarily for people who will be using Lynx
+on a remote UNIX or VMS system via an MS-DOS based terminal program.
+
+
+General Information
+===================
+Lynx comes with built-in translation tables to map the 8-bit character codes or
+character entities coming in from an HTML document to their equivalent codes,
+where possible, for various character sets. You should choose display
+character set in Lynx Options Menu according to your font installed locally.
+Please contact lynx-dev mailing list if you want any new codepage not listed
+there.
+
+Note that all points of the connection between the display at your end and Lynx
+at the remote end must be 8-bit clean. If the high bit is being stripped at
+any point in between, the only character set you can use (effectively) in Lynx
+will be "7 bit approximations". More on that later.
+
+
+MS-DOS character set weirdness
+==============================
+MS-DOS uses a bass-ackwards character set in which half the normal characters
+have been replaced by pseudo-graphic line and box-drawing characters, and in
+which almost all of the international characters are mapped to nonstandard
+numbers. It also contains Greek letters.
+
+Further confusing matters, there is more than one MS-DOS character set. The
+character sets are referred to as "codepages," each of which has a unique
+number. IBM PCs and compatibles come with one hardware-based default codepage
+and a keyboard to match. In the US market the hardware codepage is 437. PCs
+destined for other regions of the world often have a different default codepage
+which contains characters for other languages and keyboards. Under MS-DOS, one
+can load different codepages into memory and use one of them instead of the
+hardware default.
+
+If you are using Lynx through an MS-DOS based terminal program or telnet
+client, you should use an appropriate DOS codepage in Lynx and you need not any
+translation within terminal program (this is different from old-style behavior
+and works better because of superior Lynx translation support).
+
+Check your display by accessing Martin Ramsch's ISO-8859-1 table
+(iso8859-1.html in the Lynx distribution's test subdirectory).
+
+Ramsch's table describes each entity and shows examples of each. It should be
+immediately obvious that you are either seeing what you are supposed to, or
+you're not. If you see box and line-drawing characters and mismatched letters
+and so on, you are likely displaying 7 bit data, not 8. Ensure that all points
+of your connection are 8-bit clean:
+
+ On any remote UNIX systems you must pass through, do
+ 'stty cs8 -istrip' or 'stty pass8'. 'stty -a' should list
+ your settings.
+ On any remote VMS systems, do 'set terminal /eightbit'.
+ Make sure your terminal program or telnet client is not filtering
+ 8-bit data. You may found the choice between "VT-100 strict"
+ and "VT-100 relaxed" emulation mode - use relaxed.
+ Note: Procomm for DOS has a confusing "Use 7 bit or 8 bit
+ ANSI" setting -- this has to do with ANSI sequences. If set to
+ 8 bit, some 8-bit character sequences, including those passed
+ by Lynx as well as those which are for your terminal type
+ (vt100, etc.) will be processed by Procomm as ANSI screen
+ control codes and will most likely result in a garbled display.
+ Set it to 7 bit.
+ If going through a dialup terminal server, you may have to set the
+ terminal server itself to pass 8 bit data. How to do this
+ varies with the make of the server, and in some cases only a
+ system admin in charge of the box will have the authorization
+ to do that.
+ SLIP or PPP connections should already be 8-bit clean.
+
diff --git a/gnu/usr.bin/lynx/docs/README.chartrans b/gnu/usr.bin/lynx/docs/README.chartrans
new file mode 100644
index 00000000000..81aedd45760
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/README.chartrans
@@ -0,0 +1,169 @@
+Lynx CHARTRANS
+
+ Features (in addition to those which Lynx 2.7.1 already has):
+
+ - Can (attempt to) translate from any document charset to any display
+ character set, *IF* the document charset is known by a translation
+ table (compiled in at installation).
+
+ - New method to define character sets: used for input charset as well
+ as display character set, translation tables compiled in from
+ separate files (one per charset). One table is designated as default
+ and can be used for fallback translation to 7-bit replacements for
+ display.
+
+ - New method for specifying translations of SGML entities.
+
+ - Unicode (UTF8) support: can (attempt to) decode and translate UTF8 to
+ display character set, or pass through UTF to display (if terminal
+ or console understands UTF8). [raw display of UTF only tested with Slang
+ so far, does not always position everything correctly on screen]
+
+ - Support for CHARSET attribute on A tag (and sometimes LINK), as in HTML
+ i18n RFC 2070 and W3C HTML 4.0 drafts. A link can suggest the target's
+ charset in this way.
+
+ - Support for ACCEPT-CHARSET attribute of FORM tags.
+
+ - EXPERIMENTAL, currently enabled only for Linux console:
+ can (attempt to) automatically switch terminal mode and load new
+ code pages on change of display character set.
+
+ - some minor changes: sometimes invalid characters are displayed in a hex
+ notation Uxxxx (helps debugging, but I also regard it as at least not
+ worse than showing the wrong char without warning).
+
+Additions/changes to user interface:
+
+ - many new Display Character Sets are available on O)ptions screen.
+ (One can use arrow keys, HOME, END etc. for cycling through the list
+ or use selection from popup box, as for other options.)
+
+ - new command line flags:
+ -assume_charset=... assume this as charset for documents that don't
+ specify a charset parameter in HTTP headers
+ -assume_local_charset=... assume this as charset of local file
+ -assume_unrec_charset=... in case a charset parameter is not recognized;
+ docs also available as ASSUME_CHARSET etc. in lynx.cfg
+ In "Advanced User" mode, ASSUME_CHARSET can be changed during a session
+ from the Options Screen.
+
+ - The "Raw" toggle (from -raw flag, '@' key, or Options screen)
+ o toggles the assumption "Default remote charset is same as Display
+ Character Set" on or off.
+ Toggling of the assumed charset is between Display Character Set and
+ the specified ASSUME_CHARSET or, if they are the same, between the
+ specified ASSUME_CHARSET and ISO-8859-1.
+ o The default for raw mode now depends on the Display Character Set as
+ well as on the specified ASSUME_CHARSET value.
+ o should work as before for CJK charsets (turning CJK-mode on or off).
+ o If the effective ASSUME_CHARSET and the Display Character Set are
+ unchanged from the ISO-8859-1 default, toggling "Raw" may have some
+ additional effect for characters that can't be translated.
+ (Try the "Transparent" Display Character Set for more "rawness".)
+
+
+Requirements: same as for Lynx in general :)
+
+The chartrans code is now merged with Wayne Buttle's changes for
+32-bit MS Windows and DOS/DJGPP, with Thomas Dickey's and Jim Spath's
+emerging auto-configure mechanism, and with BUGFIXES from Foteos
+Macrides. See the accompanying file CHANGES.new for the current
+status.
+
+
+A warning:
+In some cases undisplayable bytes may still get sent to the terminal
+which are then interpreted as control chars, there is no protection
+against if strange things are defined in the table files.
+
+
+HOW TO GET SOURCES:
+
+The development code is available at
+ <URL: http://sol.slcc.edu/lynx/current/>
+in various formats.
+
+HOW TO INSTALL:
+
+(4) before compiling:
+
+ Check top level makefile or Makefile and userdefs.h as usual.
+
+ NOTE that there is a new "#define" in userdefs.h for MAX_CHARSETS
+ near the end (in "Section 3.").
+
+(5) Building Lynx:
+
+ Compiling the chartrans code is now integrated into the normal
+ installation procedures for UNIX (configure script) and other
+ platforms.
+
+ What's supposed to happen (in addition to the usual things when
+ building Lynx): in the new subdirectory src/chrtrans, make should
+ first compile the auxiliary program `makeuctb', then invoke that
+ program to create xxxxx_yyy.h files from the provided xxxxx_yyy.tab
+ translation table files. (See README.* files in src/chrtrans for
+ more info.)
+
+ If all goes well, just invoking make from the top-level Lynx dir
+ as usual should do everything automatically. If not, the makefiles
+ may need some tweaking... or:
+
+(6) Some things to look at if compilation fails:
+
+ In src/chrtrans/UCkd.h there is a typedef for an unsigned 16bit
+ numeric type which may need to be changed for your system.
+ See comment near top there.
+
+ For recompiling Lynx, `make clean' should not be necessary if only
+ files in src/chrtrans have been changed. On the other hand
+ may not propagate to the src/chrtrans directory (depending how things
+ are going with auto-config), you may have to cd to that directory
+ and `make clean' there to really clean up there.
+
+(7) To customize (add/change translation tables etc.):
+
+ See README.* files in src/chrtrans.
+ Make the necessary changes there, then recompile.
+ (A general `make clean' should not be necessary, but make sure
+ the ...uni.h file in src/chrtrans gets regenerated.)
+
+ Note that definition of new character entities (if e.g. you want
+ Lynx to recognize &Zcaron;) are not covered by these table files,
+ they have to be listed in entities.h.
+
+ _If you are on a Linux system_ and using Lynx on the console (i.e.
+ not xterm, not a dialup *into* the Linux box), you can compile
+ with -DEXP_CHARTRANS_AUTOSWITCH. This is very useful for testing
+ the various Display Character Sets, Lynx will try to automatically
+ change the console state. You need to have the Linux kbd package
+ installed, with a working `setfont' command executable by the user,
+ and the right font files - check the source in src/UCAuto.c for
+ the files used and/or to change them!
+ NOTE that with this enabled,
+ - Lynx currently will not clean up the console state at exit,
+ it will probably left like the last Display Character Set you used.
+ - Loading a font is global across _all_ virtual text consoles, so
+ using Lynx (compiled with this flag) may change the appearance of
+ text on other consoles (if that text contains characters
+ beyond ASCII).
+
+(8) Some suggested Web pages for testing:
+
+ <URL: http://www.tezcat.com/~kweide/lynx-chartrans/test/>
+
+ <URL: http://www.isoc.org:8080/>,
+ especially
+ <URL: http://www.isoc.org:8080/liste_ml.htm>.
+
+ <URL: http://www.accentsoft.com/un/un-all.htm>
+
+(9) Please report bugs, unexpected behavior, etc.
+ to <lynx-dev@sig.net>.
+
+ Suggestions for improvement would be welcome, as well as
+ contributed translation tables (for stuff that is not available
+ at ftp://dkuug.dk or ftp://ftp.unicode.org).
+
+KW 1997-11-06
diff --git a/gnu/usr.bin/lynx/docs/README.defines b/gnu/usr.bin/lynx/docs/README.defines
new file mode 100644
index 00000000000..5ca9c25b947
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/README.defines
@@ -0,0 +1,113 @@
+This file lists preprocessor macros (symbols) which are tested in the
+code (typically with ifdef).
+
+Does not include
+- symbols defined and documented in userdefs.h
+- symbols expected to be set by compiler to indicate system type or
+ compiler features
+- some symbols set and used only in connection with the ./configure
+ mechanism - the full and current list can be found in config.hin
+ (as a template) or, after running ./configure, in lynx_cfg.h.
+- symbols and macros defined in the source code
+
+***Not complete.***
+
+A. Symbols primarily to enable compilation on specific systems
+==============================================================
+See also under B for things needed by some systems.
+
+# if you have an SVR4 system with the "type any key" problem, try defining
+#
+# -DSVR4_BSDSELECT
+
+# Old Data General systems may need this in their SITE_LYDEFS
+# for their inet_addr(host) calls.
+#
+# -DDGUX_OLD
+
+---
+Ports have been added for Win32 (95/NT) and 386 DOS computers with a
+packet driver. I created four new defines to accomplish this.
+ _WINDOWS Defined for Win32 specific code (Mostly TCP related)
+ DJGPP Defined for 386 specific code (Mostly TCP related)
+ DOSPATH Defined for any DOS'ish computer
+ NOSIGHUP Defined for computers not supporting sighup signal calls.
+-- Wayne Buttles lynx-port@fdisk.com
+
+Added for 8+3 filesystems (DOS):
+ FNAMES_8_3 also defined in userdefs.h if __DJGPP__
+
+B. Symbols to enable or disable specific features, mostly
+=========================================================
+Note that some of these may be only usable on some system types,
+most were originally for UNIX.
+
+Network related, specific protocols
+-----------------------------------
+# -DSOCKS For making a SOCKSified lynx.
+ see comments in makefile.in
+# -DSHORTENED_RBIND For a SOCKSified lynx with the short version of Rbind.
+ see comments in makefile.in
+# -DNOPORT if you must use PASV instead of PORT for FTP
+
+Related to DirEd code - probably one usable for UNIX or similar
+---------------------------------------------------------------
+# -DDIRED_SUPPORT (see INSTALLATION, Section II-1c)
+# -DOK_GZIP (see INSTALLATION, Section II-1c)
+# -DOK_OVERRIDE (see INSTALLATION, Section II-1c)
+# -DOK_PERMIT (see INSTALLATION, Section II-1c)
+# -DOK_TAR (see INSTALLATION, Section II-1c)
+# -DOK_UUDECODE (see INSTALLATION, Section II-1c)
+# -DOK_ZIP (see INSTALLATION, Section II-1c)
+# -DARCHIVE_ONLY (see INSTALLATION, Section II-1c)
+# -DNO_CHANGE_EXECUTE_PERMS (see INSTALLATION, Section II-1c)
+
+Related to formatting of local directory listings
+-------------------------------------------------
+# -DLONG_LIST (see INSTALLATION, Section II-1c)
+# -DNO_PARENT_DIR_REFERENCE (see INSTALLATION, Section II-1c)
+
+Related to screen display
+-------------------------
+Using curses or ncurses library:
+# -DNCURSES (see INSTALLATION, Section II-1c)
+# -DFANCY_CURSES whether curses lib supports more than very basic stuff
+ for UNIX handled by ./configure, for VMS defined in code
+# -DNO_KEYPAD (old) or HAVE_KEYPAD (new) whether curses lib uses keypad().
+ for UNIX handled by ./configure, may be set in HTUtils.h
+# -DCOLOR_CURSES whether curses lib supports color (in the right way).
+ for UNIX handled by ./configure
+# -DUNDERLINE_LINKS Define if you want links underlined instead of bold.
+# -DHP_TERMINAL For DIM workaround to REVERSE problems on HP terminals.
+# -DNO_SIZECHANGE (old) or HAVE_SIZECHANGE (new) whether using code to detect
+ new size after size changes of the terminal (window).
+ for UNIX handled by ./configure, may be set in HTUtils.h
+# -DUSE_SIZECHANGEHACK enable hack to handle increasing the window size
+ above window size at startup
+
+Using slang library:
+# -DUSE_SLANG (see INSTALLATION, Section II-1c)
+# -DSLANG_MBCS_HACK prevent cutoff lines when using UTF8 console (slang only)
+Both:
+# -DREVERSE_CLEAR_SCREEN_PROBLEM
+# if you have the reverse clear screen problem of some SUN4 systems, or
+# to work around some other "garbage on the screen" problems
+
+Related to *experimental* (unsupported) character style code
+------------------------------------------------------------
+# -DUSE_COLOR_STYLE (see INSTALLATION, Section II-1c) probably needs -DNCURSES
+# -DUSE_HASH (see INSTALLATION, Section II-1c) probably needs the above
+# -DLINKEDSTYLES (see INSTALLATION, Section II-1c) probably needs the above
+
+Other
+-----
+# -DDONT_TRACK_INTERNAL_LINKS - Handle following links to same doc differently.
+# -DEXP_CHARTRANS_AUTOSWITCH also let lynx switch term mode(Linux console only)
+# -DIGNORE_CTRL_C Define if Control-C shouldn't exit lynx.
+# -DLY_FIND_LEAKS (see INSTALLATION, Section II-1c)
+# -DNO_CPU_LIMIT Disables Max CPU timeout (includes CLOCKS_PER_SECOND)
+# -DNSL_FORK For fork-based name server lookups that can be 'z'apped.
+# -DSYSLOG_REQUESTED_URLS
+# if you would like logging of client requests via syslog()
+# -DUSE_ZLIB To use some functions from zlib library if you have it.
+# -DDECLARE_WAIS_LOGFILES see comments in makefile.in
diff --git a/gnu/usr.bin/lynx/docs/SOCKETSHR.announce b/gnu/usr.bin/lynx/docs/SOCKETSHR.announce
new file mode 100644
index 00000000000..eda1c7391f8
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/SOCKETSHR.announce
@@ -0,0 +1,67 @@
+LYNX SUPPORT FOR SOCKETSHR/NETLIB 28-AUG-1996
+---------------------------------
+
+
+What is SocketShr?
+------------------
+
+SOCKETSHR is Eckhart Meyer's socket library interface to the MadGoat NETLIB
+package, which provides a vendor-independent interface to the VMS TCP/IP
+transports. Using this, the same image will run over any of the available
+packages, including UCX, Multinet, CMU, Pathway access and TCPWARE.
+
+SocketShr and NETLIB are separately available libraries that MUST be installed
+before LYNX can use them.
+
+
+How to get NETLIB and SOCKETSHR
+-------------------------------
+
+FTP:
+
+ ftp://ftp.kcl.ac.uk/default/socketshr.*
+ ftp://ftp.wku.edu/fileserv/socketshr.zip
+ ftp://ftp.spc.edu/macro32/savesets/socketshr.zip
+
+ ftp://ftp.kcl.ac.uk/madgoat/netlib.*
+ ftp://ftp.wku.edu/madgoat/netlib017.zip
+ ftp://ftp.spc.edu/macro32/savesets/netlib017.zip
+
+
+By E-Mail:
+ send the following commands in a mail message:
+
+ SEND SOCKETSHR.PACKAGE
+ SEND NETLIB.PACKAGE
+
+ To:
+ vmsserv @ kcl.ac.uk
+
+Other server's may also contain these packages.
+
+NETLIB is copyright of MadGoat Software; SOCKETSHR is copyright of Eckhart
+meyer.
+
+
+Preliminary Setup of SOCKETSHR
+------------------------------
+
+Once SOCKETSHR has been installed, TWO logical names should be defined:
+
+ SOCKETSHR Point to the appropriate shareable image
+ SOCKETSHR_LIBRARY Point to the directory containing SOCKETSHR.H
+ and IOCTL.H
+
+Both should be defined /system /exec
+
+
+Building LYNX
+-------------
+
+Run the BUILD.COM procedures and select the SOCKETSHR_TCP option. This will
+build an image that will run over the SOCKETSHR/NETLIB routines.
+
+
+Andy Harper
+Kings College London
+A.Harper@bay.cc.kcl.ac.uk
diff --git a/gnu/usr.bin/lynx/docs/TCPWARE.announce b/gnu/usr.bin/lynx/docs/TCPWARE.announce
new file mode 100644
index 00000000000..899a460e65e
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/TCPWARE.announce
@@ -0,0 +1,30 @@
+ 03-Jun-1994
+
+ The bug associated with using non-blocking socket handling with
+TCPWare's UCX emulation has been traced by Bernie Votz of Process Software
+to their TCPDRIVER.EXE, and has been fixed. The kit is on FTP.PROCESS.COM
+and is called DRIVERS_V405B.INC (it is only valid for TCPware for OpenVMS
+Version 4.0-5, which is the current version at the time of this announcement).
+The fix will be included in the next TCPWare upgrade. If you have problems,
+contact:
+
+ Bernie Volz
+ Process Software Corporation
+ VOLZ@PROCESS.COM
+
+ If you have an old version of TCPWare, and no current Process
+Software support, modify [.WWW.Library.VMS]libmake.com to include NO_IOCTL in
+the $ cc := cc/define=(...) list. You will not be able to interrupt stalled
+connects (i.e., you'll have to wait for those to time out), but you still will
+we able to interrupt long or stalled document transfers via the 'z' command.
+
+ To build for TCPWare, enter @BUILD TCPWARE or just @BUILD
+and then answer the prompt with the appropriate number for that TCPIP
+package.
+
+ Fote
+
+=========================================================================
+ Foteos Macrides Worcester Foundation for Experimental Biology
+ MACRIDES@SCI.WFEB.EDU 222 Maple Avenue, Shrewsbury, MA 01545
+=========================================================================
diff --git a/gnu/usr.bin/lynx/docs/VMSWAIS.announce b/gnu/usr.bin/lynx/docs/VMSWAIS.announce
new file mode 100644
index 00000000000..7253d0db82b
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/VMSWAIS.announce
@@ -0,0 +1,28 @@
+ 03-Jun-1994
+
+ I have added DIRECT_WAIS support for VMS to Lynx. It uses highly
+modified freeWAIS modules, collected into HTVMS_WaisUI.c, HTVMS_WaisUI.h,
+HTVMS_WaisProt.c, and HTVMS_WaisProt.h, interfaced to HTWAIS.c and HTWSRC.c
+of the WWWLib. The socket reads and writes use the code for VMS in the Lynx
+version of the WWWLib, and thus are non-blocking (interruptable via the 'z'
+command), and "already" ported to all the VMS TCPIP packages supported by
+Lynx. All messaging associated with WAIS searches and document fetches go to
+the Lynx statusline as Progress() or Alarm() reports.
+
+ I also prettied up the HTWAIS.c and HTWSRC.c screen displays for both
+VMS and Unix. I've been trying to build in recursive FORM-based interfaces,
+instead of the present iSINDEX-based interfaces, but haven't succeeded ;(.
+
+ The DIRECT_WAIS support is automatic for VMS (i.e., is implemented
+via the BUILD.COM and LIBMAKE.COM procedures, without need to specify anything
+but your TCPIP package, as in the previous, standard VMS builds). Simply
+enter @BUILD <TCPIP package> or enter @BUILD and then the number of
+your TCPIP package in response to the prompt, and you'll have DIRECT_WAIS
+support along with every other wonderful thing in Lynx 8-).
+
+ Fote
+
+=========================================================================
+ Foteos Macrides Worcester Foundation for Experimental Biology
+ MACRIDES@SCI.WFEB.EDU 222 Maple Avenue, Shrewsbury, MA 01545
+=========================================================================
diff --git a/gnu/usr.bin/lynx/docs/win-386.announce b/gnu/usr.bin/lynx/docs/win-386.announce
new file mode 100644
index 00000000000..2f36fb23723
--- /dev/null
+++ b/gnu/usr.bin/lynx/docs/win-386.announce
@@ -0,0 +1,28 @@
+Ports have been added for Win32 (95/NT) and 386 DOS computers with a
+packet driver. I created four new defines to accomplish this.
+
+_WINDOWS Defined for Win32 specific code (Mostly TCP related)
+DJGPP Defined for 386 specific code (Mostly TCP related)
+DOSPATH Defined for any DOS'ish computer
+NOSIGHUP Defined for computers not supporting sighup signal calls.
+
+To make the Win32 version you need Borland C++ 4.52 or complete
+compatable and the win32.zip package unziped into the lynx directory.
+This code expects you to have BC make in your path at the console
+prompt and also to be able to compile from the console as well.
+I can provide an IDE if needed but did not want to force on into the
+standard Lynx package. Text mode compiling is much faster anyhow (IMHO).
+The current default configuration is to have the Character Translation
+code linked in. For this to be successful you need to go into
+src\chrtrans and run makew32. After that you can come back to the
+Lynx root and run make -f makefile.w32.
+
+The DJGPP version is a little screwy. You need DJGPP 2.0, the djgpp.zip
+package unziped into the lynx directory and some paitence. I kludged it
+to compile with long filenames under Win95 so some fooling around may be
+required. To compile, run djgpp.bat that was extracted from the zip
+file. There is currently a problem with compiling HTML.c and I have
+contacted the author of DJGPP for help with getting this port further.
+
+Wayne Buttles
+lynx-port@fdisk.com
diff --git a/gnu/usr.bin/lynx/fixed512.com b/gnu/usr.bin/lynx/fixed512.com
new file mode 100644
index 00000000000..50b50fd5cdc
--- /dev/null
+++ b/gnu/usr.bin/lynx/fixed512.com
@@ -0,0 +1,54 @@
+$! v = 'f$verify(0)'
+$!
+$! FIXED512.COM: Uses the FILE utility or SET FILE/ATTR
+$! to convert binary stream_LF file headers
+$! to FIXED 512.
+$!
+$! Author: F.Macrides (macrides@sci.wfeb.edu)
+$!
+$! Usage: @Lynx_Dir:FIXED512 <stream_LF file that's actually binary>
+$!
+$! Lynx performs the conversion via internal code if the file is
+$! recognized as binary. This command procedure can be used externally
+$! if that detection failed, e.g., for binary files downloaded from FTP
+$! servers with extensions that hadn't been mapped to a binary MIME
+$! type in the Lynx configuration files.
+$!
+$!===========================================================================
+$!
+$! Get and build Joe Meadow's FILE utility for VAX and AXP:
+$! ftp://ftp.wku.edu/vms/fileserv/file.zip
+$! and define it here, or system-wide, as a foreign command.
+$!
+$! FILE := $device:[directory]FILE.EXE
+$!-----------------------------------------------------------
+$!
+$! Just exit and leave the file stream_LF if we didn't get
+$! the filename as P1, or if it's not a valid file spec.
+$!
+$ IF P1 .EQS. "" THEN EXIT
+$ IF F$SEARCH(P1) .EQS. "" THEN EXIT
+$!-----------------------------------------------------------
+$!
+$! If we have FILE installed, use it.
+$!
+$ If f$type(FILE) .eqs. "STRING"
+$ Then
+$ FILE 'P1'-
+ /TYPE=FIXED -
+ /ATTRIBUTES=NOIMPLIEDCC -
+ /CHARACTERISTICS=BEST_TRY_CONTIGUOUS -
+ /RECORD_SIZE=512 -
+ /MAXIMUM_RECORD_SIZE=512
+$ EXIT
+$ EndIf
+$!-----------------------------------------------------------
+$!
+$! If we get to here, and we're VMS v6+,
+$! we'll use SET FILE/ATTR to do it.
+$!
+$ If f$extract(1,1,f$getsyi("VERSION")) .ge. 6
+$ Then
+$ SET FILE/ATTR=(RFM:FIX,LRL:512,MRS:512,RAT:NONE) 'P1'
+$ EndIf
+$ EXIT
diff --git a/gnu/usr.bin/lynx/install.sh b/gnu/usr.bin/lynx/install.sh
new file mode 100644
index 00000000000..ab74c882e92
--- /dev/null
+++ b/gnu/usr.bin/lynx/install.sh
@@ -0,0 +1,238 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/gnu/usr.bin/lynx/lynx.cfg b/gnu/usr.bin/lynx/lynx.cfg
new file mode 100644
index 00000000000..5c73de82f68
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx.cfg
@@ -0,0 +1,1759 @@
+# lynx.cfg file.
+# The default placement for this file is /usr/local/lib/lynx.cfg (Unix)
+# or Lynx_Dir:lynx.cfg (VMS)
+#
+# Definition pairs are of the form VARIABLE:DEFINITION
+# NO spaces are allowed between the pair items.
+#
+# If you do not have access to /usr/local/bin you may change
+# the default location of this file in the userdefs.h file and recompile,
+# or specify it's location on the command line with the "-cfg"
+# command line option.
+#
+# Items may be commented out by putting a '#' as the FIRST char of the line
+#
+# All definitions must be flush left and have NO spaces.!!!
+#
+#
+# STARTFILE is the default URL if none is specified on the command line
+# or via a WWW_HOME environment variable.
+# note: these files can be remote (http://www.w3.org/default.html)
+# or local (file://localhost/PATH_TO/FILENAME
+# replace PATH_TO with the complete path to FILENAME
+# use Unix SHELL syntax and include the device on VMS systems)
+#
+STARTFILE:http://lynx.browser.org/
+
+# HELPFILE must be defined as a URL and must have a
+# complete path if local:
+# file://localhost/PATH_TO/lynx_help/lynx_help_main.html
+# Replace PATH_TO with the path to the lynx_help subdirectory
+# for this distribution (use SHELL syntax including the device
+# on VMS systems).
+# The default HELPFILE is:
+# http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html
+# This should be changed to the local path.
+#
+HELPFILE:http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html
+#HELPFILE:file://localhost/PATH_TO/lynx_help/lynx_help_main.html
+
+# DEFAULT_INDEX_FILE is the default file retrieved when the
+# user presses the 'I' key when viewing any document.
+# An index to your CWIS can be placed here or a document containing
+# pointers to lots of interesting places on the web.
+#
+DEFAULT_INDEX_FILE:http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html
+
+# Set GOTOBUFFER to TRUE if you want to have the previous goto URL,
+# if any, offered for reuse or editing when using the 'g'oto command.
+# The default is defined in userdefs.h. If left FALSE, the circular
+# buffer of previously entered goto URLs can still be invoked via the
+# Up-Arrow or Down-Arrow keys after entering the 'g'oto command.
+#
+#GOTOBUFFER:FALSE
+
+# JUMP_PROMPT is the default statusline prompt for jumps files (see below).
+# You can change the prompt here from that defined in userdefs.h. Any
+# trailing white space will be trimmed, and a single space added by Lynx
+# following the last non-white character. You must set the default prompt
+# before setting the default jumps file (below). If a default jumps file
+# was set via userdefs.h, and you change the prompt here, you must set the
+# default jumps file again (below) for the change to be implemented.
+#
+#JUMP_PROMPT:Jump to (use '?' for list):
+
+# JUMPFILE is the default local file checked for shortcut URL's when
+# the user presses the 'J' (JUMP) key. The user will be prompted for
+# a shortcut entry (analogously to 'g'oto), and can enter one
+# or use '?' for a list of the shortcuts with associated links to
+# their actual URL's. See the sample jumps files in the samples
+# subdirectory. Make sure your jumps file includes a '?' shortcut
+# for a file://localhost URL to itself:
+#
+# <dt>?<dd><a href="file://localhost/path/jumps.html">This Shortcut List</a>
+#
+# If not defined here or in userdefs.h, the JUMP command will invoke
+# the NO_JUMPFILE statusline message (see userdefs.h).
+#
+# On VMS, use Unix SHELL syntax (including a lead slash) to define it.
+#
+# Do not include "file://localhost" in the definition.
+#
+# Additional, alternate jumps files can be defined and mapped to
+# keystrokes at the bottom of lynx.cfg, but you should first define
+# the default jumps file (mapped by default to 'J', and to 'j' when
+# the "VI keys" 'o'ption is not ON) here or in userdefs.h, if you
+# wish to implement the jumps mechanism.
+#
+#JUMPFILE:/Lynx_Dir/jumps.html
+
+# Set JUMPBUFFER to TRUE if you want to have the previous jump target,
+# if any, offered for reuse or editing when using the 'J'ump command.
+# The default is defined in userdefs.h. If left FALSE, the circular
+# buffer of previously entered targets (shortcuts) can still be invoked
+# via the Up-Arrow or Down-Arrow keys after entering the 'J'ump command.
+# If multiple jumps files are installed, the recalls of shortcuts will
+# be specific to each file. If Lynx was built with PERMIT_GOTO_FROM_JUMP
+# defined, any random URLs used instead of shortcuts will be stored in the
+# goto URL buffer, not in the shortcuts buffer(s), and the single character
+# ':' can be used as a target to invoke the goto URL buffer (as if 'g'oto
+# followed by Up-Arrow had been entered).
+#
+#JUMPBUFFER:FALSE
+
+# If SAVE_SPACE is defined, it will be used as a path prefix for the
+# suggested filename in "Save to Disk" operations from the 'p'rint or
+# 'd'ownload menus. On VMS, you can use either VMS (e.g., "SYS$LOGIN:")
+# or Unix syntax (including '~' for the HOME directory). On Unix, you
+# must use Unix syntax. If the symbol is not defined, or is zero-length
+# (""), no prefix will be used, and only a filename for saving in the
+# current default directory will be suggested.
+# This definition will be overridden if a "LYNX_SAVE_SPACE" environment
+# variable has been set on Unix, or logical has been defined on VMS.
+#
+#SAVE_SPACE:~/foo/
+
+# If LYNX_HOST_NAME is defined here or in userdefs.h, it will be
+# treated as an alias for the local host name in checks for URLs on
+# the local host (e.g., when the -localhost switch is set), and this
+# host name, "localhost", and HTHostName (the fully qualified domain
+# name of the system on which Lynx is running) will all be passed as
+# local. A different definition here will override that in userdefs.h.
+#
+#LYNX_HOST_NAME:www.cc.ukans.edu
+
+# localhost aliases
+# Any LOCALHOST_ALIAS definitions also will be accepted as local when
+# the -localhost switch is set. These need not actually be local, i.e.,
+# in contrast to LYNX_HOST_NAME, you can define them to trusted hosts at
+# other Internet sites.
+#
+#LOCALHOST_ALIAS:gopher.server.domain
+#LOCALHOST_ALIAS:news.server.domain
+
+# LOCAL_DOMAIN is used for a tail match with the ut_host element of
+# the utmp or utmpx structure on systems with utmp capabilities, to
+# determine if a user is local to your campus or organization when
+# handling -restrictions=inside_foo or outside_foo settings for ftp,
+# news, telnet/tn3270 and rlogin URLs. An "inside" user is assumed
+# if your system does not have utmp capabilities. CHANGE THIS here
+# if it was not changed in userdefs.h at compilation time.
+#
+#LOCAL_DOMAIN:ukans.edu
+
+# CHARACTER_SET defines the default character set, i.e., that assumed
+# to be installed on the user's terminal. It determines which characters
+# or strings will be used to represent 8-bit character entities within
+# HTML. New character sets may be defined as explained in the README
+# files of the src/chrtrans directory in the Lynx source code distribution.
+# For Asian (CJK) character sets, it also determines how Kanji code will
+# be handled. The default is defined in userdefs.h and can be changed
+# here, and via the 'o'ptions menu. The 'o'ptions menu setting will be
+# stored in the user's RC file whenever those settings are saved, and
+# thereafter will be used as the default. For Lynx a "character set" has
+# two names: a Display Character Set string for the Options screen and
+# for setting CHARACTER_SET here, and a corresponding MIME name (for
+# recognizing properly labelled charset parameters in HTTP headers etc.).
+# Not all Display Character Set names correspond to exactly one valid MIME
+# charset (for example "Chinese", "Transparent"), in that case
+# an appropriate valid (and more specific) MIME name should be used
+# where required. The actions of the -raw switch and LYK_RAW_TOGGLE ('@')
+# are dependent on the character set. For the Asian (CJK) sets the
+# corresponding charset is assumed in documents, i.e., raw or CJK mode is
+# ON by default, so that -raw or the initial LYK_RAW_TOGGLE will turn the
+# mode OFF. The toggling also can be done via the 'o'ptions menu. In raw
+# CJK mode, 8-bit characters are not reverse translated in relation to the
+# entity conversion arrays, i.e., they are assumed to be appropriate for
+# the current character set. It should be toggled OFF when an Asian (CJK)
+# character set is selected but the document is not CJK.
+# The default for "raw mode" (before it is changed by -raw or LYK_RAW_TOGGLE),
+# if the display character set is not a CJK character set, depends on the
+# display character set as well as the ASSUME_CHARSET value (see below) from
+# either this file or an -assume_charset command line option. The mode
+# defaults to ON if the ASSUME_CHARSET value corresponds to the display
+# character set, otherwise to OFF.
+# It can be toggled ON if you believe the document has a charset which does
+# correspond to your Display Character Set, but was not detected to have
+# that charset and was handled as having the default charset (normally
+# iso-8859-1). You also can specify the default charset (to one other
+# than iso-8859-1) via the ASSUME_CHARSET value (see below) from either
+# this file or an -assume_charset command line option. Note that "raw"
+# does not mean that every byte will be passed to the screen. HTML
+# character entities may get expanded and translated, inappropriate control
+# characters filtered out, etc. Raw mode effectively changes the charset
+# assumption about unlabelled documents. There is a "Transparent" pseudo
+# character set for more "rawness".
+#
+# The default character sets include:
+# Display Character Set name MIME name
+# ========================== =========
+# 7 bit approximations us-ascii
+# Chinese euc-cn
+# DEC Multinational dec-mcs
+# DosArabic (cp864) cp864
+# DosBaltRim (cp775) cp775
+# DosCyrillic (cp866) cp866
+# DosGreek (cp737) cp737
+# DosGreek2 (cp869) cp869
+# DosHebrew (cp862) cp862
+# DosLatin1 (cp850) cp850
+# DosLatin2 (cp852) cp852
+# DosLatinUS (cp437) cp437
+# ISO 8859-10 iso-8859-10
+# ISO 8859-5 Cyrillic iso-8859-5
+# ISO 8859-6 Arabic iso-8859-6
+# ISO 8859-7 Greek iso-8859-7
+# ISO 8859-8 Hebrew iso-8859-8
+# ISO 8859-9 (Latin 5) iso-8859-9
+# ISO Latin 1 iso-8859-1
+# ISO Latin 2 iso-8859-2
+# ISO Latin 3 iso-8859-3
+# ISO Latin 4 iso-8859-4
+# Japanese (EUC) euc-jp
+# Japanese (SJIS) shift_jis
+# KOI8-R Cyrillic koi8-r
+# Korean euc-kr
+# Macintosh (8 bit) macintosh
+# NeXT character set next
+# RFC 1345 Mnemonic mnemonic
+# RFC 1345 w/o Intro mnemonic+ascii+0
+# Taipei (Big5) big5
+# Transparent x-transparent
+# UNICODE UTF 8 utf-8
+# Vietnamese (VISCII) viscii
+# WinArabic (cp1256) windows-1256
+# WinBaltRim (cp1257) windows-1257
+# WinCyrillic (cp1251) windows-1251
+# WinGreek (cp1253) windows-1253
+# WinHebrew (cp1255) windows-1255
+# WinLatin1 (cp1252) windows-1252
+# WinLatin2 (cp1250) windows-1250
+#
+#CHARACTER_SET:ISO Latin 1
+
+# ASSUME_CHARSET changes the handling of documents which do not
+# explicitly specify a charset. Normally Lynx assumes that 8-bit
+# characters in those documents are encoded according to iso-8859-1
+# (the official default for the HTTP protocol). When ASSUME_CHARSET
+# given here or by an -assume_charset command line flag is in effect,
+# Lynx will treat documents as if they were encoded accordingly.
+# See above on how this interacts with "raw mode" and the Display
+# Character Set.
+# The value should be the MIME name of a character set recognized by
+# Lynx (case insensitive).
+#
+#ASSUME_CHARSET:iso-8859-1
+
+# ASSUME_LOCAL_CHARSET is like ASSUME_CHARSET but only applies to local
+# files. If no setting is given here or by an -assume_local_charset
+# command line option, the value for ASSUME_CHARSET or -assume_charset
+# is used. It works for both text/plain and text/html files.
+# This option may interfere with "raw mode" toggling when local files
+# are viewed (it is "stronger" than the effective change of the charset
+# assumption caused by changing "raw mode"), so only use when necessary.
+#
+#ASSUME_LOCAL_CHARSET:iso-8859-1
+
+# PREPEND_CHARSET_TO_SOURCE:TRUE allow prepending a META CHARSET
+# to text/html source files when they are retrieved for 'd'ownloading
+# or passed to 'p'rint functions. This is necessary for resolving charset
+# for local html files, while the assume_local_charset just an assumption...
+# For 'd'ownload option charset will be added only if HTTP charset present.
+# The compilation default is FALSE.
+# It is generally desired to have charset information for every
+# local html file, but META CHARSET string may cause
+# compatibility problems with other browsers, so
+# if you use all CHARACTER_SET, ASSUME_CHARSET, ASSUME_LOCAL_CHARSET
+# unchanged from theirs default value iso-8859-1 you usually
+# need not change the compilation default for PREPEND_CHARSET_TO_SOURCE.
+# Note that the prepending is not done for -source dumps.
+#
+#PREPEND_CHARSET_TO_SOURCE:FALSE
+
+# If Lynx encounters a charset parameter it doesn't recognize, it will
+# replace the value given by ASSUME_UNREC_CHARSET (or a corresponding
+# -assume_unrec_charset command line option) for it. This can be used
+# to deal with charsets unknown to Lynx, if they are "sufficiently
+# similar" to one that Lynx does know about, by forcing the same
+# treatment. There is no default, and you probably should leave this
+# undefined unless necessary.
+#
+#ASSUME_UNREC_CHARSET:iso-8859-1
+
+# PREFERRED_LANGUAGE is the language in MIME notation (e.g., "en",
+# "fr") which will be indicated by Lynx in its Accept-Language headers
+# as the preferred language. If available, the document will be
+# transmitted in that language. Users can override this setting via
+# the 'o'ptions menu and save that preference in their RC file.
+# This may be a comma-separated list of languages in decreasing preference.
+#
+#PREFERRED_LANGUAGE:en
+
+# PREFERRED_CHARSET specifies the character set in MIME notation (e.g.,
+# "ISO-8859-2", "ISO-8859-5") which Lynx will indicate you prefer in
+# requests to http servers using an Accept-Charsets header. Users can
+# change it via the 'o'ptions menu and save that preference in their RC file.
+# The value should NOT include "ISO-8859-1" or "US-ASCII",
+# since those values are always assumed by default.
+# If a file in that character set is available, the server will send it.
+# If no Accept-Charset header is present, the default is that any
+# character set is acceptable. If an Accept-Charset header is present,
+# and if the server cannot send a response which is acceptable
+# according to the Accept-Charset header, then the server SHOULD send
+# an error response with the 406 (not acceptable) status code, though
+# the sending of an unacceptable response is also allowed. (RFC2068)
+#
+#PREFERRED_CHARSET:
+
+# URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES are strings which will be
+# prepended (together with a scheme://) and appended to the first element
+# of command line or 'g'oto arguments which are not complete URLs and
+# cannot be opened as a local file (file://localhost/string). Both
+# can be comma-separated lists. Each prefix must end with a dot, each
+# suffix must begin with a dot, and either may contain other dots (e.g.,
+# .com.jp). The default lists are defined in userdefs.h and can be
+# changed here. Each prefix will be used with each suffix, in order,
+# until a valid Internet host is created, based on a successful DNS
+# lookup (e.g., foo will be tested as www.foo.com and then www.foo.edu
+# etc.). The first element can include a :port and/or /path which will
+# be restored with the expanded host (e.g., wfbr:8002/dir/lynx will
+# become http://www.wfbr.edu:8002/dir/lynx). The prefixes will not be
+# used if the first element ends in a dot (or has a dot before the
+# :port or /path), and similarly the suffixes will not be used if the
+# the first element begins with a dot (e.g., .nyu.edu will become
+# http://www.nyu.edu without testing www.nyu.com). Lynx will try to
+# guess the scheme based on the first field of the expanded host name,
+# and use "http://" as the default (e.g., gopher.wfbr.edu or gopher.wfbr.
+# will be made gopher://gopher.wfbr.edu).
+#
+#URL_DOMAIN_PREFIXES:www.
+#URL_DOMAIN_SUFFIXES:.com,.edu,.net,.org
+
+# The following three definitions set the number of seconds for
+# pauses following statusline messages that would otherwise be
+# replaced immediately, and are more important than the unpaused
+# progress messages. Those set by INFOSECS are also basically
+# progress messages (e.g., that a prompted input has been cancelled)
+# and should have the shortest pause. Those set by MESSAGESECS are
+# informational (e.g., that a function is disabled) and should have
+# a pause of intermediate duration. Those set by ALERTSECS typically
+# report a serious problem and should be paused long enough to read
+# whenever they appear (typically unexpectedly). The default values
+# are defined in userdefs.h, and can be modified here should longer
+# pauses be desired for braille-based access to Lynx.
+#
+#INFOSECS:1
+#MESSAGESECS:2
+#ALERTSECS:3
+
+# If USE_SELECT_POPUPS is set FALSE, Lynx will present a vertical list of
+# radio buttons for the OPTIONs in SELECT blocks which lack the MULTIPLE
+# attribute, instead of using a popup menu. Note that if the MULTIPLE
+# attribute is present in the SELECT start tag, Lynx always will create a
+# vertical list of checkboxes for the OPTIONs.
+# The default defined here or in userdefs.h can be changed via the 'o'ptions
+# menu and saved in the RC file, and always can be toggled via the -popup
+# command line switch.
+#
+#USE_SELECT_POPUPS:TRUE
+
+# SHOW_CURSOR controls whether or not the cursor is hidden or appears
+# over the current link in documents or the current option in popups.
+# Showing the cursor is handy if you are a sighted user with a poor
+# terminal that can't do bold and reverse video at the same time or
+# at all. It also can be useful to blind users, as an alternative
+# or supplement to setting LINKS_AND_FORM_FIELDS_ARE_NUMBERED or
+# LINKS_ARE_NUMBERED.
+# The default defined here or in userdefs.h can be changed via the
+# 'o'ptions menu and saved in the RC file, and always can be toggled
+# via the -show_cursor command line switch.
+#
+#SHOW_CURSOR:FALSE
+
+# If BOLD_HEADERS is set to TRUE the HT_BOLD default style will be acted
+# upon for <H1> through <H6> headers. The compilation default is FALSE
+# (only the indentation styles are acted upon, but see BOLD_H1, below).
+# On Unix, compilation with -DUNDERLINE_LINKS also will apply to the
+# HT_BOLD style for headers when BOLD_HEADERS is TRUE.
+#
+#BOLD_HEADERS:FALSE
+
+# If BOLD_H1 is set to TRUE the HT_BOLD default style will be acted
+# upon for <H1> headers even if BOLD_HEADERS is FALSE. The compilation
+# default is FALSE. On Unix, compilation with -DUNDERLINE_LINKS also
+# will apply to the HT_BOLD style for headers when BOLD_H1 is TRUE.
+#
+#BOLD_H1:FALSE
+
+# If BOLD_NAME_ANCHORS is set to TRUE the content of anchors without
+# an HREF attribute, (i.e., anchors with a NAME or ID attribute) will
+# have the HT_BOLD default style. The compilation default is FALSE.
+# On Unix, compilation with -DUNDERLINE_LINKS also will apply to the
+# HT_BOLD style for NAME (ID) anchors when BOLD_NAME_ANCHORS is TRUE.
+#
+#BOLD_NAME_ANCHORS:FALSE
+
+# The DEFAULT_CACHE_SIZE specifies the number of WWW documents to be
+# cached in memory at one time.
+#
+# This so-called cache size (actually, number) is defined in userdefs.h and
+# may be modified here and/or with the command line argument -cache=NUMBER
+# The minimum allowed value is 2, for the current document and at least one
+# to fetch, and there is no absolute maximum number of cached documents.
+# On Unix, and VMS not compiled with VAXC, whenever the number is exceeded
+# the least recently displayed document will be removed from memory.
+#
+# On VMS compiled with VAXC, the DEFAULT_VIRTUAL_MEMORY_SIZE specifies the
+# amount (bytes) of virtual memory that can be allocated and not yet be freed
+# before previous documents are removed from memory. If the values for both
+# the DEFAULT_CACHE_SIZE and DEFAULT_VIRTUAL_MEMORY_SIZE are exceeded, then
+# least recently displayed documents will be freed until one or the other
+# value is no longer exceeded. The default value was defined in userdefs.h.
+#
+# The Unix and VMS but not VAXC implementations use the C library malloc's
+# and calloc's for memory allocation, and procedures for taking the actual
+# amount of cache into account still need to be developed. They use only
+# the DEFAULT_CACHE_SIZE value, and that specifies the absolute maximum
+# number of documents to cache (rather than the maximum number only if
+# DEFAULT_VIRTUAL_MEMORY_SIZE has been exceeded, as with VAXC/VAX).
+#
+#DEFAULT_CACHE_SIZE:10
+#DEFAULT_VIRTUAL_MEMORY_SIZE:512000
+
+# If ALWAYS_RESUBMIT_POSTS is set TRUE, Lynx always will resubmit forms
+# with method POST, dumping any cache from a previous submission of the
+# form, including when the document returned by that form is sought with
+# the PREV_DOC command or via the history list. Lynx always resubmits
+# forms with method POST when a submit button or a submitting text input
+# is activated, but normally retrieves the previously returned document
+# if it had links which you activated, and then go back with the PREV_DOC
+# command or via the history list.
+#
+# The default defined here or in userdefs.h can be toggled via
+# the -resubmit_forms command line switch.
+#
+#ALWAYS_RESUBMIT_POSTS:FALSE
+
+# If NO_ISMAP_IF_USEMAP is set TRUE, Lynx will not include a link to the
+# server-side image map if both a server-side and client-side map for the
+# same image is indicated in the HTML markup. The compilation default is
+# FALSE, such that a link with "[ISMAP]" as the link name, followed by a
+# hyphen, will be prepended to the ALT string or "[USEMAP]" pseudo-ALT for
+# accessing Lynx's text-based rendition of the client-side map (based on
+# the content of the associated MAP element). If the "[ISMAP]" link is
+# activated, Lynx will send a 0,0 coordinate pair to the server, which
+# Lynx-friendly sites can map to a for-text-client document, homologous
+# to what is intended for the content of a FIG element.
+#
+# The compilation default, or default defined here, can be toggled via
+# the "-ismap" command line switch.
+#
+#NO_ISMAP_IF_USEMAP:FALSE
+
+# If SEEK_FRAG_MAP_IN_CUR is set FALSE, then USEMAP attribute values
+# (in IMG or OBJECT tags) consisting of only a fragment (USEMAP="#foo")
+# will be resolved with respect to the current document's base, which
+# might not be the same as the current document's URL.
+# The compilation default is to use the current document's URL in all
+# cases (i.e., assume the MAP is present below, if it wasn't present
+# above the point in the HTML stream where the USEMAP attribute was
+# detected). Lynx's present "single pass" rendering engine precludes
+# checking below before making the decision on how to resolve a USEMAP
+# reference consisting solely of a fragment.
+#
+#SEEK_FRAG_MAP_IN_CUR:TRUE
+
+# If SEEK_FRAG_AREA_IN_CUR is set FALSE, then HREF attribute values
+# in AREA tags consisting of only a fragment (HREF="#foo") will be
+# resolved with respect to the current document's base, which might
+# not be the same as the current document's URL. The compilation
+# default is to use the current document's URL, as is done for the
+# HREF attribute values of Anchors and LINKs that consist solely of
+# a fragment.
+#
+#SEEK_FRAG_AREA_IN_CUR:TRUE
+
+# Local execution links and scripts are completely disabled
+# in the source code unless they are enabled in the
+# userdefs.h file and the sources recompiled. Please
+# see the Lynx source code distribution and the userdefs.h
+# file for more detail on enabling execution links and scripts.
+#
+# If you have enabled execution links or scripts the following
+# two variables control Lynx's action when an execution link
+# or script is encountered.
+#
+# If LOCAL_EXECUTION_LINKS_ALWAYS_ON is set to TRUE any execution
+# link or script will be executed no matter where it came from.
+# This is EXTREMELY dangerous. Since Lynx can access files from
+# anywhere in the world, you may encounter links or scripts that
+# will cause damage or compromise the security of your system.
+#
+# If LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE is set to TRUE only
+# links or scripts that reside on the local machine and are
+# referenced with a URL beginning with "file://localhost/" or meet
+# TRUSTED_EXEC or ALWAYS_TRUSTED_EXEC rules (see below) will be
+# executed. This is much less dangerous than enabling all execution
+# links, but can still be dangerous.
+#
+#LOCAL_EXECUTION_LINKS_ALWAYS_ON:FALSE
+#LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:FALSE
+
+# If LOCAL_EXECUTION_LINK_ON_BUT_NOT_REMOTE is TRUE, and no TRUSTED_EXEC
+# rule is defined, it defaults to "file://localhost/" and any lynxexec
+# or lynxprog command will be permitted if it was referenced with a URL
+# beginning with that string. If you wish to restrict the referencing URL's
+# further, you can extend the string to include a trusted path. You also can
+# specify a trusted directory for http URL's, which will then be treated as
+# if they were local rather than remote. For example:
+#
+# TRUSTED_EXEC:file://localhost/trusted/
+# TRUSTED_EXEC:http://www.wfbr.edu/trusted/
+#
+# If you also wish to restrict the commands which can be executed, create
+# a series of rules with the path (Unix) or command name (VMS) following
+# the string, separated by a tab. For example:
+#
+# Unix:
+# TRUSTED_EXEC:file://localhost/<tab>/bin/cp
+# TRUSTED_EXEC:file://localhost/<tab>/bin/rm
+# VMS:
+# TRUSTED_EXEC:file://localhost/<tab>copy
+# TRUSTED_EXEC:file://localhost/<tab>delete
+#
+# Once you specify a TRUSTED_EXEC referencing string, the default is
+# replaced, and all the referencing strings you desire must be specified
+# as a series. Similarly, if you associate a command with the referencing
+# string, you must specify all of the allowable commands as a series of
+# TRUSTED_EXEC rules for that string. If you specify ALWAYS_TRUSTED_EXEC
+# rules below, you need not repeat them as TRUSTED_EXEC rules.
+#
+# If EXEC_LINKS and JUMPFILE have been defined, any lynxexec or lynxprog
+# URL's in that file will be permitted, regardless of other settings. If
+# you also set LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:TRUE and a single
+# TRUSTED_EXEC rule that will always fail (e.g., "none"), then *ONLY* the
+# lynxexec or lynxprog URL's in JUMPFILE (and any ALWAYS_TRUSTED_EXEC rules,
+# see below) will be allowed. Note, however, that if Lynx was compiled with
+# CAN_ANONYMOUS_JUMP set to FALSE (default is TRUE), or -restrictions=jump
+# is included with the -anonymous switch at run time, then users of an
+# anonymous account will not be able to access the jumps file or enter
+# 'j'ump shortcuts, and this selective execution feature will be overridden
+# as well (i.e., they will only be able to access lynxexec or lynxprog
+# URLs which meet any ALWAYS_TRUSTED_EXEC rules).
+#
+#TRUSTED_EXEC:none
+
+# If EXEC_LINKS was defined, any lynxexec or lynxprog URL can be made
+# always enabled by an ALWAYS_TRUSTED_EXEC rule for it. This is useful for
+# anonymous accounts in which you have disabled execution links generally,
+# and may also have disabled jump file links, but still want to allow
+# execution of particular utility scripts or programs. The format is
+# like that for TRUSTED_EXEC. For example:
+#
+# Unix:
+# ALWAYS_TRUSTED_EXEC:file://localhost/<tab>/usr/local/kinetic/bin/usertime
+# ALWAYS_TRUSTED_EXEC:http://www.more.net/<tab>/usr/local/kinetic/bin/who.sh
+# VMS:
+# ALWAYS_TRUSTED_EXEC:file://localhost/<tab>usertime
+# ALWAYS_TRUSTED_EXEC:http://www.more.net/<tab>show users
+#
+# The default ALWAYS_TRUSTED_EXEC rule is "none".
+#
+#ALWAYS_TRUSTED_EXEC:none
+
+# Unix:
+# =====
+# TRUSTED_LYNXCGI rules define the permitted sources and/or paths for
+# lynxcgi links (if LYNXCGI_LINKS is defined in userdefs.h). The format
+# is the same as for TRUSTED_EXEC rules (see above), but no defaults are
+# defined, i.e., if no TRUSTED_LYNXCGI rules are defined here, any source
+# and path for lynxcgi links will be permitted. Example rules:
+#
+# TRUSTED_LYNXCGI:file://localhost/
+# TRUSTED_LYNXCGI:<tab>/usr/local/etc/httpd/cgi-bin/
+# TRUSTED_LYNXCGI:file://localhost/<tab>/usr/local/www/cgi-bin/
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#TRUSTED_LYNXCGI:none
+
+# Unix:
+# =====
+# LYNXCGI_ENVIRONMENT adds the current value of the specified
+# environment variable to the list of environment variables passed on to the
+# lynxcgi script. Useful variables are HOME, USER, EDITOR, etc...
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#LYNXCGI_ENVIRONMENT:
+
+# Unix:
+# =====
+# LYNXCGI_DOCUMENT_ROOT is the value of DOCUMENT_ROOT that will be passed
+# to lynxcgi scripts. If set and the URL has PATH_INFO data, then
+# PATH_TRANSLATED will also be generated. Examples:
+# LYNXCGI_DOCUMENT_ROOT:/usr/local/etc/httpd/htdocs
+# LYNXCGI_DOCUMENT_ROOT:/data/htdocs/
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#LYNXCGI_DOCUMENT_ROOT:
+
+# If FORCE_SSL_COOKIES_SECURE is set to TRUE, then SSL encrypted cookies
+# received from https servers never will be sent unencrypted to http
+# servers. The compilation default is to impose this block only if the
+# https server included a secure attribute for the cookie. The normal
+# default or that defined here can be toggled via the -force_secure
+# command line switch.
+#
+#FORCE_SSL_COOKIES_SECURE:FALSE
+
+# MAIL_SYSTEM_ERROR_LOGGING will send a message to the owner of
+# the information, or ALERTMAIL if there is no owner, every time
+# that a document cannot be accessed!
+#
+# NOTE: This can generate A LOT of mail, be warned.
+#
+#MAIL_SYSTEM_ERROR_LOGGING:FALSE
+
+# If CHECKMAIL is set to TRUE, the user will be informed (via a statusline
+# message) about the existence of any unread mail at startup of Lynx, and
+# will get statusline messages if subsequent new mail arrives. If a jumps
+# file with a lynxprog URL for invoking mail is available, or your html
+# pages include an mail launch file URL, the user thereby can access mail
+# and read the messages. The checks and statusline reports will not be
+# performed if Lynx has been invoked with the -restrictions=mail switch.
+#
+# VMS USERS !!!
+# New mail is normally broadcast as it arrives, via "unsolicited screen
+# broadcasts", which can be "wiped" from the Lynx display via the Ctrl-W
+# command. You may prefer to disable the broadcasts and use CHECKMAIL
+# instead (e.g., in a public account which will be used by people who
+# are ignorant about VMS).
+#
+#CHECKMAIL:FALSE
+
+# To enable news reading ability via Lynx, the environment variable NNTPSERVER
+# must be set so that it points to your site's NNTP server (see INSTALLATION).
+# Lynx respects RFC 1738 (http://www.ics.uci.edu/pub/ietf/uri/rfc1738.txt) and
+# and does not accept a host field in news URLs (use nntp: instead news: for
+# the scheme if you wish to specify an NNTP host in a URL, as explained in the
+# RFC). If you have not set the variable externally, you can set it at run
+# time via this configuration file. It will not override an external setting.
+# Note that on VMS it is set as a process logical rather than symbol, and will
+# outlive the Lynx image.
+#
+#NNTPSERVER:news.server.dom
+
+# If LIST_NEWS_NUMBERS is set TRUE, Lynx will use an ordered list and include
+# the numbers of articles in news listings, instead of using an unordered
+# list. The default is defined in userdefs.h, and can be overridden here.
+#
+#LIST_NEWS_NUMBERS:FALSE
+
+# If LIST_NEWS_DATES is set TRUE, Lynx will include the dates of articles in
+# news listings. The dates always are included in the articles, themselves.
+# The default is defined in userdefs.h, and can be overridden here.
+#
+#LIST_NEWS_DATES:FALSE
+
+# NEWS_CHUNK_SIZE and NEWS_MAX_CHUNK regulate the chunking of news article
+# listings with inclusion of links for listing earlier and/or later articles.
+# The defaults are defined in HTNews.c as 30 and 40, respectively. If the
+# news group contains more than NEWS_MAX_CHUNK articles, they will be listed
+# in NEWS_CHUNK_SIZE chunks. You can change the defaults here, and/or on
+# the command line via -newschunksize=NUMBER and/or -newsmaxchunk=NUMBER
+# switches. Note that if the chunk size is increased, here or on the command
+# line, to a value greater than the current maximum, the maximum will be
+# increased to that number. Conversely, if the maximum is set to a number
+# less than the current chunk size, the chunk size will be reduced to that
+# number. Thus, you need use only one of the two switches on the command
+# line, based on the direction of intended change relative to the compilation
+# or configuration defaults. The compilation defaults ensure that there will
+# be at least 10 earlier articles before bothering to chunk and create a link
+# for earlier articles.
+#
+#NEWS_CHUNK_SIZE:30
+#NEWS_MAX_CHUNK:40
+
+# Set NEWS_POSTING to FALSE if you do not want to support posting to
+# news groups via Lynx. If left TRUE, Lynx will use its news gateway to
+# post new messages or followups to news groups, using the URL schemes
+# described in the "Supported URL" section of the online 'h'elp. The
+# posts will be attempted via the nntp server specified in the URL, or
+# if none was specified, via the NNTPSERVER configuration or environment
+# variable. Links with these URLs for posting or sending followups are
+# created by the news gateway when reading group listings or articles
+# from nntp servers if the server indicates that it permits posting.
+# The compilation default set in userdefs.h can be changed here. If
+# the default is TRUE, posting can still be disallowed via the
+# -restrictions command line switch.
+#
+#NEWS_POSTING:TRUE
+
+# LYNX_SIG_FILE defines the name of a file containing a signature which
+# can be appended to email messages and news postings or followups. The
+# user will be prompted whether to append it. It is sought in the home
+# directory. If it is in a subdirectory, begin it with a dot-slash
+# (e.g., ./lynx/.lynxsig). The definition is set in userdefs.h and can
+# be changed here.
+#
+#LYNX_SIG_FILE:.lynxsig
+
+# If USE_MOUSE is set TRUE, Lynx (when configured with ncurses) will allow
+# the user to click with button-1 on links to select them.
+#USE_MOUSE: FALSE
+
+# If COLLAPSE_BR_TAGS is set FALSE, Lynx will not collapse serial BR tags.
+# Note that the valid way to insert extra blank lines in HTML is via a PRE
+# block with only newlines in the block.
+# The default is defined in userdefs.h, and can be overridden here.
+#
+#COLLAPSE_BR_TAGS:TRUE
+
+# If SET_COOKIES is set FALSE, Lynx will ignore Set-Cookie headers
+# in http server replies.
+# The default is defined in userdefs.h, and can be overridden here,
+# and/or toggled via the -cookies command line switch.
+#
+#SET_COOKIES:TRUE
+
+# VMS:
+#=====
+# The mail command and qualifiers are defined in userdefs.h. Lynx
+# will spawn a subprocess to send replies and error messages. The
+# command, and qualifiers (if any), can be re-defined here. If
+# you use PMDF then headers will we passed via a header file.
+# If you use "generic" VMS MAIL, the subject will be passed on the
+# command line via a /subject="SUBJECT" qualifier, and inclusion
+# of other relevant headers may not be possible.
+# If your mailer uses another syntax, some hacking of the mailform()
+# mailmsg() and reply_by_mail() functions in LYMail.c, and printfile()
+# function in LYPrint.c, may be required.
+#
+#SYSTEM_MAIL:PMDF SEND
+#SYSERM_MAIL_FLAGS:/headers
+#
+#SYSTEM_MAIL:MAIL
+#SYSTEM_MAIL_FLAGS:
+
+# Unix:
+#======
+# The mail path and flags normally are defined for sendmail (or submit
+# with MMDF) in userdefs.h. You can change them here, but should first
+# read the zillions of CERT advisories about security problems with Unix
+# mailers.
+#
+#SYSTEM_MAIL:/usr/mmdf/bin/submit
+#SYSTEM_MAIL_FLAGS:-mlruxto,cc\*
+#
+#SYSTEM_MAIL:/usr/sbin/sendmail
+#SYSTEM_MAIL_FLAGS:-t -oi
+#
+#SYSTEM_MAIL:/usr/lib/sendmail
+#SYSTEM_MAIL_FLAGS:-t -oi
+
+# VMS ONLY:
+#==========
+# MAIL_ADRS is defined in userdefs.h and normally is structured for PMDF's
+# IN%"INTERNET_ADDRESS" scheme. The %s is replaced with the address given
+# by the user. If you are using a different Internet mail transport, change
+# the IN appropriately (e.g., to SMTP, MX, or WINS).
+#
+#MAIL_ADRS:"IN%%""%s"""
+
+# VMS ONLY:
+#==========
+# If USE_FIXED_RECORDS is set to TRUE here or in userdefs.h, Lynx will
+# convert 'd'ownloaded binary files to FIXED 512 record format before saving
+# them to disk or acting on a DOWNLOADER option. If set to FALSE, the
+# headers of such files will indicate that they are Stream_LF with Implied
+# Carriage Control, which is incorrect, and can cause downloading software
+# to get confused and unhappy. If you do set it FALSE, you can use the
+# FIXED512.COM command file, which is included in this distribution, to do
+# the conversion externally.
+#
+#USE_FIXED_RECORDS:TRUE
+
+# VI_KEYS can be turned on by the user in the options
+# screen or the .lynxrc file. This is just the default.
+#
+#VI_KEYS_ALWAYS_ON:FALSE
+
+# EMACS_KEYS can be turned on by the user in the options
+# screen or the .lynxrc file. This is just the default.
+#
+#EMACS_KEYS_ALWAYS_ON:FALSE
+
+# DEFAULT_KEYPAD_MODE specifies whether by default the user
+# has numbers that work like arrows or else numbered links.
+# DEFAULT KEYPAD MODE may be set to TRUE for using numbers
+# as arrows as the default, or FALSE for using numbered links
+# as the default (LINKS_AND_FORM_FIELDS_ARE_NUMBERED cannot
+# currently be set by this option.).
+#
+#DEFAULT_KEYPAD_MODE_IS_NUMBERS_AS_ARROWS:TRUE
+
+# The default search type.
+# This is a default that can be overridden by the user!
+#
+#CASE_SENSITIVE_ALWAYS_ON:FALSE
+
+# DEFAULT_BOOKMARK_FILE is a default filename for use as a personal
+# bookmark file. It will reference a file from the user's home directory.
+# NOTE that a file ending in .html or other suffix mapped to text/html
+# should be used to ensure it's treatment as HTML. The built-in default
+# is lynx_bookmarks.html. On both Unix and VMS, if a subdirectory off of
+# the HOME directory is desired, the path should begin with "./" (e.g.,
+# ./BM/lynx_bookmarks.html), but the subdirectory must already exist.
+# Lynx will create the bookmark file, if it does not already exist, on
+# the first ADD_BOOKMARK attempt if the HOME directory is indicated
+# (i.e., if the definition is just filename.html without any slashes),
+# but requires a pre-existing subdirectory to create the file there.
+# The user can re-define the default bookmark file, as well as a set
+# of sub-bookmark files if multiple bookmark file support is enabled
+# (see below), via the 'o'ptions menu, and can save those definitions
+# in the .lynxrc file.
+#
+#DEFAULT_BOOKMARK_FILE:lynx_bookmarks.html
+
+# If MULTI_BOOKMARK_SUPPORT is set TRUE, and BLOCK_MULTI_BOOKMARKS (see
+# below) is FALSE, and sub-bookmarks exist, all bookmark operations will
+# first prompt the user to select an active sub-bookmark file or the
+# default bookmark file. FALSE is the default so that one (the default)
+# bookmark file will be available initially. The definition here will
+# override that in userdefs.h. The user can turn on multiple bookmark
+# support via the 'o'ptions menu, and can save that choice as the startup
+# default via the .lynxrc file. When on, the setting can be STANDARD or
+# ADVANCED. If support is set to the latter, and the user mode also is
+# ADVANCED, the VIEW_BOOKMARK command will invoke a statusline prompt at
+# which the user can enter the letter token (A - Z) of the desired bookmark,
+# or '=' to get a menu of available bookmark files. The menu always is
+# presented in NOVICE or INTERMEDIATE mode, or if the support is set to
+# STANDARD. No prompting or menu display occurs if only one (the startup
+# default) bookmark file has been defined (define additional ones via the
+# 'o'ptions menu). The startup default, however set, can be overridden on
+# the command line via the -restrictions=multibook or the -anonymous or
+# -validate switches.
+#
+#MULTI_BOOKMARK_SUPPORT:FALSE
+
+# If BLOCK_MULTI_BOOKMARKS is set TRUE, multiple bookmark support will
+# be forced off, and cannot to toggled on via the 'o'ptions menu. The
+# compilation setting is normally FALSE, and can be overridden here.
+# It can also be set via the -restrictions=multibook or the -anonymous
+# or -validate command line switches.
+#
+#BLOCK_MULTI_BOOKMARKS:FALSE
+
+# DEFAULT_USER_MODE sets the default user mode for Lynx users.
+# NOVICE shows a three line help message at the bottom of the screen
+# INTERMEDIATE shows normal amount of help (one line)
+# ADVANCED help is replaced by the URL of the current link
+#
+#DEFAULT_USER_MODE:NOVICE
+
+# DEFAULT_EDITOR sets the default editor for Lynx users.
+# If an editor is defined then the user may edit local documents
+# using that editor. The editor will also be used for sending
+# mail messages. If no editor is defined here or by the user
+# the user will not be able to edit local documents and a primitive
+# line oriented mail input mode will be used.
+# NOTE: Do not define an editor unless you know that every user will
+# know how to use it. Most users do not enjoy getting stuck in
+# an unknown editor that they can't get out of. Users can
+# easily define an editor of their own using the options menu,
+# so it is not always desirable to set the DEFAULT_EDITOR.
+#
+#DEFAULT_EDITOR:
+
+# SYSTEM_EDITOR behaves the same as DEFAULT_EDITOR except that it can't be
+# changed.
+#
+#SYSTEM_EDITOR:
+
+# Proxy variables
+# Lynx version 2.2 and beyond supports the use of proxy servers that can
+# act as firewall gateways and caching servers. They are preferable to
+# the older gateway servers. Each protocol used by Lynx can be mapped
+# separately using PROTOCOL_proxy environment variables (see INSTALLATION).
+# If you have not set them externally, you can set them at run time via
+# this configuration file. They will not override external settings.
+# The no_proxy variable can be a comma-separated list of hosts which should
+# not be proxied, or an asterisk to override all proxy variables.
+# Note that on VMS they are set as process logicals rather than symbols,
+# to preserve lowercasing, and will outlive the Lynx image.
+#
+#http_proxy:http://some.server.dom:port/
+#https_proxy:http://some.server.dom:port/
+#ftp_proxy:http://some.server.dom:port/
+#gopher_proxy:http://some.server.dom:port/
+#news_proxy:http://some.server.dom:port/
+#newspost_proxy:http://some.server.dom:port/
+#newsreply_proxy:http://some.server.dom:port/
+#snews_proxy:http://some.server.dom:port/
+#snewspost_proxy:http://some.server.dom:port/
+#snewsreply_proxy:http://some.server.dom:port/
+#nntp_proxy:http://some.server.dom:port/
+#wais_proxy:http://some.server.dom:port/
+#finger_proxy:http://some.server.dom:port/
+#cso_proxy:http://some.server.dom:port/
+#no_proxy:host.domain.dom
+
+# Printer definitions
+# any number of printers may be defined by using multiple
+# printer definition sets. Printers may be any program
+# that could be useful to your users, they do not necessarily
+# have to print.
+#
+# the definition of a printer is of the form
+# PRINTER:<printer name>:<printer command>:<printer option>:<lines/page>
+#
+# <printer name> is the name that the user will see.
+# <printer command> is the command line arguments for printing a file.
+# The %s will be replaced with the file being printed.
+# If a second %s is given the second %s will be replaced by
+# a suggested filename that is prettier than the tempfile
+# name given in the first %s. This does not remove the first
+# %s from the command line in any manner. If you need to
+# use only the second %s file name in your printer command,
+# then I suggest creating a script which will first copy the
+# first %s file name to the second %s file name, and then
+# executing your print command with the second %s file name.
+# <printer option> specifies whether the printer should be disabled for
+# users without printing options. The options are
+# TRUE or FALSE;
+# TRUE means the printer will always be ENABLED
+# regardless of printer or anonymous settings
+# FALSE means the printer will be DISABLED when
+# the -noprint option is on, or for anonymous
+# users which are not allowed to print
+#
+# <lines/page> is an optional parameter for indicating the number of
+# lines per page for the printer. Defaults to 66. Used
+# for computing the approximate number of pages and
+# generating a statusline query of whether to proceed if
+# the document is longer than 4 printer pages. Uses the
+# current screen length for the computation when the
+# built in "print to screen" option is selected.
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# If you have a very busy VMS print queue and Lynx deletes the temporary
+# files before they have been queued, use the VMSPrint.com included in
+# the distribution.
+#
+# examples
+#PRINTER:Computer Center printer:lpr -Pccprt %s:FALSE
+#PRINTER:Office printer:lpr -POffprt %s:TRUE
+#PRINTER:VMS printer:print /queue=cc$print %s:FALSE:58
+#PRINTER:Busy VMS printer:@Lynx_Dir\:VMSPrint sys$print %s:FALSE:58
+# Check out the lpansi program in utils/ for printing on vt100
+# attached printers.
+#PRINTER:Use vt100 print sequence to print from your local terminal:lpansi %s:TRUE
+# Don't use the following printer on anonymous accounts since
+# allowing shell input is very dangerous.
+#PRINTER:Specify your own print command:echo -n "Enter a print command\: "; read word; sh -c "$word %s":FALSE
+# Pass to a sophisticated file viewer (sources for most are available in
+# ftp://space.mit.edu/pub/davis/most). The most -k switch suppresses the
+# invocation of hexadecimal display mode if 8-bit or control characters
+# are present. The +s switch invokes secure mode.
+#PRINTER:Use Most to view:most -k +s %s:TRUE:23
+
+# Downloader definitions
+# any number of downloaders may be defined by using multiple
+# downloader definition sets. Downloaders may be any program
+# that could be useful to your users, they do not necessarily
+# have to be a download protocol program. The most common use
+# of a downloader is to use Ckermit or some other transfer
+# program so that the user may easily transfer files back to
+# their local machine over a serial link.
+#
+# the definition of a downloader is of the form
+# DOWNLOADER:<downloadername>:<downloader command>:<downloader option>
+#
+# <downloader name> is the name that the user will see.
+# <downloader command> is the command line arguments for downloading a file.
+# The %s will be replaced with the file being downloaded.
+# If a second %s is given the second %s will be replaced
+# by a suggested filename that is nicer than the tempfile
+# name given in the first %s. This does not replace the
+# first %s in the command line. If your command needs
+# the suggest file name on the command line only, then
+# I suggest creating a script that will first copy the
+# first %s file name to the second %s file name, and then
+# execute the downloading command using the second %s file
+# name (e.g., 'sz' needs such a script interposed).
+# <downloader option> specifies whether the downloader should be disabled for
+# anonymous users. The options are
+# TRUE or FALSE;
+# TRUE means the downloader will always be ENABLED
+# regardless of the anonymous settings (however,
+# all downloading is disabled by -validate).
+# FALSE means the downloader will be DISABLED when
+# the user is anonymous.
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# examples
+#DOWNLOADER:Use Most to view:most +s %s:TRUE
+# (don't use most's -k switch, so that binaries will invoke hexadecimal mode)
+#DOWNLOADER:Use Kermit to download to the local terminal:kermit -i -s %s -a %s:TRUE
+#DOWNLOADER:Use Zmodem to download to the local terminal:sz %s:TRUE
+#DOWNLOADER:Use Zmodem to download to the local terminal:set %s %s;td=/tmp/Lsz$$;mkdir $td;ln -s $1 $td/"$2";sz $td/"$2";rm -r $td:TRUE
+#
+# Note for Zmodem: The first variant gives wrong filenames ("sz" doesn't support
+# a suggested filename parameter, sorry). The second returns correct filenames
+# but may conflict with very strong security or permissions restrictions
+# (it uses the script to make a subdirectory in /tmp, see below).
+# (example script in lieu of :sz %s: for offering a suggested filename)
+# :set %s %s;td=/tmp/Lsz$$;mkdir $td;ln -s $1 $td/"$2";sz $td/"$2";rm -r $td:
+#
+
+# Unix ONLY:
+#===========
+# Uploader definitions (implemented only with Unix DIRED_SUPPORT;
+# see the Makefile in the top directory,
+# and the header of ./src/LYUpload.c)
+# any number of uploaders may be defined by using multiple
+# uploader definition sets. Uploaders may be any program
+# that could be useful to your users, they do not necessarily
+# have to be an upload protocol program. The most common use
+# of an uploader is to use Ckermit or some other transfer
+# program so that the user may easily transfer files from
+# their local machine over a serial link.
+#
+# the definition of an uploader is of the same form as a downloader
+# UPLOADER:<uploadername>:<uploader command>:<uploader option>
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# If you do not include a %s, you will not be prompted for an
+# output filename.
+#
+# example
+#UPLOADER:Use Kermit to upload from your computer: kermit -i -r -a %s:TRUE
+
+# If NO_DOT_FILES is TRUE (normal default via userdefs.h), the user will not
+# be allowed to specify files beginning with a dot in reply to output filename
+# prompts, and files beginning with a dot (e.g., file://localhost/path/.lynxrc)
+# will not be included in the directory browser's listings. If set FALSE, you
+# can force it to be treated as TRUE via -restrictions=dotfiles. If set FALSE
+# and not forced TRUE, the user can regulate it via the 'o'ptions menu (and
+# may save the preference in the RC file).
+#
+#NO_DOT_FILES:TRUE
+
+# If NO_FROM_HEADER is set FALSE, From headers will be sent in transmissions
+# to http or https servers if the personal_mail_address has been defined via
+# the 'o'ptions menu. The compilation default is TRUE (no From header is
+# sent) and the default can be changed here. The default can be toggled at
+# run time via the -from switch. Note that transmissions of From headers
+# have become widely considered to create an invasion of privacy risk.
+#
+#NO_FROM_HEADER:TRUE
+
+# If NO_REFERER_HEADER is TRUE, Referer headers never will be sent in
+# transmissions to servers. Lynx normally sends the URL of the document
+# from which the link was derived, but not for startfile URLs, 'g'oto
+# URLs, 'j'ump shortcuts, bookmark file links, history list links, or
+# URLs that include the content from form submissions with method GET.
+# If left FALSE here, it can be set TRUE at run time via the -noreferer
+# switch.
+#
+#NO_REFERER_HEADER:FALSE
+
+# If NO_FILE_REFERER is TRUE, Referer headers never will be sent in
+# transmissions to servers for links or actions derived from documents
+# or forms with file URLs. This would ensure that paths associated
+# with the local file system are never indicated to servers, even if
+# NO_REFERER_HEADER is FALSE. If left FALSE here, it can be set TRUE
+# at run time via the -nofilereferer switch.
+#
+#NO_FILE_REFERER:FALSE
+
+# If MAKE_LINKS_FOR_ALL_IMAGES is TRUE, all images will be given links
+# which can be ACTIVATEd. For inlines, the ALT or pseudo-ALT ("[INLINE]")
+# strings will be links for the resolved SRC rather than just text. For
+# ISMAP or other graphic links, the ALT or pseudo-ALT ("[ISMAP]" or "[LINK]")
+# strings will have '-' and a link labeled "[IMAGE]" for the resolved SRC
+# appended.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can use LYK_IMAGE_TOGGLE to toggle the feature on or off at run time.
+#
+# The default also can be toggled via an "-image_links" command line switch.
+#
+#MAKE_LINKS_FOR_ALL_IMAGES:FALSE
+
+# If MAKE_PSEUDO_ALTS_FOR_INLINES is FALSE, inline images which do not
+# specify an ALT string will not have "[INLINE]" inserted as a pseudo-ALT,
+# i.e., they'll be treated as having ALT="". If MAKE_LINKS_FOR_ALL_IMAGES
+# is defined or toggled to TRUE, however, the pseudo-ALTs will be created
+# for inlines, so that they can be used as links to the SRCs.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can use LYK_INLINE_TOGGLE to toggle the feature on or off at run time.
+#
+# The default also can be toggled via a "-pseudo_inlines" command line
+# switch.
+#
+#MAKE_PSEUDO_ALTS_FOR_INLINES:TRUE
+
+# If SUBSTITUTE_UNDERSCORES is TRUE, the _underline_ format will be used
+# for emphasis tags in dumps.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can toggle the default via a "-underscore" command line switch.
+#
+#SUBSTITUTE_UNDERSCORES:FALSE
+
+# If QUIT_DEFAULT_YES is TRUE then when the QUIT command is entered, any
+# response other than n or N will confirm. It should be FALSE if you
+# prefer the more conservative action of requiring an explicit Y or y to
+# confirm. The default defined here will override that in userdefs.h.
+#
+#QUIT_DEFAULT_YES:TRUE
+
+# If HISTORICAL_COMMENTS is TRUE, Lynx will revert to the "Historical"
+# behavior of treating any '>' as a terminator for comments, instead of
+# seeking a valid '-->' terminator (note that white space can be present
+# between the '--' and '>' in valid terminators). The compilation default
+# is FALSE.
+#
+# The compilation default, or default defined here, can be toggled via a
+# "-historical" command line switch, and via the LYK_HISTORICAL command key.
+#
+#HISTORICAL_COMMENTS:FALSE
+
+# If MINIMAL_COMMENTS is TRUE, Lynx will not use Valid comment parsing
+# of '--' pairs as serial comments within an overall comment element,
+# and instead will seek only a '-->' terminator for the overall comment
+# element. This emulates the Netscape v2.0 comment parsing bug, and
+# will help Lynx cope with the use of dashes as "decorations", which
+# consequently has become common in so-called "Enhanced for Netscape"
+# pages. Note that setting Historical comments on will override the
+# Minimal or Valid setting.
+#
+# The compilation default for MINIMAL_COMMENTS is FALSE, but we'll
+# set it TRUE here, until Netscape gets its comment parsing right,
+# and "decorative" dashes cease to be so common.
+#
+# The compilation default, or default defined here, can be toggled via a
+# "-minimal" command line switch, and via the LYK_MINIMAL command key.
+#
+MINIMAL_COMMENTS:TRUE
+
+# If SOFT_DQUOTES is TRUE, Lynx will emulate the invalid behavior of
+# treating '>' as a co-terminator of a double-quoted attribute value
+# and the tag which contains it, as was done in old versions of Netscape
+# and Mosaic. The compilation default is FALSE.
+#
+# The compilation default, or default defined here, can be toggled via
+# a "-soft_dquotes" command line switch.
+#
+#SOFT_DQUOTES:FALSE
+
+# If STRIP_DOTDOT_URLS is TRUE, Lynx emulates the invalid behavior of many
+# browsers to strip a leading "../" segment from relative URLs in HTML
+# documents with a http or https base URL, if this would otherwise lead to
+# an absolute URLs with those characters still in it. Such URLs are normally
+# erroneous and not what is intended by page authors. Lynx will issue
+# a warning message when this occurs.
+#
+# If STRIP_DOTDOT_URLS is FALSE, Lynx will use those URLs for requests
+# without taking any special actions or issuing Warnings, in most cases
+# this will result in an error response from the server.
+#
+# Note that Lynx never tries to fix similar URLs for protocols other than
+# http and https, since they are less common and may actually be valid in
+# some cases.
+#
+#STRIP_DOTDOT_URLS:TRUE
+
+# If ENABLE_SCROLLBACK is TRUE, Lynx will clear the entire screen before
+# displaying each new screenful of text. Though less efficient for normal
+# use, this allows programs that maintain a buffer of previously-displayed
+# text to recognize the continuity of what has been displayed, so that
+# previous screenfuls can be reviewed by whatever method the program uses
+# to scroll back through previous text. For example, the PC comm program
+# QModem has a key that can be pressed to scroll back; if ENABLE_SCROLLBACK
+# is TRUE, pressing the scrollback key will access previous screenfuls which
+# will have been stored on the local PC and will therefore be displayed
+# instantaneously, instead of needing to be retransmitted by Lynx at the
+# speed of the comm connection (but Lynx will not know about the change,
+# so you must restore the last screen before resuming with Lynx commands).
+#
+# The compilation default is FALSE (if REVERSE_CLEAR_SCREEN_PROBLEM was not
+# defined in the Unix Makefile to invoke this behavior as a workaround for
+# some poor curses implementations).
+#
+# The default compilation or configuration setting can be toggled via an
+# "-enable_scrollback" command line switch.
+#
+#ENABLE_SCROLLBACK:FALSE
+
+# If SCAN_FOR_BURIED_NEWS_REFS is set to TRUE, Lynx will scan the bodies
+# of news articles for buried article and URL references and convert them
+# to links. The compilation default is TRUE, but some email addresses
+# enclosed in angle brackets ("<user@address>") might be converted to false
+# news links, and uuencoded messages might be corrupted. The conversion is
+# not done when the display is toggled to source or when 'd'ownloading, so
+# uuencoded articles can be saved intact regardless of these settings.
+#
+# The default setting can be toggled via a "-buried_news" command line
+# switch.
+#
+#SCAN_FOR_BURIED_NEWS_REFS:TRUE
+
+# If PREPEND_BASE_TO_SOURCE is set to FALSE, Lynx will not prepend a
+# Request URL comment and BASE element to text/html source files when
+# they are retrieved for 'd'ownloading or passed to 'p'rint functions.
+# The compilation default is TRUE. Note that this prepending is not
+# done for -source dumps, unless the -base switch also was included on
+# the command line, and the latter switch overrides the setting of the
+# PREPEND_BASE_TO_SOURCE configuration variable.
+#
+#PREPEND_BASE_TO_SOURCE:TRUE
+
+# MIME types and viewers!
+#
+# file extensions may be assigned to MIME types using
+# the SUFFIX: definition.
+#
+# The SUFFIX definition takes the form of:
+# SUFFIX:<file extension>:<mime type>
+# for instance the following definition maps the
+# extension ".gif" to the mime type "image/gif"
+# SUFFIX:.gif:image/gif
+#
+# file suffixes are case INsensitive!
+#
+# The suffix definitions listed here in the default lynx.cfg file are
+# among those established via src/HTInit.c. You can change any of the
+# defaults by editing that file, or via the global or personal mime.types
+# files at run time. They will be overridden if you assign them here.
+#
+#SUFFIX:.ps:application/postscript
+#SUFFIX:.eps:application/postscript
+#SUFFIX:.ai:application/postscript
+#SUFFIX:.rtf:application/x-rtf
+#SUFFIX:.snd:audio/basic
+#SUFFIX:.gif:image/gif
+#SUFFIX:.rgb:image/x-rgb
+#SUFFIX:.pict:image/x-pict
+#SUFFIX:.xbm:image/x-xbitmap
+#SUFFIX:.tiff:image/x-tiff
+#SUFFIX:.jpg:image/jpeg
+#SUFFIX:.jpeg:image/jpeg
+#SUFFIX:.mpg:video/mpeg
+#SUFFIX:.mpeg:video/mpeg
+#SUFFIX:.mov:video/quicktime
+#SUFFIX:.hqx:application/octet-stream
+#SUFFIX:.bin:application/octet-stream
+#SUFFIX:.exe:application/octet-stream
+#SUFFIX:.tar:application/octet-stream
+#SUFFIX:.Z:application/octet-stream
+#SUFFIX:.gz:application/octet-stream
+#SUFFIX:.zip:application/octet-stream
+#SUFFIX:.lzh:application/octet-stream
+#SUFFIX:.lha:application/octet-stream
+#SUFFIX:.dms:application/octet-stream
+
+# The global and personal EXTENSION_MAP files allow you to assign extensions
+# to MIME types which will override any of the suffix maps in this (lynx.cfg)
+# configuration file, or in src/HTInit.c. See the example mime.types file
+# in the samples subdirectory.
+#
+# Unix:
+#GLOBAL_EXTENSION_MAP:/usr/local/lib/mosaic/mime.types
+# VMS:
+#GLOBAL_EXTENSION_MAP:Lynx_Dir:mime.types
+#
+# Unix (sought in user's home directory):
+#PERSONAL_EXTENSION_MAP:.mime.types
+# VMS (sought in user's sys$login directory):
+#PERSONAL_EXTENSION_MAP:mime.types
+
+# VMS:
+# ====
+# XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c
+# for viewing image content types when the DECW$DISPLAY logical
+# is set. Make it the foreign command for your system's X image
+# viewer (commonly, "xv"). Make it "exit" or something like that
+# if you don't have one. It can be anything that will handle GIF,
+# TIFF and other popular image formats. Freeware ports of xv for
+# VMS are available in the ftp://ftp.wku.edu/vms/unsupported and
+# http://www.openvms.digital.com/cd/XV310A/ subdirectories. You
+# must also have a "%s" for the filename. The default is defined
+# in userdefs.h and can be overridden here, or via the global or
+# personal mailcap files (see below).
+#
+#XLOADIMAGE_COMMAND:xv %s
+
+# Unix:
+# =====
+# XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c for
+# viewing image content types when the DISPLAY environment variable
+# is set. Make it the full path and name of the xli (also know as
+# xloadimage or xview) command, or other image viewer. Put 'echo' or
+# something like it here if you don't have a suitable viewer. It can
+# be anything that will handle GIF, TIFF and other popular image formats
+# (xli does). The freeware distribution of xli is available in the
+# ftp://ftp.x.org/contrib subdirectory. The shareware, xv, also is
+# suitable. You must also have a "%s" for the filename; "&" for
+# background is optional. The default is defined in userdefs.h and can be
+# overridden here, or via the global or personal mailcap files (see below).
+# Note that open is used as the default for NeXT, instead of the
+# XLOADIMAGE_COMMAND definition.
+# If you use xli, you may want to add the -quiet flag.
+#
+#XLOADIMAGE_COMMAND:xli %s &
+
+# MIME types may be assigned to external viewers using
+# the VIEWER definition.
+#
+# Note: if you do not define a viewer to a new MIME type
+# that you assigned above then it will be saved to
+# disk by default.
+#
+# The VIEWER definition takes the form of:
+# VIEWER:<mime type>:<viewer command>[:environment]
+# where -mime type is the MIME content type of the file
+# -viewer command is a system command that can be
+# used to display the file where %s is replaced
+# within the command with the physical filename
+# (e.g. "ghostview %s" becomes "ghostview /tmp/temppsfile")
+# -environment is optional. The only valid keywords
+# are currently XWINDOWS and NON_XWINDOWS. If the XWINDOWS
+# environment is specified then the viewer will only be
+# defined when the user has the environment variable DISPLAY
+# (DECW$DISPLAY on VMS) defined. If the NON_XWINDOWS environment
+# is specified the specified viewer will only be defined when the
+# user DOES NOT have the environment variable DISPLAY defined.
+# examples:
+# VIEWER:image/gif:xli %s:XWINDOWS
+# VIEWER:image/gif:ascii-view %s:NON_XWINDOWS
+# VIEWER:application/start-elm:elm
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon in the viewer command, precede it with a backslash!
+#
+# The MIME_type:viewer:XWINDOWS definitions listed here in the lynx.cfg
+# file are among those established via src/HTInit.c. For the image types,
+# HTInit.c uses the XLOADIMAGE_COMMAND definition in userdefs.h or above
+# (open is used for NeXT). You can change any of these defaults via the
+# global or personal mailcap files at run time. They will be overridden
+# if you assign them here.
+#
+#VIEWER:application/postscript:ghostview %s&:XWINDOWS
+#VIEWER:image/gif:xli %s&:XWINDOWS
+#VIEWER:image/x-xbm:xli %s&:XWINDOWS
+#VIEWER:image/x-rgb:xli %s&:XWINDOWS
+#VIEWER:image/x-tiff:xli %s&:XWINDOWS
+#VIEWER:image/jpeg:xli %s&:XWINDOWS
+#VIEWER:video/mpeg:mpeg_play %s &:XWINDOWS
+
+# The global and personal MAILCAP files allow you to specify external
+# viewers to be spawned when Lynx encounters different MIME types, which
+# will override any of the suffix maps in this (lynx.cfg) configuration
+# file, or in src/HTInit.c. See http://www.internic.net/rfc/rfc1524.txt
+# and the example mailcap file in the samples subdirectory.
+#
+# Unix:
+#GLOBAL_MAILCAP:/usr/local/lib/mosaic/mailcap
+# VMS:
+#GLOBAL_MAILCAP:Lynx_Dir:mailcap
+#
+# Sought in user's home (Unix) or sys$login (VMS) directory.
+#PERSONAL_MAILCAP:.mailcap
+
+# Key remapping definitions!
+#
+# You may redefine the keymapping of any function in Lynx by
+# using the KEYMAP variable. The form of KEYMAP is:
+# KEYMAP:<KEYSTROKE>:<LYNX FUNCTION>
+#
+# You must map upper and lowercase keys separately.
+#
+# A representative list of functions mapped to their default keys is
+# provided below. All of the mappings are commented out by default
+# since they just map to the default mappings, except for TOGGLE_HELP
+# (see below). See LYKeymap.c for the complete key mapping. Use the
+# 'K'eymap command when running Lynx for a list of the current mappings.
+#
+# Special keys map to:
+# Up Arrow: 0x100
+# Down Arrow: 0x101
+# Right Arrow: 0x102
+# Left Arrow: 0x103
+# Page Down: 0x104
+# Page Up: 0x105
+# Keypad Home: 0x106
+# Keypad End: 0x107
+# Function key 1: 0x108
+# vt100 Help Key: 0x108
+# vt100 Do Key: 0x109
+# vt100 Find Key: 0x10A
+# vt100 Select Key: 0x10B
+# vt100 Insert Key: 0x10C
+# vt100 Remove Key: 0x10D
+# (0x00) NULL KEY: 0x10E (DO_NOTHING)
+#
+
+#KEYMAP:0x2F:SOURCE # Toggle source viewing mode (show HTML source)
+#KEYMAP:^R:RELOAD # Reload the current document and redisplay
+#KEYMAP:q:QUIT # Ask the user to quit
+#KEYMAP:Q:ABORT # Quit without verification
+#KEYMAP:0x20:NEXT_PAGE # Move down to next page
+#KEYMAP:-:PREV_PAGE # Move up to previous page
+#KEYMAP:^P:UP_TWO # Move display up two lines
+#KEYMAP:0x10C:UP_TWO # Function key Insert - Move display up two lines
+#KEYMAP:^N:DOWN_TWO # Move display down two lines
+#KEYMAP:0x10D:DOWN_TWO # Function key Remove - Move display down two lines
+#KEYMAP:(:UP_HALF # Move display up half a page
+#KEYMAP:):DOWN_HALF # Move display down half a page
+#KEYMAP:^W:REFRESH # Refresh the screen
+#KEYMAP:^A:HOME # Go to top of current document
+#KEYMAP:0x106:HOME # Keypad Home - Go to top of current document
+#KEYMAP:0x10A:HOME # Function key Find - Go to top of current document
+#KEYMAP:^E:END # Go to bottom of current document
+#KEYMAP:0x107:END # Keypad End - Go to bottom of current document
+#KEYMAP:0x10B:END # Function key Select - Go to bottom of current document
+#KEYMAP:0x100:PREV_LINK # Move to the previous link
+#KEYMAP:0x101:NEXT_LINK # Move to the next link
+#KEYMAP:<:UP_LINK # Move to the link above
+#KEYMAP:>:DOWN_LINK # Move to the link below
+#KEYMAP:0x00:RIGHT_LINK # Move to the link to the right
+#KEYMAP:0x00:LEFT_LINK # Move to the link to the left
+#KEYMAP:0x7F:HISTORY # Display stack of currently-suspended documents
+#KEYMAP:0x08:HISTORY # Display stack of currently-suspended documents
+#KEYMAP:0x103:PREV_DOC # Return to the previous document
+#KEYMAP:0x102:ACTIVATE # Select the current link
+#KEYMAP:0x109:ACTIVATE # Function key Do - Select the current link
+#KEYMAP:g:GOTO # Goto a random URL
+#KEYMAP:G:ECGOTO # Edit the current document's URL and go to it
+#KEYMAP:H:HELP # Show default help screen
+#KEYMAP:0x108:HELP # Function key Help - Show default help screen
+#KEYMAP:i:INDEX # Show default index
+#*** Edit FORM_LINK_SUBMIT_MESSAGE in userdefs.h if you change NOCACHE ***
+#KEYMAP:x:NOCACHE # Force submission of form or link with no-cache
+#*** Do not change INTERRUPT from 'z' & 'Z' ***
+#KEYMAP:z:INTERRUPT # Interrupt network transmission
+#KEYMAP:m:MAIN_MENU # Return to the main menu
+#KEYMAP:o:OPTIONS # Show the options menu
+#KEYMAP:i:INDEX_SEARCH # Search a server based index
+#KEYMAP:/:WHEREIS # Find a string within the current document
+#KEYMAP:n:NEXT # Find next occurence of string within document
+#KEYMAP:c:COMMENT # Comment to the author of the current document
+#KEYMAP:e:EDIT # Edit current document
+#KEYMAP:E:ELGOTO # Edit the current link's URL or ACTION and go to it
+#KEYMAP:=:INFO # Show info about current document
+#KEYMAP:p:PRINT # Show print options
+#KEYMAP:a:ADD_BOOKMARK # Add current document to bookmark list
+#KEYMAP:v:VIEW_BOOKMARK # View the bookmark list
+#KEYMAP:V:VLINKS # List links visited during the current Lynx session
+#KEYMAP:!:SHELL # Spawn default shell
+#KEYMAP:d:DOWNLOAD # Download current link
+#KEYMAP:j:JUMP # Jump to a predefined target
+#KEYMAP:k:KEYMAP # Display the current key map
+#KEYMAP:l:LIST # List the references (links) in the current document
+#KEYMAP:#:TOOLBAR # Go to the Toolbar or Banner in the current document
+#KEYMAP:^T:TRACE_TOGGLE # Toggle tracing of browser operations
+#KEYMAP:*:IMAGE_TOGGLE # Toggle inclusion of links for all images
+#KEYMAP:[:INLINE_TOGGLE # Toggle pseudo-ALTs for inlines with no ALT string
+#KEYMAP:0x00:DO_NOTHING # Does nothing (ignore this key)
+
+# If TOGGLE_HELP is mapped, in novice mode the second help menu line
+# can be toggled among NOVICE_LINE_TWO_A, _B, and _C, as defined in
+# userdefs.h. Otherwise, it will be NOVICE_LINE_TWO.
+#
+#KEYMAP:O:TOGGLE_HELP # Show other commands in the novice help menu
+
+# Alternate jumps files can be defined and mapped to keys here. If the
+# keys have already been mapped, then those mappings will be replaced,
+# but you should leave at least one key mapped to the default jumps
+# file. You optionally may include a statusline prompt string for the
+# mapping. You must map upper and lowercase keys separately (beware of
+# mappings to keys which the user can further remap via the 'o'ptions
+# menu). The format is:
+#
+# JUMPFILE:path:key[:prompt]
+#
+# where path should begin with a '/' (i.e., not include file://localhost).
+# Any white space following a prompt string will be trimmed, and a single
+# space will be added by Lynx.
+#
+#JUMPFILE:/Lynx_Dir/ips.html:i:IP or Interest group (? for list):
+
+# VMS ONLY:
+#==========
+# On VMS, CSwing (an XTree emulation for VTxxx terminals) is intended for
+# use as the Directory/File Manager (sources, objects, or executables are
+# available from ftp://narnia.memst.edu/). CSWING_PATH should be defined
+# here or in userdefs.h to your foreign command for CSwing, with any
+# regulatory switches you want included. If not defined, or defined as
+# a zero-length string ("") or "none" (case-insensitive), the support
+# will be disabled. It will also be disabled if the -nobrowse or
+# -selective switches are used, or if the file_url restriction is set.
+#
+# When enabled, the DIRED_MENU command (normally 'f' or 'F') will invoke
+# CSwing, normally with the current default directory as an argument to
+# position the user on that node of the directory tree. However, if the
+# current document is a local directory listing, or a local file and not
+# one of the temporary menu or list files, the associated directory will
+# be passed as an argument, to position the user on that node of the tree.
+#
+#CSWING_PATH:swing
+
+# Unix ONLY:
+#===========
+# LIST_FORMAT defines the display for local files when Lynx has been
+# compiled with LONG_LIST defined in the Makefile. The default is set
+# in userdefs.h, normally to "ls -l" format, and can be changed here
+# by uncommenting the indicated lines, or adding a definition with a
+# modified parameter list.
+#
+# The percent items in the list are interpreted as follows:
+#
+# %p Unix-style permission bits
+# %l link count
+# %o owner of file
+# %g group of file
+# %d date of last modification
+# %a anchor pointing to file or directory
+# %A as above but don't show symbolic links
+# %k size of file in Kilobytes
+# %K as above but omit size for directories
+# %s size of file in bytes
+#
+# Anything between the percent and the letter is passed on to sprintf.
+# A double percent yields a literal percent on output. Other characters
+# are passed through literally.
+#
+# If you want only the filename:
+#
+#LIST_FORMAT: %a
+#
+# If you want a brief output:
+#
+#LIST_FORMAT: %4K %-12.12d %a
+#
+# If you want the Unix "ls -l" format:
+#
+#LIST_FORMAT: %p %4l %-8.8o %-8.8g %7s %-12.12d %a
+
+# Unix ONLY:
+#===========
+# DIRED_MENU items are used to compose the F)ull menu list in DIRED mode
+# The behaviour of the default configuration given here is much the same
+# as it was when this menu was hard-coded but these items can now be adjusted
+# to suit local needs. In particular, many of the LYNXDIRED actions can be
+# replaced with lynxexec, lynxprog and lynxcgi script references.
+#
+# NOTE that defining even one DIRED_MENU line overrides all the built-in
+# definitions, so a complete set must then be defined here.
+#
+# Each line consists of the following fields:
+#
+# DIRED_MENU:type:suffix:link text:extra text:action
+#
+# type: TAG: list only when one or more files are tagged
+# FILE: list only when the current selection is a regular file
+# DIR: list only when the current selection is a directory
+# LINK: list only when the current selection is a symbolic link
+#
+# suffix: list only if the current selection ends in this pattern
+#
+# link text: the displayed text of the link
+#
+# extra text: the text displayed following the link
+#
+# action: the URL to be followed upon selection
+#
+# link text and action are scanned for % sequences that are expanded
+# at display time as follows:
+#
+# %p path of current selection
+# %f filename (last component) of current selection
+# %t tagged list (full paths)
+# %l list of tagged file names
+# %d the current directory
+#
+#DIRED_MENU:::New File:(in current directory):LYNXDIRED://NEW_FILE%d
+#DIRED_MENU:::New Directory:(in current directory):LYNXDIRED://NEW_FOLDER%d
+
+#DIRED_MENU:FILE::Install:(of current selection):LYNXDIRED://INSTALL_SRC%p
+#DIRED_MENU:DIR::Install:(of current selection):LYNXDIRED://INSTALL_SRC%p
+#DIRED_MENU:FILE::Modify File Name:(of current selection):LYNXDIRED://MODIFY_NAME%p
+#DIRED_MENU:DIR::Modify Directory Name:(of current selection):LYNXDIRED://MODIFY_NAME%p
+#DIRED_MENU:LINK::Modify Name:(of selected symbolic link):LYNXDIRED://MODIFY_NAME%p
+
+# Following depends on OK_PERMIT
+#DIRED_MENU:FILE::Modify File Permissions:(of current selection):LYNXDIRED://PERMIT_SRC%p
+#DIRED_MENU:DIR::Modify Directory Permissions:(of current selection):LYNXDIRED://PERMIT_SRC%p
+
+#DIRED_MENU:FILE::Change Location:(of selected file):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:DIR::Change Location:(of selected directory):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:LINK::Change Location:(of selected symbolic link):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:FILE::Remove File:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+#DIRED_MENU:DIR::Remove Directory:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+#DIRED_MENU:LINK::Remove Symbolic Link:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+
+# Following depends on OK_UUDECODE and !ARCHIVE_ONLY
+#DIRED_MENU:FILE::UUDecode:(current selection):LYNXDIRED://UUDECODE%p
+
+# Following depends on OK_TAR and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar.Z:Expand:(current selection):LYNXDIRED://UNTAR_Z%p
+
+# Following depend on OK_TAR and OK_GZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar.gz:Expand:(current selection):LYNXDIRED://UNTAR_GZ%p
+#DIRED_MENU:FILE:.tgz:Expand:(current selection):LYNXDIRED://UNTAR_GZ%p
+
+# Following depends on !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.Z:Uncompress:(current selection):LYNXDIRED://DECOMPRESS%p
+
+# Following depends on OK_GZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.gz:Uncompress:(current selection):LYNXDIRED://UNGZIP%p
+
+# Following depends on OK_ZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.zip:Uncompress:(current selection):LYNXDIRED://UNZIP%p
+
+# Following depends on OK_TAR and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar:UnTar:(current selection):LYNXDIRED://UNTAR%p
+
+# Following depends on OK_TAR
+#DIRED_MENU:DIR::Tar:(current selection):LYNXDIRED://TAR%p
+
+# Following depends on OK_TAR and OK_GZIP
+#DIRED_MENU:DIR::Tar and compress:(using GNU gzip):LYNXDIRED://TAR_GZ%p
+
+# Following depends on OK_ZIP
+#DIRED_MENU:DIR::Package and compress:(using zip):LYNXDIRED://ZIP%p
+
+#DIRED_MENU:FILE::Compress:(using Unix compress):LYNXDIRED://COMPRESS%p
+
+# Following depends on OK_GZIP
+#DIRED_MENU:FILE::Compress:(using gzip):LYNXDIRED://GZIP%p
+
+# Following depends on OK_ZIP
+#DIRED_MENU:FILE::Compress:(using zip):LYNXDIRED://ZIP%p
+
+#DIRED_MENU:TAG::Move all tagged items to another location.::LYNXDIRED://MOVE_TAGGED%d
+#DIRED_MENU:TAG::Remove all tagged files and directories.::LYNXDIRED://REMOVE_TAGGED
+#DIRED_MENU:TAG::Untag all tagged items.::LYNXDIRED://CLEAR_TAGGED
+
+# Unix ONLY:
+#===========
+# If NO_FORCED_CORE_DUMP is set to TRUE, Lynx will not force
+# core dumps via abort() calls on fatal errors or assert()
+# calls to check potentially fatal errors. The compilation
+# default normally is FALSE, and can be changed here. The
+# compilation or configuration default can be toggled via
+# the -core command line switch.
+# Note that this setting cannot be used to prevent core dumps
+# with certainty. If this is important, means provided by the
+# operating system or kernel should be used.
+#
+#NO_FORCED_CORE_DUMP:FALSE
+
+# COLORS (only available if compiled with SVr4 curses or slang)
+#
+# The line must be of the form:
+# COLOR:Integer:Foreground:Background
+#
+# The Integer value is interpreted as follows:
+# 0 - normal - normal text
+# 1 - bold - hyperlinks, see also BOLD_* options above
+# 2 - reverse - statusline
+# 3 - bold + reverse (not used)
+# 4 - underline - text emphasis (EM, I, B tags etc.)
+# 5 - bold + underline - hyperlinks within text emphasis
+# 6 - reverse + underline - currently selected hyperlink
+# 7 - reverse + underline + bold - WHEREIS search hits
+#
+# Each Foreground and Background value must be one of:
+# black red green brown
+# blue magenta cyan lightgray
+# gray brightred brightgreen yellow
+# brightblue brightmagenta brightcyan white
+#
+# Uncomment and change any of the compilation defaults.
+#
+#COLOR:0:black:white
+#COLOR:1:blue:white
+#COLOR:2:yellow:blue
+#COLOR:3:green:white
+#COLOR:4:magenta:white
+#COLOR:5:blue:white
+#COLOR:6:red:white
+#COLOR:7:magenta:cyan
+
+# External application support. This feature allows lynx to pass a given
+# URL to an external program. It was written for three reasons.
+#
+# 1) To overcome the deficiency of Lynx_386 not supporting ftp and news.
+# External programs can be used instead by passing the URL.
+#
+# 2) To allow for background transfers in multitasking systems.
+# I use wget for http and ftp transfers via the external command.
+#
+# 3) To allow for new URLs to be used through lynx.
+# URLs can be made up such as mymail: to spawn desired applications
+# via the external command.
+#
+# Restrictions can be imposed using -restrictions=externals at the lynx
+# command line. This will disallow all EXTERNAL lines in lynx.cfg that
+# end in FALSE. TRUE lines will still function.
+#
+# The lynx.cfg line is as follows:
+#
+# EXTERNAL:<url>:<command> %s:<norestriction>
+#
+# <url> Any given URL. This can be normal ones like ftp or http or it
+# can be one made up like mymail.
+#
+# <command> The command to run with %s being the URL that will be passed.
+# In Linux I use "wget -q %s &" (no quotes) to spawn a copy of wget for
+# downloading http and ftp files in the background. In Win95 I use
+# "start ncftp %s" to spawn ncftp in a new window.
+#
+# <norestriction> This complements the -restrictions=externals feature to allow
+# for certain externals to be enabled while restricting others. TRUE means
+# a command will still function while lynx is restricted. WB
+#
+# EXTERNAL:ftp:wget %s &:TRUE
+
+# Raw DOS Key hack
+# If RAW_DOS_KEY_HACK is set to FALSE, it will bypass the DOS key hack.
+# The DOS key hack is only present if compiled with -DRAWDOSKEYHACK
+# The hack is as follows:
+# if (c == 0) c = '/';
+# if (c > 255) { /* handle raw dos keys */
+# switch (c)
+# {
+# case 464: c = '-'; break; /* keypad minus*/
+# case 465: c = '+'; break; /* keypad plus*/
+# case 459: c = 13; break; /* keypad enter*/
+# case 463: c = '*'; break; /* keypad * */
+# case 440: c = 'Q'; break; /* alt x */
+# case 265: c = 'H'; break; /* F1 */
+# default: break;
+# }
+# }
+#
+# RAW_DOS_KEY_HACK:TRUE
+
diff --git a/gnu/usr.bin/lynx/lynx.hlp b/gnu/usr.bin/lynx/lynx.hlp
new file mode 100644
index 00000000000..895e421f02e
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx.hlp
@@ -0,0 +1,463 @@
+1 LYNX
+ NAME
+ lynx - a general purpose distributed information browser for the World
+ Wide Web
+
+2 SYNOPSIS
+ Lynx [options] [path or URL]
+
+ use "lynx -help" to display a complete list of current options.
+
+2 DESCRIPTION
+ Lynx is a fully-featured World Wide Web (WWW) client for users running
+ cursor-addressable, character-cell display devices (e.g., vt100 terminals,
+ vt100 emulators running on PCs or Macs, or any other "curses-oriented"
+ display). It will display hypertext markup language (HTML) documents con-
+ taining links to files residing on the local system, as well as files
+ residing on remote systems running Gopher, HTTP, FTP, WAIS, and NNTP
+ servers. Current versions of Lynx run on Unix and VMS.
+
+ Lynx can be used to access information on the World Wide Web, or to build
+ information systems intended primarily for local access. For example, Lynx
+ has been used to build several Campus Wide Information Systems (CWIS). In
+ addition, Lynx can be used to build systems isolated within a single LAN.
+
+2 OPTIONS
+ At start up, Lynx will load any local file or remote URL specified at
+ the command line. For help with URLs, press "?" or "h" while running
+ Lynx. Then follow the link titled, "Help on URLs."
+
+ -
+ If the argument is only '-', then Lynx expects to receive
+ arguments from stdin. This is to allow for the potentially
+ very long command line that can be associated with the
+ -get_data or -post_data arguments (see below). Encase it
+ in double-quotes ("-").
+
+ -anonymous
+ used to specify the anonymous account.
+
+ -assume_charset=MIMEname
+ charset for documents that don't specify it.
+
+ -assume_local_charset=MIMEname
+ charset assumed for local files.
+
+ -assume_unrec_charset=MIMEname
+ use this instead of unrecognized charsets.
+
+ -auth=ID:PASSWD
+ set authorization ID and password for protected documents
+ at startup. Be sure to protect any script files which use
+ this switch.
+
+ -base
+ prepend a request URL comment and BASE tag to text/html
+ outputs for -source dumps.
+
+ -blink
+ forces high intensity bg colors for color mode, if available
+ and supported by the terminal.
+ Lynx needs to be compiled with the slang library for this flag.
+
+ -book
+ use the bookmark page as the startfile. The default or command
+ line startfile is still set for the Main screen command, and will
+ be used if the bookmark page is unavailable or blank.
+
+ -buried_news
+ toggles scanning of news articles for buried references, and
+ converts them to news links. Not recommended because email
+ addresses enclosed in angle brackets will be converted to
+ false news links, and uuencoded messages can be trashed.
+
+ -cache=NUMBER
+ set the NUMBER of documents cached in memory. The default is 10.
+
+ -case
+ enable case-sensitive string searching.
+
+ -cfg=FILENAME
+ specifies a Lynx configuration file other than the default lynx.cfg.
+
+ -child
+ exit on left-arrow in startfile, and disable save to disk.
+
+ -color
+ forces color mode on, if available. Default color control sequences
+ which work for many terminal types are assumed if the terminal
+ capability description does not specify how to handle color.
+ Lynx needs to be compiled with the slang library for this flag.
+ A saved show_color=always setting found in a .lynxrc file at
+ startup has the same effect. A saved show_color=always found
+ in .lynxrc on startup is overridden by this flag.
+
+ -cookies
+ toggles handling of Set-Cookie headers.
+
+ -crawl
+ with -traversal, output each page to a file.
+ with -dump, format output as with -traversal, but to stdout.
+
+ -display=DISPLAY
+ set the display variable for X rexec-ed programs.
+
+ -dump
+ dumps the formatted output of the default document or one specified
+ on the command line to standard out. This can be used in the
+ following way:
+ lynx -dump http://www.crl.com/~subir/lynx.html
+
+ -editor=EDITOR
+ enable edit mode using the specified EDITOR. (vi, ed, emacs, etc.)
+
+ -emacskeys
+ enable emacs-like key movement.
+
+ -enable_scrollback
+ toggles compatibility with comm programs' scrollback keys
+ (may be incompatible with some curses packages).
+
+ -error_file=FILE
+ define a file where Lynx will report HTTP access codes.
+
+ -fileversions
+ include all versions of files in local VMS directory listings.
+
+ -force_html
+ forces the first document to be interpreted as HTML.
+
+ -force_secure
+ toggles forcing of the secure flag for SSL cookies.
+
+ -from
+ toggles transmissions of From headers.
+
+ -ftp
+ disable ftp access.
+
+ -get_data
+ send form data from stdin using GET method and dump results.
+
+ -head
+ send a HEAD request for the mime headers.
+
+ -help
+ print this Lynx command syntax usage message.
+
+ -historical
+ toggles use of '>' or '-->' as a terminator for comments.
+
+ -homepage=URL
+ set homepage separate from start page.
+
+ -image_links
+ toggles inclusion of links for all images.
+
+ -index=URL
+ set the default index file to the specified URL.
+
+ -ismap
+ toggles inclusion of ISMAP links when client-side
+ MAPs are present.
+
+ -link=NUMBER
+ starting count for lnk#.dat files produced by -crawl.
+
+ -localhost
+ disable URLs that point to remote hosts.
+
+ -locexec
+ enable local program execution from local files only (if
+ Lynx was compiled with local execution enabled).
+
+ -mime_header
+ prints the MIME header of a fetched document along with its
+ source.
+
+ -minimal
+ toggles minimal versus valid comment parsing.
+
+ -newschunksize=NUMBER
+ number of articles in chunked news listings.
+
+ -newsmaxchunk=NUMBER
+ maximum news articles in listings before chunking.
+
+ -nobrowse
+ disable directory browsing.
+
+ -nocc
+ disable Cc: prompts for self copies of mailings. Note
+ that this does not disable any CCs which are incorporated
+ within a mailto URL or form ACTION.
+
+ -nocolor
+ force color mode off, overriding terminal capabilities and any
+ -color flags, COLORTERM variable, and saved .lynxrc settings.
+
+ -noexec
+ disable local program execution. (DEFAULT)
+
+ -nofilereferer
+ disable transmissions of Referer headers for file URLs.
+
+ -nolist
+ disable the link list feature in dumps.
+
+ -nolog
+ disable mailing of error messages to document owners.
+
+ -nopause
+ disable forced pauses for statusline messages.
+
+ -noprint
+ disable print functions.
+
+ -noredir
+ prevents automatic redirection and prints a message with a
+ link to the new URL.
+
+ -noreferer
+ disable transmissions of Referer headers.
+
+ -nosocks
+ disable SOCKS proxy usage by a SOCKSified Lynx.
+
+ -nostatus
+ disable the retrieval status messages.
+
+ -number_links
+ force numbering of links.
+
+ -pauth=ID:PASSWD
+ set authorization ID and password for a protected proxy
+ server at startup. Be sure to protect any script files
+ which use this switch.
+
+ -popup
+ toggles handling of single-choice SELECT options via
+ popup windows or as lists of radio buttons.
+
+ -post_data
+ send form data from stdin using POST method and dump results.
+
+ -preparsed
+ show HTML source preparsed and reformatted when used with -source
+ or in source view.
+
+ -print
+ enable print functions. (default)
+
+ -pseudo_inlines
+ toggles pseudo-ALTs for inlines with no ALT string.
+
+ -raw
+ toggles default setting of 8-bit character translations
+ or CJK mode for the startup character set.
+
+ -realm
+ restricts access to URLs in the starting realm.
+
+ -reload
+ flushes the cache on a proxy server
+ (only the first document affected).
+
+ -restrictions=[option][,,option]...
+ allows a list of services to be disabled selectively. The following
+ list is printed if no options are specified.
+
+ all - restricts all options.
+
+ bookmark - disallow changing the location of the bookmark file.
+
+ bookmark_exec - disallow execution links via the bookmark file.
+
+ change_exec_perms - disallow changing the eXecute permission on
+ files (but still allow it for directories) when local file
+ management is enabled.
+
+ default - same as command line option -anonymous. Disables default
+ services for anonymous users. Currently set to all restricted
+ except for: inside_telnet, outside_telnet, inside_news,
+ inside_ftp, outside_ftp, inside_rlogin, outside_rlogin, jump,
+ mail and goto. Defaults are setable within userdefs.h.
+
+ dired_support - disallow local file management.
+
+ disk_save - disallow saving to disk in the download and print
+ menus.
+
+ download - disallow downloaders in the download menu.
+
+ editor - disallow editing.
+
+ exec - disable execution scripts.
+
+ exec_frozen - disallow the user from changing the local execution
+ option.
+
+ file_url - disallow using G)oto, served links or bookmarks for
+ file: URLs.
+
+ goto - disable the 'g' (goto) command.
+
+ inside_ftp - disallow ftps for people coming from inside your domain
+ (utmp required for selectivity).
+
+ inside_news - disallow USENET news posting for people coming from
+ inside our domain (utmp required for selectivity).
+
+ inside_rlogin - disallow rlogins for people coming from inside your
+ domain (utmp required for selectivity).
+
+ inside_telnet - disallow telnets for people coming from inside your
+ domain (utmp required for selectivity).
+
+ jump - disable the 'j' (jump) command.
+
+ multibook - disallow multiple bookmark files.
+
+ mail - disallow mail.
+
+ news_post - disallow USENET News posting.
+
+ options_save - disallow saving options in .lynxrc.
+
+ outside_ftp - disallow ftps for people coming from outside your
+ domain (utmp required for selectivity).
+
+ outside_news - disallow USENET news posting for people coming from
+ outside your domain (utmp required for selectivity).
+
+ outside_rlogin - disallow rlogins for people coming from outside your
+ domain (utmp required for selectivity).
+
+ outside_telnet - disallow telnets for people coming from outside your
+ domain (utmp required for selectivity).
+
+ print - disallow most print options.
+
+ shell - disallow shell escapes and lynxexec or lynxprog G)oto's.
+
+ suspend - disallow Unix Control-Z suspends with escape to shell.
+
+ telnet_port - disallow specifying a port in telnet G)oto's.
+
+ useragent - disallow modifications of the User-Agent header.
+
+ -resubmit_posts
+ toggles forced resubmissions (no-cache) of forms with
+ method POST when the documents they returned are sought
+ with the PREV_DOC command or from the History List.
+
+ -rlogin
+ disable recognition of rlogin commands.
+
+ -selective
+ require .www_browsable files to browse directories.
+
+ -show_cursor
+ If enabled the cursor will not be hidden in the right hand corner
+ but will instead be positioned at the start of the currently
+ selected link. Show cursor is the default for systems without
+ FANCY_CURSES capabilities. The default configuration can be
+ changed in userdefs.h or lynx.cfg. The command line switch
+ toggles the default.
+
+ -source
+ works the same as dump but outputs HTML source instead of formatted
+ text.
+
+ -startfile_ok
+ allow non-http startfile and homepage with -validate.
+
+ -telnet
+ disable recognition of telnet commands.
+
+ -term=TERM
+ tell Lynx what terminal type to assume its talking to. (This may be
+ useful for remote execution, when, for example, Lynx connects to a
+ remote TCP/IP port that starts a script that, in turn, starts another
+ Lynx process.)
+
+ -tlog
+ toggles use of a Lynx Trace Log for the current session.
+
+ -trace
+ turns on WWW trace mode.
+
+ -traversal
+ traverse all http links derived from startfile. When used with
+ -crawl, each link that begins with the same string as startfile
+ is output to a file, intended for indexing. See CRAWL.announce
+ for more information.
+
+ -underscore
+ toggles use of _underline_ format in dumps.
+
+ -useragent=Name
+ set alternate Lynx User-Agent header.
+
+ -validate
+ accept only http URLs (for validation). Complete security
+ restrictions also are implemented.
+
+ -version
+ print version information
+
+ -vikeys
+ enable vi-like key movement.
+
+ -width=NUMBER
+ number of columns for formatting of dumps, default is 80.
+
+2 COMMANDS
+ o Use Up arrow and Down arrow to scroll through hypertext links.
+ o Right arrow or Return will follow a highlighted hypertext link.
+ o Left Arrow will retreat from a link.
+ o Type "h" or "?" for online help and descriptions of key-stroke commands.
+ o Type "k" for a complete list of the current key-stroke command mappings.
+
+2 NOTES
+ This is the Lynx v2.8 Release
+
+ If you wish to contribute to the further development of Lynx, subscribe
+ to our mailing list. Send email to <majordomo@sig.net> with
+ "subscribe lynx-dev" as the only line in the body of your
+ message.
+
+ Send bug reports, comments, suggestions to <lynx-dev@sig.net>
+ after subscribing.
+
+ Unsubscribe by sending email to <majordomo@sig.net> with
+ "unsubscribe lynx-dev" as the only line in the body of your message.
+ Do not send the unsubscribe message to the lynx-dev list, itself.
+
+2 ACKNOWLEDGMENTS
+ Lynx has incorporated code from a variety of sources along the way.
+ The earliest versions of Lynx included code from Earl Fogel of Computing
+ Services at the University of Saskatchewan, who implemented HYPERREZ
+ in the Unix environment. HYPERREZ was developed by Niel Larson of
+ Think.com and served as the model for the early versions of Lynx.
+ Those versions also incorporated libraries from the Unix Gopher clients
+ developed at the University of Minnesota, and the later versions of
+ Lynx rely on the WWW client library code developed by Tim Berners-Lee
+ and the WWW community. Also a special thanks to Foteos Macrides who
+ ported much of Lynx to VMS and did or organized most of its development
+ since the departures of Lou Montulli and Garrett Blythe from the
+ University of Kansas in the summer of 1994 through the release
+ of v2.7.2, and to everyone on the net who has contributed to Lynx's
+ development either directly (through patches, comments or bug reports)
+ or indirectly (through inspiration and development of other systems).
+
+2 AUTHORS
+ Lou Montulli, Garrett Blythe, Craig Lavender, Michael Grobe, Charles Rezac
+ Academic Computing Services
+ University of Kansas
+ Lawrence, Kansas 66047
+
+ Foteos Macrides
+ Worcester Foundation for Biomedical Research
+ Shrewsbury, Massachusetts 01545
+
diff --git a/gnu/usr.bin/lynx/lynx.man b/gnu/usr.bin/lynx/lynx.man
new file mode 100644
index 00000000000..7ae40c47747
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx.man
@@ -0,0 +1,554 @@
+.nr N -1
+.nr D 5
+.TH LYNX 1 Local
+.UC 4
+.SH NAME
+lynx \- a general purpose distributed information browser for the World Wide Web
+.SH SYNOPSIS
+.B Lynx
+[options] [path or URL]
+.PP
+use "lynx -help" to display a complete list of current options.
+.SH DESCRIPTION
+.\" This defines appropriate quote strings for nroff and troff
+.ds lq \&"
+.ds rq \&"
+.if t .ds lq ``
+.if t .ds rq ''
+.\" Just in case these number registers aren't set yet...
+.if \nN==0 .nr N 10
+.if \nD==0 .nr D 5
+.I
+Lynx
+is a fully-featured World Wide Web (WWW) client for users
+running cursor-addressable, character-cell display devices (e.g.,
+vt100 terminals, vt100 emulators running on PCs or Macs, or any
+other "curses-oriented" display). It will display hypertext
+markup language (HTML) documents containing links to
+files residing on the local system, as well as files residing on
+remote systems running Gopher, HTTP, FTP, WAIS, and NNTP servers.
+Current versions of
+.I
+Lynx
+run on
+Unix, VMS, Windows95/NT, 386DOS and OS/2 EMX.
+.PP
+.I
+Lynx
+can be used to access information on the World Wide Web, or
+to build information systems intended primarily for local access.
+For example,
+.I
+Lynx
+has been used to build several Campus Wide
+Information Systems (CWIS). In addition,
+.I
+Lynx
+can be used to
+build systems isolated within a single LAN.
+.SH OPTIONS
+At start up, \fILynx\fR will load any local
+file or remote URL specified at the command
+line. For help with URLs, press \fB"?"\fR
+or \fB"h"\fR while running \fILynx\fR.
+Then follow the link titled, "Help on URLs."
+.PP
+.TP
+.B -
+If the argument is only '-', then Lynx expects to receive
+the arguments from stdin. This is to allow for the
+potentially very long command line that can be associated
+with the -get_data or -post_data arguments (see below).
+.TP
+.B -anonymous
+used to specify the anonymous account.
+.TP
+.B -assume_charset\fR=\fIID\fR:\fIMIMEname
+charset for documents that don't specify it.
+.TP
+.B -assume_local_charset\fR=\fIID\fR:\fIMIMEname
+charset assumed for local files.
+.TP
+.B -assume_unrec_charset\fR=\fIID\fR:\fIMIMEname
+use this instead of unrecognized charsets.
+.TP
+.B -auth\fR=\fIID\fR:\fIPASSWD
+set authorization ID and password for protected documents
+at startup. Be sure to protect any script files which use
+this switch.
+.TP
+.B -base
+prepend a request URL comment and BASE tag to text/html
+outputs for -source dumps.
+.TP
+.B -blink
+forces high intensity bg colors for color mode, if available
+and supported by the terminal.
+Lynx needs to be compiled with the slang library for this flag.
+.TP
+.B -book
+use the bookmark page as the startfile. The default or command
+line startfile is still set for the Main screen command, and will
+be used if the bookmark page is unavailable or blank.
+.TP
+.B -buried_news
+toggles scanning of news articles for buried references, and
+converts them to news links. Not recommended because email
+addresses enclosed in angle brackets will be converted to
+false news links, and uuencoded messages can be trashed.
+.TP
+.B -cache\fR=\fINUMBER
+set the NUMBER of documents cached in memory.
+The default is 10.
+.TP
+.B -case
+enable case-sensitive string searching.
+.TP
+.B -cfg\fR=\fIFILENAME
+specifies a Lynx configuration file other than the default
+lynx.cfg.
+.TP
+.B -child
+exit on left-arrow in startfile, and disable save to disk.
+.TP
+.B -color
+forces color mode on, if available. Default color control sequences
+which work for many terminal types are assumed if the terminal
+capability description does not specify how to handle color.
+Lynx needs to be compiled with the slang library for this flag.
+A saved show_color=always setting found in a .lynxrc file at
+startup has the same effect. A saved show_color=always found
+in .lynxrc on startup is overridden by this flag.
+.TP
+.B -cookies
+toggles handling of Set-Cookie headers.
+.TP
+.B -core
+toggles forced core dumps on fatal errors.
+.TP
+.B -crawl
+with -traversal, output each page to a file.
+with -dump, format output as with -traversal, but to stdout.
+.TP
+.B -display\fR=\fIDISPLAY
+set the display variable for X rexec-ed programs.
+.TP
+.B -dump
+dumps the formatted output of the default document or one
+specified on the command line to standard out.
+This can be used in the following way:
+lynx -dump http://www.crl.com/~subir/lynx.html.
+.TP
+.B -editor\fR=\fIEDITOR
+enable edit mode using the specified
+EDITOR. (vi, ed, emacs, etc.)
+.TP
+.B -emacskeys
+enable emacs-like key movement.
+.TP
+.B -enable_scrollback
+toggles compatibility with comm programs' scrollback keys
+(may be incompatible with some curses packages).
+.TP
+.B -error_file\fR=\fIFILE
+define a file where Lynx will report HTTP access codes.
+.TP
+.B -fileversions
+include all versions of files in local VMS directory listings.
+.TP
+.B -force_html
+forces the first document to be interpreted as HTML.
+.TP
+.B -force_secure
+toggles forcing of the secure flag for SSL cookies.
+.TP
+.B -from
+toggles transmissions of From headers.
+.TP
+.B -ftp
+disable ftp access.
+.TP
+.B -get_data
+send form data from stdin using GET method and dump results.
+.TP
+.B -head
+send a HEAD request for the mime headers.
+.TP
+.B -help
+print this Lynx command syntax usage message.
+.TP
+.B -hiddenlinks=[option]
+control the display of hidden links.
+
+.I merge
+hidden links show up as bracketed numbers
+and are numbered together with other links in the sequence of their
+occurrence in the document.
+
+.I listonly
+hidden links are shown only on L)ist screens and listings generated by
+.I -dump
+or from the P)rint menu, but appear separately at the end of those lists.
+This is the default behavior.
+
+.I ignore
+hidden links do not appear even in listings.
+.TP
+.B -historical
+toggles use of '>' or '-->' as a terminator for comments.
+.TP
+.B -homepage\fR=\fIURL
+set homepage separate from start page.
+.TP
+.B -image_links
+toggles inclusion of links for all images.
+.TP
+.B -index\fR=\fIURL
+set the default index file to the specified URL.
+.TP
+.B -ismap
+toggles inclusion of ISMAP links when client-side
+MAPs are present.
+.TP
+.B -link\fR=\fINUMBER
+starting count for lnk#.dat files produced by -crawl.
+.TP
+.B -localhost
+disable URLs that point to remote hosts.
+.TP
+.B -locexec
+enable local program execution from local files only (if
+Lynx was compiled with local execution enabled).
+.TP
+.B -mime_header
+prints the MIME header of a fetched document along with its
+source.
+.TP
+.B -minimal
+toggles minimal versus valid comment parsing.
+.TP
+.B -newschunksize\fR=\fINUMBER
+number of articles in chunked news listings.
+.TP
+.B -newsmaxchunk\fR=\fINUMBER
+maximum news articles in listings before chunking.
+.TP
+.B -nobrowse
+disable directory browsing.
+.TP
+.B -nocc
+disable Cc: prompts for self copies of mailings. Note
+that this does not disable any CCs which are incorporated
+within a mailto URL or form ACTION.
+.TP
+.B -nocolor
+force color mode off, overriding terminal capabilities and any
+-color flags, COLORTERM variable, and saved .lynxrc settings.
+.TP
+.B -noexec
+disable local program execution. (DEFAULT)
+.TP
+.B -nofilereferer
+disable transmissions of Referer headers for file URLs.
+.TP
+.B -nolist
+disable the link list feature in dumps.
+.TP
+.B -nolog
+disable mailing of error messages to document owners.
+.TP
+.B -nopause
+disable forced pauses for statusline messages.
+.TP
+.B -noprint
+disable print functions.
+.TP
+.B -noredir
+prevents automatic redirection and prints a message with a
+link to the new URL.
+.TP
+.B -noreferer
+disable transmissions of Referer headers.
+.TP
+.B -nosocks
+disable SOCKS proxy usage by a SOCKSified Lynx.
+.TP
+.B -nostatus
+disable the retrieval status messages.
+.TP
+.B -number_links
+force numbering of links.
+.TP
+.B -pauth\fR=\fIID\fR:\fIPASSWD
+set authorization ID and password for a protected proxy
+server at startup. Be sure to protect any script files
+which use this switch.
+.TP
+.B -popup
+toggles handling of single-choice SELECT options via
+popup windows or as lists of radio buttons.
+.TP
+.B -post_data
+send form data from stdin using POST method and dump results.
+.TP
+.B -preparsed
+show HTML source preparsed and reformatted when used with -source
+or in source view.
+.TP
+.B -print
+enable print functions. (default)
+.TP
+.B -pseudo_inlines
+toggles pseudo-ALTs for inlines with no ALT string.
+.TP
+.B -raw
+toggles default setting of 8-bit character translations
+or CJK mode for the startup character set.
+.TP
+.B -realm
+restricts access to URLs in the starting realm.
+.TP
+.B -reload
+flushes the cache on a proxy server
+(only the first document affected).
+.TP
+.B -restrictions\fR=\fI[option][,option][,option]...
+allows a list of services to be disabled
+selectively. The following list is printed
+if no options are specified.
+
+.I all
+- restricts all options.
+
+.I bookmark
+- disallow changing the location of the bookmark
+file.
+
+.I bookmark_exec
+- disallow execution links via the bookmark file.
+
+.I change_exec_perms
+- disallow changing the eXecute permission on files
+(but still allow it for directories) when local file
+management is enabled.
+
+.I default
+- same as command line option -anonymous.
+Disables default services for anonymous users.
+Currently set to all restricted except for:
+inside_telnet, outside_telnet, inside_news,
+inside_ftp, outside_ftp, inside_rlogin,
+outside_rlogin, jump, mail and goto. Defaults
+are setable within userdefs.h.
+
+.I dired_support
+- disallow local file management.
+
+.I disk_save
+- disallow saving to disk in the download and
+print menus.
+
+.I download
+- disallow downloaders in the download menu.
+
+.I editor
+- disallow editing.
+
+.I exec
+- disable execution scripts.
+
+.I exec_frozen
+- disallow the user from changing the local
+execution option.
+
+.I file_url
+- disallow using G)oto, served links or bookmarks for
+file: URLs.
+
+.I goto
+- disable the 'g' (goto) command.
+
+.I inside_ftp
+- disallow ftps for people coming from inside your
+domain (utmp required for selectivity).
+
+.I inside_news
+- disallow USENET news posting for people coming
+from inside your domain (utmp required for selectivity).
+
+.I inside_rlogin
+- disallow rlogins for people coming from inside
+your domain (utmp required for selectivity).
+
+.I inside_telnet
+- disallow telnets for people coming from inside
+your domain (utmp required for selectivity).
+
+.I jump
+- disable the 'j' (jump) command.
+
+.I multibook
+- disallow multiple bookmarks.
+
+.I mail
+- disallow mail.
+
+.I news_post
+- disallow USENET News posting.
+
+.I options_save
+- disallow saving options in .lynxrc.
+
+.I outside_ftp
+- disallow ftps for people coming from outside your
+domain (utmp required for selectivity).
+
+.I outside_news
+- disallow USENET news posting for people coming
+from outside your domain (utmp required for selectivity).
+
+.I outside_rlogin
+- disallow rlogins for people coming from outside
+your domain (utmp required for selectivity).
+
+.I outside_telnet
+- disallow telnets for people coming from
+outside your domain (utmp required for selectivity).
+
+.I print
+- disallow most print options.
+
+.I shell
+- disallow shell escapes and lynxexec or lynxprog G)oto's.
+
+.I suspend
+- disallow Unix Control-Z suspends with escape to shell.
+
+.I telnet_port
+- disallow specifying a port in telnet G)oto's.
+
+.I useragent
+- disallow modifications of the User-Agent header.
+
+.TP
+.B -resubmit_posts
+toggles forced resubmissions (no-cache) of forms with
+method POST when the documents they returned are sought
+with the PREV_DOC command or from the History List.
+.TP
+.B -rlogin
+disable recognition of rlogin commands.
+.TP
+.B -selective
+require .www_browsable files to browse directories.
+.TP
+.B -show_cursor
+If enabled the cursor will not be hidden in the right hand
+corner but will instead be positioned at the start of the
+currently selected link. Show cursor is the default for
+systems without FANCY_CURSES capabilities. The default
+configuration can be changed in userdefs.h or lynx.cfg.
+The command line switch toggles the default.
+.TP
+.B -source
+works the same as dump but outputs HTML source instead of
+formatted text.
+.TP
+.B -startfile_ok
+allow non-http startfile and homepage with -validate.
+.TP
+.B -telnet
+disable recognition of telnet commands.
+.TP
+.B -term\fR=\fITERM
+tell Lynx what terminal type to assume its talking to.
+(This may be useful for remote execution, when, for example,
+Lynx connects to a remote TCP/IP port that starts a script that,
+in turn, starts another Lynx process.)
+.TP
+.B -tlog
+toggles use of a Lynx Trace Log for the current session.
+.TP
+.B -trace
+turns on WWW trace mode.
+.TP
+.B -traversal
+traverse all http links derived from startfile. When used with
+-crawl, each link that begins with the same string as startfile
+is output to a file, intended for indexing. See CRAWL.announce
+for more information.
+.TP
+.B -underscore
+toggles use of _underline_ format in dumps.
+.TP
+.B -useragent=Name
+set alternate Lynx User-Agent header.
+.TP
+.B -validate
+accept only http URLs (for validation). Complete security
+restrictions also are implemented.
+.TP
+.B -version
+print version information.
+.TP
+.B -vikeys
+enable vi-like key movement.
+.TP
+.B -width\fR=\fINUMBER
+number of columns for formatting of dumps, default is 80.
+.SH COMMANDS
+o Use \fBUp arrow\fR and \fBDown arrow\fR to scroll through hypertext links.
+.br
+o \fBRight arrow\fR or \fBReturn\fR will follow a highlighted hypertext link.
+.br
+o \fBLeft Arrow\fR will retreat from a link.
+.br
+o Type \fB"h"\fR or \fB"?"\fR for online help and descriptions
+of key-stroke commands.
+.br
+o Type \fB"k"\fR for a complete list of the current key-stroke
+command mappings.
+.SH NOTES
+This is the Lynx v2.8 Release
+.PP
+If you wish to contribute to the further development
+of \fILynx\fR, subscribe to our mailing list. Send email to
+<majordomo@sig.net> with "subscribe lynx-dev" as the only line
+in the body of your message.
+.PP
+Send bug reports, comments, suggestions to <lynx-dev@sig.net>
+after subscribing.
+.PP
+Unsubscribe by sending email to <majordomo@sig.net> with
+"unsubscribe lynx-dev" as the only line in the body of your message.
+Do not send the unsubscribe message to the lynx-dev list, itself.
+.SH ACKNOWLEDGMENTS
+Lynx has incorporated code from a variety of sources along the way.
+The earliest versions of Lynx included code from Earl Fogel of Computing
+Services at the University of Saskatchewan, who implemented HYPERREZ
+in the Unix environment. HYPERREZ was developed by Niel Larson of
+Think.com and served as the model for the early versions of Lynx.
+Those versions also incorporated libraries from the Unix Gopher clients
+developed at the University of Minnesota, and the later versions of
+Lynx rely on the WWW client library code developed by Tim Berners-Lee
+and the WWW community. Also a special thanks to Foteos Macrides who ported
+much of Lynx to VMS and did or organized most of its development since the
+departures of Lou Montulli and Garrett Blythe from the University of Kansas
+in the summer of 1994 through the release of v2.7.2, and to everyone
+on the net who has contributed to Lynx's development either directly (through
+patches, comments or bug reports) or indirectly (through inspiration and
+development of other systems).
+.SH AUTHORS
+Lou Montulli, Garrett Blythe, Craig Lavender, Michael Grobe, Charles Rezac
+.br
+Academic Computing Services
+.br
+University of Kansas
+.br
+Lawrence, Kansas 66047
+.PP
+Foteos Macrides
+.br
+Worcester Foundation for Biomedical Research
+.br
+Shrewsbury, Massachusetts 01545
diff --git a/gnu/usr.bin/lynx/lynx_help/Lynx_users_guide.html b/gnu/usr.bin/lynx/lynx_help/Lynx_users_guide.html
new file mode 100644
index 00000000000..49cec8d355c
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/Lynx_users_guide.html
@@ -0,0 +1,2303 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Lynx Users Guide v2.8</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+
+<body>
+<h1>Lynx Users Guide v2.8</h1>
+
+Lynx is a fully-featured <em>World Wide Web</em> (<em>WWW</em>) client
+for users running cursor-addressable, character-cell display devices (e.g.,
+vt100 terminals, vt100 emulators running on PCs or Macs, or any other
+character-cell display). It will display <em>Hypertext Markup Language</em>
+(<em>HTML</em>) documents containing links to files on the local system, as
+well as files on remote systems running <em>http</em>, <em>gopher</em>,
+<em>ftp</em>, <em>wais</em>, <em>nntp</em>, <em>finger</em>, or
+<em>cso</em>/<em>ph</em>/<em>qi</em> servers, and services accessible via
+logins to <em>telnet</em>, <em>tn3270</em> or <em>rlogin</em> accounts (see
+<a href="lynx_url_support.html">URL Schemes Supported by Lynx</a>).
+<a href="#32">Current</a> versions of Lynx run on Unix, VMS,
+Windows95/NT, 386DOS and OS/2 EMX.
+
+<p>Lynx can be used to access information on the <em>WWW</em>, or to build
+information systems intended primarily for local access. For example, Lynx
+has been used to build several <em>Campus Wide Information Systems</em>
+(<em>CWIS</em>). In addition, Lynx can be used to build systems isolated
+within a single LAN.
+
+<h2><A NAME="TOC"><em>Table of Contents</em></A></h2>
+
+<ul>
+<li><A HREF="#1">Lynx online help</A>
+<li><A HREF="#2">Viewing local files with Lynx</A>
+<li><A HREF="#3">Leaving Lynx</A>
+<li><A HREF="#4">Starting Lynx with a Remote File</A>
+<li><A HREF="#5">Starting Lynx with the WWW_HOME environment variable.</A>
+<li><A HREF="#6">Navigating hypertext documents with Lynx</A>
+<li><A HREF="#7">Printing, Mailing, and Saving rendered files to disk.</A>
+<li><A HREF="#8">Viewing the HTML document source and editing documents</A>
+<li><A HREF="#9">Downloading and Saving source files.</A>
+<li><A HREF="#10">Reloading files and refreshing the display</A>
+<li><A HREF="#11">Lynx searching commands</A>
+<li><A HREF="#12">Lynx Options Menu</A>
+<li><A HREF="#13">Comments and mailto: links</A>
+<li><A HREF="#14">USENET News posting</A>
+<li><A HREF="#15">Lynx bookmarks</A>
+<li><A HREF="#16">Jump command</A>
+<li><A HREF="#17">Directory Editing</A>
+<li><A HREF="#18">Scrolling and Other useful commands</A>
+<li><a href="#19">Lynx and HTML Forms</a>
+<li><a href="#20">Lynx and HTML Tables</a>
+| <a href="#21">Lynx and HTML Tabs</a>
+<li><a href="#22">Lynx and HTML Frames</a>
+| <a href="#23">Lynx and HTML Banners</a>
+<li><a href="#24">Lynx and HTML Footnotes</a>
+| <a href="#25">Lynx and HTML Notes</a>
+<li><a href="#26">Lynx and HTML Lists</a>
+<li><a href="#27">Lynx and HTML Quotes</a>
+<li><a href="#28">Lynx and Client-Side-Image-Maps</a>
+<li><a href="#29">Lynx and Client-Side-Pull</a>
+<li><a href="#30">Lynx and State Management</a> (Me want <em>cookie</em>!)
+<li><A HREF="#31">The Lynx command line</A>
+<li><A HREF="#32">Lynx development history</A>
+</ul>
+
+<h2><A NAME="1"><em>Lynx online help</em></A></h2>
+
+Online help is available while viewing any document. Press the
+'<em>?</em>' or '<em>H</em>' key (or the '<em>h</em> key if vi-like
+key movement is not on) to see a list of help topics. See the section
+titled <A HREF="#6">Navigating hypertext documents with Lynx</A> for
+information on navigating through the help files.
+
+<p>In addition, a summary description of all the Lynx keystroke commands
+and their key bindings is available by pressing the '<em>K</em>' key (or
+the '<em>k</em>' key if vi-like key movement is not on).
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="2"><em>Viewing local files with Lynx</em></A></h2>
+
+Lynx can be started by entering the Lynx command along with
+the name of a file to display. For example these commands could
+all be used to display an arbitrary ASCII text or HTML file:
+
+<dl>
+ <dt>UNIX
+ <dd><code>lynx filename</code>
+ <dd><code>lynx /home/my-dir/filename</code>
+ <dd><code>lynx ~/filename</code>
+ <dt>VMS
+ <dd><code>lynx filename</code>
+ <dd><code>lynx dua5:[my-directory]filename</code>
+ <dd><code>lynx /dua5/my-directory/filename</code>
+ <dd><code>lynx ~/filename</code>
+ <dd><code>lynx sys$login:filename</code>
+ <dd><code>lynx /sys$login/filename</code>
+ <dt>Win32/DOS
+ <dd><code>lynx file:///filename</code>
+ <dd><code>lynx filename</code>
+ <dd><code>lynx c:/dir/filename</code>
+ <dd><code>lynx //n/dir/filename</code>
+</dl>
+
+<p>When executed, Lynx will clear the screen and display as much of the
+specified file as will fit on the screen. Pressing a <em>down-arrow</em>
+will bring up the next screen, and pressing an <em>up-arrow</em> will bring
+up the previous screen. If no file is specified at startup, a default file
+will be displayed. (The default is configured by the system administrator
+when the command is installed.)
+
+<p>Lynx will display local files written in the <em>HyperText Markup
+Language</em> (<em>HTML</em>), if the file's name ends with the characters
+<em>.html</em>, <em>.htm</em>, <em>.shtml</em>, <em>.htmlx</em>,
+<em>.html3</em>, or <em>.ht3</em>. HTML is a file format that allows users
+to create a file that contains (among other things) hypertext links to other
+files. Several files linked together may be described as a
+<em>hypertext document</em>. If the filename does not have one of the
+suffixes mapped by Lynx to HTML, the <em>-force_html</em> command line
+option can be included to force treatment of the file as hypertext.
+
+<p>When Lynx displays an HTML file, it shows links as "bold face"
+text, except for one link, which is shown as "highlighted" text.
+Whether "boldface" or "highlighted" text shows up as reverse
+video, boldface type, or a color change, etc. depends on the
+display device being used (and the way in which that device has
+been configured). Lynx has no control over the exact presentation
+of links.
+
+<p>The one link displayed as "highlighted" text is the currently
+"selected" link. Lynx will display the file associated with the
+selected link when a <em>right-arrow</em> or a <em>Return</em> key is
+pressed. To select a particular link, press the <em>up-arrow</em> or
+<em>down-arrow</em> keys until the desired link becomes "highlighted,"
+and then press the <em>right-arrow</em> or <em>Return</em> key to view
+the linked information. Information included in the HTML file tells Lynx
+where to find the linked file and what kind of server will provide it
+(i.e. HTTP, Gopher, etc.).
+
+<p>Lynx renders HTML files and saves the rendition, not the source,
+for initial display and should you select the link again. If you do
+select a link again and have reason to desire a new fetch and rendering
+of the file, use the NOCACHE command, normally mapped to '<em>x</em>' and
+'<em>X</em>', instead of the <em>right-arrow</em> or <em>Return</em> key
+when positioned on the link. You also can force a new fetch and rendering
+of the currently displayed document via the RELOAD command, normally mapped
+to <EM>Control-R</em>.
+
+<p>When a binary file is encountered Lynx will ask the user if he/she
+wishes to download the file or cancel. If the user selects '<em>D'</em>
+for download, Lynx will transfer the file into a temporary location and
+present the user with a list of options. The only default option is
+<em>Save to disk</em>, which is disabled if Lynx is running in anonymous
+mode. Any number of additional download methods may be defined in the
+lynx.cfg file by the system administrator. Programs like kermit, zmodem
+and FTP are some possible options. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="3"><em>Leaving Lynx</em></A></h2>
+
+To exit Lynx use the '<em>q</em>' command. You will be asked whether
+you really want to quit. Answering '<em>y</em>' will exit and '<em>n</em>'
+will return you to the current document. Use '<em>Q</em>' or
+<em>Control-D</em> to quit without verification. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="4"><em>Starting Lynx with a Remote File</em></A></h2>
+
+If you wish to view a remote file (that is, a file residing on
+some computer system other than the one upon which you are running
+Lynx) without first viewing a local file, you must identify that
+file by using a Uniform Resource Locator (URL). URLs take the
+general form:
+
+<p><code>PROTOCOL :// HOST / PATH</code>
+
+<p>where
+
+<dl>
+ <dt><code>PROTOCOL</code>
+ <dd>identifies the communications protocol (<em>scheme</em>) used
+ by the server that will provide the file. As mentioned earlier,
+ Lynx (and any WWW client) can interact with a variety of servers,
+ each with its own protocol.
+
+ <dt><code>HOST</code>
+ <dd>is the Internet address of the computer system on which the
+ server is running, and
+
+ <dt><code>PATH</code>
+ <dd>is a scheme-specific field which for some schemes may
+ correspond to a directory path and/or filename.
+</dl>
+
+Here are some sample URLs.
+
+<dl>
+ <dt>HTTP (HyperText Transfer Protocol)
+ <dd><code>http://www.crl.com/~subir/lynx.html</code>
+
+ <dt>Gopher
+ <dd><code>gopher://gopher.micro.umn.edu/11/</code>
+
+ <dt>FTP (File Transfer Protocol)
+ <dd><code>ftp://ftp2.cc.ukans.edu/pub/lynx/README</code>
+
+ <dt>WAIS (Wide Area Information Service protocol)
+ <dd><code>wais://cnidr.org/directory-of-servers</code>
+
+ <dt>A URL may be specified to Lynx on the command line, as in:
+ <dd><code>lynx http://kufacts.cc.ukans.edu/cwis/kufacts_start.html</code>
+</dl>
+
+Lynx also will attempt to create a complete URL if you include adequate
+portions of it in the startfile argument. For example:<br>
+<tab indent="34"><em>wfbr</em>
+<tab indent="62">will be expanded to:<br>
+<tab indent="12"><em>http://www.wfbr.edu/</em>
+<tab indent="62">and:<br>
+<tab indent="26"><em>ftp.more.net/pub</em>
+<tab indent="62">will be expanded to:<br>
+<tab indent="14"><em>ftp://ftp.more.net/pub</em><br>
+See <a href="lynx_url_support.html">URL Schemes Supported by Lynx</a> for
+more detailed information. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="5"
+><em>Starting Lynx with the WWW_HOME environment variable.</em></A></h2>
+
+You may also specify a starting file for Lynx using the WWW_HOME
+environment variable,
+<dl>
+ <dt>UNIX
+ <dd>
+ <dl>
+ <dt>ksh
+ <dd><code>export WWW_HOME=http://www.w3.org/</code>
+ <dt>csh
+ <dd><code>setenv WWW_HOME http://www.w3.org/</code>
+ </dl>
+ <dt>VMS
+ <dd><code>define "WWW_HOME" "http://www.w3.org/"</code>
+ <dt>win32
+ <dd><code>WWW_HOME=http://www.w3.org/ [or in registry]</code>
+</dl>
+
+Note that on VMS the double-quoting <em>must</em> be included to preserve
+casing.
+
+<h2><A NAME="6"><em>Navigating hypertext documents with Lynx</em></A></h2>
+
+The process of moving within a hypertext web, selecting and displaying
+links is known as "navigation." With Lynx almost all navigation can be
+accomplished with the arrow keys and the numeric keypad.
+<pre>
+ +-------+-------+-------+
+ | TOP | /|\ | Page |
+ arrow keys | of | | | UP |
+ | text 7| | 8| 9|
+ +---------+ +-------+-------+-------+
+ | SELECT | | | | |
+ | prev /|\| | &lt;--- | | ---&gt; |
+ | link | | | 4| 5| 6|
+ +---------+---------+---------+ +-------+-------+-------+
+ | BACK | SELECT | DISPLAY | | END | | | Page |
+ |&lt;-- prev | next | | sel. --&gt;| | of | | | DOWN |
+ | doc. | link \|/| link | | text 1| \|/ 2| 3|
+ +---------+---------+---------+ +-------+-------+-------+
+</pre>
+
+There are also a few other keyboard commands to aid in navigation. The
+Control and Function keys used for navigation within the current document
+are described in <A
+HREF="#18"><em>Scrolling and Other useful commands</em></A>. Some
+additional commands depend on the fact that Lynx keeps a list of each
+link you visited to reach the current document, called the <a
+href="keystrokes/history_help.html">History Page</a>, and a
+list of all links visited during the current Lynx session, called the <a
+href="keystrokes/visited_help.html">Visited Links Page</a>. The
+HISTORY keystroke command, normally mapped to <em>Backspace</em> or
+<em>Delete</em>, will show you the <em>History Page</em> of links leading to
+your access of the current document. Any of the previous documents shown in
+the list may be revisited by selecting them from the history screen. The
+VLINKS keystroke command, normally mapped to uppercase '<em>V</em>', will
+show the <em>Visited Links Page</em>, and you similarly can select links in
+that list. The MAIN_MENU keystroke command, normally mapped to '<em>m</em>'
+and '<em>M</em>', will take you back to the starting document unless you
+specified the <em>-homepage=URL</em> option at the command line. Also, the
+LIST keystroke command, normally mapped to '<em>l</em>' and <em>L</em>',
+will create a compact list of all the links in the current document, and
+they can be selected via that list.
+
+<p>The '<em>i</em>' key presents an index of documents. The default index
+is usually a document pointing to servers around the world, but the index
+can be changed by the system administrator or on the command line using
+the <em>-index=URL</em> switch, and therefore depends on how the Lynx
+program you are using was configured.
+
+<p>If you choose a link to a server with active access authorization, Lynx
+will automatically prompt for a username and a password. If you give the
+correct information, you will then be served the requested information.
+Lynx will automatically send your username and password to the same server
+if it is needed again. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="7"
+><em>Printing, Mailing, and Saving rendered files to disk.</em></A></h2>
+
+Rendered HTML documents, and plain text files, may be printed using the
+'<em>p</em>' command while viewing the document. After pressing the
+'<em>p</em>' key a menu of <em>Print Options</em> will be displayed. The
+menu will vary according to several factors. First, some sites set up
+special accounts to let users run Lynx to access local information systems.
+Typically these accounts require no passwords and do not require users to
+identify themselves. As a result such accounts are called "anonymous"
+accounts, and their users are considered "anonymous" users. In most
+configurations, all Lynx users (including anonymous users) are able to
+mail files to themselves and print the entire file to the screen.
+
+<p>Additional print options are available for users who are using
+Lynx from their own accounts (that is, so-called "non-anonymous
+users"). In particular, the <em>Save to a local file</EM>
+option allows you to save the document into a file on your disk
+space. Any number of additional print options may also be
+available as configured by your system administrator.
+
+<p>Some options, such as <em>Save to a local file</em>, involve prompting
+for an output filename. All output filename entries are saved in a
+circular buffer, and any previous entries can be retrieved for re-use by
+pressing the <em>up-arrow</em> or <em>down-arrow</em> keys at the prompt.
+
+<p>Note that if you want exact copies of text files without any expansions
+of TAB characters to spaces you should use the <a href="#9">Download</a>
+options. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="8"
+><em>Viewing the HTML document source and editing documents</em></A></h2>
+
+When viewing HTML documents it is possible to retrieve and display the
+unrendered (i.e., the original HTML) source of the document by pressing
+the '<em>\</em>' (backslash) key. The document must be reloaded from the
+server or disk to be displayed on the screen unrendered, since Lynx
+originally rendered what it received and does not still have it as source.
+When viewing unrendered documents you may print them as any normal document.
+
+<p>Selecting the <em>Print to a local file</em> option from the Print Menu,
+makes it possible to save the source of the document to disk so that you
+may have a local copy of the document source, but it is better to <a
+href="#9">Download</a> the source.
+
+<p>NOTE: When saving an HTML document it is important to name the
+document with a <em>.html</em> extension, if you want to read it with
+Lynx again later.
+
+<p>Lynx can allow users to edit documents that reside on the local
+system. To enable editing, documents must be referenced using a
+"file:" URL or by specifying a plain filename on the command line as
+in the following two examples:
+
+<dl>
+<dt>Command
+ <dd><code>lynx file://localhost/FULL/PATH/FILENAME</code>
+ <dd><code>lynx path/filename.html</code>
+</dl>
+
+In addition, the user must also specify an editor in the
+<em>Options Menu</em> so that Lynx knows which editor to use. If the
+file is specified correctly and an editor is defined, then you may edit
+documents by using the '<em>e</em>' command. When the '<em>e</em>'
+command is entered your specified editor is spawned to edit the file.
+After changes are completed, exit your editor and you will return to Lynx.
+Lynx will reload and render the file so that changes can be immediately
+examined. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="9"><em>Downloading and Saving source files.</em></A></h2>
+
+If the DOWNLOAD keystroke command ('<em>d</em>' or <em>D</em>) is used
+when positioned on a link for an HTML, plain text, or binary file, Lynx
+will transfer the file, without rendering or modification, into a temporary
+location and present the user with a list of options, as when a link for a
+binary file of a type for which no viewer has been mapped is activated.
+As described above, the only default <em>Download option</em> is
+<em>Save to disk</em>, which is disabled if Lynx is running in
+anonymous mode, and any number of additional download methods such as
+kermit and zmodem may be defined in the <em>lynx.cfg</em> file by the
+system administrator. Downloading the sources of HTML and plain text
+files, instead of toggling to <a href="#8">display the source</a>
+('<em>\</em>') and then using <a href="#7">Printing</a> options, ensures
+that no modifications of the source (e.g., expansions of TAB characters
+to a series of spaces) will occur.
+
+<p>Some options, such as <em>Save to disk</em>, involve prompting for an
+output filename. All output filename entries are saved in a circular buffer,
+and any previous entries can be retrieved for re-use by pressing the
+<em>up-arrow</em> or <em>down-arrow</em> keys at the prompt.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="10"
+><em>Reloading files and refreshing the display</em></A></h2>
+
+The RELOAD (<em>Control-R</em>) command will reload and re-render the file
+that you are currently viewing. The REFRESH (<em>Control-L</em> or
+<em>Control-W</em>) command will refresh or wipe the screen to remove or
+correct any errors that may be caused by operating system or other messages.
+
+<p>The NOCACHE ('<em>x</em>' or '<em>X</em>') command can be used in lieu
+of ACTIVATE (<em>Return</em> or <em>right-arrow</em>) to request an uncached
+copy and new rendition for the current link, or resubmission of a FORM, if a
+cache from a previous request or submission exits. The request or submission
+will include <em>Pragma: no-cache</em> and <em>Cache-Control: no-cache</em>
+in its headers. Note that FORMs with POST content will be resubmitted
+regardless of whether the NOCACHE or ACTIVATE command is used (see <A
+HREF="#19"><em>Lynx and HTML Forms</em></A>). [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="11"><em>Lynx searching commands</em></A></h2>
+
+Two commands activate searching in Lynx: '<em>/</em>' and '<em>s</em>'.
+
+<p>While viewing a normal document use the '<em>/</em>' command to find a
+word or phrase within the current document. The search type will depend on
+the search option setting in the <a href="#12">Options Menu</a>. The search
+options are case sensitive and case insensitive. These searches are entirely
+local to Lynx.
+
+<p>Some documents are designated <em>index documents</em> by virtue of an
+ISINDEX element in their HEAD section. These documents can be used to
+retrieve additional information based on searches using words or phrases
+submitted to an index server. The Lynx statusline will indicate that you
+are viewing such a document, and if so, the '<em>s</em>' key will invoke a
+statusline prompt to enter a query string. The prompt can be specified via
+a PROMPT attribute in the ISINDEX element. Otherwise, Lynx will use an
+internally configured prompt. The address for submitting the search can be
+specified via an HREF or ACTION attribute. Otherwise, Lynx will use the
+current document's URL and append your query string as a <em>?searchpart</em>
+(see <a href="lynx_url_support.html">Supported URLs</a>).
+
+<p>All search words or strings which you have entered during a Lynx session
+are saved in a circular buffer, and can be retrieved for re-use by pressing
+the <em>up-arrow</em> or <em>down-arrow</em> keys at the prompt for a search
+word or string. Also, you can use the '<em>n</em>'ext command to repeat a
+search with the last-entered search word or phrase, starting from the current
+position in the document. The word or phrase matches will be highlighted
+throughout the document, but such highlighting will not persist for new
+documents, or if the current document is reloaded. The search cycles to the
+top of the document if the word or phrase is not located below your current
+position.
+
+<p>Although <a href="#19">HTML Forms</a> have largely replaced index
+documents for searches via http servers, they are still useful for performing
+searches directly via WAIS or Gopher servers in conjunction with the internal
+gateways for such servers. For example, an HTML index document can act as a
+<em>cover page</em> describing a WAIS database and how to formulate query
+strings for searching it, and include an element such as:<BR>
+<tab indent="12"><em>&lt;ISINDEX <tab id="idx">PROMPT="Enter WAIS query:"<BR>
+<tab to="idx">HREF="wais://net.bio.net/biologists-addresses"&gt;</em><BR>
+for submitting a search of the Biologist's Addresses database directly
+to the net.bio.net WAIS server. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="12"><em>Lynx Options Menu</em></A></h2>
+
+The Lynx <em>Options Menu</em> may be accessed by pressing the '<em>o</em>'
+key. The current <em>Options Menu</em> contains the following configurable
+options.
+
+<pre>
+ Options Menu
+
+ E)ditor : emacs
+ D)ISPLAY variable : aixtest.cc.ukans.edu:0.0
+ mu(L)ti-bookmarks: OFF B)ookmark file: lynx_bookmarks.html
+ F)TP sort criteria : By Filename
+ P)ersonal mail address : montulli@netscape.com
+ S)earching type : CASE INSENSITIVE
+ preferred document lan(G)uage: en
+ preferred document c(H)arset : NONE
+ display (C)haracter set : ISO Latin 1
+ raw 8-bit or CJK m(O)de : ON show color (&) : OFF
+ V)I keys: OFF e(M)acs keys: OFF sho(W) dot files: OFF
+ popups for selec(T) fields : ON show cursor (@) : OFF
+ K)eypad mode : Numbers act as arrows
+ li(N)e edit style : Default Binding
+ l(I)st directory style : Mixed style
+ U)ser mode : Advanced
+ user (A)gent : [User-Agent header]
+ local e(X)ecution links : FOR LOCAL FILES ONLY
+</pre>
+
+An option can be changed by entering the capital letter or character in
+parentheses for the option you wish to change (e.g. '<em>E</em>' for Editor
+or '<em>@</em>' for show cursor). For fields where text must be entered,
+simply enter the text by typing on the keyboard. The <a
+href="keystrokes/edit_help.html">Line Editor</a> can be used to
+correct mistakes, and <em>Control-U</em> can be used to erase the whole
+line. When you are done entering a change press the <em>Return</em> key
+to get back to the <em>Command?</em> prompt.
+
+<p>For fields where you must choose one of two choices, press any key
+to toggle the choices and press the <em>Return</em> key to finish the
+change.
+
+<p>For fields where you potentially have more than two choices, popup
+windows may be evoked which function homologously to those for select
+fields in <a href="#19">HTML Forms</a>. The popup windows will be invoked
+only if you have popups for select fields set to ON (see below). Otherwise,
+your cursor will be positioned at the current choice, and you can press any
+key to cycle through the choices, then press the <em>Return</em> key to
+finish the change.
+
+<p>When you are done changing options use the '<em>r</em>' command to
+return to Lynx or the '<em>&gt;</em>' command to save the options to a
+<em>.lynxrc</em> file and return to Lynx.
+
+<p>The following table describes the options available on the
+<em>Options Menu</em>:
+
+<dl>
+ <dt>Editor
+ <dd>The editor to be invoked when editing browsable files, and
+ sending mail or comments. The full pathname of the editor
+ command should be specified when possible.
+
+ <dt>DISPLAY variable
+ <dd>This option is only relevant to X Window users. The DISPLAY
+ (Unix) or DECW$DISPLAY (VMS) variable is picked up automatically
+ from the environment if it has been previously set.
+
+ <dt>Multi-bookmarks
+ <dd>Lynx supports a default bookmark file, and up to 26 total
+ bookmark files (see below). When multi-bookmarks is OFF,
+ the default bookmark file is used for the '<em>v</em>'iew
+ bookmarks and '<em>a</em>'dd bookmark link commands. If
+ multi-bookmark support is available in your account, the
+ setting can be changed to STANDARD or ADVANCED. In STANDARD
+ mode, a menu of available bookmarks always is invoked when
+ you seek to view a bookmark file or add a link, and you select
+ the bookmark file by its letter token (see
+ <em>Bookmark file</em>, below) in that menu. In ADVANCED mode,
+ you instead are prompted for the letter of the desired bookmark
+ file, but can enter '<em>=</em>' to invoke the STANDARD selection
+ menu, or <em>RETURN</em> for the default bookmark file.
+
+ <dt>Bookmark file
+ <dd>When multi-bookmarks is OFF, this is the filename and location
+ of your default personal bookmark file. Enter '<em>B</em>' to
+ modify the filename and/or location via the <a
+ href="keystrokes/edit_help.html">Line Editor</a>.
+ Bookmark files allow frequently traveled links to be stored in
+ personal easy to access files. Using the '<em>a</em>'dd bookmark
+ link command (see <a href="#15">Lynx bookmarks</a>) you may save
+ any link that does not have associated POST content into a
+ bookmark file. All bookmark files must be in or under your
+ account's home directory. If the location specified does not
+ begin with a dot-slash (./), its presence will still be assumed,
+ and referenced to the home directory. When multi-bookmarks is
+ STANDARD or ADVANCED, entering '<em>B</em>' will invoke a menu
+ of up to 26 bookmark files (associated with the letters of the
+ English alphabet), for editing their filenames and locations
+ (<em>filepath</em>), and descriptions. Lynx will create bookmark
+ files, if they don't already exist, when you first '<em>a</em>'dd
+ a bookmark link to them. However, if you've specified a
+ subdirectory (e.g., ./BM/lynx_bookmarks.html), that subdirectory
+ must already exist. Note that on VMS you should use the URL
+ syntax for the filepath (e.g., <em>not</em>
+ [.BM]lynx_bookmarks.html).
+ For Win32, see [???].
+
+ <dt>FTP sort criteria
+ <dd>This option allows you to specify how files will be sorted
+ within FTP listings. The current options include
+ "<code>By Filename</code>", "<code>By Size</code>",
+ "<code>By Type</code>", and "<code>By Date</code>".
+
+ <dt>Personal mail address
+ <dd>This mail address will be used to help you send files to
+ yourself and will be included as the From: address in any mail
+ or comments that you send. It will also be sent as the From:
+ field in HTTP or HTTPS requests if inclusion of that header
+ has been enabled via the NO_FROM_HEADER definition in lynx.cfg
+ (the compilation default is not to send the header), or via the
+ <em>-from</em> command line toggle.
+
+ <dt>Searching type
+ <dd>Searching type has two possible values: CASE INSENSITIVE
+ (default) and CASE SENSITIVE. The searching type effects
+ inter-document searches only, and determines whether searches
+ for words within documents will be done in a case-sensitive or
+ case-insensitive manner.
+
+ <dt>Preferred Document Language
+ <dd>The language you prefer if multi-language files are available
+ from servers. Use RFC 1766 abbreviations, e.g., en for English,
+ fr for French, etc. Can be a comma-separated list, which may
+ be interpreted by servers as descending order of preferences.
+ You can also make your order of preference explicit by using
+ q factors as defined by the HTTP protocol, for servers which
+ understand it, for example:
+ da,&nbsp;en-gb;q=0.8,&nbsp;en;q=0.7
+
+ <dt>Preferred Document Charset
+ <dd>The character set you prefer if sets in addition to ISO-8859-1
+ and US-ASCII are available from servers. Use MIME notation
+ (e.g., ISO-8859-2) and do not include ISO-8859-1 or US-ASCII,
+ since those values are always assumed by default. Can be a
+ comma-separated list, which may be interpreted by servers as
+ descending order of preferences. You can also make your order
+ of preference explicit by using q factors as defined by the
+ HTTP protocol, for servers which understand it, for example:
+ iso-8859-5,&nbsp;utf-8;q=0.8
+
+ <dt>Display Character set
+ <dd>This option allows you to set up the default character set for
+ your specific terminal. The display character set provides a
+ mapping from the character encodings of viewed documents and
+ from HTML entities into viewable characters. It should be set
+ according to your terminal's character set so that characters
+ other than 7-bit ASCII can be displayed correctly, using
+ approximations if necessary. You must have the selected
+ character set installed on your terminal.
+
+ <dt>Raw 8-bit or CJK Mode
+ <dd>Whether 8-bit characters are assumed to correspond with the
+ selected character set and therefore are processed without
+ translation via the chartrans conversion tables. Should be ON
+ by default when the selected character set is one of the Asian
+ (CJK) sets and the 8-bit characters are Kanji multibytes.
+ Should be OFF for the other character sets, but can be turned ON
+ when the document's charset is unknown (e.g., is not ISO-8859-1
+ and no charset parameter was specified in a reply header from
+ an HTTP server to indicate what it is) but you know by some
+ means that you have the matching display character set selected.
+ Should be OFF when an Asian (CJK) set is selected but the document
+ is ISO-8859-1. The setting also can be toggled via the RAW_TOGGLE
+ command, normally mapped to '<em>@</em>', and at startup via the
+ <em>-raw</em> switch.
+
+ <dt>Show color.
+ <dd>This option will be present if color support is available.
+ If set to ON or ALWAYS, color mode will be forced on if possible.
+ If (n)curses color support is available but cannot be used for
+ the current terminal type, selecting ON is rejected with a message.
+ If set to OFF or NEVER, color mode will be turned off.<BR>
+ ALWAYS and
+ NEVER are not offered in anonymous accounts. If saved to a
+ <em>.lynxrc</em> file in non-anonymous accounts, ALWAYS will
+ cause Lynx to set color mode on at startup if supported.
+ If Lynx is built with the slang library, this is equivalent to
+ having included the <em>-color</em> command line switch or having the
+ <em>COLORTERM</em> environment variable set. If color support is
+ provided by curses or ncurses, this is equivalent to the default
+ behavior of using color when the terminal type supports it.
+ If (n)curses color support is available but cannot be used for
+ the current terminal type, the preference can still be saved
+ but will have no effect.<BR>
+ A saved value of NEVER will
+ cause Lynx to assume a monochrome terminal at startup.
+ It is similar to the <em>-nocolor</em> switch, but (when the
+ slang library is used) can be overridden with the <em>-color</em>
+ switch.<BR>
+ If the setting is OFF or ON
+ when the current options are saved to a <em>.lynxrc</em> file,
+ the default startup behavior is retained, such that color mode
+ will be turned on at startup only if the terminal info indicates
+ that you have a color-capable terminal, or (when the
+ slang library is used) if forced on via the
+ <em>-color</em> switch or <em>COLORTERM</em> variable. This
+ default behavior always is used in anonymous accounts, or if
+ the <em>option_save</em> restriction is set explicitly. If
+ for any reason the startup color mode is incorrect for your
+ terminal, set it appropriately on or off via this option.
+
+ <dt>VI keys
+ <dd>If set to ON then the lowercase h, j, k, and l keys will be
+ mapped to left, down, up, and right arrow, respectively. The
+ uppercase H, J, K, and L keys remain mapped to their configured
+ bindings (normally HELP, JUMP, KEYMAP, and LIST, respectively).
+
+ <dt>Emacs keys
+ <dd>If set to ON then the CTRL-P, CTRL-N, CTRL-F, and CTRL-B keys
+ will be mapped to up-arrow, down-arrow, right-arrow, and
+ left-arrow, respectively. Otherwise, they remain mapped to
+ their configured bindings (normally UP_TWO lines, DOWN_TWO
+ lines, NEXT_PAGE, and PREV_PAGE, respectively).
+
+ <dt>Show dot files
+ <dd>If display/creation of hidden (dot) files/directories is
+ enabled, you can turn the feature on or off via this setting.
+
+ <dt>Popups for select fields
+ <dd>Lynx normally uses a popup window for the OPTIONs in form
+ SELECT fields when the field does not have the MULTIPLE
+ attribute specified, and thus only one OPTION can be selected.
+ The use of popup windows can be disabled by changing this setting
+ to OFF, in which case the OPTIONs will be rendered as a list of
+ radio buttons. Note that if the SELECT field does have the
+ MULTIPLE attribute specified, the OPTIONs always are rendered
+ as a list of checkboxes.
+
+ <dt>Show cursor for current link or option.
+ <dd>Lynx normally hides the cursor by positioning it to the right
+ and if possible the very bottom of the screen, so that the
+ current link or OPTION is indicated solely by its highlighting
+ or color. If show cursor is set to ON, the cursor will be
+ positioned at the left of the current link or OPTION. This
+ is helpful when Lynx is being used with a speech or braille
+ interface. It also is useful for sighted users when the
+ terminal cannot distinguish the character attributes used
+ to distinguish the current link or OPTION from the others in
+ the screen display.
+
+ <dt>Keypad as arrows, numbered links, or numbered links and form fields
+ <dd>This option gives the choice among navigating with the arrow
+ keys, or having every link numbered so that the links may be
+ selected or made current by numbers as well as using the arrow
+ keys, or having every link as well as every form field numbered
+ so that they can be selected or sought by numbers. See the<br>
+ &nbsp;&nbsp<a href="keystrokes/follow_help.html"
+ >Follow link (or page) number:</a> and<br>
+ &nbsp;&nbsp<a
+ href="keystrokes/follow_help.html#select-option"
+ >Select option (or page) number:</a><br>
+ help for more information.
+
+ <dt>Line edit style
+ <dd>This option allows you to set alternate key bindings for the
+ built-in line editor, if your system administrator has installed
+ alternates. Otherwise, Lynx uses the <a
+ href="keystrokes/edit_help.html">Default Binding</a>.
+
+ <dt>List directory style
+ <dd>Applies to Directory Editing. Files and directories can be
+ presented in the following ways:
+ <dl>
+ <dt>Mixed style
+ <dd>Files and directories are listed together in alphabetical
+ order.
+ <dt>Directories first
+ <dd>Files and directories are separated into two alphabetical
+ lists. Directories are listed first.
+ <dt>Files first
+ <dd>Files and directories are separated into two alphabetical
+ lists. Files are listed first.
+ </dl>
+
+ <dt>User Mode
+ <dd>There are three possible choices: Novice, Intermediate, and
+ Advanced.
+ <dl>
+ <dt>Novice
+ <dd>In Novice mode two lines of help are displayed at the
+ bottom of the screen.
+ <dt>Intermediate
+ <dd>Intermediate mode turns off the help lines.
+ <dt>Advanced
+ <dd>Advanced mode displays the URL of the currently selected
+ link at the bottom of the screen.
+ </dl>
+
+ <dt>User Agent
+ <dd>The header string which Lynx sends to servers to indicate the
+ User-Agent is displayed here. Changes may be disallowed via
+ the <em>-restrictions</em> switch. Otherwise, the header can be
+ changed temporarily to a string such as <em>L_y_n_x/2.8</em>
+ for access to sites which discriminate against Lynx based on
+ checks for the presence of &quot;Lynx&quot; in the header. If
+ changed during a Lynx session, the default User-Agent header can
+ be restored by deleting the modified string in the
+ <em>Options Menu</em>. Whenever the User-Agent header is
+ changed, the current document is reloaded, with the no-cache
+ flags set, on exit from the <em>Options Menu</em>. Changes of
+ the header are not saved in the RC file.
+ <dd><em>NOTE</em> that Netscape Communications Corp. has claimed
+ that false transmissions of "Mozilla" as the User-Agent are a
+ copyright infringement, which will be prosecuted. <em>DO NOT</em>
+ misrepresent Lynx as Mozilla. The <em>Options Menu</em> issues
+ a warning about possible copyright infringement whenever the
+ header is changed to one which does not include &quot;Lynx&quot;
+ or &quot;lynx&quot;.
+
+ <dt>Local execution scripts or links
+ <dd>Local execution can be activated by the system administrator.
+ If it has not been activated you will not see this option
+ in the <em>Options Menu</em>.
+ <dd>When a local execution script is encountered Lynx checks the
+ users options to see whether the script can be executed. Users
+ have the following options:
+ <dl>
+ <dt> Always off
+ <dd>Local execution scripts will never be executed
+ <dt>For Local files only
+ <dd>Local execution scripts will only be executed if the
+ script to be executed resides on the local machine,
+ and is referenced by a URL that begins with
+ <em>file://localhost</em>
+ <dt>Always on
+ <dd>All local execution scripts will be executed
+ </dl>
+
+ <dd>If the users options permit the script to be executed Lynx will
+ spawn a shell and run the script. If the script cannot be
+ executed Lynx will show the script within the Lynx window and
+ inform the user that the script is not allowed to be executed
+ and will ask the user to check his/her options.
+ [<A HREF="#TOC">ToC</A>]
+</dl>
+
+<h2><A NAME="13"><em>Comments and mailto: links</em></A></h2>
+
+At any time while viewing documents within Lynx, you may use the
+'<em>c</em>' command to send a mail message to the owner of the current
+document if the author of the document has specified ownership. If no
+ownership is specified then comments are disabled. Certain links called
+<a href="lynx_url_support.html#mailto">mailto:</a> links will also allow
+you to send mail to other people. Using the mail features within Lynx is
+straightforward.
+
+<p>Once you have decided to send a comment or have selected a
+<em>mailto:</em> link a new screen will appear showing you to whom you
+are sending the message. Lynx will ask for your name, your e-mail
+address, and the subject of the message. If you have filled in the
+"personal mail address" field in the <em>Options Menu</em>, your e-mail
+address will be filled in automatically. After entering the above
+information, if you have an editor defined in the <em>Options Menu</em>
+and you are not an anonymous user then your specified editor will be
+spawned for you so that you can enter your message. If you do not have
+an editor defined or you are an anonymous user, a simple line mode input
+scheme will allow you to enter your message.
+
+<p>To finish sending the message, exit your spawned editor or, if you are
+using the simple line mode input scheme, type a '<em>.</em>' (period) on
+a line by itself. You will be asked a final time whether to send the
+message. If you press '<em>y</em>', you will be prompted whether to
+append your signature file if one was defined in lynx.cfg and is accessible,
+and then the message will be sent, whereas if you press '<em>n</em>' the
+message will be deleted. Entering Control-G in response to any prompts
+also will cancel the mailing.[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="14"><em>USENET News posting</em></A></h2>
+
+While reading <a
+href="http://www.w3.org/hypertext/DataSources/News/Groups/Overview.html"
+>news</a> articles with Lynx you should see a link that says
+<em>Reply to: user@host</em> and, if the nntp server from which you
+received the article supports posting from your site, a link that says
+<em>Followup to: newsgroup(s)</em>
+
+<dl>
+ <dt>Reply to user@host
+ <dd>user@host will correspond to the mail address of the
+ person who posted the news article. Selecting the link will
+ allow you to send a message to the person who wrote the message
+ you are currently viewing. You will be given the option of
+ including the original message in your reply.
+
+ <dt>Followup to newsgroup(s)
+ <dd>Selecting this link will allow you to post back to the
+ newsgroup that you are currently reading and any newsgroups
+ to which the message was cross-posted. You will be given
+ the option of including the original message in your reply.
+ Once you have typed in your message, you will be asked for
+ confirmation of whether to proceed with the posting, and
+ whether to append your signature file if one was defined in
+ lynx.cfg and is accessible. See <a
+ href="lynx_url_support.html">Supported URLs</a> for more
+ information about the URL schemes for posting or sending
+ followups (replies) to nntp servers with Lynx.
+ [<A HREF="#TOC">ToC</A>]
+</dl>
+
+<h2><A NAME="15"><em>Lynx bookmarks</em></A></h2>
+
+It is often useful to place a bookmark to aid in returning quickly to
+a document. To use the bookmark feature you must first use the
+<em>Options Menu</em> to specify a bookmark filename.
+
+<p>To save a bookmark to the document you wish to place in the
+bookmark file press the '<em>a</em>' key and you will be asked:
+
+<blockquote>
+ Save D)ocument or L)ink to bookmark file or C)ancel? (d,l,c):
+</blockquote>
+
+Answer '<em>d</em>' to save a link to the document you are currently
+viewing or '<em>l</em>' to save the link that is currently selected on
+the page. Selecting '<em>c</em>' will cancel without saving anything to
+your bookmark file.
+
+<p>A bookmark file will be created in conjunction with acting on the
+'<em>a</em>'dd command if it does not already exist. Otherwise, the link
+will be added to the bottom of the pre-existing bookmark file. You must
+have created a bookmark file via the '<em>a</em>'dd command before you
+can view it.
+
+<p>Use the '<em>v</em>' command to view the list of bookmarks you have
+saved. While viewing the bookmark list you may select a bookmark as you
+would any other link.
+
+<p>You can remove a link from the bookmark list by pressing the
+'<em>r</em>' key when positioned on that link. You also can use a
+standard text editor (e.g., via the '<em>e</em>'dit command while viewing
+a bookmark file, if an external editor has been defined via the <em>Options
+menu</em>) to delete or re-order links in the bookmark file, or to modify
+a link name by editing the content of the <em>A</em>nchor element for the
+link, but you should not change the format within the line for the link,
+consisting of an <em>LI</em> element followed by the <em>A</em>nchor
+element, nor cause the line to become wrapped to a second line. You
+similarly can change the link destination by editing the double-quoted
+value for the <em>HREF</em> attribute in the <em>A</em>nchor start tag,
+but you should not otherwise change the spacing within the start tag, nor
+add other attributes. You can add a new link while editing by copying
+an existing line for a link, to ensure the proper format, and then
+modifying its <em>HREF</em> value and <em>A</em>nchor content, but you
+should not add any other HTML markup to the bookmark file. If the format
+and spacing (other than the <em>A</em>nchor content or <em>HREF</em> value)
+within lines is changed or other HTML markup is added, the '<em>a</em>'dd
+and '<em>r</em>'emove commands may not work properly.
+
+<p>When multi-bookmarks (see <a href="#12">Options Menu</a>) is OFF,
+you will always view or add links to the default bookmark file. When
+it is STANDARD, a menu of up to 26 bookmark files will be invoked,
+and you select the bookmark file by entering its letter token. When
+it is ADVANCED, you will be prompted for the letter token, but can
+enter '<em>=</em>' to invoke the STANDARD selection menu, or
+<em>RETURN</em> for the default bookmark file.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="16"><em>Jump Command</em></a></h2>
+
+A feature similar to the Lynx bookmarks is the jump command. The jump
+command allows you to enter a shortcut name to access a URL. If the jump
+feature is active, typing '<em>j</em>' will produce a prompt where you may
+enter the shortcut name. Type '<em>?</em>' at the jump prompt for a list
+of shortcut names available.
+
+<p>All jump shortcut entries are saved in a circular buffer, and any
+previous entries can be retrieved for re-use by pressing the
+<em>up-arrow</em> or <em>down-arrow</em> keys at the prompt.
+
+<p>Note to System Administrators: Read the <em>lynx.cfg</em> file on how
+to set up the jump command for your system and how to define shortcut names.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="17"><em>Directory Editing</em></a></h2>
+
+Lynx offers extended DIRED support on Unix (on VMS the more powerful
+CSwing program is recommended for character cell terminals, and can be
+offered via Lynx as a jump shortcut or execution link). When a local
+directory is accessed using a URL of the form
+<em>file://localhost/path/</em>, a new set of commands is available.
+With DIRED support you can create, edit, delete, copy, and move files
+on your local system. The commands available in DIRED mode are
+
+<dl>
+<dt><code>C)reate</code>
+<dd>Type '<em>c</em>' to create a new file. New file will be empty.
+
+<dt><code>D)ownload</code>
+<dd>Type '<em>d</em>' to download selection using one of the options defined
+ by your system administrator.
+
+<dt><code>E)dit</code>
+<dd>Type '<em>e</em>' to spawn the editor defined in <em>Options Menu</em>
+ and load a selected file for editing.
+
+<dt><code>F)ull Menu</code>
+<dd>Type '<em>f</em>' to show full menu of options available for selection.
+ Menu may vary according to type of file selected and compression
+ facilities available.
+
+<!-- List of full menu options -->
+<dt><code>M)odify</code>
+<dd>Type '<em>m</em>' to modify the name or location of file. Then type
+ '<em>n</em>' to rename the file or '<em>l</em>' to move the file to
+ a different location.
+
+<dt><code>R)emove</code>
+<dd>Type '<em>r</em>' to remove the selected file or directory.
+
+<dt><code>T)ag</code>
+<dd>Type '<em>t</em>' to tag highlighted file. Further operations will be
+ performed on tagged files instead of highlighted ones.
+
+<dt><code>U)pload</code>
+<dd>Type '<em>u</em>' to upload a file to the present directory. Upload
+ methods are defined by your system administrator.
+</dl>
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="18"><em>Scrolling and Other useful commands</em></A></h2>
+
+A summary of all the keystroke commands and their key bindings can
+be invoked via the KEYMAP command, normally mapped to '<em>k</em>' and
+'<em>K</em>'. The following describes some of the most commonly used
+commands.
+
+<dl>
+ <dt><em>^A</em>
+ <dd><em>Control-A</em> jumps you to the beginning of the current
+ document. It is a synonym for the Keypad <em>Home</em> key, and
+ can be used also when <em>Links are numbered</em> mode is on. The
+ <em>Find</em> Function key also is a synonym, and ideally the
+ latter has been mapped to the Function key labeled <em>Home</em>
+ if you are using an IBM Enhanced Keyboard.
+ <dt><em>^E</em>
+ <dd><em>Control-E</em> jumps you to the end of the current document.
+ It is a synonym for the Keypad <em>End</em> key, and can be used
+ also when <em>Links are numbered</em> mode is on. The <em>Select</em>
+ Function key also is a synonym, and ideally the latter has been
+ mapped to the Function key labeled <em>End</em> if you are using
+ an IBM Enhanced Keyboard.
+ <dt><em>^B</em>
+ <dd><em>Control-B</em> normally jumps you to the previous page of
+ the current document, and thus is a synonym for the Keypad and
+ Function <em>Page-Up</em> keys. However, <em>Control-B</em>
+ acts as <em>right-arrow</em> when emacs-like key movement is
+ enabled (see <A HREF="#12">Lynx Options Menu</A>).
+ <dt><em>^F</em>
+ <dd><em>Control-F</em> normally jumps you to the next page of the
+ current document, and thus is a synonym for the Keypad and
+ Function <em>Page-Down</em> keys. However, <em>Control-F</em>
+ becomes <em>right-arrow</em> when emacs-like key movement is
+ enabled.
+ <dt><em>^N</em>
+ <dd><em>Control-N</em> normally jumps you forward two lines in the
+ current document. The <em>Remove</em> Function key (labeled
+ <em>Delete</em> on IBM Enhanced keyboards, and distinct
+ from their <em>Backspace</em> key) is a synonym.
+ <em>Control-N</em> becomes <em>down-arrow</em> when emacs-like
+ key movement is enabled.
+ <dt><em>^P</em>
+ <dd><em>Control-P</em> normally jumps you back two lines in the
+ current document. The <em>Insert</em> Function key is a synonym.
+ <em>Control-P</em> becomes <em>up-arrow</em> when emacs-like
+ key movement is enabled.
+ <dt><em>)</em>
+ <dd>The <em>)</em> command jumps you forward half a page in the
+ current document.
+ <dt><em>(</em>
+ <dd>The <em>(</em> command jumps you back half a page in the
+ current document.
+ <dt><em>#</em>
+ <dd>The '<em>#</em>' command jumps you to the pseudo Toolbar or
+ Banner if present in the current document. Use
+ <em>left-arrow</em> to return from there to your previous
+ position in the document.
+ <dt><em>!</em>
+ <dd>When '<em>!</em>' is pressed your default shell will be spawned.
+ When you quit or exit the shell you will return to Lynx (usually
+ <em>exit</em> under Unix and <em>logout</em> under VMS). This
+ command is usually disabled for anonymous users. On VMS,
+ '<em>$</em>' normally is a synonym.
+ On Win32, this has no effect [???].
+ <dt><em>g</em>
+ <dd>The '<em>g</em>' command allows any URL to be viewed. Pressing
+ the '<em>g</em>' command will bring up a prompt asking for a URL.
+ Type in the URL that you wish to view. All previously entered
+ goto URLs are saved in a circular buffer, and can be accessed at
+ the prompt by pressing the <em>up-arrow</em> or
+ <em>down-arrow</em> keys.
+ <dt><em>G</em>
+ <dd>The '<em>G</em>' command allows you to edit the URL of the
+ current document and then use that as a goto URL. Pressing
+ the '<em>G</em>' command will bring up a prompt asking you
+ to edit the current document's URL. If you do not modify
+ it, or completely delete it, or enter Control-G, the command
+ will be cancelled. If the current document has POST content
+ associated with it, an Alert will be issued. If you do edit
+ that URL, and it does not simply involve a fragment change
+ (for seeking a position in the current document), the modified
+ URL will be submitted with method GET and no POST content. If
+ a modification of the current document's URL results in a
+ submission, that modified URL will be entered into the circular
+ buffer for goto URLs, and can be accessed for further
+ modification via the '<em>g</em>' command.
+
+ <dt><em>E</em>
+ <dd>The '<em>E</em>' command allows you to edit the URL (or ACTION)
+ of the current link and then use that as a goto URL. Pressing
+ the '<em>E</em>' command will bring up a prompt asking you
+ to edit the current link's URL. If you do not modify it, or
+ completely delete it, or enter Control-G, the command will be
+ cancelled. Otherwise, the request for the 'E'dited URL will be
+ sent with method GET, and will be entered into the circular
+ buffer for goto URLs so that it can be accessed for further
+ modification via the '<em>g</em>' command. Note that lower
+ case 'e' invokes the editor for the current document.
+
+ <dt><em>=</em>
+ <dd>The '<em>=</em>' command shows information about the current
+ document and the currently selected link if there is one. The
+ number of lines in the file, URL, title, owner, and type are
+ shown.
+ <dt><em>^T</em>
+ <dd><em>Control-T</em> toggles Lynx trace mode on and off. This is
+ useful for diagnosing bad html. If you get a <em>Bad HTML</em>
+ statusline message when loading a document, enter
+ <em>Control-T</em> and then <em>Control-R</em> to reload the
+ document in trace mode. You also can submit the document for
+ validation via links in the online help menu. If you are able
+ to diagnose the problem, send a message about it to the
+ document's author.
+ <dt><em>;</em>
+ <dd>The <em>;</em> command shows the <em>Lynx Trace Log</em>
+ (<em>lynx.trace</em> in the home directory) if one has been
+ started for the current session. If a log has not been started,
+ any trace and other stderr messages will be sent to the screen
+ (and will disturb the normal display) unless the system supports
+ piping and that was used to redirect stderr messages to a file.
+ The log is started when Lynx trace mode is turned on via the
+ <em>-trace</em> command line switch, or via the
+ <em>Control-T</em> toggle, if Lynx has been compiled to log
+ the trace and other stderr messages. If not, ability to
+ create a log can be toggled on with the <em>-tlog</em> switch.
+ Note that this ability is disabled in anonymous or validation
+ accounts.
+ <dt><em>*</em>
+ <dd>The '<em>*</em>' command toggles image_links mode on and off.
+ When on, links will be created for all images, including inlines.
+ If you have an image viewer mapped to the image's MIME type, you
+ can activate such links to view an inline image. You should
+ normally have this mode toggled off.
+ <dt><em>@</em>
+ <dd>The '<em>@</em>' command toggles raw 8-bit or CJK mode on and off.
+ When on, the charset is assumed to match the selected character
+ set and 8-bit characters are not reverse translated with respect
+ to the ISO-8859-1 conversion tables.
+ <dt><em>[</em>
+ <dd>The '<em>[</em>' command toggles pseudo_inlines mode on and off.
+ When on, inline images which have no ALT string specified will
+ have an <em>[INLINE]</em> pseudo-ALT string inserted in the Lynx
+ display. When off, they will be treated as having ALT="" (i.e.,
+ they'll be ignored). If image_links mode is toggled on, the
+ pseudo-ALT strings will be restored, to serve as links to the
+ inline images' sources.
+ <dt><em>]</em>
+ <dd>The '<em>]</em>' command is used to send HEAD requests for the
+ current document or link. It applies only to documents or links
+ (or form submit buttons) of http servers. A statusline message
+ will notify you if the context for this command was inappropriate.
+ The HEAD requests always are sent to the http server, i.e., Lynx
+ does not retrieve any previous server replies from its cache.
+ Note that for form submissions, http servers vary in whether
+ they'll treat HEAD requests as valid and return the CGI script's
+ headers, or treat it as invalid and return an error message.
+ <dt><em>^K</em>
+ <dd><em>Control-K</em> invokes the <a
+ href="keystrokes/cookie_help.html">Cookie Jar Page</a>
+ if it contains cookies.
+ <dt><em>z</em>
+ <dd>Lynx supports completely interruptible I/O processes. Press the
+ '<em>z</em>' key at any time during a connect or transfer process
+ and the process will be halted. If any data was transferred
+ before the interrupt, it will be displayed.
+ <dt><em>numbers</em>
+ <dd>Lynx offers other, advanced navigation features when numbers
+ are used to invoke the <a
+ href="keystrokes/follow_help.html"
+ >Follow link (or goto link or page) number:</a> or<br>
+ &nbsp;&nbsp;<a
+ href="keystrokes/follow_help.html#select-option"
+ >Select option (or page) number:</a><br>
+ prompts.
+ [<A HREF="#TOC">ToC</A>]
+</dl>
+
+<h2><A NAME="19"><em>Lynx and HTML Forms</em></a></h2>
+
+This section describes the Lynx Forms Interface. HTML gives document
+providers the ability to create on-line forms which may be filled out
+when the document is viewed. When a form is submitted the information
+on the form can be used to search a database or complete a survey.
+
+<p>An HTML Form provides for the use of buttons to perform an action
+(such as <em>submit</em>), checkboxes, radio buttons or popups to select
+options from a list, and fields for entering text.
+<p>
+<dl>
+<dt>Buttons:
+<dd>Buttons are displayed in the same way that Lynx displays links in
+ a document. To "push" the button press the <em>right-arrow</em> or
+ <em>Return</em> key. If it is a form submission button, you also can
+ use the RESUBMIT ('<em>x</em>') or DOWNLOAD ('<em>d</em>') keystroke
+ commands to "push" the button (see below).
+
+<dt>Checkboxes and Radio buttons
+<dd>Checkboxes are displayed as square brackets: <em>[ ]</em> and radio
+ buttons are displayed as parenthesis: <em>( )</em>. When a box is
+ checked or a button selected, an <em>x</em> appears in the brackets:
+ <em>[x]</em> or an asterisk appears within the parenthesis:
+ <em>(*)</em>. To check a box or select a radio button press the
+ <em>right-arrow</em> or <em>Return</em> key.
+
+<dt>Selection Fields
+<dd>Selection fields are displayed as brackets with the default option
+ displayed between them: <em>[default__]</em>. To select an option
+ press the <em>right-arrow</em> or <em>Return</em> key. A box with
+ a border of asterisks (or line-drawing characters) will pop up with
+ the list of possible options listed within the box. Use the
+ <em>up-arrow</em>, <em>down-arrow</em>, <em>page-up</em>,
+ <em>page-down</em>, and other navigation keys to move the cursor
+ among options, and the <em>right-arrow</em> or <em>Return</em> key to
+ select an option. You also can use the '<em>/</em>' and '<em>n</em>'ext
+ <a href="#11">searching</a> commands for navigating to options which
+ contain particular strings. <em>NOTE</em> that the popup menu
+ feature can be disabled via compilation and/or configuration options,
+ or via the <a href="#12">Options Menu</a>, in which case the selection
+ field options will be converted to a list of radio buttons. The default
+ setting for use of popups or radio button lists can be toggled via the
+ <em>-popup</em> command line switch.
+
+<dt> Text Entry Fields
+<dd>Text entry (INPUT) fields are displayed as a row of underscores the
+ length of the entry field: <em>_______</em>. You may enter text directly
+ by typing at the keyboard. Use the <a
+ href="keystrokes/edit_help.html">Line Editor</a> keys to
+ correct errors. If you try to input more text than the field can hold,
+ the line editor will not accept the additional characters. If you fill
+ a text field the cursor will not move off the field but remain at the
+ last field position. Use the <em>up-arrow</em>, and <em>down-arrow</em>,
+ <em>TAB</em> or <em>Return</em> keys to move up, or down from the text
+ entry field. NOTE, however, that <em>Return</em> also will <a
+ href="#submit">submit</a> the form if the text entry field is the
+ only non-hidden field in the form.
+<dd>TEXTAREA fields are handled as if they were a series of text entry
+ (INPUT) fields for which successive lines imply a newline at the end of
+ the preceding line. You enter text on each line to construct the overall
+ message. Any blank lines at the bottom of the TEXTAREA field will be
+ eliminated from the submission. The <em>up-arrow</em>, and
+ <em>down-arrow</em> or <em>Return</em> keys move you to the preceding,
+ or next line of the overall message, as for INPUT fields, and the
+ <em>TAB</em> key will move you down beyond the bottom of the TEXTAREA
+ field, or to the first line on the next page if the overall field
+ extends beyond the currently displayed page.
+</dl>
+
+In general, you can move around the form using the standard Lynx navigation
+keys. The <em>up-arrow</em> and <em>down-arrow</em> keys, respectively,
+select the previous or next field, box, or button. The <em>TAB</em> key
+selects the next field (or next page of a TEXTAREA if it extends onto the
+next page), box, or button.
+
+<p><em>NOTE:</em> If you have a text input field selected you will not
+have access to most of the Lynx keystroke commands, because they are
+interpreted by the <a href="keystrokes/edit_help.html"
+>Line Editor</a> as either text entries or editing commands. Select a
+button or box when you want to use Lynx keystrokes.
+
+<p>To <A name="submit"><em>submit</em></a> the form press
+<em>right-arrow</em> or <em>Return</em> when positioned on the form's
+submit button. If you've submitted the form previously during the Lynx
+session, have not changed any of the form content, and the METHOD was
+<em>GET</em>, Lynx will retrieve from its cache what was returned from the
+previous submission. If you wish to resubmit that form to the server with
+the same content as previously, use the RESUBMIT command ('<em>x</em>') when
+positioned on the submit button. The <em>right-arrow</em> and <em>Return</em>
+keys also will invoke a no-cache resubmission if the reply from a form
+submission included a META element with a no-cache Pragma or Cache-Control
+directive:<BR>
+<tab indent="12"
+><em>&lt;META HTTP-EQUIV="Pragma" CONTENT="no-cache"&gt;</em><BR>
+<tab indent="12"
+><em>&lt;META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"&gt;</em><BR>
+or the server sent a "Pragma" or "Cache-Control" MIME header with a
+no-cache directive.
+
+<p>You also can use the DOWNLOAD ('<em>d</em>') keystroke command when
+positioned on a form submit button if you wish to download the server's
+reply to the submission instead of having Lynx render and display it.
+
+<p>Forms which have <em>POST</em> as the METHOD, or a <a
+href="lynx_url_support.html#mailto">mailto:</a> URL as the ACTION, are always
+resubmitted, even if the content has not changed, when you activate the
+<em>submit</em> button. Lynx normally will not resubmit a form which has
+<em>POST</em> as the METHOD if the document returned by the form has links
+which you activated, and then you go back via the PREV_DOC
+(<em>left-arrow</em>) command or via the <a
+href="keystrokes/history_help.html">History Page</a>. Lynx can be
+compiled so that it resubmits the form in those cases as well, and the default
+can be changed via <em>lynx.cfg</em>, and toggled via the
+<em>-resubmit_posts</em> command line switch.
+
+<p>If the form has one <em>text entry</em> field and no other fields except,
+possibly, hidden INPUT fields not included in the display, then that field
+also serves as a <em>submit</em> button, and pressing <em>right-arrow</em>
+or <em>Return</em> on that field will invoke submission of the form. Be
+sure to use <em>up-arrow</em>, <em>down-arrow</em> or <em>TAB</em> to move
+off the text entry field, in such cases, if it is not your intention to
+submit the form (or to retrieve what was returned from an earlier submission
+if the content was not changed and the METHOD was <em>GET</em>).
+
+<p>Forms can have multiple <em>submit</em> buttons, if they have been
+assigned NAMEs in the markup. In such cases, information about which
+one of the buttons was used to submit the form is included in the form
+content.
+
+<p>Inlined images can be used as submit buttons in forms. If such
+buttons are assigned NAMEs in the markup, for graphic clients they can
+also serve as <a href="#28">image maps</a>, and the x,y coordinates of
+the graphic client's cursor position in the image when it was
+<em>clicked</em> are included in the form content. Since Lynx cannot
+inline the image, and the user could not have moved a cursor from the
+origin for the image, if no alternatives are made available in the
+markup Lynx sends a 0,0 coordinate pair in the form content. Document
+authors who use images as submit buttons, but have at least some concern
+for text clients and sight-challenged Webizens, should include VALUEs for
+the buttons in such markup. Lynx will then display the string assigned
+to the VALUE, as it would for a normal submit button. Some document
+authors incorrectly use an ALT instead of VALUE attribute for this purpose.
+Lynx "cooperates" by treating ALT as a synonym for VALUE when present in
+an INPUT tag with TYPE="image". If neither a VALUE nor an ALT attribute
+is present, Lynx displays "[IMAGE]-Submit" as the string for such buttons.
+If clickable images is set, the "[IMAGE]" portion of the string is a link
+for the image, and the "Submit" portion is the button for submitting the
+form. Otherwise, the entire string is treated as a submit button. If
+a VALUE or ALT attribute is present and clickable images is set, Lynx
+prepends "[IMAGE]" as a link for the image, followed by '-' and then
+the attribute's value as the displayed string for the submit button.
+Note that earlier versions of Lynx would send a name=value pair instead of
+a 0,0 coordinate pair if a TYPE="image" submit button was NAME-ed, had a
+VALUE attribute in the INPUT tag, and was used to submit the form. The
+script which analyzes the form content thus could be made aware whether
+the submission was by a user with a graphic client and had image loading
+turned on, or by a user who did not see the image nor make a conscious
+choice within it. However, requests that this be included in HTML
+specifications consistently have fallen on deaf ears, and thus Lynx now
+"fakes" a 0,0 coordinate pair whether or not a VALUE or ALT attribute is
+present in the INPUT tag. Ideally, the script which analyzes the submitted
+content will treat the 0,0 coordinate pair as an indicator that the user
+did not see the image and make a conscious choice within it.
+
+<p>Forms can have <em>hidden</em> INPUT fields, which are not displayed,
+but have NAMEs and VALUEs included in the content. These often are used
+to keep track of information across a series of related form submissions,
+but have the potential for including information about the user that might
+be considered to represent an invasion of privacy. NOTE, in this regard,
+that Lynx has implemented the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+<em>DISABLED</em> attribute for <em>all</em> of its form fields. These
+can be used to keep track of information across submissions, and to cast
+it unmodifiable in the current form, but keep the user aware that it will
+be included in the submission.
+
+<p>Forms most commonly are submitted to http servers with the content encoded
+as <em>ENCTYPE="application/x-www-form-urlencoded"</em> for analysis by a
+script, and Lynx treats that as the default if no ENCTYPE is specified in the
+FORM start tag. However, you can specify a <a
+href="lynx_url_support.html#mailto">mailto</a> URL as the form's ACTION to
+have the form content sent, instead, to an email address. In such cases, you
+may wish to specify <em>ENCTYPE="text/plain"</em> in the form markup, so that
+the content will not be encoded, but remain readable as plain text.
+
+<p>Lynx also supports <em>ENCTYPE="application/sgml-form-urlencoded"</em>
+for which all reserved characters in the content will be hex escaped, as
+with <em>application/x-www-form-urlencoded</em>, but semicolons
+('<em>;</em>') instead of ampersands ('<em>&amp;</em>') will be used as
+the separator for name=value pairs in the form content. The use of
+semicolons is preferred for forms with the <em>GET</em> METHOD, because
+the <em>GET</em> METHOD causes the encoded form content to be appended
+as a <em>?searchpart</em> for the form's ACTION, and if such URLs are used
+in <em>text/html</em> documents or bookmark files without conversion
+of the ampersands to SGML character references (<em>&amp;amp;</em> or
+<em>&amp;#38;</em>), their being followed by form field NAMEs which might
+correspond to SGML entities could lead to corruption of the intended URL.
+
+<p>NOTE, in this regard, that Lynx converts ampersands to <em>&amp;amp;</em>
+when creating bookmarks, and thus the bookmark links will not be vulnerable
+to such corruptions. Also NOTE that Lynx allows you to save links in your
+bookmark file for documents returned by forms with the <em>GET</em> METHOD,
+and which thus have the content appended as a <em>?searchpart</em>, but not
+if the METHOD was <em>POST</em>, because the content would be lost and the
+link thus would be invalid.
+
+<p>Lynx supports <em>ENCTYPE="multipart/form-data"</em> for sending form
+content with name=value pairs encoded as multipart sections with individual
+MIME headers and boundaries. However, Lynx does not yet support INPUTs
+with <em>TYPE=&quot;file&quot;</em> or <em>TYPE=&quot;range&quot;</em> and
+will set the <em>DISABLED</em> attribute for all of the form's fields if
+any INPUTs with either of those two TYPEs are present, so that the form
+can't be submitted. Otherwise, Lynx will submit the form with the multipart
+ENCTYPE.
+
+<p>A <em>Content-Disposition:&nbsp;file;&nbsp;filename=name.suffix</em>
+header can be used by CGI scripts to set the suggested filename offered
+by Lynx for '<em>d</em>'ownload and '<em>p</em>'rint menu options to save
+or mail the body returned by the script following submission of a FORM.
+Otherwise, Lynx uses the last symbolic element in the path for the FORM's
+ACTION, which is normally the script, itself, or a PATH_INFO field, and
+thus might be misleading. This also can be done via a META element in
+any document:
+<tab indent="12"
+><em>&lt;META <tab id="cdis">HTTP-EQUIV="Content-Disposition"<BR>
+<tab to="cdis">CONTENT="file;&nbsp;filename=name.suffix"&gt;</em><BR>
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="20"><em>Lynx and HTML Tables</em></a></h2>
+
+HTML includes markup for creating <em>tables</em> structured as arrays of
+cells aligned by columns and rows on the displayed page.
+
+<p>Lynx recognizes the TABLE element and all of its associated elements
+as described in <a href="ftp://ds.internic.net/rfc/rfc1942.txt"
+>ftp://ds.internic.net/rfc/rfc1942.txt</a>
+and will process any ID attributes in the start tags for handling as NAME-ed
+anchors, but does not create actual <em>tables</em>. Instead, it treats
+the TR start tag as a collapsible BR (line break), and inserts a collapsible
+space before the content of each TH and TD start tag. This generally makes
+all of the content of the <em>table</em> readable, preserves most of the
+intra-cell organization, and makes all of the links in the <em>table</em>
+accessible, but any information critically dependent on the column and row
+alignments intended for the <em>table</em> will be missed.
+
+<p>If inherently tabular data must be presented with Lynx, one can use PRE
+formatted content, or, if the <em>table</em> includes markup not allowed
+for PRE content, construct the <em>table</em> using <a
+href="#21">HTML Tabs</a>. An example <em>table</em> using <em>TAB</em>
+elements is included in the test subdirectory of the Lynx distribution.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="21"><em>Lynx and HTML Tabs</em></a></h2>
+
+Lynx implements the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+TAB element only when LEFT alignment is in effect. If the alignment is
+CENTER or RIGHT (JUSTIFY is not yet implemented in Lynx, and is treated
+as a synonym for LEFT), or if the TAB element indicates a position to the
+left of the current position on the screen, it is treated as a collapsible
+space. For purposes of implementing TAB, Lynx treats <em>en</em> units as
+half a character cell width when specified by the INDENT attribute, and
+rounds up for odd values (e.g., a value of either 5 or 6 will be treated
+as three spaces, each the width of a character cell). See the example
+<em>table</em> using TAB elements in the test subdirectory of the Lynx
+distribution as a model for using this functionality.
+
+<p>Note that this <em>Users Guide</em> and the <a
+href="lynx_url_support.html">Supported URLs</a> page include TAB markup in
+a manner which <em>degrades gracefully</em> for WWW browsers which do not
+support it. Toggle to display of <a href="#8">source</a> and <a
+href="#11">search</a> for <em>&lt;tab</em> to examine the use of TAB markup
+in these documents. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="22"><em>Lynx and HTML Frames</em></a></h2>
+
+Some implementations of HTML include markup, primarily designed for graphic
+clients, that is intended to create an array of simultaneously displayed,
+independently scrolling windows. Such windows have been termed
+<em>frames</em>.
+
+<p>Lynx recognizes the Netscape and Microsoft Explorer FRAME, FRAMESET,
+and NOFRAMES elements, but is not capable of windowing to create the
+intended positioning of <em>frames</em>. Instead, Lynx creates labeled
+links to the <em>frame</em> sources, typically positioned in the upper
+left corner of the display, and renders the NOFRAMES section. If the
+document provider has disregard for text clients and sight-challenged
+Webizens, and thus does not include substantive content in the NOFRAMES
+section or a link in it to a document suitable for text clients, you
+can usually guess from the labeling of the <em>frame</em> links which
+one has the substantive material (if there is any), or you can try each
+of those links to see if anything worthwhile is returned.
+[<A HREF="#TOC">ToC</A>]
+
+<p>Some sites -- in ignorance of Lynx capabilities -- may tell you
+(for example) "to view this page you need Netscape Navigator".
+You can simply ignore such warnings and access the frames
+via the Lynx-generated links as above.
+
+<h2><A NAME="23"><em>Lynx and HTML Banners</em></a></h2>
+
+Some implementations of HTML markup include provisions for creating a
+non-scrolling window to be positioned at the top of each page, containing
+links with brief, descriptive link names, analogous to a Windows toolbar.
+Such windows have been termed <em>banners</em>.
+
+<p>Lynx recognizes and processes all of the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+REL attribute tokens in LINK elements for creating a <em>banner</em>, and
+a number of others which have subsequently been proposed. These
+<em>banner</em> tokens are <em>Home</em>, <em>ToC</em>, <em>Contents</em>,
+<em>Index</em>, <em>Glossary</em>, <em>Copyright</em>, <em>Up</em>,
+<em>Next</em>, <em>Previous</em>, <em>Prev</em>, <em>Help</em>,
+<em>Search</em>, <em>Top</em>, <em>Origin</em>, <em>Navigator</em>,
+<em>Child</em>, <em>Disclaimer</em>, <em>Sibling</em>, <em>Parent</em>,
+<em>Author</em>, <em>Editor</em>, <em>Publisher</em>, <em>Trademark</em>,
+<em>Meta</em>, <em>URC</em>, <em>Hotlist</em>, <em>Begin</em>,
+<em>First</em>, <em>End</em>, <em>Last</em>, <em>Pointer</em>,
+<em>Translation</em>, <em>Definition</em>, <em>Chapter</em>,
+<em>Documentation</em>, <em>Biblioentry</em>, <em>Bibliography</em>,
+<em>Bookmark</em> and <em>Banner</em>. Any LINK elements with those
+tokens as the REL attribute value, and an HREF attribute value in the LINK,
+will invoke creation of a <em>banner</em> at the top of the first page,
+with the element's HREF as the link, and the token as the default link
+name. If a TITLE attribute is included in the LINK, it's value will be
+used as the link name instead of the default. <em>Bookmark</em> and
+<em>Banner</em> are intended to be accompanied by a TITLE attribute,
+which in effect makes the namespace for REL <em>banner</em> tokens
+infinite.
+
+<p>If the special token <em>Help</em> is used as the REL value and no HREF
+is included in the LINK, Lynx will use it own <em>HELPFILE</em> URL for that
+link. For the special token <em>Home</em> without an HREF, Lynx will use
+the default <em>STARTFILE</em> (i.e., derived from the configuration files
+or the WWW_HOME environment variable, <em>not</em> the command line
+<em>startfile</em> if one was used). However, if a <em>-homepage=URL</em>
+was specified on the command line, it's URL will be used as the HREF.
+For the special token <em>Index</em> without an HREF, Lynx will use the
+<em>DEFAULT_INDEX_FILE</em> derived from the configuration files, or if an
+<em>-index=URL</em> was specified on the command line, it's URL will be used
+as the HREF.
+
+<p>Lynx does not waste screen real estate maintaining the <em>banner</em> at
+the top of every page, but the Lynx TOOLBAR keystroke command ('<em>#</em>')
+will, any time it is pressed, position you on the <em>banner</em> so that
+any of its links can be activated, and pressing the <em>left-arrow</em> when
+in the <em>banner</em> will return you to where you were in the current
+document. The toolbar is indicated by a '<em>#</em>" preceding its first
+link when present on the screen, that is, when the first page of the
+document is being displayed. The availability of a toolbar is indicated by
+a '<em>#</em>' at the top, left-hand corner of the screen when the second
+or subsequent pages of the document are being displayed.
+
+<p>Lynx also recognizes the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+BANNER container element, and will create a <em>banner</em> based on its
+content if one has not already been created based on LINK elements. Lynx
+treats the Microsoft MARQUEE element as a synonym for BANNER (i.e.,
+presenting it's markup as a static <em>banner</em>, without any horizontal
+scrolling of its content). Lynx does not prefix the BANNER or MARQUEE
+content with a '<em>#</em>' because the content need not be only a series
+of links with brief, descriptive links names, but does add a '<em>#</em>'
+at the top, left-hand corner of the screen when the content is not being
+displayed, to indicate it's accessibility via the TOOLBAR keystroke command.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="24"><em>Lynx and HTML Footnotes</em></a></h2>
+
+Lynx implements the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+FN element similarly to a named <em>A</em>nchor within the current document,
+and assumes that the footnotes will be positioned at the bottom of the
+document. However, in contrast to named <em>A</em>nchors, the FN container
+element is treated as a block (i.e., as if a new paragraph were indicated
+whether or not that is indicated in its content) with greater than normal
+left and right margins, and the block will begin with a <em>FOOTNOTE:</em>
+label. For example, if the document contains:<BR>
+<tab indent="16">See the <em>&lt;A
+HREF="#fn1"&gt;</em><a href="#an1">footnote</a><em>&lt;/A&gt;</em>.<BR>
+activating that link will take you to the labeled rendering of:
+
+<p><tab indent="16"><em>&lt;FN ID="fn1"&gt;</em>&lt;p&gt;<a name="an1">Lynx
+does not use popups for FN blocks.</a>&lt;/p&gt;<em>&lt;/FN&gt;</em>
+
+<p>i.e., position it at the top of the page. Then, upon reading the footnote,
+you can return to your previous position in the document by pressing the
+<em>left-arrow</em> key. The content of an FN element can be any HTML
+markup that is valid in the BODY of the document.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="25"><em>Lynx and HTML Notes</em></a></h2>
+
+Lynx implements the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+NOTE element (<em>Admonishment</em>) as a labeled block, i.e., as if a new
+paragraph were indicated whether or not paragraphing markup is included
+in its content, with greater than normal left and right margins, and with
+the type of note indicated by an emphasized label based on the value of its
+CLASS or ROLE attribute. If no CLASS or ROLE attribute is included, the
+default label <em>NOTE:</em> will be used. Lynx recognizes the values
+<em>caution</em> and <em>warning</em>, for which, respectively, the labels
+<em>CAUTION:</em> or <em>WARNING:</em> will be used. The NOTE element can
+have an ID attribute, which will be treated as a named <em>A</em>nchor, as
+for <a href="#24">HTML Footnotes</a>, but the NOTE block need not be placed
+at the bottom of the document. The content of a NOTE block can be any HTML
+markup that is valid in the BODY of the document. This is an example:<BR>
+<tab indent="12"><em>&lt;NOTE CLASS="warning" ID="too-bad"&gt;<BR>
+<tab indent="14">&lt;p&gt;The W3C vendors did not retain
+NOTE in the HTML 3.2 draft.&lt;/p&gt;<BR>
+<tab indent="12">&lt;/NOTE&gt;</em><BR>
+It will <em>degrade gracefully</em> for WWW browsers which do not support
+NOTE, except for recognition of the ID attribute as a named <em>A</em>nchor.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="26"><em>Lynx and HTML Lists</em></a></h2>
+
+Lynx implements the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+list elements UL (<em>Unordered List</em>), OL (<em>Ordered List</em>),
+and DL (<em>Definition List</em>), and their associated attributes, and
+elements (LH, LI, DT, and DD) for the most part as described in that
+specification. The lists can be nested, yielding progressively greater
+indentation, up to six levels. The <a
+href="http://www.w3.org/MarkUp/html-spec/html-spec_toc.html"
+>HTML 2.0</a> MENU and DIR elements <em>both</em> are treated as synonyms
+for UL with the PLAIN attribute (no <em>bullets</em>, see below). Note,
+thus, that neither DIR nor MENU yields a series of columns with 24-character
+spacing. A single nesting index is maintained, so that different types of
+List elements can be used for different levels within the nest. Also, the
+<a href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+FIG, CAPTION and CREDIT elements are treated as valid within list blocks.
+They will be rendered with indentation appropriate for the current nesting
+depth, and the CAPTION or CREDIT elements will have a <em>CAPTION:</em> or
+<em>CREDIT:</em> label beginning the first line of their content. The
+content of any APPLET or OBJECT elements in the lists also will be indented
+appropriately for the current nesting depth, but those will not invoke line
+breaks unless indicated by their content, and it should not include markup
+which is inappropriate within the list.
+
+<p>Lynx also supports the TYPE attribute for OL elements, which can have
+values of <em>1</em> for Arabic numbers, <em>I</em> or <em>i</em> for
+uppercase or lowercase Roman numerals, or <em>A</em> or <em>a</em> for
+uppercase or lowercase letters, that increment for successive LI elements
+in the list block. The CONTINUE attribute can be used to continue the
+ordering from the preceding list block when the nesting depth is changed.
+
+<p>Lynx treats the OL attributes START and SEQNUM as synonyms for specifying
+the ordering value for the first LI element in the block. The values should
+be specified as Arabic numbers, but will be displayed as Arabic, Roman, or
+alphabetical depending on the TYPE for the block. The values can range from
+<em>-29997</em> to the system's maximum positive integer for Arabic numbers.
+For Roman numerals, they can range from <em>1</em> (<em>I</em> or <em>i</em>)
+to <em>3000</em> (<em>MMM</em> or <em>mmm.</em>). For alphabetical orders,
+the values can range from <em>1</em> (<em>A</em> or <em>a</em>) to
+<em>18278</em> (<em>ZZZ</em> or <em>zzz</em>). If the CONTINUE attribute is
+used, you do not need to specify a START or SEQNUM attribute to extend the
+ordering from a previous block, and you can include a TYPE attribute to
+change among Arabic, Roman, or alphabetical ordering styles, or their casing,
+without disrupting the sequence. If you do not include a START, SEQNUM or
+CONTINUE attribute, the first LI element of each OL block will default to
+<em>1</em>, and if you do not include a TYPE attribute, Lynx defaults to
+Arabic numbers.
+
+<p>For UL blocks without the PLAIN attribute, Lynx uses <em>*</em>,
+<em>+</em>, <em>o</em>, <em>#</em>, <em>@</em> and <em>-</em> as
+<em>bullets</em> to indicate, progressively, the depth within the six
+nesting levels.
+
+<p>Lynx treats UL, OL, DIR, and MENU blocks as having the COMPACT attribute
+by default, i.e., single spaces between LH and LI elements within those
+blocks. For DL blocks, double spacing will be used to separate the DT and
+DD elements unless the COMPACT attribute has been specified.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="27"><em>Lynx and HTML Quotes</em></a></h2>
+
+The <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a> and
+later specifications provide for two classes of quotation in HTML documents.
+Block quotes, designated by the BLOCKQUOTE element (or it's abbreviated
+synonym BQ in HTML 3.0), have implied paragraph breaks preceding and following
+the start and end tags for the block. Character level quotes, designated by
+the Q element, in contrast are simply directives in the markup to insert an
+appropriate quotation mark.
+
+<p>Lynx renders block quotes with a greater than normal left and right
+indentation. Lynx does not support italics, and normally substitutes
+underlining, but does not underline block quotes so as not to obscure any
+explicit emphasis elements within the quotation. The BLOCKQUOTE or BQ
+block can include a CREDIT container element, whose content will be rendered
+as an implied new paragraph with a <em>CREDIT:</em> label at the beginning of
+its first line.
+
+<p>Lynx respects nested Q start and end tags, and will use ASCII double-quotes
+(<em>&quot;</em>) versus grave accent (<em>`</em>) and apostrophe
+(<em>'</em>), respectively, for even versus odd depths in the nest.
+
+<p>Any ID attributes in BLOCKQUOTE, BQ or Q elements will be treated as
+named <em>A</em>nchors. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="28"><em>Lynx and Client-Side-Image-Maps</em></a></h2>
+
+HTML includes markup, designed primarily for graphic clients, that treats
+inlined images as maps, such that areas of the image within which a mouse
+cursor was positioned when the mouse was <em>clicked</em> can correspond
+to URLs which should be retrieved. The original implementations
+were based on the client sending an http server the x,y coordinates
+associated with the <em>click</em>, for handling by a script invoked by
+the server, and have been termed <em>server-side-image-maps</em>. Lynx
+has no rational way of coping with such a procedure, and thus simply
+sends a 0,0 coordinate pair, which some server scripts treat as an
+instruction to return a document suitable for a text client.
+
+<p>Newer HTML markup provides bases for the client to determine the
+URLs associated with areas in the image map, and/or for a text client
+to process alternative markup and allow the user to make choices based
+on textual information. These have been termed
+<em>client-side-image-maps</em>.
+
+<p>Lynx recognizes and processes the MAP container element and its AREA
+elements, and will create a menu of links for the HREF of each AREA when
+the link created for the IMG element with a USEMAP attribute is activated.
+The menu uses the ALT attributes of the AREA elements as the link names,
+or, if the document's author has disregard for text clients and
+sight-challenged Webizens, and thus did not include ALT attributes, Lynx
+uses the resolved URLs pointed to by the HREF attributes as the link names.
+Lynx uses the TITLE attribute of the IMG element, or the TITLE attribute of
+the MAP, if either was present in the markup, as the title and main header
+of the menu. Otherwise, it uses the ALT attribute of the IMG element. If
+neither TITLE nor ALT attributes were present in the markup, Lynx creates
+and uses a <em>[USEMAP]</em> pseudo-ALT. The MAPs need not be in the same
+document as the IMG elements. If not in the same document, Lynx will fetch
+the document which contains the referenced MAP, and locate it based on
+its NAME or ID attribute. All MAPs encountered in documents during a
+Lynx session are cached, so that they need not be retrieved repeatedly
+when referenced in different documents.
+
+<p>If the IMG element also indicates a <em>server-side-image-map</em>
+via an ISMAP attribute, Lynx normally will create a link for that as well,
+using an <em>[ISMAP]</em> pseudo-ALT (followed by a hyphen to indicate its
+association with the <em>client-side-image-map</em>) rather than ignoring
+it, and will submit a 0,0 coordinate pair if that link is activated.
+Although, the <em>client-side-image-map</em> may be more useful for a
+client such as Lynx, because all of the URLs associated with the image
+map can be accessed, and their nature indicated via ALT attributes,
+Lynx-friendly sites can map 0,0 such that the server returns a
+for-text-client document homologous to the content of FIG elements (see
+below). Inclusion of such a link for submissions to the server can be
+disabled by default via the configuration file (lynx.cfg), and the
+default can be toggled via the <em>-ismap</em> command line switch.
+
+<p>Lynx also recognizes the <a
+href="http://www.w3.org/MarkUp/html3/Contents.html">HTML 3.0</a>
+FIG and OVERLAY elements, and will handle them as intended for text clients.
+These are the ideal way to handle <em>client-side-image-maps</em>, because
+the FIG content provides complete alternative markup, rather than relying
+on the client to construct a relatively meager list of links with link
+names based on ALT strings.
+
+<p>The presently experimental OBJECT element encompasses much of the
+functionality of the FIG element for <em>client-side-image-maps</em>.
+Lynx will render and display the content of OBJECT elements which have
+the SHAPES attribute equivalently to its handling of FIG. Lynx also
+handles OBJECT elements with the USEMAP and/or ISMAP attributes
+equivalently to its handling of IMG elements with
+<em>client-side-image-maps</em> and/or <em>server-side-image-maps</em>.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="29"><em>Lynx and Client-Side-Pull</em></a></h2>
+
+HTML includes provision for passing instructions to clients via directives
+in META elements, and one such instruction, via the token <em>Refresh</em>,
+should invoke reloading of the document, fetched from a server with the
+same URL or a new URL, at a specified number of seconds following receipt
+of the current document. This procedure has been termed
+<em>client-side-pull</em>. An example of such an element is:<BR>
+<tab indent="12"><em>&lt;META HTTP-EQUIV="Refresh" CONTENT="3;
+URL="http://host/path"&gt;</em><BR>
+which instructs a client to fetch the indicated URL in 3 seconds after
+receiving the current document. If the <em>URL=</em> field is omitted,
+the URL defaults to that of the current document. A <em>no-cache</em>
+directive is implied when the <em>Refresh</em> if for the same URL.
+
+<p>Lynx recognizes and processes <em>Refresh</em> directives in META
+elements, but puts up a labeled link, typically in the upper left corner
+of the display, indicating the number of seconds intended before a
+refresh, and the URL for the refresh, instead of making the request
+automatically after the indicated number of seconds. This allows
+people using a braille interface any amount of time to examine the
+current document before activating the link for the next URL. In
+general, if the number of seconds indicated is short, the timing
+is not critical and you can activate the link whenever you like.
+If it is long (e.g., 60 seconds), a server process may be generating
+new documents or images at that interval, and you would be wasting
+bandwidth by activating the link at a shorter interval.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="30"><em>Lynx State Management</em></A>
+(Me want <em>cookie</em>!)</h2>
+
+HTTP provides a means to carry state information across successive
+connections between a browser and an http server. Normally, http servers
+respond to each browser request without relating that request to previous
+or subsequent requests. Though the inclusion of INPUT fields with
+TYPE="hidden" can be used as a sort of state management by <a href="#19"
+>HTML Forms</a>, a more general approach involves exchanges of MIME
+headers between the server and browser. When replying to a request,
+the server can send a <em>Set-Cookie</em> MIME header which contains
+information (<em>cookies</em>) relevant to the browser's request, and in
+subsequent requests the browser can send a <em>Cookie</em> MIME header
+with information derived from previously received cookies.
+
+<p>State Management via cookie exchanges originally was implemented by
+Netscape, and such cookies are now designated as <em>Version 0</em>. A
+more elaborate format for cookies, designated as <em>Version 1</em>, is
+being standardized by the IETF (Internet Engineering Task Force). Lynx
+supports both <em>Version 0</em> and <em>Version 1</em> cookie exchanges.
+This support can be disabled by default via the SET_COOKIES symbol in the
+compilation (<em>userdefs.h</em>) and/or run time (<em>lynx.cfg</em>)
+configuration files, and that default setting can be toggled via the
+<em>-cookies</em> command line switch.
+
+<p>When cookie support is enabled, <em>Set-Cookie</em> MIME headers
+received from an http server invoke confirmation prompts with possible
+replies of '<em>Y</em>'es or '<em>N</em>'o for acceptance of the cookie,
+'<em>A</em>'lways to accept the cookie and to allow all subsequent
+cookies from that <em>domain</em> (server's Fully Qualified Domain Name,
+or site-identifying portion of the FQDN) without further confirmation
+prompts, or ne'<em>V</em>'er to never allow cookies from that
+<em>domain</em> to be accepted (silently ignore its <em>Set-Cookie</em>
+MIME headers). All unexpired cookies are held in a hypothetical
+<em>Cookie Jar</em> which can be examined via the COOKIE_JAR keystroke
+command, normally mapped to <em>Ctrl-K</em>, for invoking the <a
+href="keystrokes/cookie_help.html">Cookie Jar Page</a>. The
+<em>Cookie Jar</em>, and any '<em>A</em>'lways or ne'<em>V</em>'er
+'allow' settings, do not presently outlast the Lynx session.
+
+<p>A common use of cookies by http servers is simply to track the
+documents visited by individual users. Though this can be useful to the
+site's WebMaster for evaluating and improving the organization of links
+in the various documents of the site, if the user has configured Lynx
+to include a <em>From</em> MIME header with the user's email address in
+http requests, or has passed personal information to the server via a
+form submission, the tracking might be used to draw inferences, possibly
+incorrect, about that user, and may be considered by some as an invasion
+of privacy.
+
+<p>An example of worthwhile State Management via cookies is the setting
+of personal preferences, typically via a form submission to the site,
+which will then apply to all documents visited at that site.
+
+<p>If you accept cookies when accessing a site, but are given no indication
+about how they will be used in subsequent requests to that site, nor can
+infer how they will be used, you can <em>Gobble</em> (delete) the cookies
+and/or change the 'allow' setting for its <em>domain</em> via the <a
+href="keystrokes/cookie_help.html">Cookie Jar Page</a>.
+[<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="31"><em>The Lynx command line</em></A></h2>
+
+A summary of the Lynx command line options (switches) is returned to
+stdout if Lynx is invoked with the <em>-help</em> switch. A description
+of the options also should be available via the system man (Unix) pages
+or help (VMS) libraries. On Win32, typing lynx -help in a DOS window
+should display similarly.
+The basic syntax of the Lynx command line can
+be represented as one of the following:
+
+<dl>
+ <dt><code>Command</code>
+ <dd><code>lynx [options]</code>
+ <dd><code>lynx [options] startfile</code>
+</dl>
+
+where
+
+<dl>
+ <dt><code>startfile</code>
+ <dd>is the file or URL that Lynx will load at start-up.
+ <ul>
+ <li>If startfile is not specified, Lynx will use a default
+ starting file and base directory determined during
+ installation.
+ <li>If a specified file is local (i.e., not a URL) Lynx
+ displays that file and uses the directory in which that
+ file resides as the base directory.
+ <li>If a URL is specified, the file will be retrieved,
+ and only the server base directory will be relevant
+ to further accesses.
+ </ul>
+ <dt><code>options</code>
+ <dd>can be selected from the following list, where items in
+ all-caps indicate that a substitution must be made.
+ <dl>
+ <dt><code>-</code>
+ <dd>If the argument is only '<code>-</code>' (dash), then Lynx
+ expects to receive the arguments from stdin. This is to
+ allow for the potentially very long command line that can
+ be associated with the <em>-get_data</em> or
+ <em>-post_data</em> arguments (see below). On VMS, it
+ must be encased in double-quotes (&quot;-&quot;) and the
+ keyboard input terminated with <em>Control-Z</em> or the
+ command file input terminated by a line that begins
+ with '<em>$</em>'. On Unix, the keyboard input terminator
+ is <em>Control-D</em>. On Win32, [???].
+ <dt><code>-anonymous</code>
+ <dd>used to specify the anonymous account.
+ <dt><code>-assume_charset=MIMEname</code>
+ <dd>charset for documents that don't specify it.
+ <dt><code>-assume_local_charset=MIMEname</code>
+ <dd>charset assumed for local files.
+ <dt><code>-assume_unrec_charset=MIMEname</code>
+ <dd>use this instead of unrecognized charsets.
+ <dt><code>-auth=ID:PW</code>
+ <dd>set authorization ID and password for protected documents
+ at startup. Be sure to protect any script files which use
+ this switch.
+ <dt><code>-base</code>
+ <dd>prepend a request URL comment and BASE tag to text/html
+ outputs for -source dumps.
+ <dt><code>-blink</code>
+ <dd>forces high intensity bg colors for color mode,
+ if available and supported by the terminal.
+ Lynx needs to be compiled with the slang library for this
+ flag.
+ <dt><code>-book</code>
+ <dd>use the bookmark page as the startfile. The default or
+ command line startfile is still set for the Main screen
+ command, and will be used if the bookmark page is
+ unavailable or blank.
+ <dt><code>-buried_news</code>
+ <dd>toggles scanning of news articles for buried references,
+ and converts them to news links. Not recommended because
+ email addresses enclosed in angle brackets will be
+ converted to false news links, and uuencoded messages can
+ be trashed.
+ <dt><code>-cache=NUMBER</code>
+ <dd>set the <em>NUMBER</em> of documents cached in memory.
+ The default is 10.
+ <dt><code>-case</code>
+ <dd>enable case-sensitive string searching.
+ <dt><code>-cfg=FILENAME</code>
+ <dd>specifies a Lynx configuration file other than the default
+ lynx.cfg.
+ <dt><code>-child</code>
+ <dd>exit on left-arrow in startfile, and disable save to disk.
+ <dt><code>-color</code>
+ <dd>forces color mode on, if available. Default color control sequences
+ which work for many terminal types are assumed if the terminal
+ capability description does not specify how to handle color.
+ Lynx needs to be compiled with the slang library for this flag.
+ A saved show_color=always setting found in a .lynxrc file at
+ startup has the same effect. A saved show_color=always found
+ in .lynxrc on startup is overridden by this flag.
+ <dt><code>-cookies</code>
+ <dd>toggles handling of Set-Cookie headers.
+ <dt><code>-core</code>
+ <dd>toggles forced core dumps on fatal errors. (Unix only)
+ <dt><code>-crawl</code>
+ <dd>with <em>-traversal</em>, output each page to a file.<br>
+ with <em>-dump</em>, format output as with
+ <em>-traversal</em>, but to stdout.
+ <dt><code>-display=DISPLAY</code>
+ <dd>set the display variable for X rexe-ced programs.
+ <dt><code>-dump</code>
+ <dd>dumps the formatted output of the default document
+ or one specified on the command line to standard out.
+ This can be used in the following way:<br>
+ <em>lynx -dump http://www.w3.org/</em>
+ <dt><code>-editor=EDITOR</code>
+ <dd>enable edit mode using the specified
+ <em>EDITOR</em>. (vi, ed, emacs, etc.)
+ <dt><code>-emacskeys</code>
+ <dd>enable emacs-like key movement.
+ <dt><code>-enable_scrollback</code>
+ <dd>toggles behavior compatible with the scrollback keys in
+ some communications software (may be incompatible with
+ some curses packages).
+ <dt><code>-error_file=FILENAME</code>
+ <dd>the status code from the HTTP request is placed in this
+ file.
+ <dt><code>-locexec</code>
+ <dd>enable local program execution from local files only
+ (if lynx was compiled with local execution enabled).
+ <dt><code>-fileversions</code>
+ <dd>include all versions of files in local VMS directory
+ listings.
+ <dt><code>-force_html</code>
+ <dd>forces the first document to be interpreted as HTML.
+ <dt><code>-force_secure</code>
+ <dd>toggles forcing of the secure flag for SSL cookies.
+ <dt><code>-from</code>
+ <dd>toggles transmissions of From headers to HTTP or HTTPS
+ servers.
+ <dt><code>-ftp</code>
+ <dd>disable ftp access.
+ <dt><code>-get_data</code>
+ <dd>properly formatted data for a get form are read in from
+ stdin and passed to the form. Input is terminated by a
+ line that starts with '---'.
+ <dt><code>-head</code>
+ <dd>send a HEAD request for the mime headers.
+ <dt><code>-help</code>
+ <dd>print this Lynx command syntax usage message.
+ <dt><code>-historical</code>
+ <dd>toggles use of '&gt;' or '--&gt;' as a terminator for
+ comments.
+ <dt><code>-homepage=URL</code>
+ <dd>set homepage separate from start page. Will be used
+ if a fetch of the start page fails or if it is a
+ script which does not return a document, and as the
+ <code>URL</code> for the '<em>m</em>'ain menu command.
+ <dt><code>-image_links</code>
+ <dd>toggles inclusion of links for all images.
+ <dt><code>-ismap</code>
+ <dd>toggles inclusion of ISMAP links when client-side
+ MAPs are present.
+ <dt><code>-index=URL</code>
+ <dd>set the default index file to the specified <em>URL</em>
+ <dt><code>-link=NUMBER</code>
+ <dd>starting count for lnk#.dat files produced by
+ <em>-crawl</em>.
+ <dt><code>-localhost</code>
+ <dd>disable URLs that point to remote hosts.
+ <dt><code>-mime_header</code>
+ <dd>include mime headers and force source dump.
+ <dt><code>-minimal</code>
+ <dd>toggles minimal versus valid comment parsing. When
+ minimal, any '--&gt;' serves as a terminator for a
+ comment element. When valid, pairs of '--' are
+ treated as delimiters for series of comments within
+ the overall comment element. If historical is set,
+ that overrides minimal or valid comment parsing.
+ <dt><code>-newschunksize=NUMBER</code>
+ <dd>number of articles in chunked news listings.
+ <dt><code>-newsmaxchunk=NUMBER</code>
+ <dd>maximum news articles in listings before chunking.
+ <dt><code>-nobrowse</code>
+ <dd>disable directory browsing.
+ <dt><code>-nocc</code>
+ <dd>disable Cc: prompts for self copies of mailings. Note
+ that this does not disable any CCs which are incorporated
+ within a mailto URL or form ACTION.
+ <dt><code>-nocolor</code>
+ <dd>force color mode off, overriding terminal capabilities and any
+ <em>-color</em> flags, <em>COLORTERM</em> variable, and saved .lynxrc settings.
+ <dt><code>-noexec</code>
+ <dd>disable local program execution. (DEFAULT)
+ <dt><code>-nofilereferer</code>
+ <dd>disable transmissions of Referer headers for file URLs.
+ <dt><code>-nolist</code>
+ <dd>disable the link list feature in dumps.
+ <dt><code>-nolog</code>
+ <dd>disable mailing of error messages to document owners.
+ <dt><code>-nopause</code>
+ <dd>disable forced pauses for statusline messages.
+ <dt><code>-noprint</code>
+ <dd>disable print functions.
+ <dt><code>-noredir</code>
+ <dd>don't follow URL redirections
+ <dt><code>-noreferer</code>
+ <dd>disable transmissions of Referer headers.
+ <dt><code>-nosocks</code>
+ <dd>disable SOCKS proxy usage by a SOCKSified Lynx.
+ <dt><code>-nostatus</code>
+ <dd>disable the retrieval status messages.
+ <dt><code>-number_links</code>
+ <dd>force numbering of links.
+ <dt><code>-pauth=ID:PW</code>
+ <dd>set authorization ID and password for a protected proxy
+ server at startup. Be sure to protect any script files
+ which use this switch.
+ <dt><code>-popup</code>
+ <dd>toggles handling of single-choice SELECT options via
+ popup windows or as lists of radio buttons. The default
+ configuration can be changed in userdefs.h or lynx.cfg.
+ It also can be set and saved via the 'o'ptions menu.
+ The command line switch toggles the default.
+ <dt><code>-post_data</code>
+ <dd>properly formatted data for a post form are read in from
+ stdin and passed to the form. Input is terminated by a
+ line that starts with '---'.
+ <dt><code>-preparsed</code>
+ <dd>show source preparsed and reformatted when used with
+ -source or in source view ('<em>\</em>').
+ <dt><code>-print</code>
+ <dd>enable print functions. (default)
+ <dt><code>-pseudo_inlines</code>
+ <dd>toggles pseudo-ALTs for inlines with no ALT string.
+ <dt><code>-raw</code>
+ <dd>toggles default setting of 8-bit character translations
+ or CJK mode for the startup character set.
+ <dt><code>-realm</code>
+ <dd>restricts access to URLs in the starting realm.
+ <dt><code>-reload</code>
+ <dd>flushes the cache on a proxy server
+ (only the first document affected).
+ <dt><code>-restrictions</code>
+ <dd>allows a list of services to be disabled
+ selectively and takes the following form:
+ <dd><em>lynx -restrictions=[option][,option][,option]...</em>
+ <dd>This list is printed if no options are specified.
+ <dl>
+ <dt>all
+ <dd>restricts all options.
+ <dt>bookmark
+ <dd>disallow changing the location of the bookmark
+ file.
+ <dt>bookmark_exec
+ <dd>disallow execution links via the bookmark file.
+ <dt>change_exec_perms
+ <dd>disallow changing the eXecute permission on
+ files (but still allow it for directories) when
+ local file management is enabled.
+ <dt>default
+ <dd>same as command line option <em>-anonymous</em>.
+ Disables default services for anonymous users.
+ Currently set to all restricted except for:
+ inside_telnet, outside_telnet, inside_news,
+ inside_ftp, outside_ftp, inside_rlogin,
+ outside_rlogin, jump, mail and goto. Defaults
+ are settable within userdefs.h.
+ <dt>dired_support
+ <dd>disallow local file management.
+ <dt>disk_save
+ <dd>disallow saving to disk in the download and print
+ menus.
+ <dt>download
+ <dd>disallow downloaders in the download menu.
+ <dt>editor
+ <dd>disallow editing.
+ <dt>exec
+ <dd>disable execution scripts.
+ <dt>exec_frozen
+ <dd>disallow the user from changing the local
+ execution option.
+ <dt>file_url
+ <dd>disallow using G)oto, served links or bookmarks
+ for file: URLs.
+ <dt>goto
+ <dd>disable the '<em>g</em>' (goto) command.
+ <dt>inside_ftp
+ <dd>disallow ftps for people coming from inside your
+ domain.
+ <dt>inside_news
+ <dd>disallow USENET news posting for people coming
+ from inside you domain.
+ <dt>inside_rlogin
+ <dd>disallow rlogins for people coming from inside
+ your domain.
+ <dt>inside_telnet
+ <dd>disallow telnets for people coming from inside
+ your domain.
+ <dt>jump
+ <dd>disable the '<em>j</em>' (jump) command.
+ <dt>mail
+ <dd>disallow mailing feature.
+ <dt>multibook
+ <dd>disallow multiple bookmarks.
+ <dt>news_post
+ <dd>disallow USENET News posting.
+ <dt>options_save
+ <dd>disallow saving options in .lynxrc.
+ <dt>outside_ftp
+ <dd>disallow ftps for people coming from outside your
+ domain.
+ <dt>outside_news
+ <dd>disallow USENET news posting for people coming
+ from outside you domain.
+ <dt>outside_rlogin
+ <dd>disallow rlogins for people coming from outside
+ your domain.
+ <dt>outside_telnet
+ <dd>disallow telnets for people coming from
+ outside your domain.
+ <dt>print
+ <dd>disallow most print options.
+ <dt>shell
+ <dd>disallow shell escapes.
+ <dt>suspend
+ <dd>disallow <em>Control-Z</em> suspends with escape
+ to shell on Unix.
+ <dt>telnet_port
+ <dd>disallow specifying a port in telnet G)oto's.
+ <dt>useragent
+ <dd>disallow modifications of the User-Agent header.
+ </dl>
+
+ <dt><code>-resubmit_posts</code>
+ <dd>toggles forced resubmissions (no-cache) of forms with
+ method POST when the documents they returned are sought
+ with the PREV_DOC (<em>left-arrow</em>) command or from
+ the <em>History Page</em>.
+ <dt><code>-rlogin</code>
+ <dd>disable recognition of rlogin commands.
+ <dt><code>-selective</code>
+ <dd>require .www_browsable files to browse directories.
+ <dt><code>-show_cursor </code>
+ <dd>If enabled the cursor will not be hidden in the right hand
+ corner but will instead be positioned at the start of the
+ currently selected link. Show cursor is the default for
+ systems without FANCY_CURSES capabilities. The default
+ configuration can be changed in userdefs.h or lynx.cfg.
+ It also can be set and saved via the 'o'ptions menu.
+ The command line switch toggles the default.
+ <dt><code>-soft_dquotes</code>
+ <dd>toggles emulation of the old Netscape and Mosaic bug which
+ treated '<em>&gt;</em>' as a co-terminator for
+ double-quotes and tags.
+ <dt><code>-source</code>
+ <dd>works the same as dump but outputs HTML source instead of
+ formatted text.
+ <dt><code>-startfile_ok</code>
+ <dd>allow non-http startfile and homepage with
+ <em>-validate</em>.
+ <dt><code>-telnet</code>
+ <dd>disable recognition of telnet commands.
+ <dt><code>-term=TERM</code>
+ <dd>tell Lynx what terminal type to assume its talking to.
+ (This may be useful for remote execution, when, for
+ example, Lynx connects to a remote TCP/IP port that starts
+ a script that, in turn, starts another Lynx process.)
+ <dt><code>-tlog</code>
+ <dd>toggles use of a <em>Lynx Trace Log</em> for the current
+ session. The log is named <em>lynx.trace</em> and is
+ created in the home directory when Lynx trace mode is
+ turned on via the <em>-trace</em> command line switch
+ (see below), or via the TOGGLE_TRACE (<em>Control-T</em>)
+ keystroke command. Once a log is started for the session,
+ all trace and other stderr messages are written to the
+ log. The contents of the log can be examined during
+ the session via the TRACE_LOG (normally, '<em>;</em>')
+ keystroke command.
+ <dt><code>-trace</code>
+ <dd>turns on Lynx trace mode. If a Lynx Trace Log
+ (<em>lynx.trace</em> in the home directory) has
+ been started for the current session, all trace and
+ other stderr messages are written to that log, and
+ can be examined during the session via the TRACE_LOG
+ (normally, '<em>;</em>') command.
+ <dt><code>-traversal</code>
+ <dd>traverse all http links derived from startfile. When
+ used with <em>-crawl</em>, each link that begins with the
+ same string as startfile is output to a file, intended for
+ indexing. See CRAWL.announce for more information.
+ <dt><code>-underscore</code>
+ <dd>toggles use of _underline_ format in dumps.
+ <dt><code>-useragent=Name</code>
+ <dd>set alternate Lynx User-Agent header.
+ <dt><code>-validate</code>
+ <dd>accept only http URLs (for validation). Complete
+ security restrictions also are implemented.
+ <dt><code>-version</code>
+ <dd>print version information
+ <dt><code>-vikeys</code>
+ <dd>enable vi-like key movement.
+ <dt><code>-width=NUMBER</code>
+ <dd>number of columns for formatting of dumps, default is 80.
+ </dl>
+</dl>
+
+<p>No options are required, nor is a startfile argument required.
+White space may be substituted for any equal sign ('<em>=</em>')
+appearing in the option list above. [<A HREF="#TOC">ToC</A>]
+
+<h2><A NAME="32"><em>Lynx development history</em></A></h2>
+
+Lynx grew out of efforts to build a campus-wide information system
+at The University of Kansas. The earliest versions of Lynx provided a
+user-friendly, distributed hypertext interface for users connected to
+multiuser (Unix and VMS) systems via curses-oriented display devices.
+A custom hypertext format was developed to support hypertext links to
+local files and files on remote Gopher servers. Using Gopher servers
+for distributed file service allowed information providers to publish
+information from a wide variety of platforms (including Unix, VMS,
+VM/CMS and Macintosh). In addition, Lynx became the most user-friendly
+Gopher client, although that was only an ancillary capability.
+
+<p>This distributed approach let providers retain complete control
+over their information, but it made communication between users
+and providers somewhat more difficult. Following the lead of Neal
+Erdwien, of Kansas State University, the Lynx hypertext format was
+extended to include links for including ownership information with
+each file. This information made it possible for users running
+Lynx clients to send comments and suggestions via e-mail to the
+providers.
+
+<p>This early version of Lynx was also augmented to support hypertext
+links to programs running on remote systems. It included the ability
+to open a Telnet connection, as well as the ability to start programs
+via rexec, inetd, or by direct socket connects. These capabilities were
+included to allow users to access databases or custom program interfaces.
+
+<p>A subsequent version of Lynx incorporated the World Wide Web libraries
+to allow access to the full list of WWW servers, along with the option to
+build hypertext documents in HTML, rather than the native Lynx format.
+HTML has become far more widely used, and the native format has been phased
+out. With the addition of the WWW libraries, Lynx became a fully-featured
+WWW client, limited only by the display capabilities offered in the curses
+environment.
+
+<p>Lynx was designed by Lou Montulli, Charles Rezac and Michael Grobe
+of Academic Computing Services at The University of Kansas. Lynx was
+implemented by Lou Montulli and maintained by Garrett Arch Blythe and
+Craig Lavender.
+
+<p><em>Foteos Macrides</em> and members of the
+<a href="lynx-dev.html">lynx-dev</a> list have developed and supported Lynx
+since release of v2.3 in May 1994.
+The Lynx2-3FM code set was released as v2.4 in June 1995.
+The Lynx2-4FM code set was released as v2.5 in May 1996.
+The Lynx2-5FM code set was released as v2.6 in September 1996.
+The Lynx2-6FM code set was released as v2.7 in February 1997.
+The v2-7FM code set was released as v2.7.1 in April 1997.
+The v2-7-1FM code set was released as v2.7.2 in January 1998.
+The 2.7.1 development set was released as v2.8 in March 1998.
+
+<p>Since early 1997, the Lynx code has expanded into autoconfigure and
+PC versions. The branching of the Lynx source base from a single
+source into two sources (FM/Foteos Macrides and ac/autoconfigure)
+should be considered a healthy synergism among groups of computer
+professionals acting in their spare time out of a common goal.
+
+<p>Lynx has incorporated code from a variety of sources along the
+way. The earliest versions of Lynx included code from Earl Fogel
+of Computing Services at the University of Saskatchewan, who
+implemented HYPERREZ in the Unix environment. Those versions also
+incorporated libraries from the Unix Gopher clients developed at
+the University of Minnesota, and the later versions of Lynx rely
+on the WWW client library code developed by Tim Berners-Lee (and
+others) and the WWW community.
+
+<p>Contributors have generally been acknowledged in the CHANGES
+file. Earlier CHANGES file can be found in the docs/ subdirectory
+of this distribution.
+
+<p>Information on obtaining the most current version of Lynx is available
+at <a href="http://www.slcc.edu/lynx/current/index.html">the current distribution page</a>.
+
+<p>[<A HREF="#TOC">ToC</A>]
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/lynx_help/about_lynx.html b/gnu/usr.bin/lynx/lynx_help/about_lynx.html
new file mode 100644
index 00000000000..33faa7cd96b
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/about_lynx.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>About Lynx</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+
+<BODY>
+<BANNER>
+[ <A HREF="lynx-dev.html">About Lynx-Dev</A> |
+<A HREF="http://www.flora.org/lynx-dev/html/">Lynx-Dev Archives</A> ]
+</BANNER>
+
+<h1><em>About Lynx</em></h1>
+
+Lynx is a fully featured World-Wide Web browser for users on both Unix and
+VMS platforms who are connected to those systems via cursor-addressable,
+character-cell terminals or emulators. That includes VT100 terminals,
+and desktop-based software packages emulating VT100 terminals (e.g.,
+Kermit, Procomm, etc.).
+
+<P>For information on how to use Lynx see the
+<A HREF="../lynx_help/Lynx_users_guide.html">Lynx User's Guide</A>, or the
+<A HREF="../lynx_help/lynx_help_main.html">Lynx help files</A>.
+
+<H2><EM>Credits and Copyright</EM></H2>
+
+Lynx was a product of the Distributed Computing Group within
+Academic Computing Services of <A
+HREF="http://www.cc.ukans.edu/index.html">The University of Kansas</A>.
+
+<P>Lynx was originally developed by
+<A HREF="http://www.cc.ukans.edu/cwis/people/Lou.Montulli.html"
+>Lou Montulli,</A>
+<A HREF="http://www.cc.ukans.edu/cwis/people/Michael.Grobe/Michael.Grobe.html"
+>Michael Grobe,</A>
+and <A HREF="http://www.cc.ukans.edu/cwis/people/Charles.Rezac.html"
+>Charles Rezac.</A>
+<A HREF="http://www.cc.ukans.edu/cwis/people/Garrett/Garrett_Arch_Blythe.html"
+>Garrett Blythe</A> created
+<A HREF="http://www.cc.ukans.edu/about_doslynx/doslynx.html">DosLynx</A>
+and later joined the Lynx effort as well. Following the departures of
+Lou and Garrett for positions at Netscape in the summer of 1994,
+<EM>Craig Lavender</EM> provided support services for Lynx, and
+<EM>Ravikumar Kolli</EM> for DosLynx.
+
+<P>Currently Lynx is being maintained and supported by members of the
+Internet community coordinated via the
+<A HREF="#lynx-dev_list"><EM>lynx-dev mailing list</EM></A>.
+
+<P>Lynx is copyrighted by the University of Kansas and is distributed
+<A HREF="COPYHEADER">without restrictions on usage or redistribution</A>
+under the <A HREF="COPYING">GNU General Public License</A>.
+
+<P>Lynx was built over an early version of the Common Code Library
+developed by the CERN WWW Project. That code is copyrighted by CERN.
+Lynx contains other sections of code that are copyrighted
+by other institutions or individuals.
+The Lynx copyright does not override or invalidate those copyrights.
+
+<P>Thanks to <A NAME="13"
+HREF="http://www.w3.org/hypertext/WWW/People.html#BernersLee"
+>Tim Berners-Lee</A> and the other <A NAME="14"
+HREF="http://www.w3.org/hypertext/WWW/People.html">CERN World Wide
+Web wizards</A> for the WWW client library code and all of their other
+work on the WWW project, NCSA and the
+<A HREF="http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/NCSAMosaicHome.html"
+>Mosaic</A> developers, and to everyone out in netland who has
+contributed to Lynx's development either directly (through comments
+or bug reports) or indirectly (through inspiration and development of
+other systems).
+
+<P>Also, special thanks go to <EM>Foteos Macrides</EM> who ported much of
+Lynx to VMS and did much of it's development following Lou Montulli's
+and Garrett Blythe's departures from the University of Kansas, and to
+<EM>Earl Fogel</EM> of the University of Saskatchewan. Earl implemented
+the hypertext engine HYPERREZ in the Unix environment. HYPERREZ was
+developed by Niel Larson of Think.com and served as the model for
+the early versions of Lynx which did not use the WWW libraries and
+had their own hypertext format.
+
+<H2><A NAME="availability"><EM>Availability</EM></A></H2>
+
+<p>Information on obtaining the most current version of Lynx is
+available via <a href="http://www.crl.com/~subir/lynx.html"
+>Lynx links</a>.
+
+<H2><A NAME="lynx-dev_list"><EM>Mailing List</EM></A></H2>
+
+We have a listserv mailing list running for lynx development discussion.
+If you are interested in joining the list, follow this <A
+HREF="lynx-dev.html">link</A>. There also are links to <A
+HREF="http://www.flora.org/lynx-dev/html/">archives</A> in html
+format for this mailing list.
+
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/bookmark_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/bookmark_help.html
new file mode 100644
index 00000000000..de08f3947f1
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/bookmark_help.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Lynx Bookmark Help</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Bookmark Help +++</h1>
+
+The <em>Bookmark files</em> are documents that resides on your local
+machine and you are able to edit and change. The append feature,
+invoked by pressing an '<em>a</em>' while viewing a document will add
+the current document or the currently highlighted link to your default
+<em>Bookmark file</em>, or to one you select if multiple bookmarks are
+enabled. The remove feature, invoked by pressing an '<em>r</em>' when
+a <em>Bookmark file</em> is being displayed, will remove the currently
+highlighted link. You may set and modify the paths and names of your
+<em>Bookmark files</em>, and enable or disable multiple bookmarks, in
+the <A HREF="option_help.html">options screen.</A>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/cookie_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/cookie_help.html
new file mode 100644
index 00000000000..0fd5b255f4e
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/cookie_help.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on the Cookie Jar Page</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Cookie Jar Page Help +++</h1>
+
+The Cookie Jar Page displays all of the unexpired cookies you have
+accumulated in the hypothetical <em>Cookie Jar</em>. The cookies are
+obtained via <em>Set-Cookie</em> MIME headers in replies from http servers,
+and are used for <A HREF="../Lynx_users_guide.html#30">State Management</A>
+across successive requests to the servers.
+
+<p>The cookies are listed by <em>domain</em> (server's Fully Qualified
+Domain Name, or site-identifying portion of the FQDN), and in order
+of decreasing specificity (number of slash-separated symbolic elements
+in the <em>path</em> attribute of the cookie). When Lynx sends requests
+to an http server whose address tail-matches a <em>domain</em> in the
+<em>Cookie Jar</em>, all its cookies with a <em>path</em> which
+head-matches the path in the URL for that request are included as a
+<em>Cookie</em> MIME header. The 'allow' setting for accepting cookies
+from each domain (always, never, or via prompt) also is indicated in the
+listing.
+
+<p>The listing also shows the <em>port</em> (normally 80) of the URL
+for the request which caused the cookie to be sent, and whether the
+<em>secure</em> flag is set for the cookie, in which case it will be
+sent only via secure connections (presently, only SSL). The
+<em>Maximum Gobble Date</em>, i.e., when the cookie is intended to
+expire, also is indicated. Note, however, that Lynx presently gobbles
+all of it's accumulated cookies on exit from the current session, even
+if the server indicated an expiration in the distant future. Also, a
+server may change the expiration date, or cause the cookie to be deleted,
+in its replies to subsequent requests from Lynx. If the server included
+any explanatory comments in its <em>Set-Cookie</em> MIME headers, those
+also are displayed in the listing.
+
+<p>The <em>domain</em>=value pairs, and each cookie's name=value, are
+links in the listing. Activating a <em>domain</em>=value link will
+invoke a prompt asking whether all cookies in that <em>domain</em>
+should be <em>Gobbled</em> (deleted from the <em>Cookie Jar</em>),
+and/or whether the <em>domain</em> entry should be <em>Gobbled</em>
+if all of its cookies have been <em>Gobbled</em>, or whether to change
+the 'allow' setting for that <em>domain</em>. Activating a cookie's
+name=value link will cause that particular cookie to be <em>Gobbled</em>.
+You will be prompted for confirmations of deletions, to avoid any
+accidental <em>Gobbling</em>.
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/dired_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/dired_help.html
new file mode 100644
index 00000000000..eb1d1ae65c8
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/dired_help.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Lynx Dired Help</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+<body>
+<h1>+++DIRED HELP+++</h1>
+
+Lynx changes into Dired mode when you use a URL of the type
+<em>file://localhost/path/</em>. While in Dired mode, some keys are
+remapped to do the following functions:
+<pre>
+ C)reate - Create a new, empty file in the current
+ directory. You will be prompted to enter
+ a name for the file.
+
+ D)ownload - Download selection using options listed in
+ the download options screen.
+
+ E)dit - Spawn the editor defined in the <a
+ href="option_help.html">options screen</a>
+ and load selection for editing.
+
+ F)ull menu - Show a full menu of commands for currently
+ selected file or directory.
+
+ M)odify - Modify the name or location of selection. If
+ multiple files have been selected, you will
+ only be able to change the location. Choose
+ between changing the name or location and then
+ enter a new filename or path.
+
+ R)emove - Delete currently selected files.
+
+ T)ag - Tag the highlighted file. Multiple files may
+ be tagged and all other commands except "Create"
+ will be performed on tagged files instead of the
+ one highlighted. Press '<em>t</em>' again to untag
+ a file.
+
+ U)pload - Upload a file to the current directory using
+ one of the options listed in the upload
+ options screen.
+</pre>
+
+<em>Note:</em> Dired mode must be activated at compile time by the
+system administrator. Otherwise, the above commands will not be available
+and lynx will treat a directory listing as a HTML file.
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/edit_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/edit_help.html
new file mode 100644
index 00000000000..52c081b2d20
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/edit_help.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Lynx Line Editor Default Key Binding</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+<body>
+<h1>+++DEFAULT BINDING+++</h1>
+
+Lynx invokes a built-in <em>Line Editor</em> for entering strings in
+response to prompts, in forms, and for email messages if an external editor
+has not been defined. Administrators can offer alternate key bindings
+by adding them in LYEditmap.c before compiling Lynx, and they can
+be selected via the 'o'ptions menu. This is the <em>Default Binding</em>:
+<pre>
+ ENTER Input complete - RETURN
+ TAB Input complete - TAB, Do
+ ABORT Input cancelled - Ctrl-G, Ctrl-O, Ctrl-C
+ ERASE Erase the line - Ctrl-U, Ctrl-X
+
+ BACK Cursor back char - Left-Arrow
+ FORW Cursor forward char - Right-Arrow
+ BACKW Cursor back word - Ctrl-P
+ FORWW Cursor forward word - Ctrl-N
+ BOL Go to begin of line - Ctrl-A, Home, Find
+ EOL Go to end of line - Ctrl-E, End, Select
+
+ DELP Delete prev char - Ctrl-H, DELETE, Remove
+ DELC Delete current char - Ctrl-D
+ DELN Delete next char - Ctrl-R
+ DELPW Delete prev word - Ctrl-B
+ DELNW Delete next word - Ctrl-F
+
+ LOWER Lower case the line - Ctrl-K
+ UPPER Upper case the line - Ctrl-T
+
+ LKCMD Invoke cmd prompt - Ctrl-V (in form text fields, only)
+</pre>
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/follow_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/follow_help.html
new file mode 100644
index 00000000000..f30fbb7754b
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/follow_help.html
@@ -0,0 +1,132 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on the Follow link (or page) number feature</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Follow link (or goto link or page) number Help +++<br>
++++ Select option (or page) number Help +++</h1>
+
+If a user has set <em>Keypad mode</em> to <em>Links are numbered</em>
+or <em>Links and form fields are numbered</em> as the default or for
+the current session via the <em>Options menu</em>, then hypertext links
+(and form fields, depending on the keypad mode)
+are prefixed with numbers in square brackets. Entering a keyboard
+or keypad number is treated as an <em>F_LINK_NUM</em> command, and should
+invoke the <em>Follow link (or goto link or page) number:</em> statusline
+prompt for a
+potentially multiple digit number corresponding to an indicated link
+number. If RETURN is pressed to terminate the number entry (e.g.,
+<em>123</em>) and it corresponds to a hypertext link, Lynx will retrieve
+the document for that link as if you had paged or used other navigation
+commands to make it the current link and then ACTIVATE-ed it. The prompt
+can be invoked via '<em>0</em>', but it will not be treated as the lead
+digit for the number entry, whereas '<em>1</em>' through '<em>9</em>' both
+invoke the prompt and are treated as the first digit. In <em>Links and
+form fields are numbered</em> mode, if the number corresponds to a form
+field you will be positioned on that field, but if it is a submit button
+it will not be ACTIVATE-ed.
+
+<p>If the number entered at the prompt has a '<em>g</em>' suffix (e.g.,
+<em>123g</em>), then Lynx will make the link corresponding to that number
+the current link, paging as appropriate if the link does not appear in
+the currently displayed page. The '<em>g</em>' suffix is implied (need
+not be entered) for form fields in <em>Links and form fields are
+numbered</em> mode.
+
+<p>Alternatively, if the number is given a '<em>p</em>' suffix (e.g.,
+<em>123p</em>), Lynx will make the page corresponding to that number
+the currently displayed page, and the first link on that page, if any,
+the current link. The '<em>g</em>' and '<em>p</em>' suffixes thus
+convert the
+<em>Follow link (or goto link or page) number:</em> feature to an advanced
+navigation aid.
+
+<p>If the user has set <em>Keypad mode</em> to <em>Numbers act as arrows</em>,
+then only '<em>0</em>', rather than every number, will be treated as an
+<em>F_LINK_NUM</em> command for invoking the <em>Follow link (or goto link or page)
+number:</em> prompt. The '<em>0</em>' will not be treated as the first
+digit for the number, or number plus suffix, entry.
+
+<p>Numbers are associated with form fields only when <em>Links and form
+fields are numbered</em> mode has been selected. If you have selected
+<em>Numbers act as arrows</em> or <em>Links are numbered</em> mode, you
+can seek form fields in the document via WHEREIS searches for strings in
+their displayed values. If they are INPUT or TEXTAREA fields with no
+values as yet, you can use two or more underscores as the search string,
+because underscores are used as placeholders for form fields in the
+displayed document.
+
+<p ID="select-option">When you have invoked a popup window for a list of
+OPTIONs in a form's SELECT block, each OPTION is associated with a number,
+and that number will be displayed in <em>Links and form fields are
+numbered</em> mode. In any keypad mode, the <em>F_LINK_NUM</em>
+('<em>0</em>') command will invoke a <em>Select option (or page)
+number:</em> prompt, and you can enter a number, and optionally a
+'<em>g</em>' or '<em>p</em>' suffix, to select or seek an OPTION in that
+list. If only an number is entered at the prompt, the corresponding OPTION
+will be selected and the popup will be retracted. If the '<em>g</em>'
+suffix is included, then you will be positioned on the corresponding OPTION
+in the list, paging through the list if necessary, but it will not be
+treated as selected unless you enter the ACTIVATE (RETURN or right-arrow)
+command when positioned on the OPTION. For purposes of paging (e.g., in
+conjunction with the '<em>p</em>' suffix), a <em>page</em> is defined as
+the number of OPTIONs displayed within the vertical dimension of the popup
+window.
+
+<p>Note that HTML can be structured so that it includes <em>hidden
+links</em>, i.e., without a visible link name intended for ACTIVATE-ing
+the link. Such links may be created, for example, by making an IMG element
+the sole content of an Anchor element, and including an ALT="" attribute
+name/value pair to suppress access to the link when the browser does not
+have support for image handling available. They also can be created by
+having truly empty Anchor content, in cases for which the value of an
+Anchor's HREF attribute is intended as a navigation aid for robots
+(typically indexers) and not as content for a browser's rendition of the
+document. With the <em>-ismap</em> command line switch, Lynx will
+additionally treat a link to a server-side image maps as hidden if
+there also is a client-side map for the same image.
+Finally, in some cases links which are not intended to be hidden
+may effectively become <em>hidden links</em> because of bad HTML.
+The <em>hidden links</em> differ from Anchors which have only a
+NAME or ID attribute name/value pair (intended as positioning targets from
+other links which do have HREF attributes and values that include a
+fragment).
+
+<p>Lynx respects instructions for <em>hidden links</em> and normally does
+not include them in the rendition of the document. However, if the command
+line switch <em>-hiddenlinks=merge</em> is used, such links will still be
+numbered in sequence with other links which are not hidden, and if <em>Links
+are numbered</em> mode is also on, link numbers will appear for them in the
+displayed text (except for links to image maps which are hidden because of
+<em>-ismap</em>). If <em>-hiddenlinks=listonly</em> or
+<em>-hiddenlinks=ignore</em> is in effect, <em>hidden links</em> will not be
+shown in the text even in <em>links are numbered</em> mode. Not using a
+<em>-hiddenlinks</em> flag at all is equivalent to
+<em>-hiddenlinks=listonly</em>.
+
+<p>If a document includes
+<em>hidden links</em>, they will be reported, with appropriate labeling,
+in the menu created for the LIST ('<em>l</em>') command,
+unless <em>-hiddenlinks=ignore</em> is used. They can then be
+ACTIVATE-ed via that menu. Also, if a link was hidden due to an ALT
+attribute in an IMG element, it will be converted to a <em>visible link</em>
+whenever the IMAGE_TOGGLE ('<em>*</em>') command is used to create links
+for SRC attritute values of IMG elements, because this indicates that the
+user does have some form of image handling enabled via a helper application,
+or wishes to download files for subsequent use with a graphic browsers or
+other suitable software.
+
+<p>HTML forms also can have fields with a HIDDEN attribute, indicating that
+a name/value pair for the fields should be included in the content submitted
+for the form, but the value should not be displayed in the rendered form.
+Lynx respects this attribute as well, and neither displays the HIDDEN field,
+nor assigns it a number for the F_LINK_NUM ('<em>0</em>') command and
+<em>Links and form fields are numbered</em> keypad mode handling, nor
+includes an entry for it in the menu created for the LIST ('<em>l</em>')
+command. However, the HIDDEN name/value pairs are included in any displays
+of submitted form content in the <em>Information about the current
+document</em> that is invoked by the INFO ('<em>=</em>') command.
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/gopher_types_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/gopher_types_help.html
new file mode 100644
index 00000000000..629256e1347
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/gopher_types_help.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Listing of Gopher types</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Gopher Types +++</h1>
+
+<dl compact>
+<dt>(FILE)
+<dd>An ASCII file
+
+<dt>(DIR)
+<dd>A directory listing
+
+<dt>(CSO)
+<dd>The Computing Services Organizations
+nameserver interface
+
+<dt>(BIN)
+<dd>A binary file with one of the following meanings
+<ul>
+<li>A Binary file with PC extensions
+<li>A Binary file with UNIX extensions
+</ul>
+
+<dt>(HQX)
+<dd>A Macintosh file that has be BinHexed
+
+<dt>(?)
+<dd>A searchable database
+
+
+<dt>(IMG)
+<dd>An unknown image type
+You must have an <A HREF="xterm_help.html">X terminal</A> to
+view images
+
+<dt>(GIF)
+<dd>An image in Graphics Interchange Format
+You must have an <A HREF="xterm_help.html">X terminal</A> to
+view images
+
+<dt>(HTML)
+<dd>A World Wide Web hypertext file
+
+<dt>(TEL)
+<dd>The link will open a connection to another host using telnet
+
+<dt>(3270)
+<dd>The link will open a connection to another
+host using tn3270
+
+<dt>(UKN)
+<dd>An unknown or unsupported type
+</dl>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/history_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/history_help.html
new file mode 100644
index 00000000000..c6e3010fdd4
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/history_help.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on the History Page</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ History Page Help +++</h1>
+
+The History Page displays all of the links that you have traveled through
+to reach your current point, including any temporary menu or list files
+that included links, bookmark files, and any documents associated with
+POST content. If you entered a document and then left it by using the
+<em>left-arrow</em> key, it will <em>not</em> be in the history stack.
+If you entered a document and left it by selecting another link within
+that document, it <em>will</em> be in the history stack.
+
+<p>You may <A HREF="movement_help.html">select</A> any link on the History
+Page to review a document that you have previously visited. That link,
+and any subsequent to it, will not be removed from the history stack if you
+return to it via the History Page. You thus should use a History Page link,
+rather than the <em>left-arrow</em> key, if you wish to review previous
+documents without needing to remember and repeat the series of selections
+for reaching your currently displayed document.
+
+<p>Upon using <em>left-arrow</em> in the document selected via the History
+Page, you will be returned to the document from which you initially went to
+the History Page.
+
+<p>If a previously visited link has been removed from the history stack,
+and it was not a temporary menu or list file, bookmark file, or document
+associated with POST content, it can still be selected conveniently via
+the <A HREF="visited_help.html">Visited Links Page</A>. The latter also
+will include links which were '<em>d</em>'ownloaded or passed to a helper
+application, and thus were not included in the history stack.
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/keystroke_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/keystroke_help.html
new file mode 100644
index 00000000000..f3a57bc35d9
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/keystroke_help.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on Lynx Keystroke Commands</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Keystroke Commands +++</h1>
+<PRE>
+ <A HREF="movement_help.html"
+ >MOVEMENT</A>: Down arrow - Highlight next topic
+ Up arrow - Highlight previous topic
+ Right arrow, - Jump to highlighted topic
+ Return, Enter
+ Left arrow - Return to previous topic
+
+ <A HREF="scrolling_help.html"
+ >SCROLLING</A>: + - Scroll down to next page (Page-Down)
+ - - Scroll up to previous page (Page-Up)
+ SPACE - Scroll down to next page (Page-Down)
+ b - Scroll up to previous page (Page-Up)
+ CTRL-A - Go to first page of the current document (Home)
+ CTRL-E - Go to last page of the current document (End)
+ CTRL-B - Scroll up to previous page (Page-Up)
+ CTRL-F - Scroll down to next page (Page-Down)
+ CTRL-N - Go forward two lines in the current document
+ CTRL-P - Go back two lines in the current document
+ ) - Go forward half a page in the current document
+ ( - Go back half a page in the current document
+ # - Go to Toolbar or Banner in the current document
+
+ <A HREF="dired_help.html">DIRED</A>: c - Create a new file
+ d - Download selected file
+ e - Edit selected file
+ E - Edit the current link's URL (or ACTION) and
+ use that as a goto URL.
+ f - Show a full menu of options for current file
+ m - Modify the name or location of selected file
+ r - Remove selected file
+ t - Tag highlighted file
+ u - Upload a file into the current directory
+
+ <A HREF="other_help.html">OTHER</A>: ? (or h) - Help (this screen)
+ a - Add the current link to a bookmark file
+ c - Send a comment to the document owner
+ d - Download the current link
+ e - Edit the current file
+ g - Goto a user specified <a
+ href="../lynx_url_support.html">URL</a> or file
+ G - Edit the current document's URL and use that
+ as a goto URL.
+ i - Show an index of documents
+ j - Execute a jump operation
+ k - Show a list of key mappings
+ l - List references (links) in current document
+ m - Return to main screen
+ o - Set your <A HREF="option_help.html">options</A>
+ p - <a href="print_help.html"
+ >Print</a> to a file, mail, printers, or other
+ q - Quit (Capital 'Q' for quick quit)
+ / - Search for a string within the current document
+ s - Enter a search string for an external search
+ n - Go to the next search string
+ v - View a <A HREF="bookmark_help.html"
+ >bookmark file</A>
+ V - Go to the <A HREF="visited_help.html"
+ >Visited Links Page</A>
+ x - Force submission of form or link with no-cache
+ z - Cancel transfer in progress
+ [backspace] - Go to the <A HREF="history_help.html"
+ >History Page</A>
+ = - Show info about current document, URL and link
+ \ - Toggle document source/rendered view
+ ! - Spawn your default shell
+ ' - Toggle "historical" vs minimal or valid comment
+ parsing
+ _ - Clear all authorization info for this session
+ ` - Toggle minimal or valid comment parsing
+ * - Toggle image_links mode on and off
+ @ - Toggle raw 8-bit translations or CJK mode
+ on or off
+ [ - Toggle pseudo_inlines mode on and off
+ ] - Send a HEAD request for the current doc or link
+ " - Toggle valid or "soft" double-quote parsing
+ CTRL-R - Reload current file and refresh the screen
+ CTRL-V - Switch to alternative parsing of HTML documents
+ CTRL-W - Refresh the screen
+ CTRL-U - Erase input line
+ CTRL-G - Cancel input or transfer
+ CTRL-T - Toggle trace mode on and off
+ ; - View the Lynx Trace Log for the current
+ session.
+ CTRL-K - Invoke the <A HREF="cookie_help.html"
+ >Cookie Jar Page</A>
+ numbers - Invoke the prompt
+ <a href="follow_help.html"
+ >Follow link (or goto link or page) number:</a>
+ or the
+ <a href="follow_help.html#select-option"
+ >Select option (or page) number:</a>
+ prompt
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/movement_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/movement_help.html
new file mode 100644
index 00000000000..4655db31a76
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/movement_help.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on Lynx Movement commands</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<H1>+++ MOVEMENT HELP +++</H1>
+<PRE>
+ Down arrow, - Move to the next hypertext link,
+ TAB or scroll down if there are no more
+ links on the page to move to.
+
+ Up arrow - Move to the previous hypertext link,
+ or scroll up if there are no links
+ above the current one, and there are
+ previous pages to move to.
+
+ Right arrow, - select the link that the cursor is
+ Return, Enter positioned on.
+
+ Left arrow - Retreat from a link. Go back to the
+ previous topic.
+
+
+ *note: If 'VI Keys' are enabled from the options menu or
+ from the '.lynxrc' file, lowercase h,j,k,l will
+ move left, down, up, and right, respectively.
+
+ *note: If 'Emacs Keys' are enabled from the options menu or
+ from the '.lynxrc' file, Ctrl-B, Ctrl-N, Ctrl-P,
+ Ctrl-F will move left, down, up, and right, respectively.
+
+ *note: If the 'Num Lock' on your keyboard is on, Lynx will
+ translate the numbers of your keypad into movement
+ commands. The translation is as follows.
+
+ 9 - page up
+ 8 - up arrow
+ 7 8 9 7 - moves to the top of a document
+ \|/ 6 - right arrow
+ 4 - 5 - 6 5 - nothing
+ /|\ 4 - left arrow
+ 1 2 3 3 - page down
+ 2 - down arrow
+ 1 - moves to the end of a document
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/option_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/option_help.html
new file mode 100644
index 00000000000..2ef8151ce4d
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/option_help.html
@@ -0,0 +1,262 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Options Screen Help</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Options Screen Help +++</h1>
+<PRE>
+ The Options Screen allows you to set and
+ modify many of Lynx's features. The following
+ options may be set.
+
+ Editor - If non-empty it defines the editor to spawn
+ when editing a local file or sending mail.
+ Any valid text editor may be entered here.
+
+ DISPLAY variable - If non-empty it specifies your <A HREF="xterm_help.html">X terminal</A>
+ display address.
+
+ Multi-bookmarks - When OFF, the default bookmark file is used
+ for the 'v'iew bookmarks and 'a'dd bookmark
+ link commands. If set to STANDARD, a menu
+ of available bookmarks always is invoked
+ when you seek to view a bookmark file or add
+ a link, and you select the bookmark file by
+ its letter token in that menu. If set to
+ ADVANCED, you instead are prompted for the
+ letter of the desired bookmark file, but can
+ enter '=' to invoke the STANDARD selection
+ menu, or RETURN for the default bookmark file.
+
+ Bookmark file - If non-empty and multi-bookmarks is OFF, it
+ specifies your default '<A HREF="bookmark_help.html">Bookmark file</A>'.
+ If multi-bookmarks is STANDARD or ADVANCED,
+ entering 'B' will invoke a menu in which you
+ can specify the filepaths and descriptions
+ of up to 26 bookmark files. The filepaths
+ must be from your home directory, and begin
+ with dot-slash (./) if subdirectories are
+ included (e.g, ./BM/lynx_bookmarks.html).
+ Lynx will create bookmark files when you
+ first 'a'dd a link, but any subdirectories
+ in the filepath must already exist.
+
+ FTP sort criteria - This option allows you to specify how files
+ will be sorted within FTP listings. The
+ current options include "By Filename",
+ "By Size", "By Type", and "By Date".
+
+ Personal Mail - You may set your mail address here so that
+ Address when mailing messages to other people or
+ mailing files to yourself, your email address
+ can be automatically filled in. Your email
+ address will also be sent to HTTP servers in
+ a from: field.
+
+ Searching type - If set to 'case sensitive', user searches
+ invoked by the '/' command will be case
+ sensitive substring searches. The
+ default is 'Case Insensitive' substring
+ searches
+
+ Preferred Document - The language you prefer if multi-language files
+ Language are available from servers. Use RFC 1766 tags,
+ e.g., en for English, fr for French, etc. Can be
+ a comma-separated list, which may be interpreted
+ by servers as descending order of preferences.
+ You can also make your order of preference explicit
+ by using q factors as defined by the HTTP protocol,
+ for servers which understand it, for example:
+ <kbd>da, en-gb;q=0.8, en;q=0.7</kbd>
+
+ Preferred Document - The character set you prefer if sets in addition
+ Charset to ISO-8859-1 and US-ASCII are available from
+ servers. Use MIME notation (e.g., ISO-8859-2)
+ and do not include ISO-8859-1 or US-ASCII, since
+ those values are always assumed by default. Can
+ be a comma-separated list, which may be interpreted
+ by servers as descending order of preferences.
+ You can also make your order of preference explicit
+ by using q factors as defined by the HTTP protocol,
+ for servers which understand it, for example:
+ <kbd>iso-8859-5, unicode-1-1;q=0.8</kbd>
+
+ Display Character - This option allows you to set up the default
+ set character set for your specific terminal.
+ The character set provides a mapping of 8-bit ISO
+ Latin character entities and/or Asian (CJK) or
+ Unicode characters into viewable characters and
+ should be set according to your terminal's
+ character set if you will be viewing such
+ characters with Lynx. You must have the selected
+ character set installed on your terminal.
+
+ Raw 8-bit or CJK - Toggles whether 8-bit characters are assumed to
+ mode correspond with the selected character set and
+ therefore are processed without translation via
+ the chartrans conversion tables. Should be ON
+ by default when the selected character set is one
+ of the Asian (CJK) sets and the 8-bit characters
+ are Kanji multibytes. Should be OFF for the other
+ character sets, but can be turned ON when the
+ document's charset is unknown (e.g., is not
+ ISO-8859-1 and no charset parameter was included in
+ a reply header from an HTTP server to indicate what
+ it is) but you know by some means that you have the
+ matching display character set selected. Should be
+ OFF when an Asian (CJK) set is selected but the
+ document is ISO-8859-1. The setting also can be
+ toggled via the RAW_TOGGLE command, normally mapped
+ to '@', and at startup via the -raw switch.
+
+ Show color - This option will be present if color support is
+ available. If set to ON or ALWAYS, color mode will
+ be forced on if possible. If (n)curses color
+ support is available but cannot be used for the
+ current terminal type, selecting ON is rejected
+ with a message. If set to OFF or NEVER, color mode
+ will be turned off.
+ ALWAYS and NEVER are not offered in anonymous
+ accounts. If saved to a '.lynxrc' file in
+ non-anonymous accounts, ALWAYS will cause Lynx to
+ set color mode on at startup if supported. If Lynx
+ is built with the slang library, this is equivalent
+ to having included the -color command line switch
+ or having the COLORTERM environment variable
+ set. If color support is provided by curses or
+ ncurses, this is equivalent to the default behavior
+ of using color when the terminal type supports it.
+ If (n)curses color support is available but cannot
+ be used for the current terminal type, the
+ preference can still be saved but will have no
+ effect.
+ A saved value of NEVER will cause Lynx to assume a
+ monochrome terminal at startup. It is similar to
+ the -nocolor switch, but (when the slang library is
+ used) can be overridden with the -color switch.
+ If the setting is OFF or ON when the current
+ options are saved to a '.lynxrc' file, the default
+ startup behavior is retained, such that color mode
+ will be turned on at startup only if the terminal
+ info indicates that you have a color-capable
+ terminal, or (when the slang library is used) if
+ forced on via the -color switch or COLORTERM
+ variable. This default behavior always is used in
+ anonymous accounts, or if the 'option'_save
+ restriction is set explicitly. If for any reason
+ the startup color mode is incorrect for your
+ terminal, set it appropriately on or off via this
+ option.
+
+ VI keys - If set to 'ON' then the lowercase h, j, k, and l,
+ keys will be mapped to left-arrow, down-arrow,
+ up-arrow, and right-arrow, respectively. The
+ uppercase H, J, K, and L keys remain mapped to
+ their configured bindings (normally HELP, JUMP,
+ KEYMAP, and LIST, respectively).
+
+ Emacs keys - If set to 'ON' then the CTRL-P, CTRL-N, CTRL-F,
+ and CTRL-B keys will be mapped to up-arrow,
+ down-arrow, right-arrow, and left-arrow,
+ respectively. Otherwise, they remain mapped
+ to their configured bindings (normally UP_TWO
+ lines, DOWN_TWO lines, NEXT_PAGE, and PREV_PAGE,
+ respectively).
+
+ Show dot files - If display/creation of hidden (dot)
+ files/directories is enabled, you can turn
+ the feature on or off via this setting.
+
+ Popups for select - Lynx normally uses a popup window for the
+ fields OPTIONs in form SELECT fields when the field
+ does not have the MULTIPLE attribute specified,
+ and thus only one OPTION can be selected. The
+ use of popup windows can be disabled by changing
+ this setting to OFF, in which case the OPTIONs
+ will be rendered as a list of radio buttons.
+ Note that if the SELECT field does have the
+ MULTIPLE attribute specified, the OPTIONs always
+ are rendered as a list of checkboxes.
+
+ Show cursor for - Lynx normally hides the cursor by positioning it
+ current link or to the right and if possible the very bottom of
+ option the screen, so that the current link or OPTION
+ is indicated solely by its highlighting or color.
+ If show cursor is set to ON, the cursor will be
+ positioned at the left of the current link or
+ OPTION. This is helpful when Lynx is being used
+ with a speech or braille interface. It also is
+ useful for sighted users when the terminal cannot
+ distinguish the character attributes used to
+ distinguish the current link or OPTION from the
+ others in the screen display.
+
+ Keypad mode - This option gives the choice between navigating
+ with the keypad (as arrows; see Lynx Navigation)
+ and having every link numbered (numbered links)
+ so that the links may be selected by numbers
+ instead of moving to them with the arrow keys.
+
+ Line edit style - This option allows you to set alternate key
+ bindings for the built-in line editor, if your
+ system administrator has installed alternates.
+ Otherwise, Lynx uses the <A HREF="edit_help.html">Default Binding</A>.
+
+ List directory - Applies to Directory Editing. Files and
+ style directories can be presented in the following
+ ways:
+ Mixed style
+ Files and directories are listed together in
+ alphabetical order.
+ Directories first
+ Files and directories are separated into two
+ alphabetical lists. Directories are listed
+ first.
+ Files first
+ Files and directories are separated into two
+ alphabetical lists. Files are listed first.
+
+ User Mode - Beginner
+ Shows two extra lines of help at the bottom
+ of the screen
+ Intermediate (normal mode)
+ The "normal" statusline messages appear.
+ Advanced
+ The URL is shown on the statusline.
+
+ User Agent - The header string which Lynx sends to servers
+ to indicate the User-Agent is displayed here.
+ Changes may be disallowed via the -restrictions
+ switch. Otherwise, the header can be changed
+ temporarily to a string such as L_y_n_x/2.7.2 for
+ access to sites which discriminate against Lynx
+ based on checks for the presence of "Lynx" in the
+ header. If changed during a Lynx session, the
+ default User-Agent header can be restored by
+ deleting the modified string in the Options Menu.
+ Whenever the User-Agent header is changed, the
+ current document is reloaded, with the no-cache
+ flags set, on exit from the Options Menu. Changes
+ of the header are not saved in the RC file.
+ NOTE that Netscape Communications Corp. has
+ claimed that false transmissions of "Mozilla" as
+ the User-Agent are a copyright infringement, which
+ will be prosecuted. DO NOT misrepresent Lynx as
+ Mozilla. The Options Menu issues a warning about
+ possible copyright infringement whenever the header
+ is changed to one which does not include "Lynx" or
+ "lynx".
+
+ Local execution - If set to 'ALWAYS ON', Lynx will locally execute
+ links commands contained inside of any links. This
+ can be HIGHLY DANGEROUS so it is recommended
+ that they remain 'ALWAYS OFF' or 'FOR LOCAL
+ FILES ONLY' unless otherwise set by your system
+ administrator. This option may not be available
+ on most versions of Lynx.
+
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/other_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/other_help.html
new file mode 100644
index 00000000000..511ddaac4b7
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/other_help.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on Misc. Lynx Commands</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Other Commands +++</h1>
+<PRE>
+ a - Places the link that you are currently positioned
+ on into a personal <A HREF="bookmark_help.html">bookmark file</A>.
+
+ c - Allows you to send a mail message to the owner
+ or maintainer of the data that you are currently
+ viewing. In the case that no owner is known,
+ you cannot send a comment.
+
+ d - Downloads the file pointed to by the current link
+ and displays an option menu allowing the file to
+ be saved or transfered by configurable options.
+ Can also be used when positioned on a form SUBMIT
+ button to download the reply to a form submission.
+
+ e - Allows you to edit the current document if it is a
+ local file.
+
+ E - Allows you to edit the current link's URL (or ACTION) and
+ use that as a <em>goto</em> URL.
+
+ g - Allows you to enter any <a href="http://www.ncsa.uiuc.edu/demoweb/url-primer.html">URL</a> or filename that
+ you wish to view, and then <em>goto</em> it.
+
+ G - Allows you to edit the current document's URL and use that
+ as a <em>goto</em> URL.
+
+ ? or H - Hypertext help to explain how to navigate in
+ Lynx and use its features.
+
+ i - Shows an index of files or subjects. This is
+ configurable by the System administrator, or
+ within documents that you may be viewing.
+
+ j - Allows you to enter a "short" name to execute a
+ jump command configured by your system administrator.
+ Press "?" and ENTER to see a list of defined
+ jump commands.
+
+ k - Shows a list of key mappings. Keys remapped in
+ "lynx.cfg" show up in this list.
+
+ l - Brings up a list of references (links) in the current
+ document, which can be used for rapid access to the
+ links in large documents.
+
+ m - Returns to the first screen and empties the
+ history stack.
+
+ p - Brings up a list of <A HREF="print_help.html">print commands</A>.
+
+ o - Brings up a list of setable <A HREF="option_help.html">options</A>.
+
+ q - Quits Lynx. ('Q' quits without asking)
+
+ / - Search for a string of characters in the current
+ document case insensitive or case sensitive
+ depending on the options set. (see <A HREF="option_help.html">options)</A>.
+
+ s - Search through an external searchable indexed document.
+
+ n - Move to the next instance of a search string if you
+ have searched previously.
+
+ v - View a <A HREF="bookmark_help.html">Bookmark file</A>.
+
+ x - Force submission of form or link with no-cache.
+
+ z - Abort a network transfer in progress. If any partial
+ data has been transfered it will be displayed.
+
+ &lt;backspace&gt; - displays the <a href="history_help.html">history page</A>.
+
+ = - Show information about the file and link that you
+ are currently viewing.
+
+ \ - Toggles between viewing the HTML source of a
+ document and the rendered version of the document.
+
+ ! - Spawns your default operating system shell.
+
+ ' - Toggles "historical" vs minimal or valid comment parsing.
+ When historical, any close-angle-bracket will be treated
+ as a comment terminator, emulating the parsing bug in old
+ versions of Mosaic and Netscape, rather than validly
+ requiring pairs of two successive dashes to delimit
+ comments within the angle-brackets.
+
+ _ - Clears all authorization info for the current session. Can
+ be used when leaving one's terminal without ending the Lynx
+ session, to guard against someone else retrieving protected
+ documents with previously entered username/password info.
+ Note that any protected documents that are still in cache
+ can still be accessed.
+
+ ` - Toggles minimal or valid comment parsing. When minimal, any
+ two successive dashes followed by a close-angle-bracket will
+ be treated as a comment terminator, emulating the parsing bug
+ in Netscape v2.0. If historical comment parsing is set, that
+ will override minimal or valid comment parsing.
+
+ * - Toggles image_links mode on and off. When on, links will
+ be created for all images, including inlines.
+
+ @ - Toggles raw 8-bit translations or CJK mode on and off.
+ Should be on when the document's charset matches the
+ selected character set, and otherwise off so that 8-bit
+ characters will be reverse translated with respect to the
+ ISO-8859-1 conversion table for the character set (see
+ <A HREF="option_help.html">options)</A>.
+
+ [ - Toggles pseudo_inlines mode on and off. When on, inline
+ images which have no ALT string specified will have an
+ "[INLINE]" pseudo-ALT string inserted in the Lynx display.
+ When off, they will be treated as having ALT="" (i.e.,
+ they'll be ignored). If image_links mode is toggled on,
+ the pseudo-ALT strings will be restored, to serve as links
+ to the inline images' sources.
+
+ ] - Sends a HEAD request for the current document or link. It
+ applies only to documents or links (or form submit buttons)
+ of http servers. A statusline message will notify you if
+ the context for this command was inappropriate. The HEAD
+ requests always are sent to the http server, i.e., Lynx
+ does not retrieve any previous server replies from its
+ cache. Note that for form submissions, http servers vary
+ in whether they'll treat HEAD requests as valid and return
+ the CGI script's headers, or treat it as invalid and return
+ an error message.
+
+ " - Toggles valid or "soft" double-quote parsing. When soft,
+ a close-angle-bracket will serve as both a close-double-
+ quote and close-tag, emulating the parsing bug in old
+ versions of Mosaic and Netscape.
+
+ CTRL-R - Reloads the current document and resets the display.
+
+ CTRL-V - Switches to an alternative way of parsing HTML documents.
+ This may help to get a more readable rendering of some
+ documents with invalidly placed HTML tags.
+
+ CTRL-W - Resets or cleans up the display.
+
+ CTRL-U - Clears text from an input field or prompt.
+
+ CTRL-G - Cancels any input prompt, mail message or data transfer.
+
+ CTRL-T - Toggles trace mode on and off.
+
+ ; - Views the Lynx Trace Log for the current session.
+
+ CTRL-K - Invokes the Cookie Jar Page.
+
+ numbers - Lynx offers other, advanced navigation features when
+ numbers are used to invoke the
+ <a href="follow_help.html"
+ >Follow link (or goto link or page) number:</a> or
+ <a href="follow_help.html#select-option"
+ >Select option (or page) number:</a>
+ prompts.
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/print_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/print_help.html
new file mode 100644
index 00000000000..153caa74c31
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/print_help.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Lynx Print Help</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Printing Help +++</h1>
+
+After entering the 'p' command you will be presented with a list of
+print options. In all cases the file will be printed in ASCII format
+with the hypertext links removed. The number of options depends on the
+level of printing that your system allows. The following print options
+may be available:
+
+<dl>
+<dt>Print to a local file:
+<dd>This allows you to save the current file as ASCII text to your
+ local disk. You will be asked for a path and filename to save
+ the file to. If no path is given, the file will be saved to the
+ directory that you were in when you began Lynx.
+
+<dt>Print to the screen:
+<dd>This option simply scrolls the entire document up the screen and
+ is intended for those who wish to capture the document with their
+ terminal.
+
+<dt>Mail the file to yourself:
+<dd>This option allows you to mail the file, in ASCII form, to any
+ valid e-mail address.
+
+<dt>Custom print options:
+<dd>Any number of custom print options may be available, as defined
+ by your system administrator.
+</dl>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/scrolling_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/scrolling_help.html
new file mode 100644
index 00000000000..d19313462bb
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/scrolling_help.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Lynx Scrolling Help</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<H1>+++ SCROLLING HELP +++</H1>
+<PRE>
+ + (or SPACE, - If the bottom of the screen informs you
+ or CTRL-F) that there is 'more' to see, you may
+ move to the next page (Page-Down).
+
+ - (or b, - If you have moved down in a document, this
+ or CTRL-B) will bring you back up one page (Page-Up).
+
+ If the 'Num Lock' on your keyboard is on, Lynx will translate
+ the numbers of your keypad into movement commands as follows:
+
+ 9 - page up
+ 8 - up arrow
+ 7 8 9 7 - moves to the top of a document
+ \|/ 6 - right arrow
+ 4 - 5 - 6 5 - nothing
+ /|\ 4 - left arrow
+ 1 2 3 3 - page down
+ 2 - down arrow
+ 1 - moves to the end of a document
+
+ CTRL-A (or Find) - This Control key, and Function key synonym,
+ brings you back to the first page of the
+ current document (Home).
+
+ CTRL-E (or Select) - This Control key, and Function key synonym,
+ takes you to the last page of the current
+ document (End).
+
+ CTRL-N (or Remove) - This Control key, and Function key synonym,
+ moves you forward two lines in the current
+ document (Down-Two).
+
+ CTRL-P (or Insert) - This Control key, and Function key synonym,
+ moves you back two lines in the current
+ document (Up-Two).
+
+ ) - Moves you forward half a page in the current
+ document (Down-Half).
+
+ ( - Moves you back half a page in the current
+ document (Up-Half).
+
+ # - Jumps you to the pseudo Toolbar or Banner if
+ present in the current document. Use left-arrow
+ to return from there to your previous position
+ in the document.
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/visited_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/visited_help.html
new file mode 100644
index 00000000000..ebb03a709b8
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/visited_help.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>Help on the Visited Links Page</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ Visited Links Page Help +++</h1>
+
+The Visited Links Page displays all of the links that you have traveled
+through during the current Lynx session, except for any temporary menu
+or list files, bookmark files, or any documents associated with POST
+content. The VLINKS keystroke command for invoking this page normally
+is mapped to uppercase '<em>V</em>'. The list of Visited Links is in
+order of recency (most recently visited links first), without repetitions
+in the list if a link was visited more than once during the session (unless
+the URLs differ due to appended fragments), and is supplementary to the
+<A HREF="history_help.html">History Page</A>.
+
+<p>You may <A HREF="movement_help.html">select</A> any link on the Visited
+Links Page to retrieve a document that you had previously visited, or you
+can use this list to save such links in your <A HREF="bookmark_help.html"
+>bookmark files</A>, or to <A HREF="../Lynx_users_guide.html#9">Download</A>
+them.
+
+<p>In contrast to the History Page, the Visited Links Page includes any
+links which were retrieved for '<em>d</em>'ownloading or were passed to
+helper applications, i.e, not just the links that were rendered and
+displayed by Lynx, itself.
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/keystrokes/xterm_help.html b/gnu/usr.bin/lynx/lynx_help/keystrokes/xterm_help.html
new file mode 100644
index 00000000000..d40ea45016f
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/keystrokes/xterm_help.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>X Terminal Help</TITLE>
+<LINK rev="made" href="mailto:lynx-dev@sig.net">
+</HEAD>
+<BODY>
+<h1>+++ X Terminal or X Server +++</h1>
+
+An X terminal is an electronic display terminal that communicates
+with a host computer system using the X Window protocol developed at the
+Massachusetts Institute of Technology.
+
+<p>The X Window protocol allows a program running on the host computer
+system to display both formatted text and graphics on the X terminal.
+Since the X Window protocol is defined to work over any TCP/IP network,
+X terminals connected to the Internet can be connected to hosts
+located anywhere on the Internet.
+
+<p>Personal computers (including both PCs and Macintoshes) can execute
+programs, usually called X servers, that make them act like X Window
+terminals and are frequently used as X terminals.
+
+<dl>
+<dt>Note:
+<dd>The terminology used to describe processes associated with X
+ terminals can be confusing. An X terminal is also known as
+ an "X display server," and the program running on the host
+ computer is usually known as the "X client."
+</dl>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/lynx_help/lynx-dev.html b/gnu/usr.bin/lynx/lynx_help/lynx-dev.html
new file mode 100644
index 00000000000..f062f6748d9
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/lynx-dev.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Lynx-Dev Discussion List</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+
+<body>
+<banner>
+[ <a href="http://www.flora.org/lynx-dev/html/">Lynx-Dev Archives</a> |
+<a href="about_lynx.html">About Lynx</a> ]
+</banner>
+
+<h1><em>Lynx-Dev Discussion List</em></h1>
+
+Lynx-dev is a majordomo mailing list used by developers and interested
+users as a forum to discuss the further development of the Lynx World
+Wide Web browser. Topic issues include fixing known bugs, porting Lynx
+to various systems, and increasing the usability of Lynx.
+
+<h2><em>Subscribing to Lynx-Dev</em></h2>
+
+If you are interested in <em>joining</em> this mailing list,
+send email to <a href="mailto:majordomo@sig.net"
+>majordomo@sig.net</a> with only the following request
+in the body of your message: <em>SUBSCRIBE LYNX-DEV address</em><br>
+where inclusion of your email address is optional if it can be obtained,
+correctly, from the mail headers of your subscription request.
+
+<p><em>NOTE:</em> Subject headers are ignored by the majordomo.
+
+<h2><em>Unsubscribing from Lynx-Dev</em></h2>
+
+To <em>unsubscribe</em>, send an email message to
+<a href="mailto:majordomo@sig.net"
+>majordomo@sig.net</a> with only the following request
+in the body: <em>UNSUBSCRIBE LYNX-DEV address</em><br>
+where inclusion of your email address is optional if it can be obtained,
+correctly, from the mail headers of your request.
+
+<h2><em>Majordomo Commands</em></h2>
+
+To receive a brief description of majordomo <em>commands</em>, place
+the following request in a message to <a href="mailto:majordomo@sig.net"
+>majordomo@sig.net</a>: <em>HELP</em>
+
+<h2><em>Contacting Lynx-Dev</em></h2>
+
+If you have questions, problems, or comments about using Lynx or
+installing it on your system, send email to
+<a href="mailto:lynx-dev@sig.net"
+>lynx-dev@sig.net</a> (<em>after you've subscribed</em>).
+
+<p>If you have problems with majordomo not responding to your requests,
+send email to the <em>list owner</em>: <a
+href="mailto:majordomo-owner@sig.net"
+>majordomo-owner@sig.net</a>. Please,
+<em>DO NOT</em> send them to <em>lynx-dev@sig.net</em> as they
+will be distributed to everyone on the list and will clutter
+up their mailboxes.
+
+<h2><em>Lynx-Dev Archives</em></h2>
+
+Archives of messages posted to lynx-dev are now in html format so that
+you can view them using Lynx.
+
+<p>Go to the <a href="http://www.flora.org/lynx-dev/html/"
+>Lynx-Dev Archives</a>.
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/lynx_help/lynx_help_main.html b/gnu/usr.bin/lynx/lynx_help/lynx_help_main.html
new file mode 100644
index 00000000000..0871f1d9f24
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/lynx_help_main.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+<title>Help! - Press the Left arrow key to exit help</title>
+</head>
+<body>
+
+<H1>Lynx Help Menu</h1>
+
+<ul plain>
+<lh><em>Choose a subject:</em></lh>
+<li><a href="Lynx_users_guide.html">Lynx Users Guide</a>
+<ul plain>
+<li><a href="keystrokes/keystroke_help.html">Key-stroke Commands</a>
+| <a href="keystrokes/edit_help.html">Line Editor</a>
+<li><a href="lynx_url_support.html">Supported URLs</a>
+| <a href="http://www.w3.org/Addressing/Addressing.html"
+>Help on URLs</a>
+<li><a href="http://leb.net/blinux/blynx/"
+>Speech-Friendly Lynx Help Files</a>
+<li><a href="http://lynx.browser.org/">Lynx Information</a>
+| <a href="http://www.crl.com/~subir/lynx.html"
+>Lynx links</a>
+| <a href="http://www.slcc.edu/lynx/faq.html"
+>Lynx FAQ</a>
+<li><a href="about_lynx.html">About Lynx</a>
+| <a href="lynx-dev.html">About Lynx-Dev</a>
+| <a href="http://www.access.digex.net/~asgilman/lynx/FAQ/"
+>Al's Picks (FAQ)</a>
+</ul>
+
+<li><a
+href="http://www.w3.org/MarkUp/html-spec/html-spec_toc.html"
+>HTML 2.0</a>
+| <a href="http://www.w3.org/MarkUp/html3/Contents.html"
+>HTML 3.0</a>
+| <a href="http://www.alis.com:8085/ietf/html/"
+>HTML i18n</a>
+| <a href="http://www.w3.org/MarkUp/"
+>HTML 3.2</a>
+| <a href="http://www.w3.org/TR/PR-html40/"
+>HTML 4.0</a>
+
+<ul plain>
+<li><a href="http://www.stonehand.com/doc/"
+>Spyglass/Stonehand Technical Reference</a>
+<ul plain>
+<li><a
+href="http://www.stonehand.com/doc/comments.html"
+>Keep Your Comments Legal</a>
+</ul>
+<li><a
+href="http://ugweb.cs.ualberta.ca/~gerald/validate/"
+>A Kinder, Gentler HTML Validator</a>
+<li><a href="http://www.webtechs.com/html-val-svc/"
+>WebTechs HTML Validation Service</a>
+<li><a href="http://www.ncsa.uiuc.edu/General/Internet/WWW/HTMLPrimer.html"
+>HTML Primer</a>
+| <a href="http://kuhttp.cc.ukans.edu/lynx_help/HTML_quick.html"
+>HTML Quick Reference Guide</a>
+</ul>
+
+<li><a
+href="http://ds.internic.net/rfc/rfc1945.txt"
+>HTTP 1.0</a>
+| <a href="http://www.w3.org/Protocols/"
+>HTTP 1.1</a>
+
+<li><a
+href="http://www.w3.org/TheProject.html"
+>The World Wide Web Consortium (W3C)</a>
+
+<li><a href="http://www.altavista.digital.com/">Alta&nbsp;Vista</a>
+| <a href="http://www.yahoo.com/">Yahoo!</a>
+| <a href="http://guaraldi.cs.colostate.edu:2000/">Savvy&nbsp;Search</a>
+| <a href="http://www.webcrawler.com/">WebCrawler</a>
+<li><a href="http://guide.Infoseek.com/">Infoseek&nbsp;Guide</a>
+| <a href="http://www.lycos.com/">Lycos</a>
+| <a href="http://www.excite.com/">Excite</a>
+| <a href="http://www.metacrawler.com/">MetaCrawler</a>
+</ul>
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/lynx_help/lynx_url_support.html b/gnu/usr.bin/lynx/lynx_help/lynx_url_support.html
new file mode 100644
index 00000000000..27f069ab41f
--- /dev/null
+++ b/gnu/usr.bin/lynx/lynx_help/lynx_url_support.html
@@ -0,0 +1,586 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<HTML>
+<HEAD>
+<TITLE>URL Schemes Supported in Lynx</TITLE>
+<LINK rev=made href="mailto:lynx-dev@sig.net">
+</HEAD>
+
+<BODY>
+<BANNER>
+<em>[</em><a href="#http">http, https</a> <em>|</em>
+<a href="#telnet">telnet, tn3270, rlogin</a> <em>|</em>
+<a href="#gopher">gopher</a> <em>|</em>
+<a href="#file">file</a> <em>|</em>
+<a href="#ftp">ftp</a> <em>|</em>
+<a href="#wais">wais</a> <em>|</em>
+<a href="#news">news, nntp, snews</a> <em>|</em>
+<a href="#newspost">newspost, newsreply, snewspost, snewsreply</a> <em>|</em>
+<a href="#mailto">mailto</a> <em>|</em>
+<a href="#finger">finger</a> <em>|</em>
+<a href="#cso">cso</a> <em>|</em>
+<a href="#exec">lynxexec, lynxprog</a> <em>|</em>
+<a href="#cgi">lynxcgi</a><em>|</em>
+<a href="#internal">internal</a><em>]</em>
+</BANNER>
+
+<H1><em>URL Schemes Supported in Lynx</em></H1>
+
+Lynx handles a number of URL types, that are enumerated below. For
+more details about URLs (Uniform Resource Locators) see <em>RFC1738</em>:
+<ul plain>
+<li><a href="http://www.w3.org/Addressing/rfc1738.txt"
+>http://www.w3.org/Addressing/rfc1738.txt</a>
+<li><a href="ftp://ds.internic.net/rfc/rfc1738.txt"
+>ftp://ds.internic.net/rfc/rfc1738.txt</a>
+</ul>
+
+<p>Lynx resolves partial or relative URLs in documents with respect to
+the BASE if one was specified, otherwise with respect to the document's
+absolute URL, using the rules described in <em>RFC1808</em>:
+<ul plain>
+<li><a href="http://www.w3.org/Addressing/rfc1808.txt"
+>http://www.w3.org/Addressing/rfc1808.txt</a>
+<li><a href="ftp://ds.internic.net/rfc/rfc1808.txt"
+>ftp://ds.internic.net/rfc/rfc1808.txt</a>
+</ul>
+
+and in subsequent drafts of the <em>IETF</em>:
+<ul plain>
+<li><a href="http://www.ics.uci.edu/pub/ietf/uri/"
+>Uniform Resource Identifiers (URI) Working Group</a>
+</ul>
+
+<p>When entering a URL on the command line to be used as the
+<em>startfile</em>, or at the prompt for a '<em>g</em>'oto entry, a
+partial host field can be used and the scheme field can be omitted if
+the scheme and fully qualified domain name can be constructed internally
+by using the URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES definitions in
+the Lynx configuration file. See the explanation of those definitions
+and their use in your <em>lynx.cfg</em>. For example, <em>wfbr</em> will
+be treated as <em>http://www.wfbr.edu/</em>, and <em>wfbr/dir/lynx</em>
+will be treated as <em>http://www.wfbr.edu/dir/lynx</em>, but
+<em>gopher.wfbr.edu/11/_fileserv/_lynx</em> will be treated as
+<em>gopher://gopher.wfbr.edu/11/_fileserv/_lynx</em>. For files or
+directories on the local host, a tilde (<em>~</em>) is expanded to
+the path of the account's login directory, e.g., <em>~/foo</em> will
+be expanded to <em>file://localhost/your/login/directory/foo</em>.
+The tilde expansion is done homologously on Unix and VMS. On VMS,
+Lynx also will expand any file or directory spec recognizable to
+DCL into a valid URL, e.g., <em>[]</em> will be expanded to
+<em>file://localhost/current/default/directory</em>. These expansions
+are <em>SOLELY</em> for <em>startfile</em> or '<em>g</em>'oto entries!
+Any partial or relative URLs within HTML documents are resolved
+according to the rules specified in RFC1808 and subsequent IETF drafts.
+<HR WIDTH="100%">
+
+<H2><a name="http">The <em>http</em> and <em>https</em> URLs:</a></H2>
+
+Lynx handles http URLs exactly as specified in RFC1738. The format
+is:<BR>
+<tab indent="12"><em>http://host:port/path?searchpart#fragment</em><BR>
+where <em>:port</em> is optional and defaults to <em>:80</em>,
+<em>/path</em> if present is a slash-separated series of symbolic
+elements, and <em>?searchpart</em> if present is the query for an ISINDEX
+search or the content of a FORM with METHOD="GET". The <em>#fragment</em>
+field if present indicates a location in the document to seek for display,
+based on a NAME-ed anchor or an ID attribute within the document, and is
+technically an instruction rather than part of the URL. Lynx will treat
+ID attributes as NAME-ed anchors for all tags in the BODY of a document
+which can correspond to positions in the rendering of the document.
+
+<p>The https URL has the same format, but the default port is <em>:443</em>.
+Patches for support of https URLs and the CONNECT procedure are available
+for qualified recipients via <a
+href="http://www.crl.com/~subir/lynx.html">Lynx links</a>. US Export laws
+and associated red tape pose severe impediments to inclusion of this support
+in the general distributions of freeware WWW clients such as Lynx. Sorry.
+<HR WIDTH="100%">
+
+<H2><a name="telnet"
+>The <em>telnet</em>, <em>tn3270</em>, and <em>rlogin</em> URLs:</a></H2>
+
+A <em>telnet</em> URL generally results in Lynx spawning a telnet
+session. Lynx implements the complete telnet URL scheme, i.e.:<BR>
+<tab indent="12"><em>telnet://user:password@host:port</em>
+
+<p>The <em>user</em> and/or <em>:password</em> fields may be omitted, and
+the <em>@</em> should be omitted if neither is present. The port defaults
+to <em>:23</em> when omitted in the URL.
+
+<p>A <em>tn3270</em> or <em>rlogin</em> URL is specified equivalently,
+and similarly spawns a tn3270 or rlogin session. The actual behavior
+is dependent on the TCP-IP software installed on the local and target
+hosts.
+
+<p>It is unwise to include the <em>:password</em> field except for
+URLs which point to anonymous or other public access accounts, and
+for most TCP-IP software you will be prompted for a password whether
+or not one was included in the URL.
+<HR WIDTH="100%">
+
+<H2><a name="gopher">The <em>gopher</em> URL:</a></H2>
+
+The gopher URL takes the form:<BR>
+<tab indent="12"><em>gopher://host:port/gopher-path</em><BR>
+where <em>:port</em> is optional and defaults to <em>:70</em>, and the
+<em>/gopher-path</em> is opaque (not fully equivalent to the
+slash-separated series of symbolic elements of http paths) as explained
+in RFC1738. Typically, the gopher-path consists of a
+<A HREF="keystrokes/gopher_types_help.html"><em>gophertype</em></A>
+indicating the file or service type (e.g., <em>0</em> or <em>I</em> for
+plain text or an image, respectively, <em>7</em> for a search, or <em>1</em>
+for a directory), followed by a platform-specific <em>selector</em>. Any
+reserved characters in the selector should be hex escaped (<em>%hh</em>),
+including slashes, although hex escaping of slashes is not required by Lynx
+in gopher URLs.
+
+<p>Lynx does not overtly support the gopher+ protocol, and does not
+represent itself as gopher+ capable when communicating with gopher
+servers. Lynx might transmit any (hex-escaped-tab-separated) extended
+gopher+ fields in a URL if an author included them in a document, but is
+likely to mishandle what the gopher server returns in such cases, and would
+not generate and transmit them itself. For pre-formed URLs to submit gopher
+searches, it may be better to use a <em>?</em> rather than hex-escaped tab
+(<em>%09</em>) as the separator for the <em>searchpart</em> in the
+<em>selector</em>, e.g.:<BR>
+<em>gopher://gopher.wfbr.edu/77/_shell/search.shell%20/_shell/walker?lynx*</em>
+Lynx will handle the <em>%09</em> if you use that instead of <em>?</em>,
+but other WWW clients may mishandle it.
+
+<p>For the <em>gophertype</em> which signifies HTML (<em>h</em>), if the
+<em>selector</em> begins with <em>GET%20/</em> Lynx will convert the gopher
+URL to an http URL, e.g.:<BR>
+<tab indent="12"><em>gopher://www.wfbr.edu:80/hGET%20/</em><BR>
+will become:<BR>
+<tab indent="12"><em>http://www.wfbr.edu/</em><BR>
+The port field will be retained if it is not <em>:80</em>, and will default
+to <em>:70</em> if it was defaulted originally. These conventions were
+adopted during development of the University of Minnesota gopher software
+to facilitate the offering of links to MIME-capable http servers in the
+listings returned by gopher servers, but should be considered Lynxisms
+and UMN Gopherisms.
+<HR WIDTH="100%">
+
+<H2><a name="file">The <em>file</em> URL:</a></H2>
+
+The file URL is used to retrieve files or generate a directory listing
+on the local host. The host field can be <em>localhost</em> or a domain
+name for the local host:<BR>
+<tab indent="12"><em>file://localhost/path</em><BR>
+If you do not use <em>localhost</em> or a domain name for the local host,
+Lynx will substitute <em>ftp://</em> for <em>file://</em> and treat it
+as an ftp URL.
+
+<p>The <em>/path</em> is treated as originating at the root, unless
+you include a tilde (<em>~</em>), e.g.:<BR>
+<tab indent="12"><em>file://localhost/~/foo</em>
+<tab indent="60">will be converted to:<BR>
+<tab indent="12"><em>file://localhost/your/login/directory/foo</em><BR>
+The latter feature is a Lynxism, is done homologously on Unix and VMS,
+and should be used ONLY in local documents intended for Lynx.
+
+<p>On VMS, the first element of the path, if not a tilde, is assumed to
+be a device, e.g.:<BR>
+<tab indent="12"
+><em>file://localhost/www_root/directory/filename.suffix</em><BR>
+should be used for: <em>www_root:[directory]filename.suffix</em><BR>
+If you are unsure how to specify a file URL in local documents on
+VMS, invoke Lynx with the desired file or directory as the
+<em>startfile</em> using any spec acceptable to DCL, and then
+use the <em>showinfo</em> command (<em>=</em>) to see the file
+URL which Lynx created for it.
+<HR WIDTH="100%">
+
+<H2><a name="ftp">The <em>ftp</em> URL:</a></H2>
+
+The ftp URL has the general format:<BR>
+<tab indent="12"
+><em>ftp://username:password@host:port/path;type=[D,I, or A]</em><BR>
+
+<p>The default port is <em>:21</em> and the default <em>username</em>
+is <em>anonymous</em>. If <em>username</em> is included but not
+<em>:password</em>, Lynx will prompt you for the password. This is
+recommended, as otherwise the URL will have it completely unencrypted.
+Do not include the <em>@</em> if neither <em>username</em> nor
+<em>:password</em> is included. For anonymous ftp, Lynx uses your
+<em>personal_mail_address</em> (user@host) as the <em>:password</em>
+if it has been defined via the '<em>o</em>'ptions menu. Otherwise,
+Lynx uses the dummy password <em>WWWUser</em>.
+
+<p>The <em>;type=</em> parameter can be used with value <em>D</em>,
+<em>I</em>, or <em>A</em> to force handling of the URL as, respectively,
+a directory listing, binary file, or ASCII file. The Lynx ftp gateway
+normally determines this itself, but the parameter can be used if the
+internal procedure draws an incorrect inference about the nature of
+the ftp URL.
+
+<p>The <em>/path</em> is treated according to RFC1738 for VMS
+and VM/CMS ftp servers. The lead slash (<em>/</em>) is treated purely
+as a separator, not as a designator for the root, and the <em>path</em>
+string if present is treated as in or under the login directory. For
+VMS ftp servers, if you wish to have the first element treated as a
+device rather than file or subdirectory name, begin it with a hex-escaped
+slash (<em>%2f</em>), e.g.:<BR>
+<tab indent="12"><em>ftp://user@myhost/%2fsys$common/syshlp</em><BR>
+can be used for a listing of sys$common:[syshlp]<BR>
+Also, on VM/CMS ftp servers, if the <em>path</em> string begins
+with <em>vmsysu%3a</em> it receives special handling as an SFS
+path, e.g.:<BR>
+<tab indent="12"><em>ftp://ubvm.cc.buffalo.edu/vmsysu%3alistserv.webshare</em>
+
+<p>For Unix and Unix-emulation ftp servers, RFC1738 is not respected
+and the lead slash is treated as the root, i.e., the <em>/path</em> is
+handled equivalently to that in file URLs. The distinction is
+irrelevant for anonymous ftp, but matters when using ftp for
+non-anonymous accounts. If you are using ftp with a Unix server and
+do wish to get a listing of the login directory or have the <em>path</em>
+string treated as a file or path under the login directory, include a
+tilde (<em>~</em>) as for <a href="#file">file</a> URLs, e.g.:<BR>
+<tab indent="12"><em>ftp://user@myhost/~</em>
+<HR WIDTH="100%">
+
+<H2><a name="wais">The <em>wais</em> URL:</a></H2>
+
+The wais URL is used to retrieve resources using the Wide Area Information
+System protocol. The format is:<BR>
+<tab indent="12"><em>wais://host:port/database</em><BR>
+<tab indent="12"><em>wais://host:port/database?wais_query</em><BR>
+<tab indent="12"><em>wais://host:port/database/wais_type/wais_path</em><BR>
+where <em>:port</em> defaults to <em>:210</em>
+
+<p>Direct wais support is built into Lynx for VMS, and can be compiled
+into Lynx on Unix.
+
+<p>If only a <em>database</em> is indicated in the URL, Lynx returns
+an ISINDEX cover page for searching that <em>database</em>, and will
+submit your search with the <em>wais_query</em> appended. Lynx will
+convert the server's reply into a hit list with URLs that include the
+<em>wais_type</em> and <em>wais_path</em> for retrieving items from
+the hit list.
+<HR WIDTH="100%">
+
+<H2><a name="news"
+>The <em>news</em>, <em>nntp</em>, and <em>snews</em> URLs:</a></H2>
+
+The news and nntp URLs are handled by Lynx as specified in RFC1738, but
+for compatibility with other clients, Lynx allows inclusion of host and
+port fields in news URLs, which properly should be used <em>only</em> in
+nntp and snews URLs. If not included in news URLs, Lynx will use the nntp
+server pointed to by the NNTPSERVER environment variable or configuration
+symbol (see lynx.cfg), with default port <em>:119</em>. A host field must
+be included in nntp URLs, and the port field is optional with the same
+default. Patches for support of snews URLs are available to qualified
+recipients via <a href="http://www.crl.com/~subir/lynx.html">Lynx links</a>
+but cannot be included in the general distribution (sorry, see <a
+href="#http">http and https</a>).
+
+<p>The formats are:<BR>
+<tab indent="12"><em>news:newsgroup</em> <tab
+id="ng">(retrieves list of messages in newsgroup)<BR>
+<tab indent="12"><em>news:messageID</em> <tab
+to="ng">(retrieves the message)<BR>
+<tab indent="12"><em>news:*</em> <tab
+to="ng">(retrieves list of all available newsgroups)<BR>
+<tab indent="12"><em>nntp://host:port/newsgroup</em><BR>
+<tab indent="12"><em>nntp://host:port/messageID</em><BR>
+<tab indent="12"><em>nntp://host:port/*</em><BR>
+(snews same as nntp, but the default port is <em>:563</em>)
+
+<p>The <em>messageID</em> is the message's unique identifier, consisting
+of an identification string and the host of origin for the message
+(<em>ident_string@origin_host</em>).
+
+<p>Lynx also supports wildcarding via an asterisk for listings of news
+hierarchies or sub-hierarchies, e.g.:<BR>
+<tab indent="12"><em>news:comp.infosystems.*</em><BR>
+<tab indent="12"><em>nntp://host:port/comp.infosystems.*</em><BR>
+(snews same as nntp, but the default port is <em>:563</em>)<BR>
+This is not in RFC1738 and may not be supported by all other clients.
+
+<p>Lynx allows you both to <em>reply</em> to the author of a news message
+via email, and, if news posting has been enabled, to send a <em>followup</em>
+message to the newsgroup (see <a href="#newspost">newspost, newsreply,
+snewspost, snewsreply</a>).
+
+<p>Lynx converts any strings in news messages which appear to be a URL
+with a supported scheme into a link for accessing that URL.
+
+<p>Lynx also supports the newsgroup and message number URL scheme:<BR>
+<tab indent="12"><em>news:newsgroup/startNo-endNo</em> <tab
+id="ngno">(lists message range in newsgroup)<BR>
+<tab indent="12"><em>news:newsgroup/messageNo</em> <tab
+to="ngno">(retrieves the message by number)<BR>
+<tab indent="12"><em>nntp://host:port/newsgroup/startNo-endNo</em><BR>
+<tab indent="12"><em>nntp://host:port/newsgroup/messageNo</em><BR>
+(snews same as nntp, but the default port is <em>:563</em>)<BR>
+Use of this scheme is not recommended, because the message numbers
+are specific to each nntp server, unlike the unique identifiers for
+news messages.
+<HR WIDTH="100%">
+
+<H2><a name="newspost"
+>The <em>newspost</em>, <em>newsreply</em>, <em>snewspost</em>, and
+<em>snewsreply</em> URLs:</a></H2>
+
+When Lynx receives group listings or articles via <em>news</em>,
+<em>nntp</em> or <em>snews</em> URLs, it also checks whether the
+nntp server supports posting from the Lynx user's site, and if so,
+includes links for posting new messages to that server, or for posting
+followups (replies) to previously posted messages. RFC1738, and IETF
+URL drafts through this release of Lynx, do not include any schemes
+for posting to news groups. Lynx has long supported newspost and
+newreply URL schemes for posting new messages or sending followups,
+respectively, to standard nntp servers, with default port <em>:119</em>.
+Lynx now also supports homologous snewspost and snewsreply URLs for use
+with SSL capable nntp servers, but the latter requires patches for built
+in SSL support, or use of a daemon which handles the secure communications
+on behalf of Lynx.
+
+<p>The formats are:<BR>
+<tab indent="12"><em>newspost://host:port/newsgroup(s)</em>&nbsp;&nbsp;<tab
+id="ngp">(post a new message)<BR>
+<tab indent="12"><em>newsreply://host:port/newsgroup(s)</em> <tab
+to="ngp">(post a followup message)<BR>
+(snewspost and snewsreply have the same formats, but the default port is
+<em>:563</em>)
+
+<p>If the host field is omitted, it defaults to that pointed to by the
+NNTPSERVER configuration or environmental variable. Inclusion of at
+least one newsgroup in the URL is required, and additional groups can
+be specified as a comma-separated list. Wildcarding of newgroup names
+is not supported for these URLs. For newsreply and snewsreply URLs, if
+an external editor has been defined via the <em>Options Menu</em>, the
+user is offered an option to include the currently displayed document,
+which presumeably is a news article with a <em>followup</em> link that
+was activated, and if confirmed, each line of that document is prefixed
+with a right-angle-bracket. The user is expected to edit such an inclusion
+so that only the passages relevant to the followup message are retained.
+
+<p>These URLs can be used as command line startfiles (in which case, Lynx
+will exit after posting the message, and the newreply or snewsreply URLs
+degrade to newspost or snewpost URLs, respectively). They also can be used
+as HREF attribute values in any HTML document homologously to <a
+href="#mailto">mailto</a> URLs, with the qualification that they presently
+are supported only by Lynx.
+<HR WIDTH="100%">
+
+<H2><a name="mailto">The <em>mailto</em> URL:</a></H2>
+
+The mailto URL is used to provide links that when activated can be
+used to send a comment or the content of a FORM to an Internet email
+address (user@host). The format is:<BR>
+<tab indent="12"><em>mailto:user@host</em>
+
+<p>The description of the mailto URL in RFC1738 has been interpreted by
+some as allowing only a single recipient, but Lynx invented the mailto URL,
+has always supported a series of user@host addresses as a comma-separated
+list, and still does. For compatibility with Explorer, Lynx also accepts
+a semi-colon-separated list.
+
+<p>For compatibility with Netscape, Lynx parses any
+<em>?subject=The%20Subject</em> appended to the URL, trims the URL
+at the <em>?</em>, and uses the value as the default Subject: for
+the message or FORM content mailing. This is not recommended practice.
+The preferred way to indicate the default Subject: for a LINK or Anchor
+with a mailto HREF, or a FORM with a mailto ACTION, is via a TITLE
+attribute with the subject string as its value, e.g.:<BR>
+<tab indent="12"><em>&lt;LINK <tab id="rev">REV="made"<BR>
+<tab to="rev">HREF="mailto:me@myhost,her@herhost" TITLE="The Subject"&gt;</em>
+
+<p><tab indent="12"><em>&lt;A
+HREF="mailto:user@host" TITLE="The Subject"&gt;...&lt;/A&gt;</em>
+
+<p><tab indent="12"><em>&lt;FORM <tab id="met">METHOD="post"
+ENCTYPE="text/plain"<BR>
+<tab to="met">ACTION="mailto:WebMaster@host" TITLE="The Subject"&gt;<BR>
+<tab indent="14">...<BR>
+<tab indent="12">&lt;/FORM&gt;</em>
+
+<p>Note that a TITLE attribute for FORM is now included in the HTML
+specifications. Some clients use a SUBJECT attribute for this purpose
+in FORM tags, and Lynx recognizes that as a synonym for TITLE.
+
+<p>Lynx also will process any <em>to=address(es)</em>,
+<em>cc=address(es)</em>, <em>keywords=word_list</em> and/or
+<em>body=message</em> fields in <em>?searchpart</em> tack-ons to mailto
+URLs. The <em>to</em> and/or <em>cc</em> values can be single addresses,
+or comma- or semi-colon-separated lists of addresses. All addresses,
+and any <em>body</em> values, will be offered for approval by the user
+before proceeding with a mailing. Any other name=value pairs in the
+<em>?searchpart</em> will be ignored. Also, if the mailto URL is the
+ACTION for a FORM, any <em>body</em> in a <em>?searchpart</em> tack-on
+will be ignored, because the body of the mailing must be constructed
+solely from the the FORM's content. Lynx expects multiple name=value
+pairs in a <em>?searchpart</em> tack-on to be separated by ampersands,
+as in the original Netscape implementation, and in an equally ill-advised
+IETF draft of that implementation (<a
+href="ftp://ftp.isi.edu/internet-drafts/draft-hoffman-mailto-url-03.txt"
+>draft-hoffman-mailto-url-03.txt</a>). These should be represented as
+entities (<em>&amp;amp;</em>) in the HTML markup. This functionality
+is generally desired, but the IETF backward compatibility principal
+normally would lead to a new scheme being used (e.g., <em>mail:</em>, or
+<em>smtp:</em>), rather than breaking <em>mailto:</em> implementations.
+
+<p>If <em>ENCTYPE="text/plain"</em> is specified for a FORM with a mailto
+ACTION, Lynx will not hex escape the name=value pairs of the FORM's content,
+and will use physical newlines instead of '<em>&amp;</em>' or '<em>;</em>'
+to separate the pairs, so that the content will be readable directly.
+Otherwise, Lynx will mail the content with the default:<BR>
+<tab indent="12"
+><em>ENCTYPE="application/x-www-form-urlencoded"</em> <tab id="enc">('<em
+>&amp;</em>' separates pairs)<BR>
+or:<BR>
+<tab indent="12"
+><em>ENCTYPE="application/sgml-form-urlencoded"</em> <tab to="enc">('<em
+>;</em>' separates pairs)<BR>
+if the latter was indicated.
+
+<p>Note that when mailing FORM content Lynx wraps any lines longer than 78
+characters, to avoid buffer overflows in mail software and to ensure reliable
+transmission across gateways. If the ENCTYPE was not <em>text/plain</em>,
+any script which decodes the mailed content should ignore the physical
+newlines and recognize only hex escaped newline characters as intended
+to be present in the decoded content.
+
+<p>If the mailto URL is not the ACTION for a FORM, and if an external
+editor has been defined via the <em>Options Menu</em>, the user is offered
+an option to include the currently displayed document. If this option is
+accepted, each line of that document is prefixed with a right-angle-bracket,
+and the prefixed inclusion should be trimmed by the user to just those
+passages relevant to the message which will be sent.
+<HR WIDTH="100%">
+
+<H2><a name="finger">The <em>finger</em> URL:</a></H2>
+
+Lynx has full support for the finger protocol, but a format for finger
+URLs has not yet been adopted by the IETF. The formats supported by Lynx
+therefore include every possibility not inconsistent with RFC1738,
+including:
+
+<pre>
+ finger://host finger://@host
+ finger://host/ finger://@host/
+ finger://host/%2fw finger://@host/w
+ finger://host/w finger://host/w/
+ finger://host/username[@host] finger://username@host
+ finger://host/username[@host]/ finger://username@host/
+ finger://host/w/username[@host] finger://username@host/w
+ finger://host/%2fw%20username[@host] finger://host/username[@host]/w
+ finger://host/w/username
+</pre>
+
+<p>Activating a finger URL will send a request to the finger server via
+port 79 on the host specified. You can include <em>:79</em> in the URL,
+but no other value is allowed. The <em>/w</em> or <em>/%2fw</em> is used
+to request a full report for finger servers which support it, and is not
+case sensitive (i.e., can be <em>/W</em> or <em>/%2fW</em>). Any strings
+in the report which appear to be a URL with a supported scheme will be
+converted into a link for accessing that URL.
+
+<p>An alternative way to access finger servers is via gopher URLs with
+port 79 and the plain text (<em>0</em>) <em>gophertype</em> specified:<BR>
+<em>gopher://host:79/0</em><BR>
+Lynx will handle such URLs equivalently to overt finger URLs, including
+creation of links for any strings which appear to be supported URLs.
+<HR WIDTH="100%">
+
+<H2><a name="cso">The <em>cso</em> URL:</a></H2>
+
+The cso URL is intended to provide a gateway to CSO/PH (QI) servers.
+The requests are made on port 105 by default (<em>:105</em>), with the
+following overt cso URL format:<BR>
+<tab indent="12"><em>cso://host</em><BR>
+
+<p>You also can use a gopher URL format with port 105 and the CSO
+(<em>2</em>) <em>gophertype</em> specified:<BR>
+<tab indent="12"><em>gopher://host:105/2</em>
+
+<p>Lynx will parse the stream returned by the server for the above
+URLs and create a FORM for submitting additional requests (searches)
+to the server. Any strings in the reports returned for these requests
+(searches) which appear to be a URL with a supported scheme will be
+converted into a link for accessing that URL.
+<HR WIDTH="100%">
+
+<H2><a name="chargen">The <em>chargen</em> URL:</a></H2>
+
+The chargen URL is intended to provide a gateway to the chargen service.
+The requests are made on port 19 (<em>:19</em>). You can omit the port,
+and no other value is allowed. The format is:<BR>
+<tab indent="12"><em>chargen://host</em><BR>
+
+<p>Lynx will accept approximately 55 lines of characters in the stream
+returned by the server, then close the connection and display the lines
+as PRE formatted text. Note that if port 19 is used for a URL with a
+scheme other than chargen, the URL will be rejected by Lynx.
+<HR WIDTH="100%">
+
+<H2><a name="exec">The <em>lynxexec</em> and <em>lynxprog</em> URLs:</a></H2>
+
+If execution of spawned commands has been enabled in your Lynx image, the
+lynxexec and lynxprog URLs can be used to execute arbitrary system commands
+or invoke system utilities. Any system command and associated switches
+or qualifiers can be used, with the syntax appropriate for a shell running
+Lynx on Unix, or for DCL on VMS, e.g.:<BR>
+<tab indent="12"><em>lynxexec:dir/date/size foo:[blah]</em> <tab
+id="listing">(VMS)<BR>
+<tab indent="12"><em>lynxexec:ls -l /foo/blah</em> <tab
+to="listing">(Unix)<BR>
+<tab indent="12"><em>lynxprog:news</em><BR>
+(Note, however, that restrictions on acceptable commands or utilities
+may be imposed by the system administrator.)
+
+<p>You optionally can include <em>//localhost/</em> in the URL, between the
+scheme field and the command, but that is always implied. The lynxexec
+and lynxprog URLs differ only in that with lynxexec you are prompted to
+enter <em>RETURN</em> before Lynx clears the screen and restores the
+previously displayed document, so that you can read any screen output
+generated by the spawned command, whereas no such pause is imposed upon exit
+from the utility invoked via lynxprog.
+
+<p>These are Lynxisms and should be used only in local documents intended
+solely for Lynx.
+<HR WIDTH="100%">
+
+<H2><a name="cgi">The <em>lynxcgi</em> URL:</a></H2>
+
+The lynxcgi URL is implemented only on Unix, can be used as the
+ACTION for a FORM, and if enabled in your Lynx image has the format:<BR>
+<tab indent="12"><em>ly<tab id="lh">
+nxcgi://localhost/path_to_CGI_script</em><BR>
+<tab to="lh">where <em>//localhost/</em> is optional and always implied.
+The output of the script should be text/html and is rendered and displayed
+by Lynx. (Note that restrictions on acceptable paths can be imposed
+by the system administrator.)
+
+<p>This is a Lynxism and should be used only in local documents intended
+solely for Lynx, or for limited local testing of CGI scripts without an
+http server.
+
+<p>On VMS, you are advised to use the threaded OSU http server, available
+from <a href="ftp://osu.edu"
+>ftp://osu.edu</a> as freeware, if your site does not already have an http
+server. It can be installed as a purely local script server, and is far
+more efficient and comprehensive than any code which might be incorporated
+within Lynx.
+<HR WIDTH="100%">
+
+<H2><a name="internal">The <em>LYNXfoo</em> internal URLs:</a></H2>
+
+Lynx uses a variety of internal URL schemes as structured stream
+objects for communication among its display modules. If you discover
+what they are, and are tempted to use them externally in documents,
+find the self-restraint to <em>resist</em> that temptation!!!
+
+<p>For example, tempting though it might be, do <em>not</em> use these:<BR>
+<tab indent="12"
+><em>Return to your &lt;A HREF="LYNXHIST:0"&gt;Startfile&lt;/A&gt;</em><BR>
+<tab indent="12"
+><em>Review your &lt;A HREF="LYNXKEYMAP:"&gt;Keymap&lt;/A&gt;</em><BR>
+(Yes, they'll work. No, they won't do any harm. But...)
+
+<p>If you <em>must</em> try one, the second is OK from the command line:<BR>
+<tab indent="12"><em>lynx LYNXKEYMAP:</em><BR>
+But within Lynx, use the '<em>K</em>' keystroke command.
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/makefile.in b/gnu/usr.bin/lynx/makefile.in
new file mode 100644
index 00000000000..ffe0dafe0f5
--- /dev/null
+++ b/gnu/usr.bin/lynx/makefile.in
@@ -0,0 +1,289 @@
+##makefile for lynx
+
+SHELL = /bin/sh
+
+x = @PROG_EXT@
+
+.SUFFIXES:
+@SET_MAKE@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+srcdir = @srcdir@
+VPATH = $(srcdir)
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+DEFS = @DEFS@
+CPPFLAGS = @CPPFLAGS@
+
+LIBS = @LIBS@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+##this is the name of the directory the lynx source code is in.
+##(e.g. lynx2-8, not the full path)
+lynxdir= lynx2-8
+lynxname= lynx2-8
+
+## Where you want lynx installed
+bindir= @bindir@
+
+## Where you want the lynx man file installed
+mandir= @mandir@/man1
+
+## Where you want the lynx.cfg file installed
+libdir= @libdir@
+
+## Where you want the help-files installed
+helpdir= @libdir@/lynx_help
+
+installbin= @INSTALL_PROGRAM@ -s -m 755
+installdoc= @INSTALL_DATA@
+
+##set the relative location of the WWW library Implementation directory,
+##from this directory
+##do not set this to be an absolute path!!!
+WWWINC= WWW/Library/Implementation
+
+# !!!!!!!!!!! SUN resolv LIBRARY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# To include resolv in the LIBS="" list for SUN 3, 4 or Solaris OS,
+# point RESOLVLIB to that library. You need this if you get the message
+# "Alert!: Unable to connect to remote host" whenever you try to
+# access a host other than localhost and have made Lynx without it.
+# See the PROBLEMS file for more information.
+#RESOLVLIB= -lresolv
+
+# !!!!!!!!!!! Alternate socket functions for SOCKS !!!!!!!!!!!!!!!!!!
+# To make a SOCKSified lynx, include -DSOCKS in your SITE_LYDEFS and
+# SITE_DEFS, below, and point SOCKSLIB to your SOCKS library. Note
+# that you may have problems accessing FTP servers. Also, instead of
+# SOCKSifying lynx for use behind a firewall, you are better off if
+# you make it normally, and set it up to use a proxy server. You can
+# SOCKSify the proxy server, and it will handle all clients, not just
+# Lynx (see the INSTALLATION file in this distribution). If your SOCKS
+# server was compiled to use the short version of Rbind, also include
+# -DSHORTENED_RBIND in your SITE_LYDEFS and SITE_DEFS. If you do
+# SOCKSify lynx, you can turn off SOCKS proxy usage via a -nosocks
+# command line switch.
+#SOCKSLIB= /usr/local/lib/libsocks.a
+
+# !!!!!!!!!!!!! DIRECT WAIS ACCESS !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# If you are adding direct wais access you must fill in the
+# location of wais.a, client.a and the standard math library, libm.a.
+# You can pick up the most current freeWAIS sources from
+# ftp://ftp.cnidr.org/pub/NIDR.tools/freewais
+# If you are using freeWAIS-0.202 or older, include -DDECLARE_WAIS_LOGFILES
+# in your SITE_DEFS.
+# Please put an ABSOLUTE address here if you want it to work!
+#WAISLIB= ../../freeWAIS-0.202/bin/client.a ../../freeWAIS-0.202/bin/wais.a /usr/lib/libm.a
+
+# !!!!!!!!!!!!! SLANG Support (For color version of Lynx). !!!!!!!!!!!!!!!!
+# The slang library is an alternative to curses, developed by John E. Davis
+# (davis@space.mit.edu). Version 0.99-27 or higher is available from
+# ftp://space.mit.edu/pub/davis
+# It provides color support for Lynx.
+
+# !!!!!!!!!!!!! NCURSES Support (For color version of Lynx). !!!!!!!!!!!!!!
+# If you need ncurses, the latest version can always be found
+# in ftp://ftp.clark.net/pub/dickey/ncurses/
+# or ftp://ftp.gnu.org/pub/gnu/
+
+# Also be sure to check out the compilation symbols in userdefs.h
+# before building Lynx!
+
+# If you apply patches which require linking to site-specific libraries, set
+# SITE_LIBS to those libraries.
+SITE_LIBS= # Your libraries here
+
+# Set SITE_LYDEFS to one or more of the defines for the WWW Library:
+SITE_LYDEFS = # Your defines here
+
+# Set SITE_DEFS to one or more of the defines for lynx below:
+SITE_DEFS = # Your defines here
+
+# defines for which there are no configure options:
+# -DHP_TERMINAL For DIM workaround to REVERSE problems on HP terminals.
+# -DIGNORE_CTRL_C Define if Control-C shouldn't exit lynx.
+# -DNOPORT if you must use PASV instead of PORT for FTP
+# -DNO_CPU_LIMIT Disables Max CPU timeout (includes CLOCKS_PER_SECOND)
+# -DSHORTENED_RBIND For a SOCKSified lynx with the short version of Rbind.
+# -DSLANG_MBCS_HACK prevent cutoff lines when using UTF8 console (slang only)
+# -DSOCKS For making a SOCKSified lynx.
+#
+# if you are linking to freeWAIS-0.202 or older, you should define this
+# in SITE_DEFS
+#
+# -DDECLARE_WAIS_LOGFILES
+#
+# if you have the reverse clear screen problem of some SUN4 systems you
+# should define this in SITE_DEFS
+#
+# -DREVERSE_CLEAR_SCREEN_PROBLEM
+#
+# if you have an SVR4 system with the "type any key" problem, try defining
+# this in LYFLAGS (SITE_LYDEFS) and SITE_DEFS
+#
+# -DSVR4_BSDSELECT
+#
+# Old Data General systems may need this in their SITE_LYDEFS
+# for their inet_addr(host) calls.
+#
+# -DDGUX_OLD
+#
+# if you would like logging of client requests via syslog(), you should
+# define this in SITE_DEFS
+#
+# -DSYSLOG_REQUESTED_URLS
+
+# defines which have configure options (see INSTALLATION, Section II-1c.):
+# -DARCHIVE_ONLY
+# -DDIRED_SUPPORT
+# -DEXP_CHARTRANS_AUTOSWITCH
+# -DLINKEDSTYLES
+# -DLONG_LIST
+# -DLY_FIND_LEAKS
+# -DNCURSES
+# -DNO_CHANGE_EXECUTE_PERMS
+# -DNO_PARENT_DIR_REFERENCE
+# -DNSL_FORK
+# -DOK_GZIP
+# -DOK_OVERRIDE
+# -DOK_PERMIT
+# -DOK_TAR
+# -DOK_UUDECODE
+# -DOK_ZIP
+# -DUNDERLINE_LINKS
+# -DUSE_COLOR_STYLE
+# -DUSE_HASH
+# -DUSE_SLANG
+# -DUSE_ZLIB
+#
+# for installation of local execution links, please see the file userdefs.h
+
+# TESTED: Linux FreeBSD SunOS Solaris IRIX CLIX HP-UX AIX SCO
+all lynx$x:
+ cd WWW/Library/unix && $(MAKE) CC="$(CC)" \
+ LY_CFLAGS="$(CFLAGS)" \
+ CPPFLAGS="$(CPPFLAGS)" \
+ LYFLAGS="$(SITE_LYDEFS)"
+ cd src && $(MAKE) all CC="$(CC)" \
+ CFLAGS="$(CFLAGS)" \
+ CPPFLAGS="$(CPPFLAGS)" \
+ LIBS="$(LIBS) $(RESOLVLIB) $(WAISLIB) $(SOCKSLIB) $(SITE_LIBS)" \
+ SITE_DEFS="$(SITE_DEFS)" \
+ WWWINC=$(WWWINC) \
+ WWWLIB="../WWW/Library/unix/libwww.a"
+
+help:
+ @echo
+ @echo "Please run make with one of the following arguments"
+ @echo "all -- to make the executable, put it in this directory"
+ @echo "clean -- removes all '.o' and 'core' files"
+ @echo "depend -- use makedepend to generate header-dependencies"
+ @echo "tar -- runs clean, removes executable, and tars the whole directory"
+ @echo "compress -- runs tar, then compresses the result"
+ @echo "zip -- runs clean, removes executable, and zips the whole directory"
+ @echo
+
+##Miscellaneous actions
+clean:
+ rm -f WWW/Library/*/*.[aob]
+ rm -f WWW/Library/*/.created
+ cd src && $(MAKE) clean
+ rm -f *.b src/lynx$x core Lynx.leaks
+
+depend:
+ cd WWW/Library/unix && $(MAKE) $@
+ cd src && $(MAKE) $@
+
+distclean: clean
+ -rm -f WWW/Library/*/*~
+ -rm -f WWW/Library/*/*.bak
+ -rm -rf src/obsolete
+ -cd src && $(MAKE) $@
+ -cd src/chrtrans && $(MAKE) $@
+ -rm -f *~ *.bak *.sav
+ -rm -f WWW/Library/unix/makefile src/makefile src/chrtrans/makefile
+ @SRCDIR_CLEAN@-find . -type f -name '*.rej' -exec -rm -f {} \;
+ @SRCDIR_CLEAN@-find . -type f -name '*.orig' -exec -rm -f {} \;
+ @SRCDIR_CLEAN@-rmdir WWW/Library/unix && rmdir WWW/Library && rmdir WWW
+ @SRCDIR_CLEAN@-rmdir src/chrtrans && rmdir src
+ -rm -f makefile lynx_cfg.h config.status config.log config.cache
+ -rm -f lynx$x install-*
+
+maintainer-clean: distclean
+ -rm -rf WWW/Library/*/obsolete
+ -rm -f Lynx.prj .*_aux
+
+tar: clean
+ rm -f lynx$x
+ $(MAKE) save
+
+turnover: clean
+ $(MAKE) save
+
+zipcompress: compress zip
+ echo "done!"
+
+zip: clean
+ rm -f src/lynx$x
+ rm -f lynx$x
+ rm -f src/a.out
+ rm -f ../$(lynxname).zip
+ cd ..; rm -f $(lynxname).zip; zip -r $(lynxname).zip $(lynxdir)
+
+save:
+ cd ..; rm -f $(lynxname).tar; tar -cf - $(lynxdir) > $(lynxname).tar
+
+compress: tar
+ cd ..; rm -f $(lynxname).tar.Z; compress -f -v $(lynxname).tar
+
+install: lynx$x install-bin install-man install-cfg @INSTALL_LSS@
+ @echo
+ @echo "Use $(MAKE) install-help to install the help-files"
+ @echo
+
+install-bin: $(bindir)
+ -mv -f $(bindir)/lynx$x $(bindir)/lynx.old
+ $(installbin) lynx$x $(bindir)/
+
+install-man : $(mandir)
+ $(installdoc) $(srcdir)/lynx.man $(mandir)/lynx.1
+
+install-help : $(helpdir)
+ (cd $(helpdir) && rm -rf *)
+ (cd $(srcdir)/lynx_help && tar cf - . ) | ( cd $(helpdir) && tar xf - )
+ (cd $(srcdir) && tar cf - C[HO]* PROBLEMS README samples test ) | \
+ ( cd $(helpdir) && tar xf - )
+ -rm -f $(libdir)/lynx.tmp
+ sh -c 'if test -f $(libdir)/lynx.cfg ; then \
+ mv $(libdir)/lynx.cfg $(libdir)/lynx.tmp ; \
+ else \
+ cp $(srcdir)/lynx.cfg $(libdir)/lynx.tmp ; \
+ fi'
+ sed -e '/^HELPFILE:http/s@^@#@' \
+ -e '/^#HELPFILE:file/s@#@@' \
+ -e '/^HELPFILE:file/s@/PATH_TO/lynx_help@$(helpdir)@' \
+ $(libdir)/lynx.tmp >$(libdir)/lynx.cfg
+ chmod 644 $(libdir)/lynx.cfg
+ -rm -f $(libdir)/lynx.tmp
+
+install-cfg : $(libdir)
+ -mv -f $(libdir)/lynx.cfg $(libdir)/lynx.oldcfg
+ $(INSTALL_DATA) $(srcdir)/lynx.cfg $(libdir)/lynx.cfg
+
+install-lss : $(libdir)
+ -mv -f $(libdir)/lynx.lss $(libdir)/lynx.oldlss
+ $(INSTALL_DATA) $(srcdir)/samples/lynx.lss $(libdir)/lynx.lss
+
+uninstall:
+ -rm -f $(bindir)/lynx$x
+ -rm -f $(mandir)/lynx.1
+ -rm -f $(libdir)/lynx.cfg
+ -rm -f $(libdir)/lynx.lss
+ -rm -rf $(libdir)/lynx_help
+
+$(bindir) $(mandir) $(libdir) $(helpdir) :
+ $(srcdir)/mkdirs.sh $@
diff --git a/gnu/usr.bin/lynx/mkdirs.sh b/gnu/usr.bin/lynx/mkdirs.sh
new file mode 100644
index 00000000000..9a20f82228d
--- /dev/null
+++ b/gnu/usr.bin/lynx/mkdirs.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Last modified: 1994-03-25
+# Public domain
+#
+
+errstatus=0
+umask 022
+
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d in ${1+"$@"} ; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" || errstatus=$?
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
diff --git a/gnu/usr.bin/lynx/samples/jumpsUnix.html b/gnu/usr.bin/lynx/samples/jumpsUnix.html
new file mode 100644
index 00000000000..6e86da1dfd4
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/jumpsUnix.html
@@ -0,0 +1,47 @@
+<html>
+<head>
+<title>Shortcut List</title>
+<link rev="made" href="mailto:WebMaster@foo.blah.dom">
+</head>
+<body>
+ <h1>Shortcut List</h1>
+ Following is a list of shortcut names and the target links associated
+ with them. In Lynx, pressing J followed by one of these shortcut names
+ will jump you directly to the link. This list will expand over time.<p>
+ <b>Name</b>&nbsp;&nbsp;&nbsp;<b>Link</b>
+<!-- The list *MUST* be kept SORTED, one entry per line -->
+<dl compact>
+<dt>?<dd><a href="file://localhost/CFN/info/jumps.html">This Shortcut List</a>
+<dt>agreement<dd><a href="file://localhost/CFN/UserAgree.html">Chebucto FreeNet User Agreement</a>
+<dt>board<dd><a href="file://localhost/CFN/BOD.html">MetroCAN Board of Directors</a>
+<dt>browser<dd><a href="file://localhost/~/">Personal File Browser</a>
+<dt>docteam<dd><a href="file://localhost/CFN/SAT/WorkArea.html">Documentation Team Work Area</a>
+<dt>events<dd><a href="file://localhost/CFN/Utilities/search-events.html">Search all event schedules by time and keyword</a>
+<dt>files<dd><a href="file://localhost/~/">Personal File Browser</a>
+<dt>forward<dd><a href="lynxexec:/cfn/bin/mail-forward">Forward your mail</a>
+<dt>freenets<dd><a href="http://duke.usask.ca/~scottp/free.html">FreeNets around the World</a>
+<dt>help<dd><a href="file://localhost/CFN/Help/UserHelpDesk.html">Help Desk</a>
+<dt>home<dd><a href="file://localhost/CFN/Home.html">Chebucto FreeNet Home Page</a>
+<dt>info<dd><a href="file://localhost/CFN/Utilities/FindingInfo.html">Finding Information</a>
+<dt>ip<dd><a href="file://localhost/CFN/IP/InformationProvider.html">Information Providers Commitee</a>
+<dt>lists<dd><a href="file://localhost/CFN/Services/MailListHome.html">Mailing Lists and Archives</a>
+<dt>mail<dd><a href="lynxprog:/cfn/bin/mail">Read and/or send mail</a>
+<dt>metrocan<dd><a href="file://localhost/CFN/MetroCAN.html">Metro*CAN Society</a>
+<dt>new<dd><a href="file://localhost/CFN/Current/WhatsNew.html">What's New</a>
+<dt>news<dd><a href="lynxprog:/cfn/bin/news">Read and Send News</a>
+<dt>newsgroups<dd><a href="file://localhost/CFN/Current/newsgroups.html">List Global Newsgroups</a>
+<dt>password<dd><a href="lynxexec:/cfn/bin/passwd">Change your password</a>
+<dt>people<dd><a href="file://localhost/CFN/Utilities/search-user.html">Find other people</a>
+<dt>profile<dd><a href="lynxprog:/cfn/bin/editor public_html/Profile.html">Update your personal profile</a>
+<dt>quota<dd><a href="lynxexec:/cfn/bin/quota">View your disk usage and quota</a>
+<dt>recent<dd><a href="http://www.cfn.cs.dal.ca/cgi-bin/recent">Recently Changed Documents on CFN</a>
+<dt>register<dd><a href="file://localhost/CFN/AccountRegister.html">New User Registration</a>
+<dt>search<dd><a href="file://localhost/CFN/Utilities/search-all.html">Search every document on CFN by keyword.</a>
+<dt>technical<dd><a href="file://localhost/CFN/Technical/Technical.html">Metro*CAN Technical Committee</a>
+<dt>terminal<dd><a href="lynxexec:/cfn/bin/set-term">Set your terminal type</a>
+<dt>volunteer<dd><a href="file://localhost/CFN/Membership/NewVolunteer.html">Volunteer with CFN</a>
+<dt>who<dd><a href="http://www.cfn.cs.dal.ca/cgi-bin/cfn-who">Find out who is online now</a>
+<dt>xsearch<dd><a href="file://localhost/CFN/Utilities/xsearch.html">Search every document on CFN by keyword.</a>
+</dl>
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/samples/jumpsVMS.html b/gnu/usr.bin/lynx/samples/jumpsVMS.html
new file mode 100644
index 00000000000..b68412feb10
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/jumpsVMS.html
@@ -0,0 +1,28 @@
+<html>
+<head>
+<title>Shortcut List</title>
+<link rev="made" href="mailto:WebMaster@foo.blah.dom">
+</head>
+<body>
+ <h1>Shortcut List</h1>
+ Following is a list of shortcut names and the target links associated
+ with them. In Lynx, pressing J followed by one of these shortcut names
+ will jump you directly to the link. This list will expand over time.<p>
+ <b>Name</b>&nbsp;&nbsp;&nbsp;<b>Link</b>
+<!-- The list *MUST* be kept SORTED, one entry per line -->
+<dl compact>
+<dt>?<dd><a href="file://localhost/Lynx_Dir/jumps.html">This Shortcut List</a>
+<dt>freenets<dd><a href="http://duke.usask.ca/~scottp/free.html">FreeNets around the World</a>
+<dt>genhelp<dd><a href="http://www.wfeb.edu/HELP/@GCGHELP:GENHELP">GCG GenHelp</a>
+<dt>genman<dd><a href="http://www.wfeb.edu/HELP/@GCGHELP:GENMANUAL">GCG GenManual</a>
+<dt>home<dd><a href="http://www.wfeb.edu/">WFEB Home Page</a>
+<dt>mail<dd><a href="lynxprog:mail">Read and/or send mail</a>
+<dt>multinet<dd><a href="http://www.wfeb.edu/HELP/@MULTINET:MULTINET">MultiNet Help</a>
+<dt>news<dd><a href="lynxprog:news">Read and Send News</a>
+<dt>swing<dd><a href="lynxprog:swing sys$login">SWING File/Directory Manager</a>
+<dt>swinghelp<dd><a href="http://www.wfeb.edu/HELP/@CSWING:CSWING/SWING">SWING Help</a>
+<dt>vmshelp<dd><a href="http://www.wfeb.edu/HELP">VMS Help</a>
+<dt>who<dd><a href="lynxexec:show users">Find out who is online now</a>
+</dl>
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/samples/lynx.cfg b/gnu/usr.bin/lynx/samples/lynx.cfg
new file mode 100644
index 00000000000..a0a89ef114e
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/lynx.cfg
@@ -0,0 +1,1734 @@
+# lynx.cfg file.
+# The default placement for this file is /usr/local/lib/lynx.cfg (Unix)
+# or Lynx_Dir:lynx.cfg (VMS)
+#
+# Definition pairs are of the form VARIABLE:DEFINITION
+# NO spaces are allowed between the pair items.
+#
+# If you do not have access to /usr/local/bin you may change
+# the default location of this file in the userdefs.h file and recompile,
+# or specify it's location on the command line with the "-cfg"
+# command line option.
+#
+# Items may be commented out by putting a '#' as the FIRST char of the line
+#
+# All definitions must be flush left and have NO spaces.!!!
+#
+#
+# STARTFILE is the default URL if none is specified on the command line
+# or via a WWW_HOME environment variable.
+# note: these files can be remote (http://www.w3.org/default.html)
+# or local (file://localhost/PATH_TO/FILENAME
+# replace PATH_TO with the complete path to FILENAME
+# use Unix SHELL syntax and include the device on VMS systems)
+#
+STARTFILE:http://lynx.browser.org/
+
+# HELPFILE must be defined as a URL and must have a
+# complete path if local:
+# file://localhost/PATH_TO/lynx_help/lynx_help_main.html
+# Replace PATH_TO with the path to the lynx_help subdirectory
+# for this distribution (use SHELL syntax including the device
+# on VMS systems).
+# The default HELPFILE is:
+# http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html
+# This should be changed to the local path.
+#
+HELPFILE:http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html
+#HELPFILE:file://localhost/PATH_TO/lynx_help/lynx_help_main.html
+
+# DEFAULT_INDEX_FILE is the default file retrieved when the
+# user presses the 'I' key when viewing any document.
+# An index to your CWIS can be placed here or a document containing
+# pointers to lots of interesting places on the web.
+#
+DEFAULT_INDEX_FILE:http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html
+
+# Set GOTOBUFFER to TRUE if you want to have the previous goto URL,
+# if any, offered for reuse or editing when using the 'g'oto command.
+# The default is defined in userdefs.h. If left FALSE, the circular
+# buffer of previously entered goto URLs can still be invoked via the
+# Up-Arrow or Down-Arrow keys after entering the 'g'oto command.
+#
+#GOTOBUFFER:FALSE
+
+# JUMP_PROMPT is the default statusline prompt for jumps files (see below).
+# You can change the prompt here from that defined in userdefs.h. Any
+# trailing white space will be trimmed, and a single space added by Lynx
+# following the last non-white character. You must set the default prompt
+# before setting the default jumps file (below). If a default jumps file
+# was set via userdefs.h, and you change the prompt here, you must set the
+# default jumps file again (below) for the change to be implemented.
+#
+#JUMP_PROMPT:Jump to (use '?' for list):
+
+# JUMPFILE is the default local file checked for shortcut URL's when
+# the user presses the 'J' (JUMP) key. The user will be prompted for
+# a shortcut entry (analogously to 'g'oto), and can enter one
+# or use '?' for a list of the shortcuts with associated links to
+# their actual URL's. See the sample jumps files in the samples
+# subdirectory. Make sure your jumps file includes a '?' shortcut
+# for a file://localhost URL to itself:
+#
+# <dt>?<dd><a href="file://localhost/path/jumps.html">This Shortcut List</a>
+#
+# If not defined here or in userdefs.h, the JUMP command will invoke
+# the NO_JUMPFILE statusline message (see userdefs.h).
+#
+# On VMS, use Unix SHELL syntax (including a lead slash) to define it.
+#
+# Do not include "file://localhost" in the definition.
+#
+# Additional, alternate jumps files can be defined and mapped to
+# keystrokes at the bottom of lynx.cfg, but you should first define
+# the default jumps file (mapped by default to 'J', and to 'j' when
+# the "VI keys" 'o'ption is not ON) here or in userdefs.h, if you
+# wish to implement the jumps mechanism.
+#
+#JUMPFILE:/Lynx_Dir/jumps.html
+
+# Set JUMPBUFFER to TRUE if you want to have the previous jump target,
+# if any, offered for reuse or editing when using the 'J'ump command.
+# The default is defined in userdefs.h. If left FALSE, the circular
+# buffer of previously entered targets (shortcuts) can still be invoked
+# via the Up-Arrow or Down-Arrow keys after entering the 'J'ump command.
+# If multiple jumps files are installed, the recalls of shortcuts will
+# be specific to each file. If Lynx was built with PERMIT_GOTO_FROM_JUMP
+# defined, any random URLs used instead of shortcuts will be stored in the
+# goto URL buffer, not in the shortcuts buffer(s), and the single character
+# ':' can be used as a target to invoke the goto URL buffer (as if 'g'oto
+# followed by Up-Arrow had been entered).
+#
+#JUMPBUFFER:FALSE
+
+# If SAVE_SPACE is defined, it will be used as a path prefix for the
+# suggested filename in "Save to Disk" operations from the 'p'rint or
+# 'd'ownload menus. On VMS, you can use either VMS (e.g., "SYS$LOGIN:")
+# or Unix syntax (including '~' for the HOME directory). On Unix, you
+# must use Unix syntax. If the symbol is not defined, or is zero-length
+# (""), no prefix will be used, and only a filename for saving in the
+# current default directory will be suggested.
+# This definition will be overridden if a "LYNX_SAVE_SPACE" environment
+# variable has been set on Unix, or logical has been defined on VMS.
+#
+#SAVE_SPACE:~/foo/
+
+# If LYNX_HOST_NAME is defined here or in userdefs.h, it will be
+# treated as an alias for the local host name in checks for URLs on
+# the local host (e.g., when the -localhost switch is set), and this
+# host name, "localhost", and HTHostName (the fully qualified domain
+# name of the system on which Lynx is running) will all be passed as
+# local. A different definition here will override that in userdefs.h.
+#
+#LYNX_HOST_NAME:www.cc.ukans.edu
+
+# localhost aliases
+# Any LOCALHOST_ALIAS definitions also will be accepted as local when
+# the -localhost switch is set. These need not actually be local, i.e.,
+# in contrast to LYNX_HOST_NAME, you can define them to trusted hosts at
+# other Internet sites.
+#
+#LOCALHOST_ALIAS:gopher.server.domain
+#LOCALHOST_ALIAS:news.server.domain
+
+# LOCAL_DOMAIN is used for a tail match with the ut_host element of
+# the utmp or utmpx structure on systems with utmp capabilities, to
+# determine if a user is local to your campus or organization when
+# handling -restrictions=inside_foo or outside_foo settings for ftp,
+# news, telnet/tn3270 and rlogin URLs. An "inside" user is assumed
+# if your system does not have utmp capabilities. CHANGE THIS here
+# if it was not changed in userdefs.h at compilation time.
+#
+#LOCAL_DOMAIN:ukans.edu
+
+# CHARACTER_SET defines the default character set, i.e., that assumed
+# to be installed on the user's terminal. It determines which characters
+# or strings will be used to represent 8-bit character entities within
+# HTML. New character sets may be defined as explained in the README
+# files of the src/chrtrans directory in the Lynx source code distribution.
+# For Asian (CJK) character sets, it also determines how Kanji code will
+# be handled. The default is defined in userdefs.h and can be changed
+# here, and via the 'o'ptions menu. The 'o'ptions menu setting will be
+# stored in the user's RC file whenever those settings are saved, and
+# thereafter will be used as the default. For Lynx a "character set" has
+# two names: a Display Character Set string for the Options screen and
+# for setting CHARACTER_SET here, and a corresponding MIME name (for
+# recognizing properly labelled charset parameters in HTTP headers etc.).
+# Not all Display Character Set names correspond to exactly one valid MIME
+# charset (for example "Chinese", "Transparent"), in that case
+# an appropriate valid (and more specific) MIME name should be used
+# where required. The actions of the -raw switch and LYK_RAW_TOGGLE ('@')
+# are dependent on the character set. For the Asian (CJK) sets the
+# corresponding charset is assumed in documents, i.e., raw or CJK mode is
+# ON by default, so that -raw or the initial LYK_RAW_TOGGLE will turn the
+# mode OFF. The toggling also can be done via the 'o'ptions menu. In raw
+# CJK mode, 8-bit characters are not reverse translated in relation to the
+# entity conversion arrays, i.e., they are assumed to be appropriate for
+# the current character set. It should be toggled OFF when an Asian (CJK)
+# character set is selected but the document is not CJK.
+# The default for "raw mode" (before it is changed by -raw or LYK_RAW_TOGGLE),
+# if the display character set is not a CJK character set, depends on the
+# display character set as well as the ASSUME_CHARSET value (see below) from
+# either this file or an -assume_charset command line option. The mode
+# defaults to ON if the ASSUME_CHARSET value corresponds to the display
+# character set, otherwise to OFF.
+# It can be toggled ON if you believe the document has a charset which does
+# correspond to your Display Character Set, but was not detected to have
+# that charset and was handled as having the default charset (normally
+# iso-8859-1). You also can specify the default charset (to one other
+# than iso-8859-1) via the ASSUME_CHARSET value (see below) from either
+# this file or an -assume_charset command line option. Note that "raw"
+# does not mean that every byte will be passed to the screen. HTML
+# character entities may get expanded and translated, inappropriate control
+# characters filtered out, etc. Raw mode effectively changes the charset
+# assumption about unlabelled documents. There is a "Transparent" pseudo
+# character set for more "rawness".
+#
+# The default character sets include:
+# Display Character Set name MIME name
+# ========================== =========
+# 7 bit approximations us-ascii
+# Chinese euc-cn
+# DEC Multinational dec-mcs
+# DosArabic (cp864) cp864
+# DosBaltRim (cp775) cp775
+# DosCyrillic (cp866) cp866
+# DosGreek (cp737) cp737
+# DosGreek2 (cp869) cp869
+# DosHebrew (cp862) cp862
+# DosLatin1 (cp850) cp850
+# DosLatin2 (cp852) cp852
+# DosLatinUS (cp437) cp437
+# ISO 8859-10 iso-8859-10
+# ISO 8859-5 Cyrillic iso-8859-5
+# ISO 8859-6 Arabic iso-8859-6
+# ISO 8859-7 Greek iso-8859-7
+# ISO 8859-8 Hebrew iso-8859-8
+# ISO 8859-9 (Latin 5) iso-8859-9
+# ISO Latin 1 iso-8859-1
+# ISO Latin 2 iso-8859-2
+# ISO Latin 3 iso-8859-3
+# ISO Latin 4 iso-8859-4
+# Japanese (EUC) euc-jp
+# Japanese (SJIS) shift_jis
+# KOI8-R Cyrillic koi8-r
+# Korean euc-kr
+# Macintosh (8 bit) macintosh
+# NeXT character set next
+# RFC 1345 Mnemonic mnemonic
+# RFC 1345 w/o Intro mnemonic+ascii+0
+# Taipei (Big5) big5
+# Transparent x-transparent
+# UNICODE UTF 8 utf-8
+# Vietnamese (VISCII) viscii
+# WinArabic (cp1256) windows-1256
+# WinBaltRim (cp1257) windows-1257
+# WinCyrillic (cp1251) windows-1251
+# WinGreek (cp1253) windows-1253
+# WinHebrew (cp1255) windows-1255
+# WinLatin1 (cp1252) windows-1252
+# WinLatin2 (cp1250) windows-1250
+#
+#CHARACTER_SET:ISO Latin 1
+
+# ASSUME_CHARSET changes the handling of documents which do not
+# explicitly specify a charset. Normally Lynx assumes that 8-bit
+# characters in those documents are encoded according to iso-8859-1
+# (the official default for the HTTP protocol). When ASSUME_CHARSET
+# given here or by an -assume_charset command line flag is in effect,
+# Lynx will treat documents as if they were encoded accordingly.
+# See above on how this interacts with "raw mode" and the Display
+# Character Set.
+# The value should be the MIME name of a character set recognized by
+# Lynx (case insensitive).
+#
+#ASSUME_CHARSET:iso-8859-1
+
+# ASSUME_LOCAL_CHARSET is like ASSUME_CHARSET but only applies to local
+# files. If no setting is given here or by an -assume_local_charset
+# command line option, the value for ASSUME_CHARSET or -assume_charset
+# is used.
+# This option may interfere with "raw mode" toggling when local files
+# are viewed (it is "stronger" than the effective change of the charset
+# assumption caused by changing "raw mode"), so only use when necessary.
+#
+#ASSUME_LOCAL_CHARSET:iso-8859-1
+
+# If Lynx encounters a charset parameter it doesn't recognize, it will
+# replace the value given by ASSUME_UNREC_CHARSET (or a corresponding
+# -assume_unrec_charset command line option) for it. This can be used
+# to deal with charsets unknown to Lynx, if they are "sufficiently
+# similar" to one that Lynx does know about, by forcing the same
+# treatment. There is no default, and you probably should leave this
+# undefined unless necessary.
+#
+#ASSUME_UNREC_CHARSET:iso-8859-1
+
+# PREFERRED_LANGUAGE is the language in MIME notation (e.g., "en",
+# "fr") which will be indicated by Lynx in its Accept-Language headers
+# as the preferred language. If available, the document will be
+# transmitted in that language. Users can override this setting via
+# the 'o'ptions menu and save that preference in their RC file.
+# This may be a comma-separated list of languages in decreasing preference.
+#
+#PREFERRED_LANGUAGE:en
+
+# PREFERRED_CHARSET specifies the character set in MIME notation (e.g.,
+# "ISO-8859-2", "ISO-8859-5") which Lynx will indicate you prefer in
+# requests to http servers using an Accept-Charsets header. Users can
+# change it via the 'o'ptions menu and save that preference in their RC file.
+# The value should NOT include "ISO-8859-1" or "US-ASCII",
+# since those values are always assumed by default.
+# If a file in that character set is available, the server will send it.
+# If no Accept-Charset header is present, the default is that any
+# character set is acceptable. If an Accept-Charset header is present,
+# and if the server cannot send a response which is acceptable
+# according to the Accept-Charset header, then the server SHOULD send
+# an error response with the 406 (not acceptable) status code, though
+# the sending of an unacceptable response is also allowed. (RFC2068)
+#
+#PREFERRED_CHARSET:
+
+# URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES are strings which will be
+# prepended (together with a scheme://) and appended to the first element
+# of command line or 'g'oto arguments which are not complete URLs and
+# cannot be opened as a local file (file://localhost/string). Both
+# can be comma-separated lists. Each prefix must end with a dot, each
+# suffix must begin with a dot, and either may contain other dots (e.g.,
+# .com.jp). The default lists are defined in userdefs.h and can be
+# changed here. Each prefix will be used with each suffix, in order,
+# until a valid Internet host is created, based on a successful DNS
+# lookup (e.g., foo will be tested as www.foo.com and then www.foo.edu
+# etc.). The first element can include a :port and/or /path which will
+# be restored with the expanded host (e.g., wfbr:8002/dir/lynx will
+# become http://www.wfbr.edu:8002/dir/lynx). The prefixes will not be
+# used if the first element ends in a dot (or has a dot before the
+# :port or /path), and similarly the suffixes will not be used if the
+# the first element begins with a dot (e.g., .nyu.edu will become
+# http://www.nyu.edu without testing www.nyu.com). Lynx will try to
+# guess the scheme based on the first field of the expanded host name,
+# and use "http://" as the default (e.g., gopher.wfbr.edu or gopher.wfbr.
+# will be made gopher://gopher.wfbr.edu).
+#
+#URL_DOMAIN_PREFIXES:www.
+#URL_DOMAIN_SUFFIXES:.com,.edu,.net,.org
+
+# The following three definitions set the number of seconds for
+# pauses following statusline messages that would otherwise be
+# replaced immediately, and are more important than the unpaused
+# progress messages. Those set by INFOSECS are also basically
+# progress messages (e.g., that a prompted input has been cancelled)
+# and should have the shortest pause. Those set by MESSAGESECS are
+# informational (e.g., that a function is disabled) and should have
+# a pause of intermediate duration. Those set by ALERTSECS typically
+# report a serious problem and should be paused long enough to read
+# whenever they appear (typically unexpectedly). The default values
+# are defined in userdefs.h, and can be modified here should longer
+# pauses be desired for braille-based access to Lynx.
+#
+#INFOSECS:1
+#MESSAGESECS:2
+#ALERTSECS:3
+
+# If USE_SELECT_POPUPS is set FALSE, Lynx will present a vertical list of
+# radio buttons for the OPTIONs in SELECT blocks which lack the MULTIPLE
+# attribute, instead of using a popup menu. Note that if the MULTIPLE
+# attribute is present in the SELECT start tag, Lynx always will create a
+# vertical list of checkboxes for the OPTIONs.
+# The default defined here or in userdefs.h can be changed via the 'o'ptions
+# menu and saved in the RC file, and always can be toggled via the -popup
+# command line switch.
+#
+#USE_SELECT_POPUPS:TRUE
+
+# SHOW_CURSOR controls whether or not the cursor is hidden or appears
+# over the current link in documents or the current option in popups.
+# Showing the cursor is handy if you are a sighted user with a poor
+# terminal that can't do bold and reverse video at the same time or
+# at all. It also can be useful to blind users, as an alternative
+# or supplement to setting LINKS_AND_FORM_FIELDS_ARE_NUMBERED or
+# LINKS_ARE_NUMBERED.
+# The default defined here or in userdefs.h can be changed via the
+# 'o'ptions menu and saved in the RC file, and always can be toggled
+# via the -show_cursor command line switch.
+#
+#SHOW_CURSOR:FALSE
+
+# If BOLD_HEADERS is set to TRUE the HT_BOLD default style will be acted
+# upon for <H1> through <H6> headers. The compilation default is FALSE
+# (only the indentation styles are acted upon, but see BOLD_H1, below).
+# On Unix, compilation with -DUNDERLINE_LINKS also will apply to the
+# HT_BOLD style for headers when BOLD_HEADERS is TRUE.
+#
+#BOLD_HEADERS:FALSE
+
+# If BOLD_H1 is set to TRUE the HT_BOLD default style will be acted
+# upon for <H1> headers even if BOLD_HEADERS is FALSE. The compilation
+# default is FALSE. On Unix, compilation with -DUNDERLINE_LINKS also
+# will apply to the HT_BOLD style for headers when BOLD_H1 is TRUE.
+#
+#BOLD_H1:FALSE
+
+# If BOLD_NAME_ANCHORS is set to TRUE the content of anchors without
+# an HREF attribute, (i.e., anchors with a NAME or ID attribute) will
+# have the HT_BOLD default style. The compilation default is FALSE.
+# On Unix, compilation with -DUNDERLINE_LINKS also will apply to the
+# HT_BOLD style for NAME (ID) anchors when BOLD_NAME_ANCHORS is TRUE.
+#
+#BOLD_NAME_ANCHORS:FALSE
+
+# The DEFAULT_CACHE_SIZE specifies the number of WWW documents to be
+# cached in memory at one time.
+#
+# This so-called cache size (actually, number) is defined in userdefs.h and
+# may be modified here and/or with the command line argument -cache=NUMBER
+# The minimum allowed value is 2, for the current document and at least one
+# to fetch, and there is no absolute maximum number of cached documents.
+# On Unix, and VMS not compiled with VAXC, whenever the number is exceeded
+# the least recently displayed document will be removed from memory.
+#
+# On VMS compiled with VAXC, the DEFAULT_VIRTUAL_MEMORY_SIZE specifies the
+# amount (bytes) of virtual memory that can be allocated and not yet be freed
+# before previous documents are removed from memory. If the values for both
+# the DEFAULT_CACHE_SIZE and DEFAULT_VIRTUAL_MEMORY_SIZE are exceeded, then
+# least recently displayed documents will be freed until one or the other
+# value is no longer exceeded. The default value was defined in userdefs.h.
+#
+# The Unix and VMS but not VAXC implementations use the C library malloc's
+# and calloc's for memory allocation, and procedures for taking the actual
+# amount of cache into account still need to be developed. They use only
+# the DEFAULT_CACHE_SIZE value, and that specifies the absolute maximum
+# number of documents to cache (rather than the maximum number only if
+# DEFAULT_VIRTUAL_MEMORY_SIZE has been exceeded, as with VAXC/VAX).
+#
+#DEFAULT_CACHE_SIZE:10
+#DEFAULT_VIRTUAL_MEMORY_SIZE:512000
+
+# If ALWAYS_RESUBMIT_POSTS is set TRUE, Lynx always will resubmit forms
+# with method POST, dumping any cache from a previous submission of the
+# form, including when the document returned by that form is sought with
+# the PREV_DOC command or via the history list. Lynx always resubmits
+# forms with method POST when a submit button or a submitting text input
+# is activated, but normally retrieves the previously returned document
+# if it had links which you activated, and then go back with the PREV_DOC
+# command or via the history list.
+#
+# The default defined here or in userdefs.h can be toggled via
+# the -resubmit_forms command line switch.
+#
+#ALWAYS_RESUBMIT_POSTS:FALSE
+
+# If NO_ISMAP_IF_USEMAP is set TRUE, Lynx will not include a link to the
+# server-side image map if both a server-side and client-side map for the
+# same image is indicated in the HTML markup. The compilation default is
+# FALSE, such that a link with "[ISMAP]" as the link name, followed by a
+# hyphen, will be prepended to the ALT string or "[USEMAP]" pseudo-ALT for
+# accessing Lynx's text-based rendition of the client-side map (based on
+# the content of the associated MAP element). If the "[ISMAP]" link is
+# activated, Lynx will send a 0,0 coordinate pair to the server, which
+# Lynx-friendly sites can map to a for-text-client document, homologous
+# to what is intended for the content of a FIG element.
+#
+# The compilation default, or default defined here, can be toggled via
+# the "-ismap" command line switch.
+#
+#NO_ISMAP_IF_USEMAP:FALSE
+
+# If SEEK_FRAG_MAP_IN_CUR is set FALSE, then USEMAP attribute values
+# (in IMG or OBJECT tags) consisting of only a fragment (USEMAP="#foo")
+# will be resolved with respect to the current document's base, which
+# might not be the same as the current document's URL.
+# The compilation default is to use the current document's URL in all
+# cases (i.e., assume the MAP is present below, if it wasn't present
+# above the point in the HTML stream where the USEMAP attribute was
+# detected). Lynx's present "single pass" rendering engine precludes
+# checking below before making the decision on how to resolve a USEMAP
+# reference consisting solely of a fragment.
+#
+#SEEK_FRAG_MAP_IN_CUR:TRUE
+
+# If SEEK_FRAG_AREA_IN_CUR is set FALSE, then HREF attribute values
+# in AREA tags consisting of only a fragment (HREF="#foo") will be
+# resolved with respect to the current document's base, which might
+# not be the same as the current document's URL. The compilation
+# default is to use the current document's URL, as is done for the
+# HREF attribute values of Anchors and LINKs that consist solely of
+# a fragment.
+#
+#SEEK_FRAG_AREA_IN_CUR:TRUE
+
+# Local execution links and scripts are completely disabled
+# in the source code unless they are enabled in the
+# userdefs.h file and the sources recompiled. Please
+# see the Lynx source code distribution and the userdefs.h
+# file for more detail on enabling execution links and scripts.
+#
+# If you have enabled execution links or scripts the following
+# two variables control Lynx's action when an execution link
+# or script is encountered.
+#
+# If LOCAL_EXECUTION_LINKS_ALWAYS_ON is set to TRUE any execution
+# link or script will be executed no matter where it came from.
+# This is EXTREMELY dangerous. Since Lynx can access files from
+# anywhere in the world, you may encounter links or scripts that
+# will cause damage or compromise the security of your system.
+#
+# If LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE is set to TRUE only
+# links or scripts that reside on the local machine and are
+# referenced with a URL beginning with "file://localhost/" or meet
+# TRUSTED_EXEC or ALWAYS_TRUSTED_EXEC rules (see below) will be
+# executed. This is much less dangerous than enabling all execution
+# links, but can still be dangerous.
+#
+#LOCAL_EXECUTION_LINKS_ALWAYS_ON:FALSE
+#LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:FALSE
+
+# If LOCAL_EXECUTION_LINK_ON_BUT_NOT_REMOTE is TRUE, and no TRUSTED_EXEC
+# rule is defined, it defaults to "file://localhost/" and any lynxexec
+# or lynxprog command will be permitted if it was referenced with a URL
+# beginning with that string. If you wish to restrict the referencing URL's
+# further, you can extend the string to include a trusted path. You also can
+# specify a trusted directory for http URL's, which will then be treated as
+# if they were local rather than remote. For example:
+#
+# TRUSTED_EXEC:file://localhost/trusted/
+# TRUSTED_EXEC:http://www.wfbr.edu/trusted/
+#
+# If you also wish to restrict the commands which can be executed, create
+# a series of rules with the path (Unix) or command name (VMS) following
+# the string, separated by a tab. For example:
+#
+# Unix:
+# TRUSTED_EXEC:file://localhost/<tab>/bin/cp
+# TRUSTED_EXEC:file://localhost/<tab>/bin/rm
+# VMS:
+# TRUSTED_EXEC:file://localhost/<tab>copy
+# TRUSTED_EXEC:file://localhost/<tab>delete
+#
+# Once you specify a TRUSTED_EXEC referencing string, the default is
+# replaced, and all the referencing strings you desire must be specified
+# as a series. Similarly, if you associate a command with the referencing
+# string, you must specify all of the allowable commands as a series of
+# TRUSTED_EXEC rules for that string. If you specify ALWAYS_TRUSTED_EXEC
+# rules below, you need not repeat them as TRUSTED_EXEC rules.
+#
+# If EXEC_LINKS and JUMPFILE have been defined, any lynxexec or lynxprog
+# URL's in that file will be permitted, regardless of other settings. If
+# you also set LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:TRUE and a single
+# TRUSTED_EXEC rule that will always fail (e.g., "none"), then *ONLY* the
+# lynxexec or lynxprog URL's in JUMPFILE (and any ALWAYS_TRUSTED_EXEC rules,
+# see below) will be allowed. Note, however, that if Lynx was compiled with
+# CAN_ANONYMOUS_JUMP set to FALSE (default is TRUE), or -restrictions=jump
+# is included with the -anonymous switch at run time, then users of an
+# anonymous account will not be able to access the jumps file or enter
+# 'j'ump shortcuts, and this selective execution feature will be overridden
+# as well (i.e., they will only be able to access lynxexec or lynxprog
+# URLs which meet any ALWAYS_TRUSTED_EXEC rules).
+#
+#TRUSTED_EXEC:none
+
+# If EXEC_LINKS was defined, any lynxexec or lynxprog URL can be made
+# always enabled by an ALWAYS_TRUSTED_EXEC rule for it. This is useful for
+# anonymous accounts in which you have disabled execution links generally,
+# and may also have disabled jump file links, but still want to allow
+# execution of particular utility scripts or programs. The format is
+# like that for TRUSTED_EXEC. For example:
+#
+# Unix:
+# ALWAYS_TRUSTED_EXEC:file://localhost/<tab>/usr/local/kinetic/bin/usertime
+# ALWAYS_TRUSTED_EXEC:http://www.more.net/<tab>/usr/local/kinetic/bin/who.sh
+# VMS:
+# ALWAYS_TRUSTED_EXEC:file://localhost/<tab>usertime
+# ALWAYS_TRUSTED_EXEC:http://www.more.net/<tab>show users
+#
+# The default ALWAYS_TRUSTED_EXEC rule is "none".
+#
+#ALWAYS_TRUSTED_EXEC:none
+
+# Unix:
+# =====
+# TRUSTED_LYNXCGI rules define the permitted sources and/or paths for
+# lynxcgi links (if LYNXCGI_LINKS is defined in userdefs.h). The format
+# is the same as for TRUSTED_EXEC rules (see above), but no defaults are
+# defined, i.e., if no TRUSTED_LYNXCGI rules are defined here, any source
+# and path for lynxcgi links will be permitted. Example rules:
+#
+# TRUSTED_LYNXCGI:file://localhost/
+# TRUSTED_LYNXCGI:<tab>/usr/local/etc/httpd/cgi-bin/
+# TRUSTED_LYNXCGI:file://localhost/<tab>/usr/local/www/cgi-bin/
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#TRUSTED_LYNXCGI:none
+
+# Unix:
+# =====
+# LYNXCGI_ENVIRONMENT adds the current value of the specified
+# environment variable to the list of environment variables passed on to the
+# lynxcgi script. Useful variables are HOME, USER, EDITOR, etc...
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#LYNXCGI_ENVIRONMENT:
+
+# Unix:
+# =====
+# LYNXCGI_DOCUMENT_ROOT is the value of DOCUMENT_ROOT that will be passed
+# to lynxcgi scripts. If set and the URL has PATH_INFO data, then
+# PATH_TRANSLATED will also be generated. Examples:
+# LYNXCGI_DOCUMENT_ROOT:/usr/local/etc/httpd/htdocs
+# LYNXCGI_DOCUMENT_ROOT:/data/htdocs/
+#
+# VMS:
+# ====
+# Do not define this.
+#
+#LYNXCGI_DOCUMENT_ROOT:
+
+# If FORCE_SSL_COOKIES_SECURE is set to TRUE, then SSL encrypted cookies
+# received from https servers never will be sent unencrypted to http
+# servers. The compilation default is to impose this block only if the
+# https server included a secure attribute for the cookie. The normal
+# default or that defined here can be toggled via the -force_secure
+# command line switch.
+#
+#FORCE_SSL_COOKIES_SECURE:FALSE
+
+# MAIL_SYSTEM_ERROR_LOGGING will send a message to the owner of
+# the information, or ALERTMAIL if there is no owner, every time
+# that a document cannot be accessed!
+#
+# NOTE: This can generate A LOT of mail, be warned.
+#
+#MAIL_SYSTEM_ERROR_LOGGING:FALSE
+
+# If CHECKMAIL is set to TRUE, the user will be informed (via a statusline
+# message) about the existence of any unread mail at startup of Lynx, and
+# will get statusline messages if subsequent new mail arrives. If a jumps
+# file with a lynxprog URL for invoking mail is available, or your html
+# pages include an mail launch file URL, the user thereby can access mail
+# and read the messages. The checks and statusline reports will not be
+# performed if Lynx has been invoked with the -restrictions=mail switch.
+#
+# VMS USERS !!!
+# New mail is normally broadcast as it arrives, via "unsolicited screen
+# broadcasts", which can be "wiped" from the Lynx display via the Ctrl-W
+# command. You may prefer to disable the broadcasts and use CHECKMAIL
+# instead (e.g., in a public account which will be used by people who
+# are ignorant about VMS).
+#
+#CHECKMAIL:FALSE
+
+# To enable news reading ability via Lynx, the environment variable NNTPSERVER
+# must be set so that it points to your site's NNTP server (see INSTALLATION).
+# Lynx respects RFC 1738 (http://www.ics.uci.edu/pub/ietf/uri/rfc1738.txt) and
+# and does not accept a host field in news URLs (use nntp: instead news: for
+# the scheme if you wish to specify an NNTP host in a URL, as explained in the
+# RFC). If you have not set the variable externally, you can set it at run
+# time via this configuration file. It will not override an external setting.
+# Note that on VMS it is set as a process logical rather than symbol, and will
+# outlive the Lynx image.
+#
+#NNTPSERVER:news.server.dom
+
+# If LIST_NEWS_NUMBERS is set TRUE, Lynx will use an ordered list and include
+# the numbers of articles in news listings, instead of using an unordered
+# list. The default is defined in userdefs.h, and can be overridden here.
+#
+#LIST_NEWS_NUMBERS:FALSE
+
+# If LIST_NEWS_DATES is set TRUE, Lynx will include the dates of articles in
+# news listings. The dates always are included in the articles, themselves.
+# The default is defined in userdefs.h, and can be overridden here.
+#
+#LIST_NEWS_DATES:FALSE
+
+# NEWS_CHUNK_SIZE and NEWS_MAX_CHUNK regulate the chunking of news article
+# listings with inclusion of links for listing earlier and/or later articles.
+# The defaults are defined in HTNews.c as 30 and 40, respectively. If the
+# news group contains more than NEWS_MAX_CHUNK articles, they will be listed
+# in NEWS_CHUNK_SIZE chunks. You can change the defaults here, and/or on
+# the command line via -newschunksize=NUMBER and/or -newsmaxchunk=NUMBER
+# switches. Note that if the chunk size is increased, here or on the command
+# line, to a value greater than the current maximum, the maximum will be
+# increased to that number. Conversely, if the maximum is set to a number
+# less than the current chunk size, the chunk size will be reduced to that
+# number. Thus, you need use only one of the two switches on the command
+# line, based on the direction of intended change relative to the compilation
+# or configuration defaults. The compilation defaults ensure that there will
+# be at least 10 earlier articles before bothering to chunk and create a link
+# for earlier articles.
+#
+#NEWS_CHUNK_SIZE:30
+#NEWS_MAX_CHUNK:40
+
+# Set NEWS_POSTING to FALSE if you do not want to support posting to
+# news groups via Lynx. If left TRUE, Lynx will use its news gateway to
+# post new messages or followups to news groups, using the URL schemes
+# described in the "Supported URL" section of the online 'h'elp. The
+# posts will be attempted via the nntp server specified in the URL, or
+# if none was specified, via the NNTPSERVER configuration or environment
+# variable. Links with these URLs for posting or sending followups are
+# created by the news gateway when reading group listings or articles
+# from nntp servers if the server indicates that it permits posting.
+# The compilation default set in userdefs.h can be changed here. If
+# the default is TRUE, posting can still be disallowed via the
+# -restrictions command line switch.
+#
+#NEWS_POSTING:TRUE
+
+# LYNX_SIG_FILE defines the name of a file containing a signature which
+# can be appended to email messages and news postings or followups. The
+# user will be prompted whether to append it. It is sought in the home
+# directory. If it is in a subdirectory, begin it with a dot-slash
+# (e.g., ./lynx/.lynxsig). The definition is set in userdefs.h and can
+# be changed here.
+#
+#LYNX_SIG_FILE:.lynxsig
+
+# If USE_MOUSE is set TRUE, Lynx (when configured with ncurses) will allow
+# the user to click with button-1 on links to select them.
+#USE_MOUSE: FALSE
+
+# If COLLAPSE_BR_TAGS is set FALSE, Lynx will not collapse serial BR tags.
+# Note that the valid way to insert extra blank lines in HTML is via a PRE
+# block with only newlines in the block.
+# The default is defined in userdefs.h, and can be overridden here.
+#
+#COLLAPSE_BR_TAGS:TRUE
+
+# If SET_COOKIES is set FALSE, Lynx will ignore Set-Cookie headers
+# in http server replies.
+# The default is defined in userdefs.h, and can be overridden here,
+# and/or toggled via the -cookies command line switch.
+#
+#SET_COOKIES:TRUE
+
+# VMS:
+#=====
+# The mail command and qualifiers are defined in userdefs.h. Lynx
+# will spawn a subprocess to send replies and error messages. The
+# command, and qualifiers (if any), can be re-defined here. If
+# you use PMDF then headers will we passed via a header file.
+# If you use "generic" VMS MAIL, the subject will be passed on the
+# command line via a /subject="SUBJECT" qualifier, and inclusion
+# of other relevant headers may not be possible.
+# If your mailer uses another syntax, some hacking of the mailform()
+# mailmsg() and reply_by_mail() functions in LYMail.c, and printfile()
+# function in LYPrint.c, may be required.
+#
+#SYSTEM_MAIL:PMDF SEND
+#SYSERM_MAIL_FLAGS:/headers
+#
+#SYSTEM_MAIL:MAIL
+#SYSTEM_MAIL_FLAGS:
+
+# Unix:
+#======
+# The mail path and flags normally are defined for sendmail (or submit
+# with MMDF) in userdefs.h. You can change them here, but should first
+# read the zillions of CERT advisories about security problems with Unix
+# mailers.
+#
+#SYSTEM_MAIL:/usr/mmdf/bin/submit
+#SYSTEM_MAIL_FLAGS:-mlruxto,cc\*
+#
+#SYSTEM_MAIL:/usr/sbin/sendmail
+#SYSTEM_MAIL_FLAGS:-t -oi
+#
+#SYSTEM_MAIL:/usr/lib/sendmail
+#SYSTEM_MAIL_FLAGS:-t -oi
+
+# VMS ONLY:
+#==========
+# MAIL_ADRS is defined in userdefs.h and normally is structured for PMDF's
+# IN%"INTERNET_ADDRESS" scheme. The %s is replaced with the address given
+# by the user. If you are using a different Internet mail transport, change
+# the IN appropriately (e.g., to SMTP, MX, or WINS).
+#
+#MAIL_ADRS:"IN%%""%s"""
+
+# VMS ONLY:
+#==========
+# If USE_FIXED_RECORDS is set to TRUE here or in userdefs.h, Lynx will
+# convert 'd'ownloaded binary files to FIXED 512 record format before saving
+# them to disk or acting on a DOWNLOADER option. If set to FALSE, the
+# headers of such files will indicate that they are Stream_LF with Implied
+# Carriage Control, which is incorrect, and can cause downloading software
+# to get confused and unhappy. If you do set it FALSE, you can use the
+# FIXED512.COM command file, which is included in this distribution, to do
+# the conversion externally.
+#
+#USE_FIXED_RECORDS:TRUE
+
+# VI_KEYS can be turned on by the user in the options
+# screen or the .lynxrc file. This is just the default.
+#
+#VI_KEYS_ALWAYS_ON:FALSE
+
+# EMACS_KEYS can be turned on by the user in the options
+# screen or the .lynxrc file. This is just the default.
+#
+#EMACS_KEYS_ALWAYS_ON:FALSE
+
+# DEFAULT_KEYPAD_MODE specifies whether by default the user
+# has numbers that work like arrows or else numbered links.
+# DEFAULT KEYPAD MODE may be set to TRUE for using numbers
+# as arrows as the default, or FALSE for using numbered links
+# as the default (LINKS_AND_FORM_FIELDS_ARE_NUMBERED cannot
+# currently be set by this option.).
+#
+#DEFAULT_KEYPAD_MODE_IS_NUMBERS_AS_ARROWS:TRUE
+
+# The default search type.
+# This is a default that can be overridden by the user!
+#
+#CASE_SENSITIVE_ALWAYS_ON:FALSE
+
+# DEFAULT_BOOKMARK_FILE is a default filename for use as a personal
+# bookmark file. It will reference a file from the user's home directory.
+# NOTE that a file ending in .html or other suffix mapped to text/html
+# should be used to ensure it's treatment as HTML. The built-in default
+# is lynx_bookmarks.html. On both Unix and VMS, if a subdirectory off of
+# the HOME directory is desired, the path should begin with "./" (e.g.,
+# ./BM/lynx_bookmarks.html), but the subdirectory must already exist.
+# Lynx will create the bookmark file, if it does not already exist, on
+# the first ADD_BOOKMARK attempt if the HOME directory is indicated
+# (i.e., if the definition is just filename.html without any slashes),
+# but requires a pre-existing subdirectory to create the file there.
+# The user can re-define the default bookmark file, as well as a set
+# of sub-bookmark files if multiple bookmark file support is enabled
+# (see below), via the 'o'ptions menu, and can save those definitions
+# in the .lynxrc file.
+#
+#DEFAULT_BOOKMARK_FILE:lynx_bookmarks.html
+
+# If MULTI_BOOKMARK_SUPPORT is set TRUE, and BLOCK_MULTI_BOOKMARKS (see
+# below) is FALSE, and sub-bookmarks exist, all bookmark operations will
+# first prompt the user to select an active sub-bookmark file or the
+# default bookmark file. FALSE is the default so that one (the default)
+# bookmark file will be available initially. The definition here will
+# override that in userdefs.h. The user can turn on multiple bookmark
+# support via the 'o'ptions menu, and can save that choice as the startup
+# default via the .lynxrc file. When on, the setting can be STANDARD or
+# ADVANCED. If support is set to the latter, and the user mode also is
+# ADVANCED, the VIEW_BOOKMARK command will invoke a statusline prompt at
+# which the user can enter the letter token (A - Z) of the desired bookmark,
+# or '=' to get a menu of available bookmark files. The menu always is
+# presented in NOVICE or INTERMEDIATE mode, or if the support is set to
+# STANDARD. No prompting or menu display occurs if only one (the startup
+# default) bookmark file has been defined (define additional ones via the
+# 'o'ptions menu). The startup default, however set, can be overridden on
+# the command line via the -restrictions=multibook or the -anonymous or
+# -validate switches.
+#
+#MULTI_BOOKMARK_SUPPORT:FALSE
+
+# If BLOCK_MULTI_BOOKMARKS is set TRUE, multiple bookmark support will
+# be forced off, and cannot to toggled on via the 'o'ptions menu. The
+# compilation setting is normally FALSE, and can be overridden here.
+# It can also be set via the -restrictions=multibook or the -anonymous
+# or -validate command line switches.
+#
+#BLOCK_MULTI_BOOKMARKS:FALSE
+
+# DEFAULT_USER_MODE sets the default user mode for Lynx users.
+# NOVICE shows a three line help message at the bottom of the screen
+# INTERMEDIATE shows normal amount of help (one line)
+# ADVANCED help is replaced by the URL of the current link
+#
+#DEFAULT_USER_MODE:NOVICE
+
+# DEFAULT_EDITOR sets the default editor for Lynx users.
+# If an editor is defined then the user may edit local documents
+# using that editor. The editor will also be used for sending
+# mail messages. If no editor is defined here or by the user
+# the user will not be able to edit local documents and a primitive
+# line oriented mail input mode will be used.
+# NOTE: Do not define an editor unless you know that every user will
+# know how to use it. Most users do not enjoy getting stuck in
+# an unknown editor that they can't get out of. Users can
+# easily define an editor of their own using the options menu,
+# so it is not always desirable to set the DEFAULT_EDITOR.
+#
+#DEFAULT_EDITOR:
+
+# SYSTEM_EDITOR behaves the same as DEFAULT_EDITOR except that it can't be
+# changed.
+#
+#SYSTEM_EDITOR:
+
+# Proxy variables
+# Lynx version 2.2 and beyond supports the use of proxy servers that can
+# act as firewall gateways and caching servers. They are preferable to
+# the older gateway servers. Each protocol used by Lynx can be mapped
+# separately using PROTOCOL_proxy environment variables (see INSTALLATION).
+# If you have not set them externally, you can set them at run time via
+# this configuration file. They will not override external settings.
+# The no_proxy variable can be a comma-separated list of hosts which should
+# not be proxied, or an asterisk to override all proxy variables.
+# Note that on VMS they are set as process logicals rather than symbols,
+# to preserve lowercasing, and will outlive the Lynx image.
+#
+#http_proxy:http://some.server.dom:port/
+#https_proxy:http://some.server.dom:port/
+#ftp_proxy:http://some.server.dom:port/
+#gopher_proxy:http://some.server.dom:port/
+#news_proxy:http://some.server.dom:port/
+#newspost_proxy:http://some.server.dom:port/
+#newsreply_proxy:http://some.server.dom:port/
+#snews_proxy:http://some.server.dom:port/
+#snewspost_proxy:http://some.server.dom:port/
+#snewsreply_proxy:http://some.server.dom:port/
+#nntp_proxy:http://some.server.dom:port/
+#wais_proxy:http://some.server.dom:port/
+#finger_proxy:http://some.server.dom:port/
+#cso_proxy:http://some.server.dom:port/
+#no_proxy:host.domain.dom
+
+# Printer definitions
+# any number of printers may be defined by using multiple
+# printer definition sets. Printers may be any program
+# that could be useful to your users, they do not necessarily
+# have to print.
+#
+# the definition of a printer is of the form
+# PRINTER:<printer name>:<printer command>:<printer option>:<lines/page>
+#
+# <printer name> is the name that the user will see.
+# <printer command> is the command line arguments for printing a file.
+# The %s will be replaced with the file being printed.
+# If a second %s is given the second %s will be replaced by
+# a suggested filename that is prettier than the tempfile
+# name given in the first %s. This does not remove the first
+# %s from the command line in any manner. If you need to
+# use only the second %s file name in your printer command,
+# then I suggest creating a script which will first copy the
+# first %s file name to the second %s file name, and then
+# executing your print command with the second %s file name.
+# <printer option> specifies whether the printer should be disabled for
+# users without printing options. The options are
+# TRUE or FALSE;
+# TRUE means the printer will always be ENABLED
+# regardless of printer or anonymous settings
+# FALSE means the printer will be DISABLED when
+# the -noprint option is on, or for anonymous
+# users which are not allowed to print
+#
+# <lines/page> is an optional parameter for indicating the number of
+# lines per page for the printer. Defaults to 66. Used
+# for computing the approximate number of pages and
+# generating a statusline query of whether to proceed if
+# the document is longer than 4 printer pages. Uses the
+# current screen length for the computation when the
+# built in "print to screen" option is selected.
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# If you have a very busy VMS print queue and Lynx deletes the temporary
+# files before they have been queued, use the VMSPrint.com included in
+# the distribution.
+#
+# examples
+#PRINTER:Computer Center printer:lpr -Pccprt %s:FALSE
+#PRINTER:Office printer:lpr -POffprt %s:TRUE
+#PRINTER:VMS printer:print /queue=cc$print %s:FALSE:58
+#PRINTER:Busy VMS printer:@Lynx_Dir\:VMSPrint sys$print %s:FALSE:58
+# Check out the lpansi program in utils/ for printing on vt100
+# attached printers.
+#PRINTER:Use vt100 print sequence to print from your local terminal:lpansi %s:TRUE
+# Don't use the following printer on anonymous accounts since
+# allowing shell input is very dangerous.
+#PRINTER:Specify your own print command:echo -n "Enter a print command\: "; read word; sh -c "$word %s":FALSE
+# Pass to a sophisticated file viewer (sources for most are available in
+# ftp://space.mit.edu/pub/davis/most). The most -k switch suppresses the
+# invocation of hexadecimal display mode if 8-bit or control characters
+# are present. The +s switch invokes secure mode.
+#PRINTER:Use Most to view:most -k +s %s:TRUE:23
+
+# Downloader definitions
+# any number of downloaders may be defined by using multiple
+# downloader definition sets. Downloaders may be any program
+# that could be useful to your users, they do not necessarily
+# have to be a download protocol program. The most common use
+# of a downloader is to use Ckermit or some other transfer
+# program so that the user may easily transfer files back to
+# their local machine over a serial link.
+#
+# the definition of a downloader is of the form
+# DOWNLOADER:<downloadername>:<downloader command>:<downloader option>
+#
+# <downloader name> is the name that the user will see.
+# <downloader command> is the command line arguments for downloading a file.
+# The %s will be replaced with the file being downloaded.
+# If a second %s is given the second %s will be replaced
+# by a suggested filename that is nicer than the tempfile
+# name given in the first %s. This does not replace the
+# first %s in the command line. If your command needs
+# the suggest file name on the command line only, then
+# I suggest creating a script that will first copy the
+# first %s file name to the second %s file name, and then
+# execute the downloading command using the second %s file
+# name (e.g., 'sz' needs such a script interposed).
+# <downloader option> specifies whether the downloader should be disabled for
+# anonymous users. The options are
+# TRUE or FALSE;
+# TRUE means the downloader will always be ENABLED
+# regardless of the anonymous settings (however,
+# all downloading is disabled by -validate).
+# FALSE means the downloader will be DISABLED when
+# the user is anonymous.
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# examples
+#DOWNLOADER:Use Most to view:most +s %s:TRUE
+# (don't use most's -k switch, so that binaries will invoke hexadecimal mode)
+#DOWNLOADER:Use Kermit to download to the local terminal:kermit -i -s %s -a %s:TRUE
+#DOWNLOADER:Use Zmodem to download to the local terminal:sz %s:TRUE
+# (example script in lieu of :sz %s: for offering a suggested filename)
+# :set %s %s;td=/tmp/Lsz$$;mkdir $td;ln -s $1 $td/"$2";sz $td/"$2";rm -r $td:
+
+# Unix ONLY:
+#===========
+# Uploader definitions (implemented only with Unix DIRED_SUPPORT;
+# see the Makefile in the top directory,
+# and the header of ./src/LYUpload.c)
+# any number of uploaders may be defined by using multiple
+# uploader definition sets. Uploaders may be any program
+# that could be useful to your users, they do not necessarily
+# have to be an upload protocol program. The most common use
+# of an uploader is to use Ckermit or some other transfer
+# program so that the user may easily transfer files from
+# their local machine over a serial link.
+#
+# the definition of an uploader is of the same form as a downloader
+# UPLOADER:<uploadername>:<uploader command>:<uploader option>
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon, precede it with a backslash!
+#
+# If you do not include a %s, you will not be prompted for an
+# output filename.
+#
+# example
+#UPLOADER:Use Kermit to upload from your computer: kermit -i -r -a %s:TRUE
+
+# If NO_DOT_FILES is TRUE (normal default via userdefs.h), the user will not
+# be allowed to specify files beginning with a dot in reply to output filename
+# prompts, and files beginning with a dot (e.g., file://localhost/path/.lynxrc)
+# will not be included in the directory browser's listings. If set FALSE, you
+# can force it to be treated as TRUE via -restrictions=dotfiles. If set FALSE
+# and not forced TRUE, the user can regulate it via the 'o'ptions menu (and
+# may save the preference in the RC file).
+#
+#NO_DOT_FILES:TRUE
+
+# If NO_FROM_HEADER is set FALSE, From headers will be sent in transmissions
+# to http or https servers if the personal_mail_address has been defined via
+# the 'o'ptions menu. The compilation default is TRUE (no From header is
+# sent) and the default can be changed here. The default can be toggled at
+# run time via the -from switch. Note that transmissions of From headers
+# have become widely considered to create an invasion of privacy risk.
+#
+#NO_FROM_HEADER:TRUE
+
+# If NO_REFERER_HEADER is TRUE, Referer headers never will be sent in
+# transmissions to servers. Lynx normally sends the URL of the document
+# from which the link was derived, but not for startfile URLs, 'g'oto
+# URLs, 'j'ump shortcuts, bookmark file links, history list links, or
+# URLs that include the content from form submissions with method GET.
+# If left FALSE here, it can be set TRUE at run time via the -noreferer
+# switch.
+#
+#NO_REFERER_HEADER:FALSE
+
+# If NO_FILE_REFERER is TRUE, Referer headers never will be sent in
+# transmissions to servers for links or actions derived from documents
+# or forms with file URLs. This would ensure that paths associated
+# with the local file system are never indicated to servers, even if
+# NO_REFERER_HEADER is FALSE. If left FALSE here, it can be set TRUE
+# at run time via the -nofilereferer switch.
+#
+#NO_FILE_REFERER:FALSE
+
+# If MAKE_LINKS_FOR_ALL_IMAGES is TRUE, all images will be given links
+# which can be ACTIVATEd. For inlines, the ALT or pseudo-ALT ("[INLINE]")
+# strings will be links for the resolved SRC rather than just text. For
+# ISMAP or other graphic links, the ALT or pseudo-ALT ("[ISMAP]" or "[LINK]")
+# strings will have '-' and a link labeled "[IMAGE]" for the resolved SRC
+# appended.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can use LYK_IMAGE_TOGGLE to toggle the feature on or off at run time.
+#
+# The default also can be toggled via an "-image_links" command line switch.
+#
+#MAKE_LINKS_FOR_ALL_IMAGES:FALSE
+
+# If MAKE_PSEUDO_ALTS_FOR_INLINES is FALSE, inline images which do not
+# specify an ALT string will not have "[INLINE]" inserted as a pseudo-ALT,
+# i.e., they'll be treated as having ALT="". If MAKE_LINKS_FOR_ALL_IMAGES
+# is defined or toggled to TRUE, however, the pseudo-ALTs will be created
+# for inlines, so that they can be used as links to the SRCs.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can use LYK_INLINE_TOGGLE to toggle the feature on or off at run time.
+#
+# The default also can be toggled via a "-pseudo_inlines" command line
+# switch.
+#
+#MAKE_PSEUDO_ALTS_FOR_INLINES:TRUE
+
+# If SUBSTITUTE_UNDERSCORES is TRUE, the _underline_ format will be used
+# for emphasis tags in dumps.
+#
+# The default defined here will override that in userdefs.h, and the user
+# can toggle the default via a "-underscore" command line switch.
+#
+#SUBSTITUTE_UNDERSCORES:FALSE
+
+# If QUIT_DEFAULT_YES is TRUE then when the QUIT command is entered, any
+# response other than n or N will confirm. It should be FALSE if you
+# prefer the more conservative action of requiring an explicit Y or y to
+# confirm. The default defined here will override that in userdefs.h.
+#
+#QUIT_DEFAULT_YES:TRUE
+
+# If HISTORICAL_COMMENTS is TRUE, Lynx will revert to the "Historical"
+# behavior of treating any '>' as a terminator for comments, instead of
+# seeking a valid '-->' terminator (note that white space can be present
+# between the '--' and '>' in valid terminators). The compilation default
+# is FALSE.
+#
+# The compilation default, or default defined here, can be toggled via a
+# "-historical" command line switch, and via the LYK_HISTORICAL command key.
+#
+#HISTORICAL_COMMENTS:FALSE
+
+# If MINIMAL_COMMENTS is TRUE, Lynx will not use Valid comment parsing
+# of '--' pairs as serial comments within an overall comment element,
+# and instead will seek only a '-->' terminator for the overall comment
+# element. This emulates the Netscape v2.0 comment parsing bug, and
+# will help Lynx cope with the use of dashes as "decorations", which
+# consequently has become common in so-called "Enhanced for Netscape"
+# pages. Note that setting Historical comments on will override the
+# Minimal or Valid setting.
+#
+# The compilation default for MINIMAL_COMMENTS is FALSE, but we'll
+# set it TRUE here, until Netscape gets its comment parsing right,
+# and "decorative" dashes cease to be so common.
+#
+# The compilation default, or default defined here, can be toggled via a
+# "-minimal" command line switch, and via the LYK_MINIMAL command key.
+#
+MINIMAL_COMMENTS:TRUE
+
+# If SOFT_DQUOTES is TRUE, Lynx will emulate the invalid behavior of
+# treating '>' as a co-terminator of a double-quoted attribute value
+# and the tag which contains it, as was done in old versions of Netscape
+# and Mosaic. The compilation default is FALSE.
+#
+# The compilation default, or default defined here, can be toggled via
+# a "-soft_dquotes" command line switch.
+#
+#SOFT_DQUOTES:FALSE
+
+# If STRIP_DOTDOT_URLS is TRUE, Lynx emulates the invalid behavior of many
+# browsers to strip a leading "../" segment from relative URLs in HTML
+# documents with a http or https base URL, if this would otherwise lead to
+# an absolute URLs with those characters still in it. Such URLs are normally
+# erroneous and not what is intended by page authors. Lynx will issue
+# a warning message when this occurs.
+#
+# If STRIP_DOTDOT_URLS is FALSE, Lynx will use those URLs for requests
+# without taking any special actions or issuing Warnings, in most cases
+# this will result in an error response from the server.
+#
+# Note that Lynx never tries to fix similar URLs for protocols other than
+# http and https, since they are less common and may actually be valid in
+# some cases.
+#
+#STRIP_DOTDOT_URLS:TRUE
+
+# If ENABLE_SCROLLBACK is TRUE, Lynx will clear the entire screen before
+# displaying each new screenful of text. Though less efficient for normal
+# use, this allows programs that maintain a buffer of previously-displayed
+# text to recognize the continuity of what has been displayed, so that
+# previous screenfuls can be reviewed by whatever method the program uses
+# to scroll back through previous text. For example, the PC comm program
+# QModem has a key that can be pressed to scroll back; if ENABLE_SCROLLBACK
+# is TRUE, pressing the scrollback key will access previous screenfuls which
+# will have been stored on the local PC and will therefore be displayed
+# instantaneously, instead of needing to be retransmitted by Lynx at the
+# speed of the comm connection (but Lynx will not know about the change,
+# so you must restore the last screen before resuming with Lynx commands).
+#
+# The compilation default is FALSE (if REVERSE_CLEAR_SCREEN_PROBLEM was not
+# defined in the Unix Makefile to invoke this behavior as a workaround for
+# some poor curses implementations).
+#
+# The default compilation or configuration setting can be toggled via an
+# "-enable_scrollback" command line switch.
+#
+#ENABLE_SCROLLBACK:FALSE
+
+# If SCAN_FOR_BURIED_NEWS_REFS is set to TRUE, Lynx will scan the bodies
+# of news articles for buried article and URL references and convert them
+# to links. The compilation default is TRUE, but some email addresses
+# enclosed in angle brackets ("<user@address>") might be converted to false
+# news links, and uuencoded messages might be corrupted. The conversion is
+# not done when the display is toggled to source or when 'd'ownloading, so
+# uuencoded articles can be saved intact regardless of these settings.
+#
+# The default setting can be toggled via a "-buried_news" command line
+# switch.
+#
+#SCAN_FOR_BURIED_NEWS_REFS:TRUE
+
+# If PREPEND_BASE_TO_SOURCE is set to FALSE, Lynx will not prepend a
+# Request URL comment and BASE element to text/html source files when
+# they are retrieved for 'd'ownloading or passed to 'p'rint functions.
+# The compilation default is TRUE. Note that this prepending is not
+# done for -source dumps, unless the -base switch also was included on
+# the command line, and the latter switch overrides the setting of the
+# PREPEND_BASE_TO_SOURCE configuration variable.
+#
+#PREPEND_BASE_TO_SOURCE:TRUE
+
+# MIME types and viewers!
+#
+# file extensions may be assigned to MIME types using
+# the SUFFIX: definition.
+#
+# The SUFFIX definition takes the form of:
+# SUFFIX:<file extension>:<mime type>
+# for instance the following definition maps the
+# extension ".gif" to the mime type "image/gif"
+# SUFFIX:.gif:image/gif
+#
+# file suffixes are case INsensitive!
+#
+# The suffix definitions listed here in the default lynx.cfg file are
+# among those established via src/HTInit.c. You can change any of the
+# defaults by editing that file, or via the global or personal mime.types
+# files at run time. They will be overridden if you assign them here.
+#
+#SUFFIX:.ps:application/postscript
+#SUFFIX:.eps:application/postscript
+#SUFFIX:.ai:application/postscript
+#SUFFIX:.rtf:application/x-rtf
+#SUFFIX:.snd:audio/basic
+#SUFFIX:.gif:image/gif
+#SUFFIX:.rgb:image/x-rgb
+#SUFFIX:.pict:image/x-pict
+#SUFFIX:.xbm:image/x-xbitmap
+#SUFFIX:.tiff:image/x-tiff
+#SUFFIX:.jpg:image/jpeg
+#SUFFIX:.jpeg:image/jpeg
+#SUFFIX:.mpg:video/mpeg
+#SUFFIX:.mpeg:video/mpeg
+#SUFFIX:.mov:video/quicktime
+#SUFFIX:.hqx:application/octet-stream
+#SUFFIX:.bin:application/octet-stream
+#SUFFIX:.exe:application/octet-stream
+#SUFFIX:.tar:application/octet-stream
+#SUFFIX:.Z:application/octet-stream
+#SUFFIX:.gz:application/octet-stream
+#SUFFIX:.zip:application/octet-stream
+#SUFFIX:.lzh:application/octet-stream
+#SUFFIX:.lha:application/octet-stream
+#SUFFIX:.dms:application/octet-stream
+
+# The global and personal EXTENSION_MAP files allow you to assign extensions
+# to MIME types which will override any of the suffix maps in this (lynx.cfg)
+# configuration file, or in src/HTInit.c. See the example mime.types file
+# in the samples subdirectory.
+#
+# Unix:
+#GLOBAL_EXTENSION_MAP:/usr/local/lib/mosaic/mime.types
+# VMS:
+#GLOBAL_EXTENSION_MAP:Lynx_Dir:mime.types
+#
+# Unix (sought in user's home directory):
+#PERSONAL_EXTENSION_MAP:.mime.types
+# VMS (sought in user's sys$login directory):
+#PERSONAL_EXTENSION_MAP:mime.types
+
+# VMS:
+# ====
+# XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c
+# for viewing image content types when the DECW$DISPLAY logical
+# is set. Make it the foreign command for your system's X image
+# viewer (commonly, "xv"). Make it "exit" or something like that
+# if you don't have one. It can be anything that will handle GIF,
+# TIFF and other popular image formats. Freeware ports of xv for
+# VMS are available in the ftp://ftp.wku.edu/vms/unsupported and
+# http://www.openvms.digital.com/cd/XV310A/ subdirectories. You
+# must also have a "%s" for the filename. The default is defined
+# in userdefs.h and can be overridden here, or via the global or
+# personal mailcap files (see below).
+#
+#XLOADIMAGE_COMMAND:xv %s
+
+# Unix:
+# =====
+# XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c for
+# viewing image content types when the DISPLAY environment variable
+# is set. Make it the full path and name of the xli (also know as
+# xloadimage or xview) command, or other image viewer. Put 'echo' or
+# something like it here if you don't have a suitable viewer. It can
+# be anything that will handle GIF, TIFF and other popular image formats
+# (xli does). The freeware distribution of xli is available in the
+# ftp://ftp.x.org/contrib subdirectory. The shareware, xv, also is
+# suitable. You must also have a "%s" for the filename; "&" for
+# background is optional. The default is defined in userdefs.h and can be
+# overridden here, or via the global or personal mailcap files (see below).
+# Note that open is used as the default for NeXT, instead of the
+# XLOADIMAGE_COMMAND definition.
+# If you use xli, you may want to add the -quiet flag.
+#
+#XLOADIMAGE_COMMAND:xli %s &
+
+# MIME types may be assigned to external viewers using
+# the VIEWER definition.
+#
+# Note: if you do not define a viewer to a new MIME type
+# that you assigned above then it will be saved to
+# disk by default.
+#
+# The VIEWER definition takes the form of:
+# VIEWER:<mime type>:<viewer command>[:environment]
+# where -mime type is the MIME content type of the file
+# -viewer command is a system command that can be
+# used to display the file where %s is replaced
+# within the command with the physical filename
+# (e.g. "ghostview %s" becomes "ghostview /tmp/temppsfile")
+# -environment is optional. The only valid keywords
+# are currently XWINDOWS and NON_XWINDOWS. If the XWINDOWS
+# environment is specified then the viewer will only be
+# defined when the user has the environment variable DISPLAY
+# (DECW$DISPLAY on VMS) defined. If the NON_XWINDOWS environment
+# is specified the specified viewer will only be defined when the
+# user DOES NOT have the environment variable DISPLAY defined.
+# examples:
+# VIEWER:image/gif:xli %s:XWINDOWS
+# VIEWER:image/gif:ascii-view %s:NON_XWINDOWS
+# VIEWER:application/start-elm:elm
+#
+# You must put the whole definition on one line.
+#
+# If you must use a colon in the viewer command, precede it with a backslash!
+#
+# The MIME_type:viewer:XWINDOWS definitions listed here in the lynx.cfg
+# file are among those established via src/HTInit.c. For the image types,
+# HTInit.c uses the XLOADIMAGE_COMMAND definition in userdefs.h or above
+# (open is used for NeXT). You can change any of these defaults via the
+# global or personal mailcap files at run time. They will be overridden
+# if you assign them here.
+#
+#VIEWER:application/postscript:ghostview %s&:XWINDOWS
+#VIEWER:image/gif:xli %s&:XWINDOWS
+#VIEWER:image/x-xbm:xli %s&:XWINDOWS
+#VIEWER:image/x-rgb:xli %s&:XWINDOWS
+#VIEWER:image/x-tiff:xli %s&:XWINDOWS
+#VIEWER:image/jpeg:xli %s&:XWINDOWS
+#VIEWER:video/mpeg:mpeg_play %s &:XWINDOWS
+
+# The global and personal MAILCAP files allow you to specify external
+# viewers to be spawned when Lynx encounters different MIME types, which
+# will override any of the suffix maps in this (lynx.cfg) configuration
+# file, or in src/HTInit.c. See http://www.internic.net/rfc/rfc1524.txt
+# and the example mailcap file in the samples subdirectory.
+#
+# Unix:
+#GLOBAL_MAILCAP:/usr/local/lib/mosaic/mailcap
+# VMS:
+#GLOBAL_MAILCAP:Lynx_Dir:mailcap
+#
+# Sought in user's home (Unix) or sys$login (VMS) directory.
+#PERSONAL_MAILCAP:.mailcap
+
+# Key remapping definitions!
+#
+# You may redefine the keymapping of any function in Lynx by
+# using the KEYMAP variable. The form of KEYMAP is:
+# KEYMAP:<KEYSTROKE>:<LYNX FUNCTION>
+#
+# You must map upper and lowercase keys separately.
+#
+# A representative list of functions mapped to their default keys is
+# provided below. All of the mappings are commented out by default
+# since they just map to the default mappings, except for TOGGLE_HELP
+# (see below). See LYKeymap.c for the complete key mapping. Use the
+# 'K'eymap command when running Lynx for a list of the current mappings.
+#
+# Special keys map to:
+# Up Arrow: 0x100
+# Down Arrow: 0x101
+# Right Arrow: 0x102
+# Left Arrow: 0x103
+# Page Down: 0x104
+# Page Up: 0x105
+# Keypad Home: 0x106
+# Keypad End: 0x107
+# Function key 1: 0x108
+# vt100 Help Key: 0x108
+# vt100 Do Key: 0x109
+# vt100 Find Key: 0x10A
+# vt100 Select Key: 0x10B
+# vt100 Insert Key: 0x10C
+# vt100 Remove Key: 0x10D
+# (0x00) NULL KEY: 0x10E (DO_NOTHING)
+#
+
+#KEYMAP:0x2F:SOURCE # Toggle source viewing mode (show HTML source)
+#KEYMAP:^R:RELOAD # Reload the current document and redisplay
+#KEYMAP:q:QUIT # Ask the user to quit
+#KEYMAP:Q:ABORT # Quit without verification
+#KEYMAP:0x20:NEXT_PAGE # Move down to next page
+#KEYMAP:-:PREV_PAGE # Move up to previous page
+#KEYMAP:^P:UP_TWO # Move display up two lines
+#KEYMAP:0x10C:UP_TWO # Function key Insert - Move display up two lines
+#KEYMAP:^N:DOWN_TWO # Move display down two lines
+#KEYMAP:0x10D:DOWN_TWO # Function key Remove - Move display down two lines
+#KEYMAP:(:UP_HALF # Move display up half a page
+#KEYMAP:):DOWN_HALF # Move display down half a page
+#KEYMAP:^W:REFRESH # Refresh the screen
+#KEYMAP:^A:HOME # Go to top of current document
+#KEYMAP:0x106:HOME # Keypad Home - Go to top of current document
+#KEYMAP:0x10A:HOME # Function key Find - Go to top of current document
+#KEYMAP:^E:END # Go to bottom of current document
+#KEYMAP:0x107:END # Keypad End - Go to bottom of current document
+#KEYMAP:0x10B:END # Function key Select - Go to bottom of current document
+#KEYMAP:0x100:PREV_LINK # Move to the previous link
+#KEYMAP:0x101:NEXT_LINK # Move to the next link
+#KEYMAP:<:UP_LINK # Move to the link above
+#KEYMAP:>:DOWN_LINK # Move to the link below
+#KEYMAP:0x00:RIGHT_LINK # Move to the link to the right
+#KEYMAP:0x00:LEFT_LINK # Move to the link to the left
+#KEYMAP:0x7F:HISTORY # Display stack of currently-suspended documents
+#KEYMAP:0x08:HISTORY # Display stack of currently-suspended documents
+#KEYMAP:0x103:PREV_DOC # Return to the previous document
+#KEYMAP:0x102:ACTIVATE # Select the current link
+#KEYMAP:0x109:ACTIVATE # Function key Do - Select the current link
+#KEYMAP:g:GOTO # Goto a random URL
+#KEYMAP:G:ECGOTO # Edit the current document's URL and go to it
+#KEYMAP:H:HELP # Show default help screen
+#KEYMAP:0x108:HELP # Function key Help - Show default help screen
+#KEYMAP:i:INDEX # Show default index
+#*** Edit FORM_LINK_SUBMIT_MESSAGE in userdefs.h if you change NOCACHE ***
+#KEYMAP:x:NOCACHE # Force submission of form or link with no-cache
+#*** Do not change INTERRUPT from 'z' & 'Z' ***
+#KEYMAP:z:INTERRUPT # Interrupt network transmission
+#KEYMAP:m:MAIN_MENU # Return to the main menu
+#KEYMAP:o:OPTIONS # Show the options menu
+#KEYMAP:i:INDEX_SEARCH # Search a server based index
+#KEYMAP:/:WHEREIS # Find a string within the current document
+#KEYMAP:n:NEXT # Find next occurence of string within document
+#KEYMAP:c:COMMENT # Comment to the author of the current document
+#KEYMAP:e:EDIT # Edit current document
+#KEYMAP:E:ELGOTO # Edit the current link's URL or ACTION and go to it
+#KEYMAP:=:INFO # Show info about current document
+#KEYMAP:p:PRINT # Show print options
+#KEYMAP:a:ADD_BOOKMARK # Add current document to bookmark list
+#KEYMAP:v:VIEW_BOOKMARK # View the bookmark list
+#KEYMAP:V:VLINKS # List links visited during the current Lynx session
+#KEYMAP:!:SHELL # Spawn default shell
+#KEYMAP:d:DOWNLOAD # Download current link
+#KEYMAP:j:JUMP # Jump to a predefined target
+#KEYMAP:k:KEYMAP # Display the current key map
+#KEYMAP:l:LIST # List the references (links) in the current document
+#KEYMAP:#:TOOLBAR # Go to the Toolbar or Banner in the current document
+#KEYMAP:^T:TRACE_TOGGLE # Toggle tracing of browser operations
+#KEYMAP:*:IMAGE_TOGGLE # Toggle inclusion of links for all images
+#KEYMAP:[:INLINE_TOGGLE # Toggle pseudo-ALTs for inlines with no ALT string
+#KEYMAP:0x00:DO_NOTHING # Does nothing (ignore this key)
+
+# If TOGGLE_HELP is mapped, in novice mode the second help menu line
+# can be toggled among NOVICE_LINE_TWO_A, _B, and _C, as defined in
+# userdefs.h. Otherwise, it will be NOVICE_LINE_TWO.
+#
+#KEYMAP:O:TOGGLE_HELP # Show other commands in the novice help menu
+
+# Alternate jumps files can be defined and mapped to keys here. If the
+# keys have already been mapped, then those mappings will be replaced,
+# but you should leave at least one key mapped to the default jumps
+# file. You optionally may include a statusline prompt string for the
+# mapping. You must map upper and lowercase keys separately (beware of
+# mappings to keys which the user can further remap via the 'o'ptions
+# menu). The format is:
+#
+# JUMPFILE:path:key[:prompt]
+#
+# where path should begin with a '/' (i.e., not include file://localhost).
+# Any white space following a prompt string will be trimmed, and a single
+# space will be added by Lynx.
+#
+#JUMPFILE:/Lynx_Dir/ips.html:i:IP or Interest group (? for list):
+
+# VMS ONLY:
+#==========
+# On VMS, CSwing (an XTree emulation for VTxxx terminals) is intended for
+# use as the Directory/File Manager (sources, objects, or executables are
+# available from ftp://narnia.memst.edu/). CSWING_PATH should be defined
+# here or in userdefs.h to your foreign command for CSwing, with any
+# regulatory switches you want included. If not defined, or defined as
+# a zero-length string ("") or "none" (case-insensitive), the support
+# will be disabled. It will also be disabled if the -nobrowse or
+# -selective switches are used, or if the file_url restriction is set.
+#
+# When enabled, the DIRED_MENU command (normally 'f' or 'F') will invoke
+# CSwing, normally with the current default directory as an argument to
+# position the user on that node of the directory tree. However, if the
+# current document is a local directory listing, or a local file and not
+# one of the temporary menu or list files, the associated directory will
+# be passed as an argument, to position the user on that node of the tree.
+#
+#CSWING_PATH:swing
+
+# Unix ONLY:
+#===========
+# LIST_FORMAT defines the display for local files when Lynx has been
+# compiled with LONG_LIST defined in the Makefile. The default is set
+# in userdefs.h, normally to "ls -l" format, and can be changed here
+# by uncommenting the indicated lines, or adding a definition with a
+# modified parameter list.
+#
+# The percent items in the list are interpreted as follows:
+#
+# %p Unix-style permission bits
+# %l link count
+# %o owner of file
+# %g group of file
+# %d date of last modification
+# %a anchor pointing to file or directory
+# %A as above but don't show symbolic links
+# %k size of file in Kilobytes
+# %K as above but omit size for directories
+# %s size of file in bytes
+#
+# Anything between the percent and the letter is passed on to sprintf.
+# A double percent yields a literal percent on output. Other characters
+# are passed through literally.
+#
+# If you want only the filename:
+#
+#LIST_FORMAT: %a
+#
+# If you want a brief output:
+#
+#LIST_FORMAT: %4K %-12.12d %a
+#
+# If you want the Unix "ls -l" format:
+#
+#LIST_FORMAT: %p %4l %-8.8o %-8.8g %7s %-12.12d %a
+
+# Unix ONLY:
+#===========
+# DIRED_MENU items are used to compose the F)ull menu list in DIRED mode
+# The behaviour of the default configuration given here is much the same
+# as it was when this menu was hard-coded but these items can now be adjusted
+# to suit local needs. In particular, many of the LYNXDIRED actions can be
+# replaced with lynxexec, lynxprog and lynxcgi script references.
+#
+# NOTE that defining even one DIRED_MENU line overrides all the built-in
+# definitions, so a complete set must then be defined here.
+#
+# Each line consists of the following fields:
+#
+# DIRED_MENU:type:suffix:link text:extra text:action
+#
+# type: TAG: list only when one or more files are tagged
+# FILE: list only when the current selection is a regular file
+# DIR: list only when the current selection is a directory
+# LINK: list only when the current selection is a symbolic link
+#
+# suffix: list only if the current selection ends in this pattern
+#
+# link text: the displayed text of the link
+#
+# extra text: the text displayed following the link
+#
+# action: the URL to be followed upon selection
+#
+# link text and action are scanned for % sequences that are expanded
+# at display time as follows:
+#
+# %p path of current selection
+# %f filename (last component) of current selection
+# %t tagged list (full paths)
+# %l list of tagged file names
+# %d the current directory
+#
+#DIRED_MENU:::New File:(in current directory):LYNXDIRED://NEW_FILE%d
+#DIRED_MENU:::New Directory:(in current directory):LYNXDIRED://NEW_FOLDER%d
+
+#DIRED_MENU:FILE::Install:(of current selection):LYNXDIRED://INSTALL_SRC%p
+#DIRED_MENU:DIR::Install:(of current selection):LYNXDIRED://INSTALL_SRC%p
+#DIRED_MENU:FILE::Modify File Name:(of current selection):LYNXDIRED://MODIFY_NAME%p
+#DIRED_MENU:DIR::Modify Directory Name:(of current selection):LYNXDIRED://MODIFY_NAME%p
+#DIRED_MENU:LINK::Modify Name:(of selected symbolic link):LYNXDIRED://MODIFY_NAME%p
+
+# Following depends on OK_PERMIT
+#DIRED_MENU:FILE::Modify File Permissions:(of current selection):LYNXDIRED://PERMIT_SRC%p
+#DIRED_MENU:DIR::Modify Directory Permissions:(of current selection):LYNXDIRED://PERMIT_SRC%p
+
+#DIRED_MENU:FILE::Change Location:(of selected file):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:DIR::Change Location:(of selected directory):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:LINK::Change Location:(of selected symbolic link):LYNXDIRED://MODIFY_LOCATION%p
+#DIRED_MENU:FILE::Remove File:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+#DIRED_MENU:DIR::Remove Directory:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+#DIRED_MENU:LINK::Remove Symbolic Link:(current selection):LYNXDIRED://REMOVE_SINGLE%p
+
+# Following depends on OK_UUDECODE and !ARCHIVE_ONLY
+#DIRED_MENU:FILE::UUDecode:(current selection):LYNXDIRED://UUDECODE%p
+
+# Following depends on OK_TAR and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar.Z:Expand:(current selection):LYNXDIRED://UNTAR_Z%p
+
+# Following depend on OK_TAR and OK_GZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar.gz:Expand:(current selection):LYNXDIRED://UNTAR_GZ%p
+#DIRED_MENU:FILE:.tgz:Expand:(current selection):LYNXDIRED://UNTAR_GZ%p
+
+# Following depends on !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.Z:Uncompress:(current selection):LYNXDIRED://DECOMPRESS%p
+
+# Following depends on OK_GZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.gz:Uncompress:(current selection):LYNXDIRED://UNGZIP%p
+
+# Following depends on OK_ZIP and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.zip:Uncompress:(current selection):LYNXDIRED://UNZIP%p
+
+# Following depends on OK_TAR and !ARCHIVE_ONLY
+#DIRED_MENU:FILE:.tar:UnTar:(current selection):LYNXDIRED://UNTAR%p
+
+# Following depends on OK_TAR
+#DIRED_MENU:DIR::Tar:(current selection):LYNXDIRED://TAR%p
+
+# Following depends on OK_TAR and OK_GZIP
+#DIRED_MENU:DIR::Tar and compress:(using GNU gzip):LYNXDIRED://TAR_GZ%p
+
+# Following depends on OK_ZIP
+#DIRED_MENU:DIR::Package and compress:(using zip):LYNXDIRED://ZIP%p
+
+#DIRED_MENU:FILE::Compress:(using Unix compress):LYNXDIRED://COMPRESS%p
+
+# Following depends on OK_GZIP
+#DIRED_MENU:FILE::Compress:(using gzip):LYNXDIRED://GZIP%p
+
+# Following depends on OK_ZIP
+#DIRED_MENU:FILE::Compress:(using zip):LYNXDIRED://ZIP%p
+
+#DIRED_MENU:TAG::Move all tagged items to another location.::LYNXDIRED://MOVE_TAGGED%d
+#DIRED_MENU:TAG::Remove all tagged files and directories.::LYNXDIRED://REMOVE_TAGGED
+#DIRED_MENU:TAG::Untag all tagged items.::LYNXDIRED://CLEAR_TAGGED
+
+# Unix ONLY:
+#===========
+# If NO_FORCED_CORE_DUMP is set to TRUE, Lynx will not force
+# core dumps via abort() calls on fatal errors or assert()
+# calls to check potentially fatal errors. The compilation
+# default normally is FALSE, and can be changed here. The
+# compilation or configuration default can be toggled via
+# the -core command line switch.
+# Note that this setting cannot be used to prevent core dumps
+# with certainty. If this is important, means provided by the
+# operating system or kernel should be used.
+#
+#NO_FORCED_CORE_DUMP:FALSE
+
+# COLORS (only available if compiled with SVr4 curses or slang)
+#
+# The line must be of the form:
+# COLOR:Integer:Foreground:Background
+#
+# The Integer value is interpreted as follows:
+# 0 - normal - normal text
+# 1 - bold - hyperlinks, see also BOLD_* options above
+# 2 - reverse - statusline
+# 3 - bold + reverse (not used)
+# 4 - underline - text emphasis (EM, I, B tags etc.)
+# 5 - bold + underline - hyperlinks within text emphasis
+# 6 - reverse + underline - currently selected hyperlink
+# 7 - reverse + underline + bold - WHEREIS search hits
+#
+# Each Foreground and Background value must be one of:
+# black red green brown
+# blue magenta cyan lightgray
+# gray brightred brightgreen yellow
+# brightblue brightmagenta brightcyan white
+#
+# Uncomment and change any of the compilation defaults.
+#
+#COLOR:0:black:white
+#COLOR:1:blue:white
+#COLOR:2:yellow:blue
+#COLOR:3:green:white
+#COLOR:4:magenta:white
+#COLOR:5:blue:white
+#COLOR:6:red:white
+#COLOR:7:magenta:cyan
+
+# External application support. This feature allows lynx to pass a given
+# URL to an external program. It was written for three reasons.
+#
+# 1) To overcome the deficiency of Lynx_386 not supporting ftp and news.
+# External programs can be used instead by passing the URL.
+#
+# 2) To allow for background transfers in multitasking systems.
+# I use wget for http and ftp transfers via the external command.
+#
+# 3) To allow for new URLs to be used through lynx.
+# URLs can be made up such as mymail: to spawn desired applications
+# via the external command.
+#
+# Restrictions can be imposed using -restrictions=externals at the lynx
+# command line. This will disallow all EXTERNAL lines in lynx.cfg that
+# end in FALSE. TRUE lines will still function.
+#
+# The lynx.cfg line is as follows:
+#
+# EXTERNAL:<url>:<command> %s:<norestriction>
+#
+# <url> Any given URL. This can be normal ones like ftp or http or it
+# can be one made up like mymail.
+#
+# <command> The command to run with %s being the URL that will be passed.
+# In Linux I use "wget -q %s &" (no quotes) to spawn a copy of wget for
+# downloading http and ftp files in the background. In Win95 I use
+# "start ncftp %s" to spawn ncftp in a new window.
+#
+# <norestriction> This complements the -restrictions=externals feature to allow
+# for certain externals to be enabled while restricting others. TRUE means
+# a command will still function while lynx is restricted. WB
+#
+# EXTERNAL:ftp:wget %s &:TRUE
+
+# Raw DOS Key hack
+# This will bypass the DOS key hack if is compiled in.
+# The hack is as follows:
+# if (c == 0) c = '/';
+# if (c > 255) { /* handle raw dos keys */
+# switch (c)
+# {
+# case 464: c = '-'; break; /* keypad minus*/
+# case 465: c = '+'; break; /* keypad plus*/
+# case 459: c = 13; break; /* keypad enter*/
+# case 463: c = '*'; break; /* keypad * */
+# case 440: c = 'Q'; break; /* alt x */
+# default: break;
+# }
+# }
+#
+# RAW_DOS_KEY_HACK = TRUE
+
diff --git a/gnu/usr.bin/lynx/samples/lynx.com b/gnu/usr.bin/lynx/samples/lynx.com
new file mode 100644
index 00000000000..568d3e22d1e
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/lynx.com
@@ -0,0 +1,59 @@
+$ ! LYNX.COM
+$ ! sets up lynx as a command so that it will accept command line arguments
+$ ! It is assumed that this file is located in the same place as the LYNX
+$ ! Image. If it is not then you must change the lynx symbol.
+$ ! Written by Danny Mayer, Digital Equipment Corporation
+$ !
+$ !
+$ THIS_PATH = F$PARSE(F$ENV("PROCEDURE"),,,"DEVICE") + -
+ F$PARSE(F$ENV("PROCEDURE"),,,"DIRECTORY")
+$ alpha = F$GETSYI("HW_MODEL") .GT. 1023
+$ !
+$ CPU := VAX
+$ IF alpha THEN CPU :== AXP
+$ lynx:==$'THIS_PATH'lynx_'CPU'.exe
+$!
+$! fill in another gateway if you wish
+$!
+$define "WWW_wais_GATEWAY" "http://www.w3.org:8001"
+$!
+$! fill in your NNTP news server here
+$!
+$ !define "NNTPSERVER" "news"
+$ !
+$ ! Set up the Proxy Information Here
+$ !
+$ ! no_proxy environmental variable
+$ ! The no_proxy environmental variable is checked to get the list of
+$ ! of hosts for which the proxy server is not consulted.
+$ ! NOTE: THE no_proxy VARIABLE MUST BE IN LOWER CASE. On VMS systems
+$ ! this is accomplished by defining a logical name in double-quotes.
+$ !
+$ ! The no_proxy environmental variable is a comma-separated or
+$ ! space-separated list of machine or domain names, with optional
+$ ! :port part. If no :port part is present, it applies to all ports
+$ ! on that domain.
+$ !
+$ ! Example:
+$ ! define "no_proxy" "cern.ch,some.domain:8001"
+$ !
+$ !
+$ define "no_proxy" "yourorg.com" ! Use only for outside of yourorg
+$ !
+$ ! proxy server environmental variables
+$ ! In Lynx, each protocol needs an environmental variable defined for
+$ ! it in order for it to use a proxy server set up for that protocol.
+$ ! The proxy environmental variable is of the form:
+$ ! protocol_proxy where protocol is the protocol name part of the URL,
+$ ! for example: http or ftp. NOTE: the protocol server proxy variable
+$ ! MUST BE IN LOWER CASE.
+$ ! Example:
+$ ! define "http_proxy" "http://your_proxy.yourorg:8080/"
+$ !
+$ Proxy_Server = "http://your_proxy.yourorg:8080/"
+$ define "http_proxy" "''Proxy_Server'"
+$ define "ftp_proxy" "''Proxy_Server'"
+$ define "gopher_proxy" "''Proxy_Server'"
+$ define "news_proxy" "''Proxy_Server'"
+$ define "wais_proxy" "''Proxy_Server'"
+$ !
diff --git a/gnu/usr.bin/lynx/samples/lynx.lss b/gnu/usr.bin/lynx/samples/lynx.lss
new file mode 100644
index 00000000000..771097629d5
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/lynx.lss
@@ -0,0 +1,60 @@
+#
+#it's best to put these in a .lss file and use "lynx -lss=file.lss whatever" for now.
+#
+#----/cut here for my styles/----
+# normal type styles, use bold if mono, otherwise brightblue on <defaultbackground>
+em:bold:brightblue
+strong:bold:brightred
+b:bold:red
+i:bold:blue
+alink:reverse:yellow:black
+a:bold:green
+img:dim:brown
+status:reverse:yellow:blue
+fig:normal:gray
+caption:reverse:brown
+hr:normal:yellow
+blockquote:normal:brightblue
+ul:normal:brown
+address:normal:magenta
+title:normal:magenta:default
+tt:dim:gray:blue
+h1:bold:yellow:blue
+label:normal:magenta
+value:normal:green
+high:bold:brightmagenta
+q:normal:yellow:magenta
+small:dim:gray
+big:bold:yellow
+sup:bold:yellow
+sub:dim:gray
+lh:bold:yellow:magenta
+
+# styles with classes <ul class=red> etc.
+ul.red:underline:brightred
+ul.blue:bold:brightblue
+li.red:reverse:red:yellow
+li:normal:magenta
+li.blue:bold:blue
+strong.a:bold:black:red
+em.a:reverse:black:blue
+strong.b:bold:white:red
+em.b:reverse:white:blue
+alert:bold:yellow:red
+strong.debug:reverse:green
+tr:bold:brown
+tr.baone:bold:yellow
+tr.batwo:bold:green
+tr.bathree:bold:red
+# special cases for link - the type is appended after the class
+link.green:bold:brightgreen
+# special cases for link - the rel is appended after the class
+# <link rel=next class=red href="1">
+link.red.next:bold:red
+link.red.prev:bold:yellow:red
+link.blue.prev:bold:yellow:blue
+link.blue.next:bold:blue
+link.red:bold:black:red
+link.blue:bold:white:blue
+link.toc:bold:black:white
+link.green.toc:bold:white:green
diff --git a/gnu/usr.bin/lynx/samples/mailcap b/gnu/usr.bin/lynx/samples/mailcap
new file mode 100644
index 00000000000..9dd36ccf8ac
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/mailcap
@@ -0,0 +1,99 @@
+# Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
+#
+# Permission to use, copy, modify, and distribute this material
+# for any purpose and without fee is hereby granted, provided
+# that the above copyright notice and this permission notice
+# appear in all copies, and that the name of Bellcore not be
+# used in advertising or publicity pertaining to this
+# material without the specific, prior written permission
+# of an authorized representative of Bellcore. BELLCORE
+# MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
+# OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
+# WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+#
+# Prototype Mailcap file
+# Note that support for text & multipart are "built in" to metamail,
+# as are rudimentary support for message, and application.
+# However, any of these may be overridden in mailcap.
+#
+# Note that users may override or extend this with a .mailcap
+# file in their own directory. However, there is NO NEED
+# for them to copy entries from this file, as metamail will
+# pick up entries from both the system and personal mailcap files.
+#
+
+# NOTE: This file has been heavily modified for use as an example
+# configuration file for Lynx
+
+# In the samples given test=test -n "$DISPLAY" is used to
+# determine if the current session is X capible by checking
+# for the existance of a DISPLAY environment variable.
+# Lynx actually uses a getenv() call for DISPLAY (DECW$DISPLAY
+# on VMS) when it encounters test=test -n "$DISPLAY" or
+# test=test -z "$DISPLAY" in a viewer assignment, instead of
+# spawning to execute "test" via a system() call, i.e., those
+# two strings, respectively, are handled equivalently to the
+# :XWINDOWS and :NON_XWINDOWS flags for VIEWER: assignments
+# in lynx.cfg. Any system without the DISPLAY (or DECW$DISPLAY)
+# environment variable will be assumed to be Non-X.
+
+# You can append a ';' followed by "q=#.#", e.g., ; q=0.002
+# to set the quality parameter for the Content-Type, which can be
+# included in the Accept: header Lynx sends to http servers (the
+# default quality value is 1.0, and Lynx appends the parameter
+# to the Content-Type only if the value is less than 1.0).
+
+# You can append a ';' followed by "mxb=#", e.g., ; mxb=1000000
+# to set the maxbytes parameter for the Content-Type, which can be
+# included in the Accept: header Lynx sends to http servers (the
+# default maxbytes value is 0, meaning no maximum, and Lynx appends
+# the parameter to the Content-Type only if the value exceeds 0).
+
+# The following line is for sites where xv understands jpeg but xloadimage
+# is preferred.
+#
+# the test line specifies that this viewer should only be used if
+# the display variable is set.
+image/jpeg; xv %s; test=test -n "$DISPLAY"
+
+# The following sends all other image subtypes to xloadimage
+#image/*; xloadimage %s; ; test=test -n "$DISPLAY"
+
+# The following sends all other image subtypes to xv
+image/*; xv %s; ; test=test -n "$DISPLAY"
+
+
+# If you have an interactive Postscript interpreter, you should think carefully
+# before replacing lpr with it in the following line, because PostScript
+# can be an enormous security hole. It is RELATIVELY harmless
+# when sent to the printer...
+
+# This one is for NON-X
+#application/postscript; lpr %s \; echo SENT FILE TO PRINTER; ;test=test -z "$DISPLAY"
+
+# This one is for X. It's already the default via src/HTInit.c.
+#application/postscript; ghostview %s; ; test=test -n "$DISPLAY"
+
+# The following should be commented out if you do NOT have safe-tcl
+# and should be uncommented if you DO have safe-tcl
+#application/safe-tcl; swish -safe -messaging -f %s
+
+# A common problem with the mailcap mechanism is getting differential
+# behavior from different programs. This problem is compounded by the fact
+# that some programs, notably Mosaic, do not implement the "test" clause in
+# mailcap files. If you are using Lynx and X Mosaic together you should
+# place all X-centric entries before non-X entries. X Mosaic will use
+# whichever entry is defined first so further entries will be ignored.
+#
+# Lynx exports the environment variable LYNX_VERSION, so it can be tested
+# by scripts to determine if Lynx is running or not. However, the string
+# test=test -n "$LYNX_VERSION"
+# is handled simply as a flag which yields success when Lynx encounters it
+# in the mailcap file (i.e., Lynx does not bother to execute "test" via a
+# system() call to find out if it's running, because it obviously is).
+# Inclusion of the string for that test can be used to prevent other
+# software which reads the mailcap file from acting on assignments intended
+# only for Lynx. The string
+# test=test -z "$LYNX_VERSION"
+# similarly is treated by Lynx simply as a flag which yields failure.
+
diff --git a/gnu/usr.bin/lynx/samples/mime.types b/gnu/usr.bin/lynx/samples/mime.types
new file mode 100644
index 00000000000..7f05e7abaeb
--- /dev/null
+++ b/gnu/usr.bin/lynx/samples/mime.types
@@ -0,0 +1,24 @@
+# example mime.types file.
+# see the NCSA X Mosaic documentation at
+# http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/extension-map.html
+# for more details
+
+application/postscript ai eps ps
+application/rtf rtf
+application/x-tex tex
+application/x-texinfo texinfo texi
+application/x-troff t tr roff
+audio/basic au snd
+audio/x-aiff aif aiff aifc
+audio/x-wav wav
+image/gif gif
+image/ief ief
+image/jpeg jpeg jpg jpe
+image/tiff tiff tif
+image/x-xwindowdump xwd
+text/html html
+text/plain txt c cc h
+video/mpeg mpeg mpg mpe
+video/quicktime qt mov
+video/x-msvideo avi
+video/x-sgi-movie movie
diff --git a/gnu/usr.bin/lynx/src/AttrList.h b/gnu/usr.bin/lynx/src/AttrList.h
new file mode 100644
index 00000000000..bc5710dbda6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/AttrList.h
@@ -0,0 +1,68 @@
+#if !defined(__ATTRLIST_H)
+#define __ATTRLIST_H
+
+#include "HText.h"
+#include "HTMLDTD.h"
+
+#define TEMPSTRINGSIZE 256
+
+enum {
+ ABS_OFF = 0,
+ STACK_OFF = 0,
+ STACK_ON,
+ ABS_ON
+};
+
+#define STARTAT 8
+
+enum {
+ DSTYLE_LINK = HTML_A+STARTAT,
+ DSTYLE_STATUS = HTML_ELEMENTS+STARTAT,
+ DSTYLE_ALINK, /* active link */
+ DSTYLE_NORMAL, /* default attributes */
+ DSTYLE_OPTION, /* option on the option screen */
+ DSTYLE_VALUE, /* value on the option screen */
+ DSTYLE_HIGH,
+ DSTYLE_CANDY, /* possibly going to vanish */
+ DSTYLE_ELEMENTS
+};
+
+enum {
+ MSTYLE_NORMAL = 0,
+ MSTYLE_EM = 1,
+ MSTYLE_STRONG = 2,
+ MSTYLE_PHYSICAL = 3,
+ MSTYLE_A = 4,
+ MSTYLE_A_OFF = 4,
+ MSTYLE_A_ON,
+ MSTYLE_BOLD,
+ MSTYLE_UL,
+ MSTYLE_STATUS,
+ MSTYLE_CANDY,
+ MSTYLE_NOMORE
+};
+
+typedef struct {
+ int color; /* color highlighting to be done */
+ int mono; /* mono highlighting to be done */
+ int cattr; /* attributes to go with the color */
+} HTCharStyle;
+
+#ifdef NOT_USED
+
+typedef struct _linkedlist {
+ char name[64];
+ struct _linkedlist *next;
+} linked_list;
+#endif
+
+#define HText_characterStyle if(TRACE)fprintf(stderr,"HTC called from %s/%d\n",__FILE__,__LINE__);_internal_HTC
+
+#undef HText_characterStyle
+#define HText_characterStyle _internal_HTC
+
+#if defined(USE_COLOR_STYLE)
+extern void _internal_HTC PARAMS((HText * text, int style, int dir));
+#endif
+
+#endif
diff --git a/gnu/usr.bin/lynx/src/DefaultStyle.c b/gnu/usr.bin/lynx/src/DefaultStyle.c
new file mode 100644
index 00000000000..7299ede1054
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/DefaultStyle.c
@@ -0,0 +1,401 @@
+/* A real style sheet for the Character Grid browser
+**
+** The dimensions are all in characters!
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTStyle.h"
+#include "HTFont.h"
+
+#include "LYLeaks.h"
+
+/* Tab arrays:
+*/
+PRIVATE CONST HTTabStop tabs_8[] = {
+ { 0, 8 }, {0, 16}, {0, 24}, {0, 32}, {0, 40},
+ { 0, 48 }, {0, 56}, {0, 64}, {0, 72}, {0, 80},
+ { 0, 88 }, {0, 96}, {0, 104}, {0, 112}, {0, 120},
+ { 0, 128 }, {0, 136}, {0, 144}, {0, 152}, {0, 160},
+ {0, 168}, {0, 176},
+ {0, 0 } /* Terminate */
+};
+
+#ifdef NOT_USED
+PRIVATE HTTabStop tabs_16[] = {
+ { 0, 16 }, {0, 32}, {0, 48}, {0, 64}, {0, 80},
+ {0, 96}, {0, 112},
+ {0, 0 } /* Terminate */
+};
+#endif /* NOT_USED */
+
+/* Template:
+** link to next, name, tag,
+** font, size, colour, superscript, anchor id,
+** indents: 1st, left, right, alignment lineheight, descent, tabs,
+** word wrap, free format, space: before, after, flags.
+*/
+
+PRIVATE HTStyle HTStyleNormal = {
+ 0, "Normal", "P",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 3, 6, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleDivCenter = {
+ &HTStyleNormal, "DivCenter", "DCENTER",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 3, 6, HT_CENTER, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleDivLeft = {
+ &HTStyleDivCenter, "DivLeft", "DLEFT",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 3, 6, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleDivRight = {
+ &HTStyleDivLeft, "DivRight", "DRIGHT",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 3, 6, HT_RIGHT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleBanner = {
+ &HTStyleDivRight, "Banner", "BANNER",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 3, 6, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleBlockquote = {
+ &HTStyleBanner, "Blockquote", "BLOCKQUOTE",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 5, 5, 7, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleBq = { /* HTML 3.0 BLOCKQUOTE - FM */
+ &HTStyleBlockquote, "Bq", "BQ",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 5, 5, 7, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleFootnote = { /* HTML 3.0 FN - FM */
+ &HTStyleBq, "Footnote", "FN",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 5, 5, 7, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleList = {
+ &HTStyleFootnote, "List", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 7, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList1 = {
+ &HTStyleList, "List1", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 8, 12, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList2 = {
+ &HTStyleList1, "List2", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 13, 17, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList3 = {
+ &HTStyleList2, "List3", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 18, 22, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList4 = {
+ &HTStyleList3, "List4", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 23, 27, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList5 = {
+ &HTStyleList4, "List5", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 28, 32, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleList6 = {
+ &HTStyleList5, "List6", "UL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 33, 37, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleMenu = {
+ &HTStyleList6, "Menu", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 7, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu1 = {
+ &HTStyleMenu, "Menu1", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 8, 12, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu2= {
+ &HTStyleMenu1, "Menu2", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 13, 17, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu3= {
+ &HTStyleMenu2, "Menu3", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 18, 22, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu4= {
+ &HTStyleMenu3, "Menu4", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 23, 27, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu5= {
+ &HTStyleMenu4, "Menu5", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 28, 33, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleMenu6= {
+ &HTStyleMenu5, "Menu6", "MENU",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 33, 38, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary = {
+ &HTStyleMenu6, "Glossary", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 10, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary1 = {
+ &HTStyleGlossary, "Glossary1", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 8, 16, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary2 = {
+ &HTStyleGlossary1, "Glossary2", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 14, 22, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary3 = {
+ &HTStyleGlossary2, "Glossary3", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 20, 28, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary4 = {
+ &HTStyleGlossary3, "Glossary4", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 26, 34, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary5 = {
+ &HTStyleGlossary4, "Glossary5", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 32, 40, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossary6 = {
+ &HTStyleGlossary5, "Glossary6", "DL",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 38, 46, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact = {
+ &HTStyleGlossary6, "GlossaryCompact", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 3, 10, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact1 = {
+ &HTStyleGlossaryCompact, "GlossaryCompact1", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 8, 15, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact2 = {
+ &HTStyleGlossaryCompact1, "GlossaryCompact2", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 13, 20, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact3 = {
+ &HTStyleGlossaryCompact2, "GlossaryCompact3", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 18, 25, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact4 = {
+ &HTStyleGlossaryCompact3, "GlossaryCompact4", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 23, 30, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact5 = {
+ &HTStyleGlossaryCompact4, "GlossaryCompact5", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 28, 35, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleGlossaryCompact6 = {
+ &HTStyleGlossaryCompact5, "GlossaryCompact6", "DLC",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 33, 40, 6, HT_LEFT, 1, 0, 0,
+ YES, YES, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleExample = {
+ &HTStyleGlossaryCompact6, "Example", "XMP",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, tabs_8,
+ NO, NO, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStylePreformatted = {
+ &HTStyleExample, "Preformatted", "PRE",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, tabs_8,
+ NO, NO, 0, 0, 0
+};
+
+PRIVATE HTStyle HTStyleListing = {
+ &HTStylePreformatted, "Listing", "LISTING",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, tabs_8,
+ NO, NO, 0, 0, 0 };
+
+PRIVATE HTStyle HTStyleAddress = {
+ &HTStyleListing, "Address", "ADDRESS",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 4, 4, 7, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 2, 0, 0 };
+
+PRIVATE HTStyle HTStyleNote = { /* HTML 3.0 NOTE - FM */
+ &HTStyleAddress, "Note", "NOTE",
+ HT_FONT, 1, HT_BLACK, 0, 0,
+ 5, 5, 7, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeading1 = {
+ &HTStyleNote, "Heading1", "H1",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_CENTER, 1, 0, 0,
+ YES, YES, 1, 1, 0 };
+
+PRIVATE HTStyle HTStyleHeading2 = {
+ &HTStyleHeading1, "Heading2", "H2",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 1, 0 };
+
+PRIVATE HTStyle HTStyleHeading3 = {
+ &HTStyleHeading2, "Heading3", "H3",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 2, 2, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeading4 = {
+ &HTStyleHeading3, "Heading4", "H4",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 4, 4, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeading5 = {
+ &HTStyleHeading4, "Heading5", "H5",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 6, 6, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeading6 = {
+ &HTStyleHeading5, "Heading6", "H6",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 8, 8, 0, HT_LEFT, 1, 0, 0,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeadingCenter = {
+ &HTStyleHeading6, "HeadingCenter", "HCENTER",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 0, 0, 3, HT_CENTER, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeadingLeft = {
+ &HTStyleHeadingCenter, "HeadingLeft", "HLEFT",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 0, 0, 3, HT_LEFT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+PRIVATE HTStyle HTStyleHeadingRight = {
+ &HTStyleHeadingLeft, "HeadingRight", "HRIGHT",
+ HT_FONT+HT_BOLD, 1, HT_BLACK, 0, 0,
+ 0, 0, 3, HT_RIGHT, 1, 0, tabs_8,
+ YES, YES, 1, 0, 0 };
+
+/* Style sheet points to the last in the list:
+*/
+PRIVATE HTStyleSheet sheet = { "default.style",
+ &HTStyleHeadingRight }; /* sheet */
+
+PUBLIC HTStyleSheet * DefaultStyle NOARGS
+{
+ static HTStyleSheet *result;
+ HTStyle *p, *q;
+
+ /*
+ * The first time we're called, allocate a copy of the 'sheet' linked
+ * list. Thereafter, simply copy the data from 'sheet' into our copy
+ * (preserving the copy's linked-list pointers). We do this to reset the
+ * parameters of a style that might be altered while processing a page.
+ */
+ if (result == 0) { /* allocate & copy */
+ result = HTStyleSheetNew ();
+ *result = sheet;
+ result->styles = 0;
+ for (p = sheet.styles; p != 0; p = p->next) {
+ q = HTStyleNew ();
+ *q = *p;
+ q->next = result->styles;
+ result->styles = q;
+ }
+ } else { /* recopy the data */
+ for (p = result->styles, q = sheet.styles;
+ p != 0 && q != 0;
+ p = p->next, q = q->next) {
+ HTStyle *r = p->next;
+ HTStyle temp;
+ temp = *p;
+ temp.next = q->next;
+ *p = *q;
+ p->next = r;
+ }
+ }
+ return result;
+}
diff --git a/gnu/usr.bin/lynx/src/GridText.c b/gnu/usr.bin/lynx/src/GridText.c
new file mode 100644
index 00000000000..160b5fe9850
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/GridText.c
@@ -0,0 +1,8267 @@
+/* Character grid hypertext object
+** ===============================
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTString.h"
+#include "HTFont.h"
+#include "HTAccess.h"
+#include "HTAnchor.h"
+#include "HTParse.h"
+#include "HTTP.h"
+#include "HTAlert.h"
+#include "HTCJK.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include <assert.h>
+#include <ctype.h>
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+#include <syslog.h>
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#include "GridText.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYStructs.h"
+#include "LYGlobalDefs.h"
+#include "LYGetFile.h"
+#include "LYSignal.h"
+#include "LYMail.h"
+#include "LYList.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h" /* LYUCTranslateBack... */
+#include "UCMap.h"
+#ifdef EXP_CHARTRANS_AUTOSWITCH
+#include "UCAuto.h"
+#endif /* EXP_CHARTRANS_AUTOSWITCH */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+#include "LYHash.h"
+
+unsigned int cached_styles[CACHEH][CACHEW];
+
+#endif
+
+#ifdef USE_COLOR_STYLE_UNUSED
+void LynxClearScreenCache NOARGS
+{
+ int i,j;
+if (TRACE)
+ fprintf(stderr, "flushing cached screen styles\n");
+ for (i=0;i<CACHEH;i++)
+ for (j=0;j<CACHEW;j++)
+ cached_styles[i][j]=s_a;
+}
+#endif /* USE_COLOR_STYLE */
+
+struct _HTStream { /* only know it as object */
+ CONST HTStreamClass * isa;
+ /* ... */
+};
+
+#define TITLE_LINES 1
+#define IS_UTF_EXTRA(ch) (text->T.output_utf8 && \
+ ((unsigned char)(ch)&0xc0) == 0x80)
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern BOOL HTPassHighCtrlRaw;
+extern HTkcode kanji_code;
+extern HTCJKlang HTCJK;
+
+/* Exports
+*/
+PUBLIC HText * HTMainText = NULL; /* Equivalent of main window */
+PUBLIC HTParentAnchor * HTMainAnchor = NULL; /* Anchor for HTMainText */
+
+PUBLIC char * HTAppName = "Lynx"; /* Application name */
+PUBLIC char * HTAppVersion = LYNX_VERSION; /* Application version */
+
+PUBLIC int HTFormNumber = 0;
+PUBLIC int HTFormFields = 0;
+PUBLIC char * HTCurSelectGroup = NULL; /* Form select group name */
+PRIVATE int HTCurSelectGroupCharset = -1; /* ... and name's charset */
+PUBLIC int HTCurSelectGroupType = F_RADIO_TYPE; /* Group type */
+PUBLIC char * HTCurSelectGroupSize = NULL; /* Length of select */
+PRIVATE char * HTCurSelectedOptionValue = NULL; /* Select choice */
+
+PUBLIC char * checked_box = "[X]";
+PUBLIC char * unchecked_box = "[ ]";
+PUBLIC char * checked_radio = "(*)";
+PUBLIC char * unchecked_radio = "( )";
+
+PUBLIC BOOLEAN underline_on = OFF;
+PUBLIC BOOLEAN bold_on = OFF;
+
+#if defined(USE_COLOR_STYLE)
+#define MAX_STYLES_ON_LINE 64
+
+typedef struct _stylechange {
+ int horizpos; /* horizontal position of this change */
+ int style; /* which style to change to */
+ int direction; /* on or off */
+ int previous; /* previous style */
+} HTStyleChange;
+#endif
+
+typedef struct _line {
+ struct _line *next;
+ struct _line *prev;
+ int unsigned offset; /* Implicit initial spaces */
+ int unsigned size; /* Number of characters */
+ BOOL split_after; /* Can we split after? */
+ BOOL bullet; /* Do we bullet? */
+#if defined(USE_COLOR_STYLE)
+ HTStyleChange styles[MAX_STYLES_ON_LINE];
+ int numstyles;
+#endif
+ char data[1]; /* Space for terminator at least! */
+} HTLine;
+
+#define LINE_SIZE(l) (sizeof(HTLine)+(l)) /* Allow for terminator */
+
+typedef struct _TextAnchor {
+ struct _TextAnchor * next;
+ int number; /* For user interface */
+ int start; /* Characters */
+ int line_pos; /* Position in text */
+ int extent; /* Characters */
+ int line_num; /* Place in document */
+ char * hightext; /* The link text */
+ char * hightext2; /* A second line*/
+ int hightext2offset;/* offset from left */
+ int link_type; /* Normal, internal, or form? */
+ FormInfo * input_field; /* Info for form links */
+ BOOL show_anchor; /* Show the anchor? */
+ BOOL inUnderline; /* context is underlined */
+ HTChildAnchor * anchor;
+} TextAnchor;
+
+typedef struct _HTTabID {
+ char * name; /* ID value of TAB */
+ int column; /* Zero-based column value */
+} HTTabID;
+
+
+/* Notes on struct _Htext:
+** next_line is valid if state is false.
+** top_of_screen line means the line at the top of the screen
+** or just under the title if there is one.
+*/
+struct _HText {
+ HTParentAnchor * node_anchor;
+ HTLine * last_line;
+ int Lines; /* Number of them */
+ int chars; /* Number of them */
+ TextAnchor * first_anchor; /* Singly linked list */
+ TextAnchor * last_anchor;
+ HTList * forms; /* also linked internally */
+ int last_anchor_number; /* user number */
+ BOOL source; /* Is the text source? */
+ BOOL toolbar; /* Toolbar set? */
+ HTList * tabs; /* TAB IDs */
+ HTList * hidden_links; /* Content-less links ... */
+ int hiddenlinkflag; /* ... and how to treat them */
+ BOOL no_cache; /* Always refresh? */
+ char LastChar; /* For absorbing white space */
+ BOOL IgnoreExcess; /* Ignore chars at wrap point */
+
+/* For Internal use: */
+ HTStyle * style; /* Current style */
+ int display_on_the_fly; /* Lines left */
+ int top_of_screen; /* Line number */
+ HTLine * top_of_screen_line; /* Top */
+ HTLine * next_line; /* Bottom + 1 */
+ int permissible_split; /* in last line */
+ BOOL in_line_1; /* of paragraph */
+ BOOL stale; /* Must refresh */
+ BOOL page_has_target; /* has target on screen */
+
+ HTkcode kcode; /* Kanji code? */
+ enum grid_state { S_text, S_esc, S_dollar, S_paren,
+ S_nonascii_text, S_dollar_paren,
+ S_jisx0201_text }
+ state; /* Escape sequence? */
+ char kanji_buf; /* Lead multibyte */
+ int in_sjis; /* SJIS flag */
+ int halted; /* emergency halt */
+
+ BOOL have_8bit_chars; /* Any non-ASCII chars? */
+ LYUCcharset * UCI; /* node_anchor UCInfo */
+ int UCLYhndl; /* charset we are fed */
+ UCTransParams T;
+
+ HTStream * target; /* Output stream */
+ HTStreamClass targetClass; /* Output routines */
+};
+
+PRIVATE void HText_AddHiddenLink PARAMS((HText *text, TextAnchor *textanchor));
+
+/*
+ * Boring static variable used for moving cursor across
+ */
+#define UNDERSCORES(n) \
+ ((n) >= MAX_LINE ? underscore_string : &underscore_string[(MAX_LINE-1)] - (n))
+
+/*
+ * Memory leak fixed.
+ * 05-29-94 Lynx 2-3-1 Garrett Arch Blythe
+ * Changed to arrays.
+ */
+PRIVATE char underscore_string[MAX_LINE + 1];
+PUBLIC char star_string[MAX_LINE + 1];
+
+PRIVATE int ctrl_chars_on_this_line = 0; /* num of ctrl chars in current line */
+
+PRIVATE HTStyle default_style =
+ { 0, "(Unstyled)", "",
+ (HTFont)0, 1, HT_BLACK, 0, 0,
+ 0, 0, 0, HT_LEFT, 1, 0, 0,
+ NO, NO, 0, 0, 0 };
+
+
+
+PRIVATE HTList * loaded_texts = NULL; /* A list of all those in memory */
+PUBLIC HTList * search_queries = NULL; /* isindex and whereis queries */
+PRIVATE void free_all_texts NOARGS;
+PRIVATE int HText_TrueLineSize PARAMS((
+ HTLine * line,
+ HText * text,
+ BOOL IgnoreSpaces));
+
+#ifndef VMS /* VMS has a better way - right? - kw */
+#define CHECK_FREE_MEM
+#endif
+
+#ifdef CHECK_FREE_MEM
+
+/*
+ * text->halted = 1: have set fake 'Z' and output a message
+ * 2: next time when HText_appendCharacter is called
+ * it will append *** MEMORY EXHAUSTED ***, then set
+ * to 3.
+ * 3: normal text output will be suppressed (but not anchors,
+ * form fields etc.)
+ */
+PRIVATE void HText_halt NOARGS
+{
+ if (HTFormNumber > 0)
+ HText_DisableCurrentForm();
+ if (!HTMainText)
+ return;
+ if (HTMainText->halted < 2)
+ HTMainText->halted = 2;
+}
+
+#define MIN_NEEDED_MEM 5000
+
+/*
+ * Check whether factor*min(bytes,MIN_NEEDED_MEM) is available,
+ * or bytes if factor is 0.
+ * MIN_NEEDED_MEM and factor together represent a security margin,
+ * to take account of all the memory allocations where we don't check
+ * and of buffers which may be emptied before HTCheckForInterupt()
+ * is (maybe) called and other things happening, with some chance of
+ * success.
+ * This just tries to malloc() the to-be-checked-for amount of memory,
+ * which might make the situation worse depending how allocation works.
+ * There should be a better way... - kw
+ */
+PRIVATE BOOL mem_is_avail ARGS2(
+ size_t, factor,
+ size_t, bytes)
+{
+ void *p;
+ if (bytes < MIN_NEEDED_MEM && factor > 0)
+ bytes = MIN_NEEDED_MEM;
+ if (factor == 0)
+ factor = 1;
+ p = malloc(factor * bytes);
+ if (p) {
+ FREE(p);
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
+/*
+ * Replacement for calloc which checks for "enough" free memory
+ * (with some security margins) and tries various recovery actions
+ * if deemed necessary. - kw
+ */
+PRIVATE void * LY_check_calloc ARGS2(
+ size_t, nmemb,
+ size_t, size)
+{
+ int i, n;
+ if (mem_is_avail(4, nmemb * size)) {
+ return (calloc(nmemb, size));
+ }
+ n = HTList_count(loaded_texts);
+ for (i = n - 1; i > 0; i--) {
+ HText * t = HTList_objectAt(loaded_texts, i);
+ if (t == HTMainText)
+ t = NULL; /* shouldn't happen */
+ if (TRACE) {
+ fprintf(stderr,
+ "\r *** Emergency freeing document %d/%d for '%s'%s!\n",
+ i + 1, n,
+ ((t && t->node_anchor &&
+ t->node_anchor->address) ?
+ t->node_anchor->address : "unknown anchor"),
+ ((t && t->node_anchor &&
+ t->node_anchor->post_data) ?
+ " with POST data" : ""));
+ }
+ HTList_removeObjectAt(loaded_texts, i);
+ HText_free(t);
+ if (mem_is_avail(4, nmemb * size)) {
+ return (calloc(nmemb, size));
+ }
+ }
+ LYFakeZap(YES);
+ if (!HTMainText || HTMainText->halted <= 1) {
+ if (!mem_is_avail(2, nmemb * size)) {
+ HText_halt();
+ if (mem_is_avail(0, 700)) {
+ HTAlert("Memory exhausted, display interrupted!");
+ }
+ } else {
+ if ((!HTMainText || HTMainText->halted == 0) &&
+ mem_is_avail(0, 700)) {
+ HTAlert("Memory exhausted, will interrupt transfer!");
+ if (HTMainText)
+ HTMainText->halted = 1;
+ }
+ }
+ }
+ return (calloc(nmemb, size));
+}
+
+#define LY_CALLOC LY_check_calloc
+
+#else /* CHECK_FREE_MEM */
+
+ /* using the regular calloc */
+#define LY_CALLOC calloc
+
+#endif /* CHECK_FREE_MEM */
+
+PRIVATE void HText_getChartransInfo ARGS1(
+ HText *, me)
+{
+ me->UCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor, UCT_STAGE_HTEXT);
+ if (me->UCLYhndl < 0) {
+ int chndl = current_char_set;
+ HTAnchor_setUCInfoStage(me->node_anchor, chndl,
+ UCT_STAGE_HTEXT, UCT_SETBY_STRUCTURED);
+ me->UCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_HTEXT);
+ }
+ me->UCI = HTAnchor_getUCInfoStage(me->node_anchor, UCT_STAGE_HTEXT);
+}
+
+PRIVATE void PerFormInfo_free ARGS1(
+ PerFormInfo *, form)
+{
+ if (form) {
+ FREE(form->accept_cs);
+ FREE(form->thisacceptcs);
+ FREE(form);
+ }
+}
+
+PRIVATE void FormList_delete ARGS1(
+ HTList *, forms)
+{
+ HTList *cur = forms;
+ PerFormInfo *form;
+ while ((form = (PerFormInfo *)HTList_nextObject(cur)) != NULL)
+ PerFormInfo_free(form);
+ HTList_delete(forms);
+}
+
+/* Creation Method
+** ---------------
+*/
+PUBLIC HText * HText_new ARGS1(
+ HTParentAnchor *, anchor)
+{
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+#include <lib$routines.h>
+ int status, VMType=3, VMTotal;
+#endif /* VMS && VAXC && !__DECC */
+ HTLine * line = NULL;
+ HText * self = (HText *) calloc(1, sizeof(*self));
+ if (!self)
+ return self;
+
+#if defined(VMS) && defined (VAXC) && !defined(__DECC)
+ status = lib$stat_vm(&VMType, &VMTotal);
+ if (TRACE)
+ fprintf(stderr, "GridText: VMTotal = %d\n", VMTotal);
+#endif /* VMS && VAXC && !__DECC */
+
+ if (!loaded_texts) {
+ loaded_texts = HTList_new();
+ atexit(free_all_texts);
+ }
+
+ /*
+ * Links between anchors & documents are a 1-1 relationship. If
+ * an anchor is already linked to a document we didn't call
+ * HTuncache_current_document(), e.g., for the showinfo, options,
+ * download, print, etc., temporary file URLs, so we'll check now
+ * and free it before reloading. - Dick Wesseling (ftu@fi.ruu.nl)
+ */
+ if (anchor->document) {
+ HTList_removeObject(loaded_texts, anchor->document);
+ if (TRACE)
+ fprintf(stderr, "GridText: Auto-uncaching\n") ;
+ ((HText *)anchor->document)->node_anchor = NULL;
+ HText_free((HText *)anchor->document);
+ anchor->document = NULL;
+ }
+
+ HTList_addObject(loaded_texts, self);
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+ while (HTList_count(loaded_texts) > HTCacheSize &&
+ VMTotal > HTVirtualMemorySize) {
+#else
+ if (HTList_count(loaded_texts) > HTCacheSize) {
+#endif /* VMS && VAXC && !__DECC */
+ if (TRACE)
+ fprintf(stderr, "GridText: Freeing off cached doc.\n");
+ HText_free((HText *)HTList_removeFirstObject(loaded_texts));
+#if defined(VMS) && defined (VAXC) && !defined(__DECC)
+ status = lib$stat_vm(&VMType, &VMTotal);
+ if (TRACE)
+ fprintf(stderr, "GridText: VMTotal reduced to %d\n", VMTotal);
+#endif /* VMS && VAXC && !__DECC */
+ }
+
+ line = self->last_line = (HTLine *)calloc(1, LINE_SIZE(MAX_LINE));
+ if (line == NULL)
+ outofmem(__FILE__, "HText_New");
+ line->next = line->prev = line;
+ line->offset = line->size = 0;
+#ifdef USE_COLOR_STYLE
+ line->numstyles = 0;
+#endif
+ self->Lines = self->chars = 0;
+ self->first_anchor = self->last_anchor = NULL;
+ self->style = &default_style;
+ self->top_of_screen = 0;
+ self->node_anchor = anchor;
+ self->last_anchor_number = 0; /* Numbering of them for references */
+ self->stale = YES;
+ self->toolbar = NO;
+ self->tabs = NULL;
+ /*
+ * If we are going to render the List Page, always merge in hidden
+ * links to get the numbering consistent if form fields are numbered
+ * and show up as hidden links in the list of links. - kw
+ */
+ if (anchor->address && !strcmp(anchor->address, LYlist_temp_url()))
+ self->hiddenlinkflag = HIDDENLINKS_MERGE;
+ else
+ self->hiddenlinkflag = LYHiddenLinks;
+ self->hidden_links = NULL;
+ self->no_cache = ((anchor->no_cache || anchor->post_data) ?
+ YES : NO);
+ self->LastChar = '\0';
+ self->IgnoreExcess = FALSE;
+
+ if (HTOutputFormat == WWW_SOURCE)
+ self->source = YES;
+ else
+ self->source = NO;
+ HTAnchor_setDocument(anchor, (HyperDoc *)self);
+ HTFormNumber = 0; /* no forms started yet */
+ HTMainText = self;
+ HTMainAnchor = anchor;
+ self->display_on_the_fly = 0;
+ self->kcode = NOKANJI;
+ self->state = S_text;
+ self->kanji_buf = '\0';
+ self->in_sjis = 0;
+ self->have_8bit_chars = NO;
+ HText_getChartransInfo(self);
+ UCSetTransParams(&self->T,
+ self->UCLYhndl, self->UCI,
+ current_char_set,
+ &LYCharSet_UC[current_char_set]);
+
+ /*
+ * Check the kcode setting if the anchor has a charset element. - FM
+ */
+ if (anchor->charset)
+ HText_setKcode(self, anchor->charset,
+ HTAnchor_getUCInfoStage(anchor, UCT_STAGE_HTEXT));
+
+ /*
+ * Memory leak fixed.
+ * 05-29-94 Lynx 2-3-1 Garrett Arch Blythe
+ * Check to see if our underline and star_string need initialization
+ * if the underline is not filled with dots.
+ */
+ if (underscore_string[0] != '.') {
+ /*
+ * Create an array of dots for the UNDERSCORES macro. - FM
+ */
+ memset(underscore_string, '.', (MAX_LINE-1));
+ underscore_string[(MAX_LINE-1)] = '\0';
+ underscore_string[MAX_LINE] = '\0';
+ /*
+ * Create an array of underscores for the STARS macro. - FM
+ */
+ memset(star_string, '_', (MAX_LINE-1));
+ star_string[(MAX_LINE-1)] = '\0';
+ star_string[MAX_LINE] = '\0';
+ }
+
+ underline_on = FALSE; /* reset */
+ bold_on = FALSE;
+
+ return self;
+}
+
+/* Creation Method 2
+** ---------------
+**
+** Stream is assumed open and left open.
+*/
+PUBLIC HText * HText_new2 ARGS2(
+ HTParentAnchor *, anchor,
+ HTStream *, stream)
+
+{
+ HText * this = HText_new(anchor);
+
+ if (stream) {
+ this->target = stream;
+ this->targetClass = *stream->isa; /* copy action procedures */
+ }
+ return this;
+}
+
+/* Free Entire Text
+** ----------------
+*/
+PUBLIC void HText_free ARGS1(
+ HText *, self)
+{
+ if (!self)
+ return;
+
+ HTAnchor_setDocument(self->node_anchor, (HyperDoc *)0);
+
+ while (YES) { /* Free off line array */
+ HTLine * l = self->last_line;
+ if (l) {
+ l->next->prev = l->prev;
+ l->prev->next = l->next; /* Unlink l */
+ self->last_line = l->prev;
+ if (l != self->last_line) {
+ FREE(l);
+ } else {
+ free(l);
+ }
+ }
+ if (l == self->last_line) { /* empty */
+ l = NULL;
+ break;
+ }
+ };
+
+ while (self->first_anchor) { /* Free off anchor array */
+ TextAnchor * l = self->first_anchor;
+ self->first_anchor = l->next;
+
+ if (l->link_type == INPUT_ANCHOR && l->input_field) {
+ /*
+ * Free form fields.
+ */
+ if (l->input_field->type == F_OPTION_LIST_TYPE &&
+ l->input_field->select_list != NULL) {
+ /*
+ * Free off option lists if present.
+ * It should always be present for F_OPTION_LIST_TYPE
+ * unless we had invalid markup which prevented
+ * HText_setLastOptionValue from finishing its job
+ * and left the input field in an insane state. - kw
+ */
+ OptionType *optptr = l->input_field->select_list;
+ OptionType *tmp;
+ while (optptr) {
+ tmp = optptr;
+ optptr = tmp->next;
+ FREE(tmp->name);
+ FREE(tmp->cp_submit_value);
+ FREE(tmp);
+ }
+ l->input_field->select_list = NULL;
+ /*
+ * Don't free the value field on option
+ * lists since it points to a option value
+ * same for orig value.
+ */
+ l->input_field->value = NULL;
+ l->input_field->orig_value = NULL;
+ l->input_field->cp_submit_value = NULL;
+ l->input_field->orig_submit_value = NULL;
+ } else {
+ FREE(l->input_field->value);
+ FREE(l->input_field->orig_value);
+ FREE(l->input_field->cp_submit_value);
+ FREE(l->input_field->orig_submit_value);
+ }
+ FREE(l->input_field->name);
+ FREE(l->input_field->submit_action);
+ FREE(l->input_field->submit_enctype);
+ FREE(l->input_field->submit_title);
+
+ FREE(l->input_field->accept_cs);
+
+ FREE(l->input_field);
+ }
+
+ FREE(l->hightext);
+ FREE(l->hightext2);
+
+ FREE(l);
+ }
+ FormList_delete(self->forms);
+
+ /*
+ * Free the tabs list. - FM
+ */
+ if (self->tabs) {
+ HTTabID * Tab = NULL;
+ HTList * cur = self->tabs;
+
+ while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) {
+ FREE(Tab->name);
+ FREE(Tab);
+ }
+ HTList_delete(self->tabs);
+ self->tabs = NULL;
+ }
+
+ /*
+ * Free the hidden links list. - FM
+ */
+ if (self->hidden_links) {
+ char * href = NULL;
+ HTList * cur = self->hidden_links;
+
+ while (NULL != (href = (char *)HTList_nextObject(cur)))
+ FREE(href);
+ HTList_delete(self->hidden_links);
+ self->hidden_links = NULL;
+ }
+
+ /*
+ * Invoke HTAnchor_delete() to free the node_anchor
+ * if it is not a destination of other links. - FM
+ */
+ if (self->node_anchor) {
+ HTAnchor_resetUCInfoStage(self->node_anchor, -1, UCT_STAGE_STRUCTURED,
+ UCT_SETBY_NONE);
+ HTAnchor_resetUCInfoStage(self->node_anchor, -1, UCT_STAGE_HTEXT,
+ UCT_SETBY_NONE);
+ if (HTAnchor_delete(self->node_anchor))
+ /*
+ * Make sure HTMainAnchor won't point
+ * to an invalid structure. - KW
+ */
+ HTMainAnchor = NULL;
+ }
+
+ FREE(self);
+}
+
+/* Display Methods
+** ---------------
+*/
+
+
+/* Output a line
+** -------------
+*/
+PRIVATE int display_line ARGS2(
+ HTLine *, line,
+ HText *, text)
+{
+ register int i, j;
+ char buffer[7];
+ char *data;
+ size_t utf_extra = 0;
+#ifdef USE_COLOR_STYLE
+ int current_style = 0;
+#endif
+ char LastDisplayChar = ' ';
+
+ /*
+ * Set up the multibyte character buffer,
+ * and clear the line to which we will be
+ * writing.
+ */
+ buffer[0] = buffer[1] = buffer[2] = '\0';
+ clrtoeol();
+
+ /*
+ * Add offset, making sure that we do not
+ * go over the COLS limit on the display.
+ */
+ j = (int)line->offset;
+ if (j > (int)LYcols - 1)
+ j = (int)LYcols - 1;
+#ifdef USE_SLANG
+ SLsmg_forward (j);
+ i = j;
+#else
+#ifdef USE_COLOR_STYLE
+ if (line->size == 0)
+ i = j;
+ else
+#endif
+ for (i = 0; i < j; i++)
+ addch (' ');
+#endif /* USE_SLANG */
+
+ /*
+ * Add the data, making sure that we do not
+ * go over the COLS limit on the display.
+ */
+ data = line->data;
+ i++;
+ while ((i < LYcols) && ((buffer[0] = *data) != '\0')) {
+ data++;
+
+#if defined(USE_COLOR_STYLE) || defined(SLSC)
+#define CStyle line->styles[current_style]
+
+ while (current_style < line->numstyles &&
+ i >= CStyle.horizpos + line->offset + 1)
+ {
+ (void) LynxChangeStyle (CStyle.style,CStyle.direction,CStyle.previous);
+ current_style++;
+ }
+#endif
+ switch (buffer[0]) {
+
+#ifndef USE_COLOR_STYLE
+ case LY_UNDERLINE_START_CHAR:
+ if (dump_output_immediately && use_underscore) {
+ addch('_');
+ i++;
+ } else {
+ start_underline();
+ }
+ break;
+
+ case LY_UNDERLINE_END_CHAR:
+ if (dump_output_immediately && use_underscore) {
+ addch('_');
+ i++;
+ } else {
+ stop_underline();
+ }
+ break;
+
+ case LY_BOLD_START_CHAR:
+ start_bold();
+ break;
+
+ case LY_BOLD_END_CHAR:
+ stop_bold ();
+ break;
+#endif
+
+ case LY_SOFT_HYPHEN:
+ if (*data != '\0' ||
+ isspace((unsigned char)LastDisplayChar) ||
+ LastDisplayChar == '-') {
+ /*
+ * Ignore the soft hyphen if it is not the last
+ * character in the line. Also ignore it if it
+ * first character following the margin, or if it
+ * is preceded by a white character (we loaded 'M'
+ * into LastDisplayChar if it was a multibyte
+ * character) or hyphen, though it should have
+ * been excluded by HText_appendCharacter() or by
+ * split_line() in those cases. - FM
+ */
+ break;
+ } else {
+ /*
+ * Make it a hard hyphen and fall through. - FM
+ */
+ buffer[0] = '-';
+ i++;
+ }
+
+ default:
+ i++;
+ if (text->T.output_utf8 && !isascii(buffer[0])) {
+ if ((*buffer & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*buffer & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*buffer & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*buffer & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*buffer & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(data) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ LastDisplayChar = 'M';
+ }
+ if (utf_extra) {
+ strncpy(&buffer[1], data, utf_extra);
+ buffer[utf_extra+1] = '\0';
+ addstr(buffer);
+ buffer[1] = '\0';
+ data += utf_extra;
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(buffer[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ buffer[1] = *data;
+ data++;
+ addstr(buffer);
+ buffer[1] = '\0';
+ /*
+ * For now, load 'M' into LastDisplayChar,
+ * but we should check whether it's white
+ * and if so, use ' '. I don't know if
+ * there actually are white CJK characters,
+ * and we're loading ' ' for multibyte
+ * spacing characters in this code set,
+ * but this will become an issue when
+ * the development code set's multibyte
+ * character handling is used. - FM
+ */
+ LastDisplayChar = 'M';
+ } else {
+ addstr(buffer);
+ LastDisplayChar = buffer[0];
+ }
+ } /* end of switch */
+ } /* end of while */
+
+ /*
+ * Add the return.
+ */
+ addch('\n');
+
+#ifndef USE_COLOR_STYLE
+ stop_underline();
+ stop_bold();
+#else
+ while (current_style < line->numstyles)
+ {
+ (void) LynxChangeStyle (CStyle.style, CStyle.direction, CStyle.previous);
+ current_style++;
+ }
+#undef CStyle
+#endif
+ return(0);
+}
+
+/* Output the title line
+** ---------------------
+*/
+PRIVATE void display_title ARGS1(
+ HText *, text)
+{
+ char *title = NULL;
+ char percent[20];
+ char *cp = NULL;
+ unsigned char *tmp = NULL;
+ int i = 0, j = 0;
+
+ /*
+ * Make sure we have a text structure. - FM
+ */
+ if (!text)
+ return;
+
+ lynx_start_title_color ();
+#ifdef USE_COLOR_STYLE
+/* turn the TITLE style on */
+ LynxChangeStyle(s_title, ABS_ON, 0);
+#endif /* USE_COLOR_STYLE */
+
+ /*
+ * Load the title field. - FM
+ */
+ StrAllocCopy(title,
+ (HTAnchor_title(text->node_anchor) ?
+ HTAnchor_title(text->node_anchor) : ""));
+
+ /*
+ * There shouldn't be any \n in the title field,
+ * but if there is, lets kill it now. Also trim
+ * any trailing spaces. - FM
+ */
+ if ((cp = strchr(title,'\n')) != NULL)
+ *cp = '\0';
+ i = (*title ? (strlen(title) - 1) : 0);
+ while ((i >= 0) && title[i] == ' ')
+ title[i--] = '\0';
+
+ /*
+ * Generate the page indicator (percent) string.
+ */
+ if ((text->Lines + 1) > (display_lines)) {
+ /*
+ * In a small attempt to correct the number of pages counted....
+ * GAB 07-14-94
+ *
+ * In a bigger attempt (hope it holds up 8-)....
+ * FM 02-08-95
+ */
+ int total_pages =
+ (((text->Lines + 1) + (display_lines - 1))/(display_lines));
+ int start_of_last_page =
+ ((text->Lines + 1) < display_lines) ? 0 :
+ ((text->Lines + 1) - display_lines);
+
+ sprintf(percent, " (p%d of %d)",
+ ((text->top_of_screen >= start_of_last_page) ?
+ total_pages :
+ ((text->top_of_screen + display_lines)/(display_lines))),
+ total_pages);
+ } else {
+ percent[0] = '\0'; /* Null string */
+ }
+
+ /*
+ * Generate and display the title string, with page indicator
+ * if appropriate, preceded by the toolbar token if appropriate,
+ * and truncated if necessary. - FM & KW
+ */
+ if (HTCJK != NOCJK) {
+ if (*title &&
+ (tmp = (unsigned char *)calloc(1, (strlen(title) + 1)))) {
+ if (kanji_code == EUC) {
+ TO_EUC((unsigned char *)title, tmp);
+ } else if (kanji_code == SJIS) {
+ TO_SJIS((unsigned char *)title, tmp);
+ } else {
+ for (i = 0, j = 0; title[i]; i++) {
+ if (title[i] != '\033') {
+ tmp[j++] = title[i];
+ }
+ }
+ tmp[j] = '\0';
+ }
+ StrAllocCopy(title, (CONST char *)tmp);
+ FREE(tmp);
+ }
+ }
+ move(0, 0);
+ clrtoeol();
+ if (text->top_of_screen > 0 && HText_hasToolbar(text)) {
+ addch('#');
+ }
+ i = (LYcols - 1) - strlen(percent) - strlen(title);
+ if (i > 0) {
+ move(0, i);
+ } else {
+ /*
+ * Note that this truncation is not taking into
+ * account the possibility that multibyte
+ * characters might be present. - FM
+ */
+ title[((LYcols - 2) - strlen(percent))] = '\0';
+ move(0, 1);
+ }
+ addstr(title);
+ if (percent[0] != '\0')
+ addstr(percent);
+ addch('\n');
+ FREE(title);
+
+#ifdef USE_COLOR_STYLE
+/* turn the TITLE style off */
+ LynxChangeStyle(s_title, ABS_OFF, 0);
+#endif /* USE_COLOR_STYLE */
+ lynx_stop_title_color ();
+
+ return;
+}
+
+/* Output a page
+** -------------
+*/
+PRIVATE void display_page ARGS3(
+ HText *, text,
+ int, line_number,
+ char *, target)
+{
+ HTLine * line = NULL;
+ int i;
+ char *cp, tmp[7];
+ int last_screen;
+ TextAnchor *Anchor_ptr = NULL;
+ FormInfo *FormInfo_ptr;
+ BOOL display_flag = FALSE;
+ HTAnchor *link_dest;
+ HTAnchor *link_dest_intl = NULL;
+ static int last_nlinks = 0;
+ static int charset_last_displayed = -1;
+
+ lynx_mode = NORMAL_LYNX_MODE;
+
+ if (text == NULL) {
+ /*
+ * Check whether to force a screen clear to enable scrollback,
+ * or as a hack to fix a reverse clear screen problem for some
+ * curses packages. - shf@access.digex.net & seldon@eskimo.com
+ */
+ if (enable_scrollback) {
+ addch('*');
+ refresh();
+ clear();
+ }
+ addstr("\n\nError accessing document!\nNo data available!\n");
+ refresh();
+ nlinks = 0; /* set number of links to 0 */
+ return;
+ }
+
+ tmp[0] = tmp[1] = tmp[2] = '\0';
+ text->page_has_target = NO;
+ last_screen = text->Lines - (display_lines - 2);
+ line = text->last_line->prev;
+
+ /*
+ * Constrain the line number to be within the document.
+ */
+ if (text->Lines < (display_lines))
+ line_number = 0;
+ else if (line_number > text->Lines)
+ line_number = last_screen;
+ else if (line_number < 0)
+ line_number = 0;
+
+ for (i = 0, line = text->last_line->next; /* Find line */
+ i < line_number && (line != text->last_line);
+ i++, line = line->next) { /* Loop */
+#ifndef VMS
+ if (!LYNoCore) {
+ assert(line->next != NULL);
+ } else if (line->next == NULL) {
+ if (enable_scrollback) {
+ addch('*');
+ refresh();
+ clear();
+ }
+ addstr("\n\nError drawing page!\nBad HText structure!\n");
+ refresh();
+ nlinks = 0; /* set number of links to 0 */
+ return;
+ }
+#else
+ assert(line->next != NULL);
+#endif /* !VMS */
+ }
+
+ if (LYlowest_eightbit[current_char_set] <= 255 &&
+ (current_char_set != charset_last_displayed) &&
+ /*
+ * current_char_set has changed since last invocation,
+ * and it's not just 7-bit.
+ * Also we don't want to do this for -dump and -source etc.
+ */
+ LYCursesON) {
+ charset_last_displayed = current_char_set;
+#ifdef EXP_CHARTRANS_AUTOSWITCH
+#ifdef LINUX
+ /*
+ * Currently implemented only for LINUX
+ */
+ stop_curses();
+ UCChangeTerminalCodepage(current_char_set,
+ &LYCharSet_UC[current_char_set]);
+ start_curses();
+#endif /* LINUX */
+#endif /* EXP_CHARTRANS_AUTOSWITCH */
+ }
+
+ /*
+ * Check whether to force a screen clear to enable scrollback,
+ * or as a hack to fix a reverse clear screen problem for some
+ * curses packages. - shf@access.digex.net & seldon@eskimo.com
+ */
+ if (enable_scrollback) {
+ addch('*');
+ refresh();
+ clear();
+ }
+
+ text->top_of_screen = line_number;
+ display_title(text); /* will move cursor to top of screen */
+ display_flag=TRUE;
+
+ /*
+ * Output the page.
+ */
+ if (line) {
+ char *data;
+ int offset, HitOffset, LenNeeded;
+ for (i = 0; i < (display_lines); i++) {
+ /*
+ * Verify and display each line.
+ */
+#ifndef VMS
+ if (!LYNoCore) {
+ assert(line != NULL);
+ } else if (line == NULL) {
+ if (enable_scrollback) {
+ addch('*');
+ refresh();
+ clear();
+ }
+ addstr("\n\nError drawing page!\nBad HText structure!\n");
+ refresh();
+ nlinks = 0; /* set number of links to 0 */
+ return;
+ }
+#else
+ assert(line != NULL);
+#endif /* !VMS */
+ display_line(line, text);
+
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ /*
+ * If the target is on this line, recursively
+ * seek and emphasize it. - FM
+ */
+ data = (char *)line->data;
+ offset = (int)line->offset;
+ while ((target && *target) &&
+ (case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ text->T.output_utf8,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ text->T.output_utf8,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ ((int)line->offset + LenNeeded) < LYcols) {
+ int itmp = 0;
+ int written = 0;
+ int x_pos = offset + (int)(cp - data);
+ int len = strlen(target);
+ size_t utf_extra = 0;
+ int y;
+
+ text->page_has_target = YES;
+
+ /*
+ * Start the emphasis.
+ */
+ LYstartTargetEmphasis();
+
+ /*
+ * Output the target characters.
+ */
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ if (IsSpecialAttrChar(tmp[0])) {
+ /*
+ * Ignore special characters.
+ */
+ x_pos--;
+
+ } else if (cp == &data[itmp]) {
+ /*
+ * First printable character of target.
+ */
+ move((i + 1), x_pos);
+ if (text->T.output_utf8 && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&line->data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ strncpy(&tmp[1], &line->data[itmp+1], utf_extra);
+ tmp[utf_extra+1] = '\0';
+ itmp += utf_extra;
+ addstr(tmp);
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ addstr(tmp);
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ addstr(tmp);
+ written++;
+ }
+
+ } else if (&data[itmp] > cp) {
+ /*
+ * Output all the other printable target chars.
+ */
+ if (text->T.output_utf8 && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&line->data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ strncpy(&tmp[1], &line->data[itmp+1], utf_extra);
+ tmp[utf_extra+1] = '\0';
+ itmp += utf_extra;
+ addstr(tmp);
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ addstr(tmp);
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ addstr(tmp);
+ written++;
+ }
+ }
+ }
+
+ /*
+ * Stop the emphasis, and reset the offset and
+ * data pointer for our current position in the
+ * line. - FM
+ */
+ LYstopTargetEmphasis();
+ LYGetYX(y, offset);
+ data = (char *)&data[itmp];
+
+ /*
+ * Adjust the cursor position, should we be at
+ * the end of the line, or not have another hit
+ * in it. - FM
+ */
+ move((i + 2), 0);
+ }
+#endif /* FANCY CURSES || USE_SLANG */
+
+ /*
+ * Stop if this is the last line. Otherwise, make sure
+ * display_flag is set and process the next line. - FM
+ */
+ if (line == text->last_line) {
+ /*
+ * Clear remaining lines of display.
+ */
+ for (i++; i < (display_lines); i++) {
+ move((i + 1), 0);
+ clrtoeol();
+ }
+ break;
+ }
+ display_flag = TRUE;
+ line = line->next;
+ }
+ }
+
+ text->next_line = line; /* Line after screen */
+ text->stale = NO; /* Display is up-to-date */
+
+ /*
+ * Add the anchors to Lynx structures.
+ */
+ nlinks = 0;
+ for (Anchor_ptr=text->first_anchor; Anchor_ptr != NULL &&
+ Anchor_ptr->line_num <= line_number+(display_lines);
+ Anchor_ptr = Anchor_ptr->next) {
+
+ if (Anchor_ptr->line_num >= line_number &&
+ Anchor_ptr->line_num < line_number+(display_lines)) {
+ /*
+ * Load normal hypertext anchors.
+ */
+ if (Anchor_ptr->show_anchor && Anchor_ptr->hightext &&
+ strlen(Anchor_ptr->hightext) > 0 &&
+ (Anchor_ptr->link_type & HYPERTEXT_ANCHOR)) {
+
+ links[nlinks].hightext = Anchor_ptr->hightext;
+ links[nlinks].hightext2 = Anchor_ptr->hightext2;
+ links[nlinks].hightext2_offset = Anchor_ptr->hightext2offset;
+ links[nlinks].inUnderline = Anchor_ptr->inUnderline;
+
+ links[nlinks].anchor_number = Anchor_ptr->number;
+ links[nlinks].anchor_line_num = Anchor_ptr->line_num;
+
+ link_dest = HTAnchor_followMainLink(
+ (HTAnchor *)Anchor_ptr->anchor);
+ {
+ /*
+ * Memory leak fixed 05-27-94
+ * Garrett Arch Blythe
+ */
+ auto char *cp_AnchorAddress = NULL;
+ if (traversal)
+ cp_AnchorAddress = stub_HTAnchor_address(link_dest);
+ else {
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (Anchor_ptr->link_type == INTERNAL_LINK_ANCHOR) {
+ link_dest_intl = HTAnchor_followTypedLink(
+ (HTAnchor *)Anchor_ptr->anchor, LINK_INTERNAL);
+ if (link_dest_intl && link_dest_intl != link_dest) {
+ if (TRACE)
+ fprintf(stderr,
+ "display_page: unexpected typed link to %s!\n",
+ link_dest_intl->parent->address);
+ link_dest_intl = NULL;
+ }
+ } else
+ link_dest_intl = NULL;
+ if (link_dest_intl) {
+ char *cp2 = HTAnchor_address(link_dest_intl);
+ cp_AnchorAddress = cp2;
+ } else
+#endif
+ cp_AnchorAddress = HTAnchor_address(link_dest);
+ }
+ FREE(links[nlinks].lname);
+
+ if (cp_AnchorAddress != NULL)
+ links[nlinks].lname = cp_AnchorAddress;
+ else
+ StrAllocCopy(links[nlinks].lname, empty_string);
+ }
+
+ links[nlinks].lx = Anchor_ptr->line_pos;
+ links[nlinks].ly = ((Anchor_ptr->line_num + 1) - line_number);
+ if (link_dest_intl)
+ links[nlinks].type = WWW_INTERN_LINK_TYPE;
+ else
+ links[nlinks].type = WWW_LINK_TYPE;
+ links[nlinks].target = empty_string;
+ links[nlinks].form = NULL;
+
+ nlinks++;
+ display_flag = TRUE;
+
+ } else if (Anchor_ptr->link_type == INPUT_ANCHOR
+ && Anchor_ptr->input_field->type != F_HIDDEN_TYPE) {
+ /*
+ * Handle form fields.
+ */
+ lynx_mode = FORMS_LYNX_MODE;
+
+ FormInfo_ptr = Anchor_ptr->input_field;
+
+ links[nlinks].anchor_number = Anchor_ptr->number;
+ links[nlinks].anchor_line_num = Anchor_ptr->line_num;
+
+ links[nlinks].form = FormInfo_ptr;
+ links[nlinks].lx = Anchor_ptr->line_pos;
+ links[nlinks].ly = ((Anchor_ptr->line_num + 1) - line_number);
+ links[nlinks].type = WWW_FORM_LINK_TYPE;
+ links[nlinks].inUnderline = Anchor_ptr->inUnderline;
+ links[nlinks].target = empty_string;
+ StrAllocCopy(links[nlinks].lname, empty_string);
+
+ if (FormInfo_ptr->type == F_RADIO_TYPE) {
+ if (FormInfo_ptr->num_value)
+ links[nlinks].hightext = checked_radio;
+ else
+ links[nlinks].hightext = unchecked_radio;
+
+ } else if (FormInfo_ptr->type == F_CHECKBOX_TYPE) {
+ if (FormInfo_ptr->num_value)
+ links[nlinks].hightext = checked_box;
+ else
+ links[nlinks].hightext = unchecked_box;
+
+ } else if (FormInfo_ptr->type == F_PASSWORD_TYPE) {
+ links[nlinks].hightext = STARS(strlen(FormInfo_ptr->value));
+
+ } else { /* TEXT type */
+ links[nlinks].hightext = FormInfo_ptr->value;
+ }
+
+ /*
+ * Never a second line on form types.
+ */
+ links[nlinks].hightext2 = NULL;
+ links[nlinks].hightext2_offset = 0;
+
+ nlinks++;
+ /*
+ * Bold the link after incrementing nlinks.
+ */
+ highlight(OFF, (nlinks - 1), target);
+
+ display_flag = TRUE;
+
+ } else {
+ /*
+ * Not showing anchor.
+ */
+ if (TRACE &&
+ Anchor_ptr->hightext && *Anchor_ptr->hightext)
+ fprintf(stderr,
+ "\nGridText: Not showing link, hightext=%s\n",
+ Anchor_ptr->hightext);
+ }
+ }
+
+ if (Anchor_ptr == text->last_anchor)
+ /*
+ * No more links in document. - FM
+ */
+ break;
+
+ if (nlinks == MAXLINKS) {
+ /*
+ * Links array is full. If interactive, tell user
+ * to use half-page or two-line scrolling. - FM
+ */
+ if (LYCursesON) {
+ _statusline(MAXLINKS_REACHED);
+ sleep(AlertSecs);
+ }
+ if (TRACE)
+ fprintf(stderr, "\ndisplay_page: MAXLINKS reached.\n");
+ break;
+ }
+ }
+
+ /*
+ * Free any un-reallocated links[] entries
+ * from the previous page draw. - FM
+ */
+ for (i = nlinks; i < last_nlinks; i++)
+ FREE(links[i].lname);
+ last_nlinks = nlinks;
+
+ /*
+ * If Anchor_ptr is not NULL and is not pointing to the last
+ * anchor, then there are anchors farther down in the document,
+ * and we need to flag this for traversals.
+ */
+ more_links = FALSE;
+ if (traversal && Anchor_ptr) {
+ if (Anchor_ptr->next)
+ more_links = TRUE;
+ }
+
+ if (!display_flag) {
+ /*
+ * Nothing on the page.
+ */
+ addstr("\n Document is empty");
+ }
+
+ if (HTCJK != NOCJK || text->T.output_utf8 || TRACE) {
+ /*
+ * For non-multibyte curses.
+ */
+ lynx_force_repaint();
+ }
+ refresh();
+
+}
+
+
+/* Object Building methods
+** -----------------------
+**
+** These are used by a parser to build the text in an object
+*/
+PUBLIC void HText_beginAppend ARGS1(
+ HText *, text)
+{
+ text->permissible_split = 0;
+ text->in_line_1 = YES;
+
+}
+
+
+/* Add a new line of text
+** ----------------------
+**
+** On entry,
+**
+** split is zero for newline function, else number of characters
+** before split.
+** text->display_on_the_fly
+** may be set to indicate direct output of the finished line.
+** On exit,
+** A new line has been made, justified according to the
+** current style. Text after the split (if split nonzero)
+** is taken over onto the next line.
+**
+** If display_on_the_fly is set, then it is decremented and
+** the finished line is displayed.
+*/
+#define new_line(text) split_line(text, 0)
+
+PRIVATE void split_line ARGS2(
+ HText *, text,
+ int, split)
+{
+ HTStyle * style = text->style;
+ HTLine * temp;
+ int spare;
+#if defined(USE_COLOR_STYLE)
+ int inew;
+#endif
+ int indent = text->in_line_1 ?
+ text->style->indent1st : text->style->leftIndent;
+ TextAnchor * a;
+ int CurLine = text->Lines;
+ int HeadTrim = 0;
+ int SpecialAttrChars = 0;
+ int TailTrim = 0;
+
+ /*
+ * Make new line.
+ */
+ HTLine * previous = text->last_line;
+ int ctrl_chars_on_previous_line = 0;
+ char * cp;
+ HTLine * line = (HTLine *)LY_CALLOC(1, LINE_SIZE(MAX_LINE));
+ if (line == NULL)
+ outofmem(__FILE__, "split_line_1");
+
+ ctrl_chars_on_this_line = 0; /*reset since we are going to a new line*/
+ text->LastChar = ' ';
+
+ if (TRACE)
+ fprintf(stderr,"GridText: split_line called\n");
+
+ text->Lines++;
+
+ previous->next->prev = line;
+ line->prev = previous;
+ line->next = previous->next;
+#if defined(USE_COLOR_STYLE)
+#define LastStyle (previous->numstyles-1)
+ line->numstyles = 0;
+ inew = MAX_STYLES_ON_LINE - 1;
+ spare = previous->numstyles;
+ while (previous->numstyles && inew >= 0) {
+ if (previous->numstyles >= 2 &&
+ previous->styles[LastStyle].style
+ == previous->styles[previous->numstyles-2].style &&
+ previous->styles[LastStyle].horizpos
+ == previous->styles[previous->numstyles-2].horizpos &&
+ ((previous->styles[LastStyle].direction == STACK_OFF &&
+ previous->styles[previous->numstyles-2].direction == STACK_ON) ||
+ (previous->styles[LastStyle].direction == ABS_OFF &&
+ previous->styles[previous->numstyles-2].direction == ABS_ON) ||
+ (previous->styles[LastStyle].direction == ABS_ON &&
+ previous->styles[previous->numstyles-2].direction == ABS_OFF)
+ )) {
+ /*
+ * Discard pairs of ON/OFF for the same color style, but only
+ * if they appear at the same position. - kw
+ */
+ previous->numstyles -= 2;
+ if (spare > previous->numstyles)
+ spare = previous->numstyles;
+ } else if (spare > 0 && previous->styles[spare - 1].direction &&
+ previous->numstyles < MAX_STYLES_ON_LINE) {
+ /*
+ * The index variable spare walks backwards through the
+ * list of color style changes on the previous line, trying
+ * to find an ON change which isn't followed by a
+ * corresponding OFF. When it finds one, the missing OFF
+ * change is appended to the end, and an ON change is added
+ * at the beginning of the current line. The OFF change
+ * appended to the previous line may get removed again in
+ * the next iteration. - kw
+ */
+ line->styles[inew].horizpos = 0;
+ line->styles[inew].direction = ON;
+ line->styles[inew].style = previous->styles[spare - 1].style;
+ inew --;
+ line->numstyles ++;
+ previous->styles[previous->numstyles].style = line->styles[inew + 1].style;
+
+ previous->styles[previous->numstyles].direction = ABS_OFF;
+ previous->styles[previous->numstyles].horizpos = previous->size;
+ previous->numstyles++;
+ spare --;
+ } else if (spare >= 2 &&
+ previous->styles[spare - 1].style == previous->styles[spare - 2].style &&
+ ((previous->styles[spare - 1].direction == STACK_OFF &&
+ previous->styles[spare - 2].direction == STACK_ON) ||
+ (previous->styles[spare - 1].direction == ABS_OFF &&
+ previous->styles[spare - 2].direction == ABS_ON) ||
+ (previous->styles[spare - 1].direction == STACK_ON &&
+ previous->styles[spare - 2].direction == STACK_OFF) ||
+ (previous->styles[spare - 1].direction == ABS_ON &&
+ previous->styles[spare - 2].direction == ABS_OFF)
+ )) {
+ /*
+ * Skip pairs of adjacent ON/OFF or OFF/ON changes.
+ */
+ spare -= 2;
+ } else if (spare && !previous->styles[spare - 1].direction) {
+ /*
+ * Found an OFF change not part of a matched pair.
+ * Assume it is safer to leave whatever comes before
+ * it on the previous line alone. Setting spare to 0
+ * ensures that it won't be used in a following
+ * iteration. - kw
+ */
+ spare = 0;
+ } else {
+ /*
+ * Nothing applied, so we are done with the loop. - kw
+ */
+ break;
+ }
+ }
+ if (previous->numstyles > 0 && previous->styles[LastStyle].direction) {
+ if (TRACE)
+ fprintf(stderr, "%s\n%s%s\n",
+ "........... Too many character styles on line:",
+ "........... ", previous->data);
+ }
+ if (line->numstyles > 0 && line->numstyles < MAX_STYLES_ON_LINE) {
+ int n;
+ inew ++;
+ for (n = line->numstyles; n >= 0; n--)
+ line->styles[n + inew] = line->styles[n];
+ } else
+ if (line->numstyles == 0)
+ /* FIXME: RJP - shouldn't use 0xffffffff for largest integer */
+ line->styles[0].horizpos = 0xffffffff;
+ if (previous->numstyles == 0)
+ previous->styles[0].horizpos = 0xffffffff;
+#endif
+ previous->next = line;
+ text->last_line = line;
+ line->size = 0;
+ line->offset = 0;
+ text->permissible_split = 0; /* 12/13/93 */
+ line->data[0] = '\0';
+
+ /*
+ * If we are not splitting and need an underline char, add it now. - FM
+ */
+ if ((split < 1) &&
+ !(dump_output_immediately && use_underscore) && underline_on) {
+ line->data[line->size++] = LY_UNDERLINE_START_CHAR;
+ line->data[line->size] = '\0';
+ ctrl_chars_on_this_line++;
+ }
+ /*
+ * If we are not splitting and need a bold char, add it now. - FM
+ */
+ if ((split < 1) && bold_on) {
+ line->data[line->size++] = LY_BOLD_START_CHAR;
+ line->data[line->size] = '\0';
+ ctrl_chars_on_this_line++;
+ }
+
+ /*
+ * Split at required point
+ */
+ if (split > 0) { /* Delete space at "split" splitting line */
+ char *p, *prevdata = previous->data, *linedata = line->data;
+ unsigned int plen;
+ int i;
+
+ /*
+ * Split the line. - FM
+ */
+ prevdata[previous->size] = '\0';
+ previous->size = split;
+
+ /*
+ * Trim any spaces or soft hyphens from the beginning
+ * of our new line. - FM
+ */
+ p = prevdata + split;
+ while (*p == ' ' || *p == LY_SOFT_HYPHEN) {
+ p++;
+ HeadTrim++;
+ }
+ plen = strlen(p);
+
+ /*
+ * Add underline char if needed. - FM
+ */
+ if (!(dump_output_immediately && use_underscore)) {
+ /*
+ * Make sure our global flag is correct. - FM
+ */
+ underline_on = NO;
+ for (i = (split-1); i >= 0; i--) {
+ if (prevdata[i] == LY_UNDERLINE_END_CHAR) {
+ break;
+ }
+ if (prevdata[i] == LY_UNDERLINE_START_CHAR) {
+ underline_on = YES;
+ break;
+ }
+ }
+ /*
+ * Act on the global flag if set above. - FM
+ */
+ if (underline_on && *p != LY_UNDERLINE_END_CHAR) {
+ linedata[line->size++] = LY_UNDERLINE_START_CHAR;
+ linedata[line->size] = '\0';
+ ctrl_chars_on_this_line++;
+ SpecialAttrChars++;
+ }
+ for (i = (plen - 1); i >= 0; i--) {
+ if (p[i] == LY_UNDERLINE_START_CHAR) {
+ underline_on = YES;
+ break;
+ }
+ if (p[i] == LY_UNDERLINE_END_CHAR) {
+ underline_on = NO;
+ break;
+ }
+ }
+ for (i = (plen - 1); i >= 0; i--) {
+ if (p[i] == LY_UNDERLINE_START_CHAR ||
+ p[i] == LY_UNDERLINE_END_CHAR) {
+ ctrl_chars_on_this_line++;
+ }
+ }
+ }
+
+ /*
+ * Add bold char if needed, first making
+ * sure that our global flag is correct. - FM
+ */
+ bold_on = NO;
+ for (i = (split - 1); i >= 0; i--) {
+ if (prevdata[i] == LY_BOLD_END_CHAR) {
+ break;
+ }
+ if (prevdata[i] == LY_BOLD_START_CHAR) {
+ bold_on = YES;
+ break;
+ }
+ }
+ /*
+ * Act on the global flag if set above. - FM
+ */
+ if (bold_on && *p != LY_BOLD_END_CHAR) {
+ linedata[line->size++] = LY_BOLD_START_CHAR;
+ linedata[line->size] = '\0';
+ ctrl_chars_on_this_line++;
+ SpecialAttrChars++;;
+ }
+ for (i = (plen - 1); i >= 0; i--) {
+ if (p[i] == LY_BOLD_START_CHAR) {
+ bold_on = YES;
+ break;
+ }
+ if (p[i] == LY_BOLD_END_CHAR) {
+ bold_on = NO;
+ break;
+ }
+ }
+ for (i = (plen - 1); i >= 0; i--) {
+ if (p[i] == LY_BOLD_START_CHAR ||
+ p[i] == LY_BOLD_END_CHAR ||
+ IS_UTF_EXTRA(p[i]) ||
+ p[i] == LY_SOFT_HYPHEN) {
+ ctrl_chars_on_this_line++;
+ }
+ if (p[i] == LY_SOFT_HYPHEN && text->permissible_split < i) {
+ text->permissible_split = i + 1;
+ }
+ }
+
+ /*
+ * Add the data to the new line. - FM
+ */
+ strcat(linedata, p);
+ line->size += plen;
+ }
+
+ /*
+ * Economize on space.
+ */
+ while ((previous->size > 0) &&
+ (previous->data[previous->size-1] == ' ')) {
+ /*
+ * Strip trailers.
+ */
+ previous->data[previous->size-1] = '\0';
+ previous->size--;
+ TailTrim++;
+ }
+ temp = (HTLine *)LY_CALLOC(1, LINE_SIZE(previous->size));
+ if (temp == NULL)
+ outofmem(__FILE__, "split_line_2");
+ memcpy(temp, previous, LINE_SIZE(previous->size));
+ FREE(previous);
+ previous = temp;
+
+ previous->prev->next = previous; /* Link in new line */
+ previous->next->prev = previous; /* Could be same node of course */
+
+ /*
+ * Terminate finished line for printing.
+ */
+ previous->data[previous->size] = '\0';
+
+ /*
+ * Align left, right or center.
+ */
+ for (cp = previous->data; *cp; cp++) {
+ if (*cp == LY_UNDERLINE_START_CHAR ||
+ *cp == LY_UNDERLINE_END_CHAR ||
+ *cp == LY_BOLD_START_CHAR ||
+ *cp == LY_BOLD_END_CHAR ||
+ IS_UTF_EXTRA(*cp) ||
+ *cp == LY_SOFT_HYPHEN)
+ ctrl_chars_on_previous_line++;
+ }
+ /* @@ first line indent */
+ spare = (LYcols-1) -
+ (int)style->rightIndent - indent +
+ ctrl_chars_on_previous_line - previous->size -
+ ((previous->size > 0) &&
+ (int)(previous->data[previous->size-1] ==
+ LY_SOFT_HYPHEN ?
+ 1 : 0));
+
+ switch (style->alignment) {
+ case HT_CENTER :
+ previous->offset = previous->offset + indent + spare/2;
+ break;
+ case HT_RIGHT :
+ previous->offset = previous->offset + indent + spare;
+ break;
+ case HT_LEFT :
+ case HT_JUSTIFY : /* Not implemented */
+ default:
+ previous->offset = previous->offset + indent;
+ break;
+ } /* switch */
+
+ text->chars = text->chars + previous->size + 1; /* 1 for the line */
+ text->in_line_1 = NO; /* unless caller sets it otherwise */
+
+ /*
+ * If we split the line, adjust the anchor
+ * structure values for the new line. - FM
+ */
+ if (split > 0) {
+ for (a = text->first_anchor; a; a = a->next) {
+ if (a->line_num == CurLine) {
+ if (a->line_pos >= split) {
+ a->start += (1 + SpecialAttrChars - HeadTrim - TailTrim);
+ a->line_pos -= (split - SpecialAttrChars + HeadTrim);
+ a->line_num = text->Lines;
+ } else if ((a->link_type & HYPERTEXT_ANCHOR) &&
+ (a->line_pos + a->extent) >= split) {
+ a->extent -= (TailTrim + HeadTrim);
+ if (a->extent < 0) {
+ a->extent = 0;
+ }
+ }
+ }
+ }
+ }
+} /* split_line */
+
+
+/* Allow vertical blank space
+** --------------------------
+*/
+PRIVATE void blank_lines ARGS2(
+ HText *, text,
+ int, newlines)
+{
+ BOOL IgnoreSpaces = FALSE;
+
+ if (!HText_LastLineSize(text, IgnoreSpaces)) { /* No text on current line */
+ HTLine * line = text->last_line->prev;
+ while ((line != text->last_line) &&
+ (HText_TrueLineSize(line, text, IgnoreSpaces) == 0)) {
+ if (newlines == 0)
+ break;
+ newlines--; /* Don't bother: already blank */
+ line = line->prev;
+ }
+ } else {
+ newlines++; /* Need also to finish this line */
+ }
+
+ for (; newlines; newlines--) {
+ new_line(text);
+ }
+ text->in_line_1 = YES;
+}
+
+
+/* New paragraph in current style
+** ------------------------------
+** See also: setStyle.
+*/
+PUBLIC void HText_appendParagraph ARGS1(
+ HText *, text)
+{
+ int after = text->style->spaceAfter;
+ int before = text->style->spaceBefore;
+ blank_lines(text, ((after > before) ? after : before));
+}
+
+
+/* Set Style
+** ---------
+**
+** Does not filter unnecessary style changes.
+*/
+PUBLIC void HText_setStyle ARGS2(
+ HText *, text,
+ HTStyle *, style)
+{
+ int after, before;
+
+ if (!style)
+ return; /* Safety */
+ after = text->style->spaceAfter;
+ before = style->spaceBefore;
+ if (TRACE)
+ fprintf(stderr, "GridText: Change to style %s\n", style->name);
+
+ blank_lines (text, ((after > before) ? after : before));
+
+ text->style = style;
+}
+
+/* Append a character to the text object
+** -------------------------------------
+*/
+PUBLIC void HText_appendCharacter ARGS2(
+ HText *, text,
+ char, ch)
+{
+ HTLine * line;
+ HTStyle * style;
+ int indent;
+
+ /*
+ * Make sure we don't crash on NULLs.
+ */
+ if (!text)
+ return;
+
+ if (text->halted > 1) {
+ /*
+ * We should stop outputting more text, because low memory was
+ * detected. - kw
+ */
+ if (text->halted == 2) {
+ /*
+ * But if we haven't done so yet, first append a warning.
+ * We should still have a few bytes left for that :).
+ * We temporarily reset test->halted to 0 for this, since
+ * this function will get called recursively. - kw
+ */
+ text->halted = 0;
+ text->kanji_buf = '\0';
+ HText_appendText(text, " *** MEMORY EXHAUSTED ***");
+ }
+ text->halted = 3;
+ return;
+ }
+ /*
+ * Make sure we don't hang on escape sequences.
+ */
+ if (ch == '\033' && HTCJK == NOCJK) /* decimal 27 */
+ return;
+#ifndef USE_SLANG
+ /*
+ * Block 8-bit chars not allowed by the current display character
+ * set if they are below what LYlowest_eightbit indicates.
+ * Slang used its own replacements, so for USE_SLANG blocking here
+ * is not necessary to protect terminals from those characters.
+ * They should have been filtered out or translated by an earlier
+ * processing stage anyway. - kw
+ */
+ if ((unsigned char)ch >= 128 && HTCJK == NOCJK &&
+ !text->T.transp && !text->T.output_utf8 &&
+ (unsigned char)ch < LYlowest_eightbit[current_char_set])
+ return;
+#endif /* USE_SLANG */
+ if ((unsigned char)ch == 155 && HTCJK == NOCJK) { /* octal 233 */
+ if (!HTPassHighCtrlRaw &&
+ !text->T.transp && !text->T.output_utf8 &&
+ (155 < LYlowest_eightbit[current_char_set]) &&
+ strncmp(LYchar_set_names[current_char_set],
+ "DosLatin1 (cp850)", 17) &&
+ strncmp(LYchar_set_names[current_char_set],
+ "DosLatinUS (cp437)", 18) &&
+ strncmp(LYchar_set_names[current_char_set],
+ "Macintosh (8 bit)", 17) &&
+ strncmp(LYchar_set_names[current_char_set],
+ "NeXT character set", 18)) {
+ return;
+ }
+ }
+
+ line = text->last_line;
+ style = text->style;
+
+ indent = text->in_line_1 ? (int)style->indent1st : (int)style->leftIndent;
+
+ if (HTCJK != NOCJK) {
+ switch(text->state) {
+ case S_text:
+ if (ch == '\033') {
+ /*
+ ** Setting up for CJK escape sequence handling (based on
+ ** Takuya ASADA's (asada@three-a.co.jp) CJK Lynx). - FM
+ */
+ text->state = S_esc;
+ text->kanji_buf = '\0';
+ return;
+ }
+ break;
+
+ case S_esc:
+ /*
+ * Expecting '$'or '(' following CJK ESC.
+ */
+ if (ch == '$') {
+ text->state = S_dollar;
+ return;
+ } else if (ch == '(') {
+ text->state = S_paren;
+ return;
+ } else {
+ text->state = S_text;
+ }
+
+ case S_dollar:
+ /*
+ * Expecting '@', 'B', 'A' or '(' after CJK "ESC$".
+ */
+ if (ch == '@' || ch == 'B' || ch=='A') {
+ text->state = S_nonascii_text;
+ return;
+ } else if (ch == '(') {
+ text->state = S_dollar_paren;
+ return;
+ } else {
+ text->state = S_text;
+ }
+ break;
+
+ case S_dollar_paren:
+ /*
+ * Expecting 'C' after CJK "ESC$(".
+ */
+ if (ch == 'C') {
+ text->state = S_nonascii_text;
+ return;
+ } else {
+ text->state = S_text;
+ }
+ break;
+
+ case S_paren:
+ /*
+ * Expecting 'B', 'J', 'T' or 'I' after CJK "ESC(".
+ */
+ if (ch == 'B' || ch == 'J' || ch == 'T') {
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+ text->state = S_text;
+ return;
+ } else if (ch == 'I') {
+ text->state = S_jisx0201_text;
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+ return;
+ } else {
+ text->state = S_text;
+ }
+ break;
+
+ case S_nonascii_text:
+ /*
+ * Expecting CJK ESC after non-ASCII text.
+ */
+ if (ch == '\033') {
+ text->state = S_esc;
+ text->kanji_buf = '\0';
+ return;
+ } else {
+ ch |= 0200;
+ }
+ break;
+
+ /*
+ * JIS X0201 Kana in JIS support. - by ASATAKU
+ */
+ case S_jisx0201_text:
+ if (ch == '\033') {
+ text->state = S_esc;
+ text->kanji_buf = '\0';
+ return;
+ } else {
+ text->kanji_buf = '\x8E';
+ ch |= 0200;
+ }
+ break;
+ }
+
+ if (!text->kanji_buf) {
+ if ((ch & 0200) != 0) {
+ /*
+ * JIS X0201 Kana in SJIS support. - by ASATAKU
+ */
+ if ((text->kcode == SJIS) &&
+ ((unsigned char)ch >= 0xA1) &&
+ ((unsigned char)ch <= 0xDF)) {
+ unsigned char c = (unsigned char)ch;
+ unsigned char kb = (unsigned char)text->kanji_buf;
+ JISx0201TO0208_SJIS(c,
+ (unsigned char *)&kb,
+ (unsigned char *)&c);
+ ch = (char)c;
+ text->kanji_buf = (char)kb;
+ } else {
+ text->kanji_buf = ch;
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+ return;
+ }
+ }
+ } else {
+ goto check_IgnoreExcess;
+ }
+ } else if (ch == '\033') {
+ return;
+ }
+
+ if (IsSpecialAttrChar(ch)) {
+#ifndef USE_COLOR_STYLE
+ if (ch == LY_UNDERLINE_START_CHAR) {
+ line->data[line->size++] = LY_UNDERLINE_START_CHAR;
+ line->data[line->size] = '\0';
+ underline_on = ON;
+ if (!(dump_output_immediately && use_underscore))
+ ctrl_chars_on_this_line++;
+ return;
+ } else if (ch == LY_UNDERLINE_END_CHAR) {
+ line->data[line->size++] = LY_UNDERLINE_END_CHAR;
+ line->data[line->size] = '\0';
+ underline_on = OFF;
+ if (!(dump_output_immediately && use_underscore))
+ ctrl_chars_on_this_line++;
+ return;
+ } else if (ch == LY_BOLD_START_CHAR) {
+ line->data[line->size++] = LY_BOLD_START_CHAR;
+ line->data[line->size] = '\0';
+ bold_on = ON;
+ ctrl_chars_on_this_line++;
+ return;
+ } else if (ch == LY_BOLD_END_CHAR) {
+ line->data[line->size++] = LY_BOLD_END_CHAR;
+ line->data[line->size] = '\0';
+ bold_on = OFF;
+ ctrl_chars_on_this_line++;
+ return;
+ } else if (ch == LY_SOFT_HYPHEN) {
+ int i;
+
+ /*
+ * Ignore the soft hyphen if it is the first character
+ * on the line, or if it is preceded by a space or
+ * hyphen. - FM
+ */
+ if (line->size < 1 || text->permissible_split >= (int)line->size)
+ return;
+
+ for (i = (text->permissible_split + 1); line->data[i]; i++) {
+ if (!IsSpecialAttrChar((unsigned char)line->data[i]) &&
+ !isspace((unsigned char)line->data[i]) &&
+ (unsigned char)line->data[i] != '-' &&
+ (unsigned char)line->data[i] != HT_NON_BREAK_SPACE &&
+ (unsigned char)line->data[i] != HT_EM_SPACE) {
+ break;
+ }
+ }
+ if (line->data[i] == '\0') {
+ return;
+ }
+ }
+#else
+ return;
+#endif
+ }
+
+ if (IS_UTF_EXTRA(ch)) {
+ line->data[line->size++] = ch;
+ line->data[line->size] = '\0';
+ ctrl_chars_on_this_line++;
+ return;
+ }
+
+ /*
+ * New Line.
+ */
+ if (ch == '\n') {
+ new_line(text);
+ text->in_line_1 = YES; /* First line of new paragraph */
+ /*
+ * There are some pages written in
+ * different kanji codes. - TA & kw
+ */
+ if (HTCJK == JAPANESE)
+ text->kcode = NOKANJI;
+ return;
+ }
+
+ /*
+ * Convert EM_SPACE to a space here so that it doesn't get collapsed.
+ */
+ if (ch == HT_EM_SPACE)
+ ch = ' ';
+
+ /*
+ * I'm going to cheat here in a BIG way. Since I know that all
+ * \r's will be trapped by HTML_put_character I'm going to use
+ * \r to mean go down a line but don't start a new paragraph.
+ * i.e. use the second line indenting.
+ */
+ if (ch == '\r') {
+ new_line(text);
+ text->in_line_1 = NO;
+ /*
+ * There are some pages written in
+ * different kanji codes. - TA & kw
+ */
+ if (HTCJK == JAPANESE)
+ text->kcode = NOKANJI;
+ return;
+ }
+
+
+ /*
+ * Tabs.
+ */
+ if (ch == '\t') {
+ CONST HTTabStop * Tab;
+ int target; /* Where to tab to */
+ int here;
+
+ if (line->size > 0 && line->data[line->size-1] == LY_SOFT_HYPHEN) {
+ /*
+ * A tab shouldn't follow a soft hyphen, so
+ * if one does, we'll dump the soft hyphen. - FM
+ */
+ line->data[--line->size] = '\0';
+ ctrl_chars_on_this_line--;
+ }
+ here = (((int)line->size + (int)line->offset) + indent)
+ - ctrl_chars_on_this_line; /* Consider special chars GAB */
+ if (style->tabs) { /* Use tab table */
+ for (Tab = style->tabs;
+ Tab->position <= here;
+ Tab++)
+ if (!Tab->position) {
+ new_line(text);
+ return;
+ }
+ target = Tab->position;
+ } else if (text->in_line_1) { /* Use 2nd indent */
+ if (here >= (int)style->leftIndent) {
+ new_line(text); /* wrap */
+ return;
+ } else {
+ target = (int)style->leftIndent;
+ }
+ } else { /* Default tabs align with left indent mod 8 */
+#ifdef DEFAULT_TABS_8
+ target = (((int)line->offset + (int)line->size + 8) & (-8))
+ + (int)style->leftIndent;
+#else
+ new_line(text);
+ return;
+#endif
+ }
+
+ if (target > (LYcols-1) - (int)style->rightIndent &&
+ HTOutputFormat != WWW_SOURCE) {
+ new_line(text);
+ return;
+ } else {
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)line->size;
+ if (line->size == 0) {
+ line->offset = line->offset + target - here;
+ } else {
+ for (; here<target; here++) {
+ /* Put character into line */
+ line->data[line->size++] = ' ';
+ line->data[line->size] = '\0';
+ }
+ }
+ return;
+ }
+ /*NOTREACHED*/
+ } /* if tab */
+
+
+ if (ch == ' ') {
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+ /*
+ * There are some pages written in
+ * different kanji codes. - TA
+ */
+ if (HTCJK == JAPANESE)
+ text->kcode = NOKANJI;
+ }
+
+ /*
+ * Check if we should ignore characters at the wrap point.
+ */
+check_IgnoreExcess:
+ if (text->IgnoreExcess &&
+ ((indent + (int)line->offset + (int)line->size) +
+ (int)style->rightIndent - ctrl_chars_on_this_line) >= (LYcols-1))
+ return;
+
+ /*
+ * Check for end of line.
+ */
+ if (((indent + (int)line->offset + (int)line->size) +
+ (int)style->rightIndent - ctrl_chars_on_this_line +
+ ((line->size > 0) &&
+ (int)(line->data[line->size-1] ==
+ LY_SOFT_HYPHEN ?
+ 1 : 0))) >= (LYcols - 1)) {
+
+ if (style->wordWrap && HTOutputFormat != WWW_SOURCE) {
+ split_line(text, text->permissible_split);
+ if (ch == ' ') return; /* Ignore space causing split */
+
+ } else if (HTOutputFormat == WWW_SOURCE) {
+ /*
+ * For source output we don't want to wrap this stuff
+ * unless absolutely necessary. - LJM
+ * !
+ * If we don't wrap here we might get a segmentation fault.
+ * but let's see what happens
+ */
+ if ((int)line->size >= (int)(MAX_LINE-1))
+ new_line(text); /* try not to linewrap */
+ } else {
+ /*
+ * For normal stuff like pre let's go ahead and
+ * wrap so the user can see all of the text.
+ */
+ new_line(text);
+ }
+ } else if ((int)line->size >= (int)(MAX_LINE-1)) {
+ /*
+ * Never overrun memory if LYcols is set to a large value - KW
+ */
+ new_line(text);
+ }
+
+ /*
+ * Insert normal characters.
+ */
+ if (ch == HT_NON_BREAK_SPACE) {
+ ch = ' ';
+ }
+
+ if (ch & 0x80)
+ text->have_8bit_chars = YES;
+
+ {
+ HTFont font = style->font;
+ unsigned char hi, lo, tmp[2];
+
+ line = text->last_line; /* May have changed */
+ if (HTCJK != NOCJK && text->kanji_buf) {
+ hi = (unsigned char)text->kanji_buf, lo = (unsigned char)ch;
+ if (HTCJK == JAPANESE && text->kcode == NOKANJI) {
+ if (IS_SJIS(hi, lo, text->in_sjis) && IS_EUC(hi, lo)) {
+ text->kcode = NOKANJI;
+ } else if (IS_SJIS(hi, lo, text->in_sjis)) {
+ text->kcode = SJIS;
+ } else if (IS_EUC(hi, lo)) {
+ text->kcode = EUC;
+ }
+ }
+ if (HTCJK == JAPANESE &&
+ (kanji_code == EUC) && (text->kcode == SJIS)) {
+ SJIS_TO_EUC1(hi, lo, tmp);
+ line->data[line->size++] = tmp[0];
+ line->data[line->size++] = tmp[1];
+ } else if (HTCJK == JAPANESE &&
+ (kanji_code == EUC) && (text->kcode == EUC)) {
+ JISx0201TO0208_EUC(hi, lo, &hi, &lo);
+ line->data[line->size++] = hi;
+ line->data[line->size++] = lo;
+ } else if (HTCJK == JAPANESE &&
+ (kanji_code == SJIS) && (text->kcode == EUC)) {
+ EUC_TO_SJIS1(hi, lo, tmp);
+ line->data[line->size++] = tmp[0];
+ line->data[line->size++] = tmp[1];
+ } else {
+ line->data[line->size++] = hi;
+ line->data[line->size++] = lo;
+ }
+ text->kanji_buf = 0;
+ } else if (HTCJK != NOCJK) {
+ line->data[line->size++] = (kanji_code != NOKANJI) ?
+ ch :
+ (font & HT_CAPITALS) ?
+ TOUPPER(ch) : ch;
+ } else {
+ line->data[line->size++] = /* Put character into line */
+ font & HT_CAPITALS ? TOUPPER(ch) : ch;
+ }
+ line->data[line->size] = '\0';
+ if (font & HT_DOUBLE) /* Do again if doubled */
+ HText_appendCharacter(text, HT_NON_BREAK_SPACE);
+ /* NOT a permissible split */
+
+ if (ch == LY_SOFT_HYPHEN) {
+ ctrl_chars_on_this_line++;
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+ }
+ }
+}
+
+#ifdef USE_COLOR_STYLE
+/* Insert a style change into the current line
+** -------------------------------------------
+*/
+PUBLIC void _internal_HTC ARGS3(HText *,text, int,style, int,dir)
+{
+ HTLine* line;
+ static int last_style = -1;
+ static int last_dir = -1;
+
+ /* can't change style if we have no text to change style with */
+ if (!text) return;
+
+ line = text->last_line;
+
+ if ((style != last_style || dir != last_dir) && line->numstyles < MAX_STYLES_ON_LINE)
+ {
+ line->styles[line->numstyles].horizpos = line->size;
+ line->styles[line->numstyles].style = style;
+ line->styles[line->numstyles].direction = dir;
+ line->numstyles++;
+ }
+ last_style = style;
+ last_dir = dir;
+}
+#endif
+
+
+
+/* Set LastChar element in the text object.
+** ----------------------------------------
+*/
+PUBLIC void HText_setLastChar ARGS2(
+ HText *, text,
+ char, ch)
+{
+ if (!text)
+ return;
+
+ text->LastChar = ch;
+}
+
+/* Get LastChar element in the text object.
+** ----------------------------------------
+*/
+PUBLIC char HText_getLastChar ARGS1(
+ HText *, text)
+{
+ if (!text)
+ return('\0');
+
+ return((char)text->LastChar);
+}
+
+/* Set IgnoreExcess element in the text object.
+** --------------------------------------------
+*/
+PUBLIC void HText_setIgnoreExcess ARGS2(
+ HText *, text,
+ BOOL, ignore)
+{
+ if (!text)
+ return;
+
+ text->IgnoreExcess = ignore;
+}
+
+/* Anchor handling
+** ---------------
+*/
+
+/* Start an anchor field
+*/
+PUBLIC int HText_beginAnchor ARGS3(
+ HText *, text,
+ BOOL, underline,
+ HTChildAnchor *, anc)
+{
+ char marker[16];
+
+ TextAnchor * a = (TextAnchor *) calloc(1, sizeof(*a));
+
+ if (a == NULL)
+ outofmem(__FILE__, "HText_beginAnchor");
+ a->hightext = NULL;
+ a->hightext2 = NULL;
+ a->start = text->chars + text->last_line->size;
+ a->inUnderline = underline;
+
+ a->line_num = text->Lines;
+ a->line_pos = text->last_line->size;
+ if (text->last_anchor) {
+ text->last_anchor->next = a;
+ } else {
+ text->first_anchor = a;
+ }
+ a->next = 0;
+ a->anchor = anc;
+ a->extent = 0;
+ a->link_type = HYPERTEXT_ANCHOR;
+ text->last_anchor = a;
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (HTAnchor_followTypedLink((HTAnchor*)anc, LINK_INTERNAL)) {
+ a->number = ++(text->last_anchor_number);
+ a->link_type = INTERNAL_LINK_ANCHOR;
+ } else
+#endif
+ if (HTAnchor_followMainLink((HTAnchor*)anc)) {
+ a->number = ++(text->last_anchor_number);
+ } else {
+ a->number = 0;
+ }
+
+ /*
+ * If we are doing link_numbering add the link number.
+ */
+ if ((a->number > 0) &&
+ (keypad_mode == LINKS_ARE_NUMBERED ||
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED)) {
+ sprintf(marker,"[%d]", a->number);
+ HText_appendText(text, marker);
+ a->start = text->chars + text->last_line->size;
+ a->line_num = text->Lines;
+ a->line_pos = text->last_line->size;
+ }
+
+ return(a->number);
+}
+
+
+PUBLIC void HText_endAnchor ARGS2(
+ HText *, text,
+ int, number)
+{
+ TextAnchor *a;
+
+ /*
+ * The number argument is set to 0 in HTML.c and
+ * LYCharUtils.c when we want to end the anchor
+ * for the immediately preceding HText_beginAnchor()
+ * call. If it's greater than 0, we want to handle
+ * a particular anchor. This allows us to set links
+ * for positions indicated by NAME or ID attributes,
+ * without needing to close any anchor with an HREF
+ * within which that link might be embedded. - FM
+ */
+ if (number <= 0 || number == text->last_anchor->number) {
+ a = text->last_anchor;
+ } else {
+ for (a = text->first_anchor; a; a = a->next) {
+ if (a->number == number) {
+ break;
+ }
+ }
+ if (a == NULL) {
+ /*
+ * There's no anchor with that number,
+ * so we'll default to the last anchor,
+ * and cross our fingers. - FM
+ */
+ a = text->last_anchor;
+ }
+ }
+ if (TRACE)
+ fprintf(stderr, "HText_endAnchor: number:%d link_type:%d\n",
+ a->number, a->link_type);
+ if (a->link_type == INPUT_ANCHOR) {
+ /*
+ * Shouldn't happen, but put test here anyway to be safe. - LE
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HText_endAnchor: internal error: last anchor was input field!\n");
+ return;
+ }
+ if (a->number) {
+ /*
+ * If it goes somewhere...
+ */
+ int i, j, k, l;
+ BOOL remove_numbers_on_empty =
+ ((keypad_mode == LINKS_ARE_NUMBERED ||
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) &&
+ (text->hiddenlinkflag != HIDDENLINKS_MERGE ||
+ (LYNoISMAPifUSEMAP &&
+ HTAnchor_isISMAPScript(
+ HTAnchor_followMainLink((HTAnchor *)a->anchor)))));
+ HTLine *last = text->last_line;
+ HTLine *prev = text->last_line->prev;
+ int CurBlankExtent = 0;
+ int BlankExtent = 0;
+
+ /*
+ * Check if the anchor content has only
+ * white and special characters, starting
+ * with the content on the last line. - FM
+ */
+ a->extent += (text->chars + last->size) - a->start -
+ (text->Lines - a->line_num);
+ if (a->extent > last->size) {
+ /*
+ * The anchor extends over more than one line,
+ * so set up to check the entire last line. - FM
+ */
+ i = last->size;
+ } else {
+ /*
+ * The anchor is restricted to the last line,
+ * so check from the start of the anchor. - FM
+ */
+ i = a->extent;
+ }
+ j = (last->size - i);
+ while (j < last->size) {
+ if (!IsSpecialAttrChar(last->data[j]) &&
+ !isspace((unsigned char)last->data[j]) &&
+ last->data[j] != HT_NON_BREAK_SPACE &&
+ last->data[j] != HT_EM_SPACE)
+ break;
+ i--;
+ j++;
+ }
+ if (i == 0) {
+ if (a->extent > last->size) {
+ /*
+ * The anchor starts on a preceding line, and
+ * the last line has only white and special
+ * characters, so declare the entire extent
+ * of the last line as blank. - FM
+ */
+ CurBlankExtent = BlankExtent = last->size;
+ } else {
+ /*
+ * The anchor starts on the last line, and
+ * has only white or special characters, so
+ * declare the anchor's extent as blank. - FM
+ */
+ CurBlankExtent = BlankExtent = a->extent;
+ }
+ }
+ /*
+ * While the anchor starts on a line preceding
+ * the one we just checked, and the one we just
+ * checked has only white and special characters,
+ * check whether the anchor's content on the
+ * immediately preceding line also has only
+ * white and special characters. - FM
+ */
+ while (i == 0 && a->extent > CurBlankExtent) {
+ j = prev->size - a->extent + CurBlankExtent;
+ if (j < 0) {
+ /*
+ * The anchor starts on a preceding line,
+ * so check all of this line. - FM
+ */
+ j = 0;
+ i = prev->size;
+ } else {
+ /*
+ * The anchor starts on this line. - FM
+ */
+ i = a->extent - CurBlankExtent;
+ }
+ while (j < prev->size) {
+ if (!IsSpecialAttrChar(prev->data[j]) &&
+ !isspace((unsigned char)prev->data[j]) &&
+ prev->data[j] != HT_NON_BREAK_SPACE &&
+ prev->data[j] != HT_EM_SPACE)
+ break;
+ i--;
+ j++;
+ }
+ if (i == 0) {
+ if (a->extent > (CurBlankExtent + prev->size)) {
+ /*
+ * This line has only white and special
+ * characters, so treat its entire extent
+ * as blank, and decrement the pointer for
+ * the line to be analyzed. - FM
+ */
+ CurBlankExtent += prev->size;
+ BlankExtent = CurBlankExtent;
+ prev = prev->prev;
+ } else {
+ /*
+ * The anchor starts on this line, and it
+ * has only white or special characters, so
+ * declare the anchor's extent as blank. - FM
+ */
+ BlankExtent = a->extent;
+ break;
+ }
+ }
+ }
+ if (i == 0) {
+ /*
+ * It's an invisible anchor probably from an ALT=""
+ * or an ignored ISMAP attribute due to a companion
+ * USEMAP. - FM
+ */
+ a->show_anchor = NO;
+
+ /*
+ * If links are numbered, then try to get rid of the
+ * numbered bracket and adjust the anchor count. - FM
+ *
+ * Well, let's do this only if -hiddenlinks=merged is not in
+ * effect, or if we can be reasonably sure that
+ * this is the result of an intentional non-generation of
+ * anchor text via NO_ISMAP_IF_USEMAP. In other cases it can
+ * actually be a feature that numbered links alert the viewer
+ * to the presence of a link which is otherwise not selectable -
+ * possibly caused by HTML errors. - kw
+ */
+ if (remove_numbers_on_empty) {
+ HTLine *start;
+ int NumSize = 0;
+ TextAnchor *anc;
+
+ /*
+ * Set start->data[j] to the close-square-bracket,
+ * or to the beginning of the line on which the
+ * anchor start. - FM
+ */
+ if (prev == last->prev) {
+ /*
+ * The anchor starts on the last line. - FM
+ */
+ start = last;
+ j = (last->size - a->extent - 1);
+ } else {
+ /*
+ * The anchor starts on a previous line. - FM
+ */
+ start = prev;
+ prev = prev->prev;
+ j = (start->size - a->extent + CurBlankExtent - 1);
+ }
+ if (j < 0)
+ j = 0;
+ i = j;
+
+ /*
+ * If start->data[j] is a close-square-bracket, verify
+ * that it's the end of the numbered bracket, and if so,
+ * strip the numbered bracket. If start->data[j] is not
+ * a close-square-bracket, check whether we had a wrap
+ * and the close-square-bracket is at the end of the
+ * previous line. If so, strip the numbered bracket
+ * from that line. - FM
+ */
+ if (start->data[j] == ']') {
+ j--;
+ NumSize++;
+ while (j >= 0 && isdigit((unsigned char)start->data[j])) {
+ j--;
+ NumSize++;
+ }
+ while (j < 0) {
+ j++;
+ NumSize--;
+ }
+ if (start->data[j] == '[') {
+ /*
+ * The numbered bracket is entirely
+ * on this line. - FM
+ */
+ NumSize++;
+ k = j + NumSize;
+ while (k < start->size)
+ start->data[j++] = start->data[k++];
+ if (start != last)
+ text->chars -= NumSize;
+ for (anc = a; anc; anc = anc->next) {
+ anc->start -= NumSize;
+ anc->line_pos -= NumSize;
+ }
+ start->size = j;
+ start->data[j++] = '\0';
+ while (j < k)
+ start->data[j++] = '\0';
+ } else if (prev && prev->size > 1) {
+ k = (i + 1);
+ j = (prev->size - 1);
+ while ((j >= 0) &&
+ (prev->data[j] == LY_BOLD_START_CHAR ||
+ prev->data[j] == LY_BOLD_END_CHAR ||
+ prev->data[j] == LY_UNDERLINE_START_CHAR ||
+ prev->data[j] == LY_UNDERLINE_END_CHAR ||
+ prev->data[j] == LY_SOFT_HYPHEN))
+ j--;
+ i = (j + 1);
+ while (j >= 0 &&
+ isdigit((unsigned char)prev->data[j])) {
+ j--;
+ NumSize++;
+ }
+ while (j < 0) {
+ j++;
+ NumSize--;
+ }
+ if (prev->data[j] == '[') {
+ /*
+ * The numbered bracket started on the
+ * previous line, and part of it was
+ * wrapped to this line. - FM
+ */
+ NumSize++;
+ l = (i - j);
+ while (i < prev->size)
+ start->data[j++] = start->data[i++];
+ text->chars -= l;
+ for (anc = a; anc; anc = anc->next) {
+ anc->start -= l;
+ }
+ prev->size = j;
+ prev->data[j] = '\0';
+ while (j < i)
+ start->data[j++] = '\0';
+ j = 0;
+ i = k;
+ while (k < start->size)
+ start->data[j++] = start->data[k++];
+ if (start != last)
+ text->chars -= i;
+ for (anc = a; anc; anc = anc->next) {
+ anc->start -= i;
+ anc->line_pos -= i;
+ }
+ start->size = j;
+ start->data[j++] = '\0';
+ while (j < k)
+ start->data[j++] = '\0';
+ } else {
+ /*
+ * Shucks! We didn't find the
+ * numbered bracket. - FM
+ */
+ a->show_anchor = YES;
+ }
+ } else {
+ /*
+ * Shucks! We didn't find the
+ * numbered bracket. - FM
+ */
+ a->show_anchor = YES;
+ }
+ } else if (prev && prev->size > 2) {
+ j = (prev->size - 1);
+ while ((j >= 0) &&
+ (prev->data[j] == LY_BOLD_START_CHAR ||
+ prev->data[j] == LY_BOLD_END_CHAR ||
+ prev->data[j] == LY_UNDERLINE_START_CHAR ||
+ prev->data[j] == LY_UNDERLINE_END_CHAR ||
+ prev->data[j] == LY_SOFT_HYPHEN))
+ j--;
+ if (j < 0)
+ j = 0;
+ i = (j + 1);
+ if ((j > 2) &&
+ (prev->data[j] == ']' &&
+ isdigit((unsigned char)prev->data[j - 1]))) {
+ j--;
+ NumSize++;
+ k = (j + 1);
+ while (j >= 0 &&
+ isdigit((unsigned char)prev->data[j])) {
+ j--;
+ NumSize++;
+ }
+ while (j < 0) {
+ j++;
+ NumSize--;
+ }
+ if (prev->data[j] == '[') {
+ /*
+ * The numbered bracket is all on the
+ * previous line, and the anchor content
+ * was wrapped to the last line. - FM
+ */
+ NumSize++;
+ k = j + NumSize;
+ while (k < prev->size)
+ prev->data[j++] = prev->data[k++];
+ text->chars -= NumSize;
+ for (anc = a; anc; anc = anc->next) {
+ anc->start -= NumSize;
+ }
+ prev->size = j;
+ prev->data[j++] = '\0';
+ while (j < k)
+ start->data[j++] = '\0';
+ } else {
+ /*
+ * Shucks! We didn't find the
+ * numbered bracket. - FM
+ */
+ a->show_anchor = YES;
+ }
+ } else {
+ /*
+ * Shucks! We didn't find the
+ * numbered bracket. - FM
+ */
+ a->show_anchor = YES;
+ }
+ } else {
+ /*
+ * Shucks! We didn't find the
+ * numbered bracket. - FM
+ */
+ a->show_anchor = YES;
+ }
+ }
+ } else {
+ /*
+ * The anchor's content is not restricted to only
+ * white and special characters, so we'll show it
+ * as a link. - FM
+ */
+ a->show_anchor = YES;
+ }
+ if (a->show_anchor == NO) {
+ /*
+ * The anchor's content is restricted to white
+ * and special characters, so set it's number
+ * and extent to zero, decrement the visible
+ * anchor number counter, and add this anchor
+ * to the hidden links list. - FM
+ */
+ a->extent = 0;
+ if (text->hiddenlinkflag != HIDDENLINKS_MERGE) {
+ a->number = 0;
+ text->last_anchor_number--;
+ HText_AddHiddenLink(text, a);
+ }
+ } else {
+ /*
+ * The anchor's content is not restricted to white
+ * and special characters, so we'll display the
+ * content, but shorten it's extent by any trailing
+ * blank lines we've detected. - FM
+ */
+ a->extent -= ((BlankExtent < a->extent) ?
+ BlankExtent : 0);
+ }
+ } else {
+ /*
+ * It's a named anchor without an HREF, so it
+ * should be registered but not shown as a
+ * link. - FM
+ */
+ a->show_anchor = NO;
+ a->extent = 0;
+ }
+}
+
+
+PUBLIC void HText_appendText ARGS2(
+ HText *, text,
+ CONST char *, str)
+{
+ CONST char *p;
+
+ if (str == NULL)
+ return;
+
+ if (text->halted == 3)
+ return;
+
+ for (p = str; *p; p++) {
+ HText_appendCharacter(text, *p);
+ }
+}
+
+
+PRIVATE void remove_special_attr_chars ARGS1(
+ char *, buf)
+{
+ register char *cp;
+
+ for (cp = buf; *cp != '\0' ; cp++) {
+ /*
+ * Don't print underline chars.
+ */
+ if (!IsSpecialAttrChar(*cp)) {
+ *buf = *cp,
+ buf++;
+ }
+ }
+ *buf = '\0';
+}
+
+
+/*
+** This function trims blank lines from the end of the document, and
+** then gets the hightext from the text by finding the char position,
+** and brings the anchors in line with the text by adding the text
+** offset to each of the anchors.
+*/
+PUBLIC void HText_endAppend ARGS1(
+ HText *, text)
+{
+ int cur_line, cur_char, cur_shift, len;
+ TextAnchor *anchor_ptr;
+ HTLine *line_ptr;
+ unsigned char ch;
+
+ if (!text)
+ return;
+ if (TRACE)
+ fprintf(stderr,"Gridtext: Entering HText_endAppend\n");
+
+ /*
+ * Create a blank line at the bottom.
+ */
+ new_line(text);
+
+ if (text->halted) {
+ /*
+ * If output was stopped because memory was low, and we made
+ * it to the end of the document, reset those flags and hope
+ * things are better now. - kw
+ */
+ LYFakeZap(NO);
+ text->halted = 0;
+ }
+
+ /*
+ * Get the first line.
+ */
+ line_ptr = text->last_line->next;
+ cur_char = line_ptr->size;
+ cur_line = 0;
+ cur_shift = 0;
+
+ /*
+ * Remove the blank lines at the end of document.
+ */
+ while (text->last_line->data[0] == '\0' && text->Lines > 2) {
+ HTLine *next_to_the_last_line = text->last_line->prev;
+
+ if (TRACE)
+ fprintf(stderr, "GridText: Removing bottom blank line: %s\n",
+ text->last_line->data);
+ /*
+ * line_ptr points to the first line.
+ */
+ next_to_the_last_line->next = line_ptr;
+ line_ptr->prev = next_to_the_last_line;
+ FREE(text->last_line);
+ text->last_line = next_to_the_last_line;
+ text->Lines--;
+#ifdef NOTUSED_BAD_FOR_SCREEN
+ if (TRACE) {
+ fprintf(stderr, "GridText: New bottom line: %s\n",
+ text->last_line->data);
+ }
+#endif
+ }
+
+ /*
+ * Fix up the anchor structure values and
+ * create the hightext strings. - FM
+ */
+ for (anchor_ptr = text->first_anchor;
+ anchor_ptr; anchor_ptr=anchor_ptr->next) {
+re_parse:
+ /*
+ * Find the right line.
+ */
+ for (; anchor_ptr->start >= cur_char;
+ line_ptr = line_ptr->next,
+ cur_char += line_ptr->size+1,
+ cur_line++) {
+ ; /* null body */
+ }
+ if (anchor_ptr->start == cur_char) {
+ anchor_ptr->line_pos = line_ptr->size;
+ } else {
+ anchor_ptr->line_pos = anchor_ptr->start -
+ (cur_char - line_ptr->size);
+ }
+ if (anchor_ptr->line_pos < 0)
+ anchor_ptr->line_pos = 0;
+ if (TRACE)
+ fprintf(stderr, "Gridtext: Anchor found on line:%d col:%d\n",
+ cur_line, anchor_ptr->line_pos);
+
+ /*
+ * Strip off any spaces or SpecialAttrChars at the beginning,
+ * if they exist, but only on HYPERTEXT_ANCHORS.
+ */
+ if (anchor_ptr->link_type & HYPERTEXT_ANCHOR) {
+ ch = (unsigned char)line_ptr->data[anchor_ptr->line_pos];
+ while (isspace(ch) ||
+ IsSpecialAttrChar(ch)) {
+ anchor_ptr->line_pos++;
+ anchor_ptr->extent--;
+ cur_shift++;
+ ch = (unsigned char)line_ptr->data[anchor_ptr->line_pos];
+ }
+ }
+ if (anchor_ptr->extent < 0) {
+ anchor_ptr->extent = 0;
+ }
+#ifdef NOTUSED_BAD_FOR_SCREEN
+ if (TRACE)
+ fprintf(stderr, "anchor text: '%s' pos: %d\n",
+ line_ptr->data, anchor_ptr->line_pos);
+#endif
+ /*
+ * If the link begins with an end of line and we have more
+ * lines, then start the highlighting on the next line. - FM
+ */
+ if (anchor_ptr->line_pos >= strlen(line_ptr->data) &&
+ cur_line < text->Lines) {
+ anchor_ptr->start += (cur_shift + 1);
+ cur_shift = 0;
+ if (TRACE)
+ fprintf(stderr, "found anchor at end of line\n");
+ goto re_parse;
+ }
+ cur_shift = 0;
+#ifdef NOTUSED_BAD_FOR_SCREEN
+ if (TRACE)
+ fprintf(stderr, "anchor text: '%s' pos: %d\n",
+ line_ptr->data, anchor_ptr->line_pos);
+#endif
+ /*
+ * Copy the link name into the data structure.
+ */
+ if (line_ptr->data &&
+ anchor_ptr->extent > 0 && anchor_ptr->line_pos >= 0) {
+ StrnAllocCopy(anchor_ptr->hightext,
+ &line_ptr->data[anchor_ptr->line_pos],
+ anchor_ptr->extent);
+ } else {
+ StrAllocCopy(anchor_ptr->hightext, "");
+ }
+
+ /*
+ * If true the anchor extends over two lines,
+ * copy that into the data structure.
+ */
+ if (anchor_ptr->extent > strlen(anchor_ptr->hightext)) {
+ HTLine *line_ptr2 = line_ptr->next;
+ /*
+ * Double check that we have a line pointer,
+ * and if so, copy into hightext2.
+ */
+ if (line_ptr2) {
+ StrnAllocCopy(anchor_ptr->hightext2,
+ line_ptr2->data,
+ (anchor_ptr->extent -
+ strlen(anchor_ptr->hightext)));
+ anchor_ptr->hightext2offset = line_ptr2->offset;
+ remove_special_attr_chars(anchor_ptr->hightext2);
+ if (anchor_ptr->link_type & HYPERTEXT_ANCHOR) {
+ if ((len = strlen(anchor_ptr->hightext2)) > 0) {
+ len--;
+ while (len >= 0 &&
+ isspace((unsigned char)
+ anchor_ptr->hightext2[len])) {
+ anchor_ptr->hightext2[len] = '\0';
+ len--;
+ }
+ }
+ if (len <= 0 && anchor_ptr->hightext2[0] == '\0') {
+ FREE(anchor_ptr->hightext2);
+ anchor_ptr->hightext2offset = 0;
+ }
+ }
+ }
+ }
+ remove_special_attr_chars(anchor_ptr->hightext);
+ if (anchor_ptr->link_type & HYPERTEXT_ANCHOR) {
+ if ((len = strlen(anchor_ptr->hightext)) > 0) {
+ len--;
+ while (len >= 0 &&
+ isspace((unsigned char)anchor_ptr->hightext[len])) {
+ anchor_ptr->hightext[len] = '\0';
+ len--;
+ }
+ }
+ }
+
+ /*
+ * Subtract any formatting characters from the x position
+ * of the link.
+ */
+ if (anchor_ptr->line_pos > 0) {
+ register int offset = 0, i = 0;
+ for (; i < anchor_ptr->line_pos; i++)
+ if (IS_UTF_EXTRA(line_ptr->data[i]) ||
+ IsSpecialAttrChar(line_ptr->data[i]))
+ offset++;
+ anchor_ptr->line_pos -= offset;
+ }
+
+ /*
+ * Add the offset, and set the line number.
+ */
+ anchor_ptr->line_pos += line_ptr->offset;
+ anchor_ptr->line_num = cur_line;
+ if (TRACE)
+ fprintf(stderr,
+ "GridText: adding link on line %d in HText_endAppend\n",
+ cur_line);
+
+ /*
+ * If this is the last anchor, we're done!
+ */
+ if (anchor_ptr == text->last_anchor)
+ break;
+ }
+}
+
+
+/* Dump diagnostics to stderr
+*/
+PUBLIC void HText_dump ARGS1(
+ HText *, text GCC_UNUSED)
+{
+ fprintf(stderr, "HText: Dump called\n");
+}
+
+
+/* Return the anchor associated with this node
+*/
+PUBLIC HTParentAnchor * HText_nodeAnchor ARGS1(
+ HText *, text)
+{
+ return text->node_anchor;
+}
+
+/* GridText specials
+** =================
+*/
+/*
+ * HTChildAnchor() returns the anchor with index N.
+ * The index corresponds to the [number] we print for the anchor.
+ */
+PUBLIC HTChildAnchor * HText_childNumber ARGS1(
+ int, number)
+{
+ TextAnchor * a;
+
+ if (!(HTMainText && HTMainText->first_anchor) || number <= 0)
+ return (HTChildAnchor *)0; /* Fail */
+
+ for (a = HTMainText->first_anchor; a; a = a->next) {
+ if (a->number == number)
+ return(a->anchor);
+ }
+ return (HTChildAnchor *)0; /* Fail */
+}
+
+/*
+ * HText_FormDescNumber() returns a description of the form field
+ * with index N. The index corresponds to the [number] we print
+ * for the field. - FM & LE
+ */
+PUBLIC void HText_FormDescNumber ARGS2(
+ int, number,
+ char **, desc)
+{
+ TextAnchor * a;
+
+ if (!desc)
+ return;
+
+ if (!(HTMainText && HTMainText->first_anchor) || number <= 0) {
+ *desc = "unknown field or link";
+ return;
+ }
+
+ for (a = HTMainText->first_anchor; a; a = a->next) {
+ if (a->number == number) {
+ if (!(a->input_field && a->input_field->type)) {
+ *desc = "unknown field or link";
+ return;
+ }
+ break;
+ }
+ }
+
+ switch (a->input_field->type) {
+ case F_TEXT_TYPE:
+ *desc = "text entry field";
+ return;
+ case F_PASSWORD_TYPE:
+ *desc = "password entry field";
+ return;
+ case F_CHECKBOX_TYPE:
+ *desc = "checkbox";
+ return;
+ case F_RADIO_TYPE:
+ *desc = "radio button";
+ return;
+ case F_SUBMIT_TYPE:
+ *desc = "submit button";
+ return;
+ case F_RESET_TYPE:
+ *desc = "reset button";
+ return;
+ case F_OPTION_LIST_TYPE:
+ *desc = "popup menu";
+ return;
+ case F_HIDDEN_TYPE:
+ *desc = "hidden form field";
+ return;
+ case F_TEXTAREA_TYPE:
+ *desc = "text entry area";
+ return;
+ case F_RANGE_TYPE:
+ *desc = "range entry field";
+ return;
+ case F_FILE_TYPE:
+ *desc = "file entry field";
+ return;
+ case F_TEXT_SUBMIT_TYPE:
+ *desc = "text-submit field";
+ return;
+ case F_IMAGE_SUBMIT_TYPE:
+ *desc = "image-submit button";
+ return;
+ case F_KEYGEN_TYPE:
+ *desc = "keygen field";
+ return;
+ default:
+ *desc = "unknown form field";
+ return;
+ }
+}
+
+/*
+ * HTGetLinkInfo returns some link info based on the number.
+ *
+ * If want_go is not NULL, caller requests to know a line number for
+ * the link indicated by number. It will be returned in *go_line, and
+ * *linknum will be set to an index into the links[] array, to use after
+ * the line in *line has been made the new top screen line.
+ * *hightext and *lname are unchanged. - KW
+ *
+ * If want_go is 0 and the number doesn't represent an input field, info
+ * on the link indicated by number is deposited in *hightext and *lname.
+ */
+PUBLIC int HTGetLinkInfo ARGS6(
+ int, number,
+ int, want_go,
+ int *, go_line,
+ int *, linknum,
+ char **, hightext,
+ char **, lname)
+{
+ TextAnchor *a;
+ HTAnchor *link_dest;
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ HTAnchor *link_dest_intl = NULL;
+#endif
+ int anchors_this_line = 0, anchors_this_screen = 0;
+ int prev_anchor_line = -1, prev_prev_anchor_line = -1;
+
+ if (!HTMainText)
+ return(NO);
+
+ for (a = HTMainText->first_anchor; a; a = a->next) {
+ /*
+ * Count anchors, first on current line if there is more
+ * than one. We have to count all links, including form
+ * field anchors and others with a->number == 0, because
+ * they are or will be included in the links[] array.
+ * The exceptions are hidden form fields and anchors with
+ * show_anchor not set, because they won't appear in links[]
+ * and don't count towards nlinks. - KW
+ */
+ if ((a->show_anchor) &&
+ (a->link_type != INPUT_ANCHOR ||
+ a->input_field->type != F_HIDDEN_TYPE)) {
+ if (a->line_num == prev_anchor_line) {
+ anchors_this_line++;
+ } else {
+ /*
+ * This anchor is on a different line than the previous one.
+ * Remember which was the line number of the previous anchor,
+ * for use in screen positioning later. - KW
+ */
+ anchors_this_line = 1;
+ prev_prev_anchor_line = prev_anchor_line;
+ prev_anchor_line = a->line_num;
+ }
+ if (a->line_num >= HTMainText->top_of_screen) {
+ /*
+ * Count all anchors starting with the top line of the
+ * currently displayed screen. Just keep on counting
+ * beyond this screen's bottom line - we'll know whether
+ * a found anchor is below the current screen by a check
+ * against nlinks later. - KW
+ */
+ anchors_this_screen++;
+ }
+ }
+
+ if (a->number == number) {
+ /*
+ * We found it. Now process it, depending
+ * on what kind of info is requested. - KW
+ */
+ if (want_go || a->link_type == INPUT_ANCHOR) {
+ if (a->show_anchor == NO) {
+ /*
+ * The number requested has been assigned to an anchor
+ * without any selectable text, so we cannot position
+ * on it. The code for suppressing such anchors in
+ * HText_endAnchor() may not have applied, or it may
+ * have failed. Return a failure indication so that
+ * the user will notice that something is wrong,
+ * instead of positioning on some other anchor which
+ * might result in inadvertent activation. - KW
+ */
+ return(NO);
+ }
+ if (anchors_this_screen > 0 &&
+ anchors_this_screen <= nlinks &&
+ a->line_num >= HTMainText->top_of_screen &&
+ a->line_num < HTMainText->top_of_screen+(display_lines)) {
+ /*
+ * If the requested anchor is within the current screen,
+ * just set *go_line so that the screen window won't move
+ * (keep it as it is), and set *linknum to the index of
+ * this link in the current links[] array. - KW
+ */
+ *go_line = HTMainText->top_of_screen;
+ if (linknum)
+ *linknum = anchors_this_screen - 1;
+ } else {
+ /*
+ * if the requested anchor is not within the currently
+ * displayed screen, set *go_line such that the top line
+ * will be either
+ * (1) the line immediately below the previous
+ * anchor, or
+ * (2) about one third of a screenful above the line
+ * with the target, or
+ * (3) the first line of the document -
+ * whichever comes last. In all cases the line with our
+ * target will end up being the first line with any links
+ * on the new screen, so that we can use the
+ * anchors_this_line counter to point to the anchor in
+ * the new links[] array. - kw
+ */
+ int max_offset = SEARCH_GOAL_LINE - 1;
+ if (max_offset < 0)
+ max_offset = 0;
+ else if (max_offset >= display_lines)
+ max_offset = display_lines - 1;
+ *go_line = prev_anchor_line - max_offset;
+ if (*go_line <= prev_prev_anchor_line)
+ *go_line = prev_prev_anchor_line + 1;
+ if (*go_line < 0)
+ *go_line = 0;
+ if (linknum)
+ *linknum = anchors_this_line - 1;
+ }
+ return(LINK_LINE_FOUND);
+ } else {
+ *hightext= a->hightext;
+ link_dest = HTAnchor_followMainLink((HTAnchor *)a->anchor);
+ {
+ char *cp_freeme = NULL;
+ if (traversal) {
+ cp_freeme = stub_HTAnchor_address(link_dest);
+ } else {
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (a->link_type == INTERNAL_LINK_ANCHOR) {
+ link_dest_intl = HTAnchor_followTypedLink(
+ (HTAnchor *)a->anchor, LINK_INTERNAL);
+ if (link_dest_intl && link_dest_intl != link_dest) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTGetLinkInfo: unexpected typed link to %s!\n",
+ link_dest_intl->parent->address);
+ link_dest_intl = NULL;
+ }
+ }
+ if (link_dest_intl) {
+ char *cp2 = HTAnchor_address(link_dest_intl);
+ FREE(*lname);
+ *lname = cp2;
+ return(WWW_INTERN_LINK_TYPE);
+ } else
+#endif
+ cp_freeme = HTAnchor_address(link_dest);
+ }
+ StrAllocCopy(*lname, cp_freeme);
+ FREE(cp_freeme);
+ }
+ return(WWW_LINK_TYPE);
+ }
+ }
+ }
+ return(NO);
+}
+
+/*
+ * This function finds the line indicated by line_num in the
+ * HText structure indicated by text, and searches that line
+ * for the first hit with the string indicated by target. If
+ * there is no hit, FALSE is returned. If there is a hit, then
+ * a copy of the line starting at that first hit is loaded into
+ * *data with all IsSpecial characters stripped, it's offset and
+ * the printable target length (without IsSpecial, or extra CJK
+ * or utf8 characters) are loaded into *offset and *tLen, and
+ * TRUE is returned. - FM
+ */
+PUBLIC BOOL HText_getFirstTargetInLine ARGS7(
+ HText *, text,
+ int, line_num,
+ BOOL, utf_flag,
+ int *, offset,
+ int *, tLen,
+ char **, data,
+ char *, target)
+{
+ HTLine *line;
+ char *LineData;
+ int LineOffset, HitOffset, LenNeeded, i;
+ char *cp;
+
+ /*
+ * Make sure we have an HText structure, that line_num is
+ * in its range, and that we have a target string. - FM
+ */
+ if (!(text && line_num >= 0 && line_num <= text->Lines &&
+ target && *target))
+ return(FALSE);
+
+ /*
+ * Find the line and set up its data and offset - FM
+ */
+ for (i = 0, line = text->last_line->next;
+ i < line_num && (line != text->last_line);
+ i++, line = line->next) {
+ if (line->next == NULL) {
+ return(FALSE);
+ }
+ }
+ if (!line && line->data[0])
+ return(FALSE);
+ LineData = (char *)line->data;
+ LineOffset = (int)line->offset;
+
+ /*
+ * If the target is on the line, load the offset of
+ * its first character and the subsequent line data,
+ * strip any special characters from the loaded line
+ * data, and return TRUE. - FM
+ */
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(LineData,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(LineData,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (LineOffset + LenNeeded) < LYcols) {
+ /*
+ * We had a hit so load the results,
+ * remove IsSpecial characters from
+ * the allocated data string, and
+ * return TRUE. - FM
+ */
+ *offset = (LineOffset + HitOffset);
+ *tLen = (LenNeeded - HitOffset);
+ StrAllocCopy(*data, cp);
+ remove_special_attr_chars(*data);
+ return(TRUE);
+ }
+
+ /*
+ * The line does not contain the target. - FM
+ */
+ return(FALSE);
+}
+
+/*
+ * HText_getNumOfLines returns the number of lines in the
+ * current document.
+ */
+PUBLIC int HText_getNumOfLines NOARGS
+{
+ return(HTMainText ? HTMainText->Lines : 0);
+}
+
+/*
+ * HText_getTitle returns the title of the
+ * current document.
+ */
+PUBLIC char * HText_getTitle NOARGS
+{
+ return(HTMainText ?
+ (char *) HTAnchor_title(HTMainText->node_anchor) : NULL);
+}
+
+#ifdef USE_HASH
+PUBLIC char *HText_getStyle NOARGS
+{
+ return(HTMainText ?
+ (char *) HTAnchor_style(HTMainText->node_anchor) : NULL);
+}
+#endif
+
+/*
+ * HText_getSugFname returns the suggested filename of the current
+ * document (normally derived from a Content-Disposition header with
+ * attachment; filename=name.suffix). - FM
+ */
+PUBLIC char * HText_getSugFname NOARGS
+{
+ return(HTMainText ?
+ (char *) HTAnchor_SugFname(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HTCheckFnameForCompression receives the address of an allocated
+ * string containing a filename, and an anchor pointer, and expands
+ * or truncates the string's suffix if appropriate, based on whether
+ * the anchor indicates that the file is compressed. We assume
+ * that the file was not uncompressed (as when downloading), and
+ * believe the headers about whether it's compressed or not. - FM
+ *
+ * Added third arg - if strip_ok is FALSE, we don't trust the anchor
+ * info enough to remove a compression suffix if the anchor object
+ * does not indicate compression. - kw
+ */
+PUBLIC void HTCheckFnameForCompression ARGS3(
+ char **, fname,
+ HTParentAnchor *, anchor,
+ BOOL, strip_ok)
+{
+ char *fn = *fname;
+ char *dot = NULL, *cp = NULL;
+ CONST char *ct = NULL;
+ CONST char *ce = NULL;
+ BOOLEAN method = 0;
+
+ /*
+ * Make sure we have a string and anchor. - FM
+ */
+ if (!(fn && *fn && anchor))
+ return;
+
+ /*
+ * Make sure we have a file, not directory, name. -FM
+ */
+ if ((cp = strrchr(fn, '/')) != NULL) {
+ fn = (cp +1);
+ if (*fn == '\0') {
+ return;
+ }
+ }
+
+ /*
+ * Check the anchor's content_type and content_encoding
+ * elements for a gzip or Unix compressed file. - FM
+ */
+ ct = HTAnchor_content_type(anchor);
+ ce = HTAnchor_content_encoding(anchor);
+ if (ce == NULL) {
+ /*
+ * No Content-Encoding, so check
+ * the Content-Type. - FM
+ */
+ if (!strncasecomp((ct ? ct : ""), "application/gzip", 16) ||
+ !strncasecomp((ct ? ct : ""), "application/x-gzip", 18)) {
+ method = 1;
+ } else if (!strncasecomp((ct ? ct : ""),
+ "application/compress", 20) ||
+ !strncasecomp((ct ? ct : ""),
+ "application/x-compress", 22)) {
+ method = 2;
+ }
+ } else if (!strcasecomp(ce, "gzip") ||
+ !strcasecomp(ce, "x-gzip")) {
+ /*
+ * It's gzipped. - FM
+ */
+ method = 1;
+ } else if (!strcasecomp(ce, "compress") ||
+ !strcasecomp(ce, "x-compress")) {
+ /*
+ * It's Unix compressed. - FM
+ */
+ method = 2;
+ }
+
+ /*
+ * If no Content-Encoding has been detected via the anchor
+ * pointer, but strip_ok is not set, there is nothing left
+ * to do. - kw
+ */
+ if (method == 0 && !strip_ok)
+ return;
+
+ /*
+ * Seek the last dot, and check whether
+ * we have a gzip or compress suffix. - FM
+ */
+ if ((dot = strrchr(fn, '.')) != NULL) {
+ if (!strcasecomp(dot, ".tgz") ||
+ !strcasecomp(dot, ".gz") ||
+ !strcasecomp(dot, ".Z")) {
+ if (!method) {
+ /*
+ * It has a suffix which signifies a gzipped
+ * or compressed file for us, but the anchor
+ * claims otherwise, so tweak the suffix. - FM
+ */
+ cp = (dot + 1);
+ *dot = '\0';
+ if (!strcasecomp(cp, "tgz")) {
+ StrAllocCat(*fname, ".tar");
+ }
+ }
+ return;
+ }
+ if (strlen(dot) > 4) {
+ cp = ((dot + strlen(dot)) - 3);
+ if (!strcasecomp(cp, "-gz") ||
+ !strcasecomp(cp, "_gz")) {
+ if (!method) {
+ /*
+ * It has a tail which signifies a gzipped
+ * file for us, but the anchor claims otherwise,
+ * so tweak the suffix. - FM
+ */
+ *dot = '\0';
+ } else {
+ /*
+ * The anchor claims it's gzipped, and we
+ * believe it, so force this tail to the
+ * conventional suffix. - FM
+ */
+#ifdef VMS
+ *cp = '-';
+#else
+ *cp = '.';
+#endif /* VMS */
+ cp++;
+ *cp = TOLOWER(*cp);
+ cp++;
+ *cp = TOLOWER(*cp);
+ }
+ return;
+ }
+ }
+ if (strlen(dot) > 3) {
+ cp = ((dot + strlen(dot)) - 2);
+ if (!strcasecomp(cp, "-Z") ||
+ !strcasecomp(cp, "_Z")) {
+ if (!method) {
+ /*
+ * It has a tail which signifies a compressed
+ * file for us, but the anchor claims otherwise,
+ * so tweak the suffix. - FM
+ */
+ *dot = '\0';
+ } else {
+ /*
+ * The anchor claims it's compressed, and
+ * we believe it, so force this tail to the
+ * conventional suffix. - FM
+ */
+#ifdef VMS
+ *cp = '-';
+#else
+ *cp = '.';
+#endif /* VMS */
+ cp++;
+ *cp = TOUPPER(*cp);
+ }
+ return;
+ }
+ }
+ }
+ if (!method) {
+ /*
+ * Don't know what compression method
+ * was used, if any, so we won't do
+ * anything. - FM
+ */
+ return;
+ }
+
+ /*
+ * Add the appropriate suffix. - FM
+ */
+ if (!dot) {
+ StrAllocCat(*fname, ((method == 1) ? ".gz" : ".Z"));
+ return;
+ }
+ dot++;
+ if (*dot == '\0') {
+ StrAllocCat(*fname, ((method == 1) ? "gz" : "Z"));
+ return;
+ }
+#ifdef VMS
+ StrAllocCat(*fname, ((method == 1) ? "-gz" : "-Z"));
+#else
+ StrAllocCat(*fname, ((method == 1) ? ".gz" : ".Z"));
+#endif /* !VMS */
+ return;
+}
+
+/*
+ * HText_getLastModified returns the Last-Modified header
+ * if available, for the current document. - FM
+ */
+PUBLIC char * HText_getLastModified NOARGS
+{
+ return(HTMainText ?
+ (char *) HTAnchor_last_modified(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HText_getDate returns the Date header
+ * if available, for the current document. - FM
+ */
+PUBLIC char * HText_getDate NOARGS
+{
+ return(HTMainText ?
+ (char *) HTAnchor_date(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HText_getServer returns the Server header
+ * if available, for the current document. - FM
+ */
+PUBLIC char * HText_getServer NOARGS
+{
+ return(HTMainText ?
+ (char *)HTAnchor_server(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HText_pageDisplay displays a screen of text
+ * starting from the line 'line_num'-1
+ * this is the primary call for lynx
+ */
+PUBLIC void HText_pageDisplay ARGS2(
+ int, line_num,
+ char *, target)
+{
+ display_page(HTMainText, line_num-1, target);
+
+ is_www_index = HTAnchor_isIndex(HTMainAnchor);
+}
+
+/*
+ * Return YES if we have a whereis search target on the displayed
+ * page. - kw
+ */
+PUBLIC BOOL HText_pageHasPrevTarget NOARGS
+{
+ if (!HTMainText)
+ return NO;
+ else
+ return HTMainText->page_has_target;
+}
+
+/*
+ * HText_LinksInLines returns the number of links in the
+ * 'Lines' number of lines beginning with 'line_num'-1. - FM
+ */
+PUBLIC int HText_LinksInLines ARGS3(
+ HText *, text,
+ int, line_num,
+ int, Lines)
+{
+ int total = 0;
+ int start = (line_num - 1);
+ int end = (start + Lines);
+ TextAnchor *Anchor_ptr = NULL;
+
+ if (!text)
+ return total;
+
+ for (Anchor_ptr = text->first_anchor;
+ Anchor_ptr != NULL && Anchor_ptr->line_num <= end;
+ Anchor_ptr = Anchor_ptr->next) {
+ if (Anchor_ptr->line_num >= start &&
+ Anchor_ptr->line_num < end &&
+ Anchor_ptr->show_anchor &&
+ (Anchor_ptr->link_type != INPUT_ANCHOR ||
+ Anchor_ptr->input_field->type != F_HIDDEN_TYPE))
+ ++total;
+ if (Anchor_ptr == text->last_anchor)
+ break;
+ }
+
+ return total;
+}
+
+PUBLIC void HText_setStale ARGS1(
+ HText *, text)
+{
+ text->stale = YES;
+}
+
+PUBLIC void HText_refresh ARGS1(
+ HText *, text)
+{
+ if (text->stale)
+ display_page(text, text->top_of_screen, "");
+}
+
+PUBLIC int HText_sourceAnchors ARGS1(
+ HText *, text)
+{
+ return (text ? text->last_anchor_number : -1);
+}
+
+PUBLIC BOOL HText_canScrollUp ARGS1(
+ HText *, text)
+{
+ return (text->top_of_screen != 0);
+}
+
+PUBLIC BOOL HText_canScrollDown NOARGS
+{
+ HText * text = HTMainText;
+
+ return ((text->top_of_screen + display_lines) < text->Lines+1);
+}
+
+/* Scroll actions
+*/
+PUBLIC void HText_scrollTop ARGS1(
+ HText *, text)
+{
+ display_page(text, 0, "");
+}
+
+PUBLIC void HText_scrollDown ARGS1(
+ HText *, text)
+{
+ display_page(text, text->top_of_screen + display_lines, "");
+}
+
+PUBLIC void HText_scrollUp ARGS1(
+ HText *, text)
+{
+ display_page(text, text->top_of_screen - display_lines, "");
+}
+
+PUBLIC void HText_scrollBottom ARGS1(
+ HText *, text)
+{
+ display_page(text, text->Lines - display_lines, "");
+}
+
+
+/* Browsing functions
+** ==================
+*/
+
+/* Bring to front and highlight it
+*/
+PRIVATE int line_for_char ARGS2(
+ HText *, text,
+ int, char_num)
+{
+ int line_number = 0;
+ int characters = 0;
+ HTLine * line = text->last_line->next;
+ for (;;) {
+ if (line == text->last_line) return 0; /* Invalid */
+ characters = characters + line->size + 1;
+ if (characters > char_num) return line_number;
+ line_number ++;
+ line = line->next;
+ }
+}
+
+PUBLIC BOOL HText_select ARGS1(
+ HText *, text)
+{
+ if (text != HTMainText) {
+ HTMainText = text;
+ HTMainAnchor = text->node_anchor;
+
+ /*
+ * Reset flag for whereis search string - cannot be true here
+ * since text is not our HTMainText. - kw
+ */
+ if (text)
+ text->page_has_target = NO;
+ /*
+ * Make this text the most current in the loaded texts list. - FM
+ */
+ if (loaded_texts && HTList_removeObject(loaded_texts, text))
+ HTList_addObject(loaded_texts, text);
+ /* let lynx do it */
+ /* display_page(text, text->top_of_screen, ""); */
+ }
+ return YES;
+}
+
+/*
+ * This function returns TRUE if doc's post_data, address
+ * and isHEAD elements are identical to those of a loaded
+ * (memory cached) text. - FM
+ */
+PUBLIC BOOL HText_POSTReplyLoaded ARGS1(
+ document *, doc)
+{
+ HText *text = NULL;
+ HTList *cur = loaded_texts;
+ char *post_data, *address;
+ BOOL is_head;
+
+ /*
+ * Make sure we have the structures. - FM
+ */
+ if (!cur || !doc)
+ return(FALSE);
+
+ /*
+ * Make sure doc is for a POST reply. - FM
+ */
+ if ((post_data = doc->post_data) == NULL ||
+ (address = doc->address) == NULL)
+ return(FALSE);
+ is_head = doc->isHEAD;
+
+ /*
+ * Loop through the loaded texts looking for a
+ * POST reply match. - FM
+ */
+ while (NULL != (text = (HText *)HTList_nextObject(cur))) {
+ if (text->node_anchor &&
+ text->node_anchor->post_data &&
+ !strcmp(post_data, text->node_anchor->post_data) &&
+ text->node_anchor->address &&
+ !strcmp(address, text->node_anchor->address) &&
+ is_head == text->node_anchor->isHEAD) {
+ return(TRUE);
+ }
+ }
+
+ return(FALSE);
+}
+
+PUBLIC BOOL HTFindPoundSelector ARGS1(
+ char *, selector)
+{
+ TextAnchor * a;
+
+ for (a=HTMainText->first_anchor; a; a=a->next) {
+
+ if (a->anchor && a->anchor->tag)
+ if (!strcmp(a->anchor->tag, selector)) {
+
+ www_search_result = a->line_num+1;
+ if (TRACE)
+ fprintf(stderr,
+ "HText: Selecting anchor [%d] at character %d, line %d\n",
+ a->number, a->start, www_search_result);
+ if (!strcmp(selector, LYToolbarName))
+ --www_search_result;
+
+ return(YES);
+ }
+ }
+
+ return(NO);
+
+}
+
+PUBLIC BOOL HText_selectAnchor ARGS2(
+ HText *, text,
+ HTChildAnchor *, anchor)
+{
+ TextAnchor * a;
+
+/* This is done later, hence HText_select is unused in GridText.c
+ Should it be the contrary ? @@@
+ if (text != HTMainText) {
+ HText_select(text);
+ }
+*/
+
+ for (a=text->first_anchor; a; a=a->next) {
+ if (a->anchor == anchor) break;
+ }
+ if (!a) {
+ if (TRACE) fprintf(stderr, "HText: No such anchor in this text!\n");
+ return NO;
+ }
+
+ if (text != HTMainText) { /* Comment out by ??? */
+ HTMainText = text; /* Put back in by tbl 921208 */
+ HTMainAnchor = text->node_anchor;
+ }
+
+ {
+ int l = line_for_char(text, a->start);
+ if (TRACE) fprintf(stderr,
+ "HText: Selecting anchor [%d] at character %d, line %d\n",
+ a->number, a->start, l);
+
+ if ( !text->stale &&
+ (l >= text->top_of_screen) &&
+ ( l < text->top_of_screen + display_lines+1))
+ return YES;
+
+ www_search_result = l - (display_lines/3); /* put in global variable */
+ }
+
+ return YES;
+}
+
+
+/* Editing functions - NOT IMPLEMENTED
+** =================
+**
+** These are called from the application. There are many more functions
+** not included here from the original text object.
+*/
+
+/* Style handling:
+*/
+/* Apply this style to the selection
+*/
+PUBLIC void HText_applyStyle ARGS2(
+ HText *, me GCC_UNUSED,
+ HTStyle *, style GCC_UNUSED)
+{
+
+}
+
+
+/* Update all text with changed style.
+*/
+PUBLIC void HText_updateStyle ARGS2(
+ HText *, me GCC_UNUSED,
+ HTStyle *, style GCC_UNUSED)
+{
+
+}
+
+
+/* Return style of selection
+*/
+PUBLIC HTStyle * HText_selectionStyle ARGS2(
+ HText *, me GCC_UNUSED,
+ HTStyleSheet *, sheet GCC_UNUSED)
+{
+ return 0;
+}
+
+
+/* Paste in styled text
+*/
+PUBLIC void HText_replaceSel ARGS3(
+ HText *, me GCC_UNUSED,
+ CONST char *, aString GCC_UNUSED,
+ HTStyle *, aStyle GCC_UNUSED)
+{
+}
+
+
+/* Apply this style to the selection and all similarly formatted text
+** (style recovery only)
+*/
+PUBLIC void HTextApplyToSimilar ARGS2(
+ HText *, me GCC_UNUSED,
+ HTStyle *, style GCC_UNUSED)
+{
+
+}
+
+
+/* Select the first unstyled run.
+** (style recovery only)
+*/
+PUBLIC void HTextSelectUnstyled ARGS2(
+ HText *, me GCC_UNUSED,
+ HTStyleSheet *, sheet GCC_UNUSED)
+{
+
+}
+
+
+/* Anchor handling:
+*/
+PUBLIC void HText_unlinkSelection ARGS1(
+ HText *, me GCC_UNUSED)
+{
+
+}
+
+PUBLIC HTAnchor * HText_referenceSelected ARGS1(
+ HText *, me GCC_UNUSED)
+{
+ return 0;
+}
+
+
+PUBLIC int HText_getTopOfScreen NOARGS
+{
+ HText * text = HTMainText;
+ return text->top_of_screen;
+}
+
+PUBLIC int HText_getLines ARGS1(
+ HText *, text)
+{
+ return text->Lines;
+}
+
+PUBLIC HTAnchor * HText_linkSelTo ARGS2(
+ HText *, me GCC_UNUSED,
+ HTAnchor *, anchor GCC_UNUSED)
+{
+ return 0;
+}
+
+/*
+ * Utility for freeing the list of previous isindex and whereis queries. - FM
+ */
+PUBLIC void HTSearchQueries_free NOARGS
+{
+ char *query;
+ HTList *cur = search_queries;
+
+ if (!cur)
+ return;
+
+ while (NULL != (query = (char *)HTList_nextObject(cur))) {
+ FREE(query);
+ }
+ HTList_delete(search_queries);
+ search_queries = NULL;
+ return;
+}
+
+/*
+ * Utility for listing isindex and whereis queries, making
+ * any repeated queries the most current in the list. - FM
+ */
+PUBLIC void HTAddSearchQuery ARGS1(
+ char *, query)
+{
+ char *new;
+ char *old;
+ HTList *cur;
+
+ if (!(query && *query))
+ return;
+
+ if ((new = (char *)calloc(1, (strlen(query) + 1))) == NULL)
+ outofmem(__FILE__, "HTAddSearchQuery");
+ strcpy(new, query);
+
+ if (!search_queries) {
+ search_queries = HTList_new();
+ atexit(HTSearchQueries_free);
+ HTList_addObject(search_queries, new);
+ return;
+ }
+
+ cur = search_queries;
+ while (NULL != (old = (char *)HTList_nextObject(cur))) {
+ if (!strcmp(old, new)) {
+ HTList_removeObject(search_queries, old);
+ FREE(old);
+ break;
+ }
+ }
+ HTList_addObject(search_queries, new);
+
+ return;
+}
+
+PUBLIC int do_www_search ARGS1(
+ document *, doc)
+{
+ char searchstring[256], temp[256], *cp, *tmpaddress = NULL;
+ int ch, recall, i;
+ int QueryTotal;
+ int QueryNum;
+ BOOLEAN PreviousSearch = FALSE;
+
+ /*
+ * Load the default query buffer
+ */
+ if ((cp=strchr(doc->address, '?')) != NULL) {
+ /*
+ * This is an index from a previous search.
+ * Use its query as the default.
+ */
+ PreviousSearch = TRUE;
+ strcpy(searchstring, ++cp);
+ for (cp=searchstring; *cp; cp++)
+ if (*cp == '+')
+ *cp = ' ';
+ HTUnEscape(searchstring);
+ strcpy(temp, searchstring);
+ /*
+ * Make sure it's treated as the most recent query. - FM
+ */
+ HTAddSearchQuery(searchstring);
+ } else {
+ /*
+ * New search; no default.
+ */
+ searchstring[0] = '\0';
+ temp[0] = '\0';
+ }
+
+ /*
+ * Prompt for a query string.
+ */
+ if (searchstring[0] == '\0') {
+ if (HTMainAnchor->isIndexPrompt)
+ _statusline(HTMainAnchor->isIndexPrompt);
+ else
+ _statusline(ENTER_DATABASE_QUERY);
+ } else
+ _statusline(EDIT_CURRENT_QUERY);
+ QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
+ recall = (((PreviousSearch && QueryTotal >= 2) ||
+ (!PreviousSearch && QueryTotal >= 1)) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+get_query:
+ if ((ch=LYgetstr(searchstring, VISIBLE,
+ sizeof(searchstring), recall)) < 0 ||
+ *searchstring == '\0' || ch == UPARROW || ch == DNARROW) {
+ if (recall && ch == UPARROW) {
+ if (PreviousSearch) {
+ /*
+ * Use the second to last query in the list. - FM
+ */
+ QueryNum = 1;
+ PreviousSearch = FALSE;
+ } else {
+ /*
+ * Go back to the previous query in the list. - FM
+ */
+ QueryNum++;
+ }
+ if (QueryNum >= QueryTotal)
+ /*
+ * Roll around to the last query in the list. - FM
+ */
+ QueryNum = 0;
+ if ((cp=(char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(searchstring, cp);
+ if (*temp && !strcmp(temp, searchstring)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*temp && QueryTotal == 2) ||
+ (!(*temp) && QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ goto get_query;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (PreviousSearch) {
+ /*
+ * Use the first query in the list. - FM
+ */
+ QueryNum = QueryTotal - 1;
+ PreviousSearch = FALSE;
+ } else {
+ /*
+ * Advance to the next query in the list. - FM
+ */
+ QueryNum--;
+ }
+ if (QueryNum < 0)
+ /*
+ * Roll around to the first query in the list. - FM
+ */
+ QueryNum = QueryTotal - 1;
+ if ((cp=(char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(searchstring, cp);
+ if (*temp && !strcmp(temp, searchstring)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*temp && QueryTotal == 2) ||
+ (!(*temp) && QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ goto get_query;
+ }
+ }
+
+ /*
+ * Search cancelled.
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(NULLFILE);
+ }
+
+ /*
+ * Strip leaders and trailers. - FM
+ */
+ cp = searchstring;
+ while (*cp && isspace((unsigned char)*cp))
+ cp++;
+ if (!(*cp)) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(NULLFILE);
+ }
+ if (cp > searchstring) {
+ for (i = 0; *cp; i++)
+ searchstring[i] = *cp++;
+ searchstring[i] = '\0';
+ }
+ cp = searchstring + strlen(searchstring) - 1;
+ while ((cp > searchstring) && isspace((unsigned char)*cp))
+ *cp-- = '\0';
+
+ /*
+ * Don't resubmit the same query unintentionally.
+ */
+ if (!LYforce_no_cache && 0 == strcmp(temp, searchstring)) {
+ _statusline(USE_C_R_TO_RESUB_CUR_QUERY);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ }
+
+ /*
+ * Add searchstring to the query list,
+ * or make it the most current. - FM
+ */
+ HTAddSearchQuery(searchstring);
+
+ /*
+ * Show the URL with the new query.
+ */
+ if ((cp=strchr(doc->address, '?')) != NULL)
+ *cp = '\0';
+ StrAllocCopy(tmpaddress, doc->address);
+ StrAllocCat(tmpaddress, "?");
+ StrAllocCat(tmpaddress, searchstring);
+ user_message(WWW_WAIT_MESSAGE, tmpaddress);
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ syslog(LOG_INFO|LOG_LOCAL5, "%s", tmpaddress);
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+ FREE(tmpaddress);
+ if (cp)
+ *cp = '?';
+
+ /*
+ * OK, now we do the search.
+ */
+ if (HTSearch(searchstring, HTMainAnchor)) {
+ /*
+ * Memory leak fixed.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ auto char *cp_freeme = NULL;
+ if (traversal)
+ cp_freeme = stub_HTAnchor_address((HTAnchor *)HTMainAnchor);
+ else
+ cp_freeme = HTAnchor_address((HTAnchor *)HTMainAnchor);
+ StrAllocCopy(doc->address, cp_freeme);
+ FREE(cp_freeme);
+
+ if (TRACE)
+ fprintf(stderr,"\ndo_www_search: newfile: %s\n",doc->address);
+
+ /*
+ * Yah, the search succeeded.
+ */
+ return(NORMAL);
+ }
+
+ /*
+ * Either the search failed (Yuk), or we got redirection.
+ * If it's redirection, use_this_url_instead is set, and
+ * mainloop() will deal with it such that security features
+ * and restrictions are checked before acting on the URL, or
+ * rejecting it. - FM
+ */
+ return(NOT_FOUND);
+}
+
+/*
+ * Print the contents of the file in HTMainText to
+ * the file descriptor fp.
+ * If is_reply is TRUE add ">" to the beginning of each
+ * line to specify the file is a reply to message.
+ */
+PUBLIC void print_wwwfile_to_fd ARGS2(
+ FILE *, fp,
+ int, is_reply)
+{
+ register int i;
+ HTLine * line;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ if (!HTMainText)
+ return;
+
+ line = HTMainText->last_line->next;
+ for (;; line = line->next) {
+ /*
+ * Add news-style quotation if requested. - FM
+ */
+ if (is_reply) {
+ fputc('>',fp);
+ }
+
+ /*
+ * Add offset.
+ */
+ for (i = 0; i < (int)line->offset; i++) {
+ fputc(' ', fp);
+ }
+
+ /*
+ * Add data.
+ */
+ for (i = 0; line->data[i] != '\0'; i++) {
+ if (!IsSpecialAttrChar(line->data[i])) {
+ fputc(line->data[i],fp);
+ } else if (line->data[i] == LY_SOFT_HYPHEN &&
+ line->data[i + 1] == '\0') { /* last char on line */
+ if (dump_output_immediately &&
+ LYRawMode &&
+ LYlowest_eightbit[current_char_set] <= 173 &&
+ (current_char_set == 0 ||
+ LYCharSet_UC[current_char_set].enc == UCT_ENC_8859 ||
+ LYCharSet_UC[current_char_set].like8859 &
+ UCT_R_8859SPECL)) {
+ fputc(0xad, fp); /* the iso8859 byte for SHY */
+ } else {
+ fputc('-', fp);
+ }
+ } else if (dump_output_immediately && use_underscore) {
+ switch (line->data[i]) {
+ case LY_UNDERLINE_START_CHAR:
+ case LY_UNDERLINE_END_CHAR:
+ fputc('_', fp);
+ break;
+ case LY_BOLD_START_CHAR:
+ case LY_BOLD_END_CHAR:
+ break;
+ }
+ }
+ }
+
+ /*
+ * Add the return.
+ */
+ fputc('\n',fp);
+
+ if (line == HTMainText->last_line)
+ break;
+
+#ifdef VMS
+ if (HadVMSInterrupt)
+ break;
+#endif /* VMS */
+ }
+
+}
+
+/*
+ * Print the contents of the file in HTMainText to
+ * the file descriptor fp.
+ * First output line is "thelink", ie, the URL for this file.
+ */
+PUBLIC void print_crawl_to_fd ARGS3(
+ FILE *, fp,
+ char *, thelink,
+ char *, thetitle)
+{
+ register int i;
+ HTLine * line;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ if (!HTMainText)
+ return;
+
+ line = HTMainText->last_line->next;
+ fprintf(fp, "THE_URL:%s\n", thelink);
+ if (thetitle != NULL) {
+ fprintf(fp, "THE_TITLE:%s\n", thetitle);
+ }
+
+ for (;; line = line->next) {
+ /*
+ * Add offset.
+ */
+ for (i = 0; i < (int)line->offset; i++) {
+ fputc(' ', fp);
+ }
+
+ /*
+ * Add data.
+ */
+ for (i = 0; line->data[i] != '\0'; i++) {
+ if (!IsSpecialAttrChar(line->data[i])) {
+ fputc(line->data[i], fp);
+ } else if (line->data[i] == LY_SOFT_HYPHEN &&
+ line->data[i + 1] == '\0') { /* last char on line */
+ if (dump_output_immediately &&
+ LYRawMode &&
+ LYlowest_eightbit[current_char_set] <= 173 &&
+ (current_char_set == 0 ||
+ LYCharSet_UC[current_char_set].enc == UCT_ENC_8859 ||
+ LYCharSet_UC[current_char_set].like8859 &
+ UCT_R_8859SPECL)) {
+ fputc(0xad, fp); /* the iso8859 byte for SHY */
+ } else {
+ fputc('-', fp);
+ }
+ }
+ }
+
+ /*
+ * Add the return.
+ */
+ fputc('\n',fp);
+
+ if (line == HTMainText->last_line) {
+ break;
+ }
+ }
+
+ /*
+ * Add the References list if appropriate
+ */
+ if ((nolist == FALSE) &&
+ (keypad_mode == LINKS_ARE_NUMBERED ||
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED)) {
+ printlist(fp,FALSE);
+ }
+
+#ifdef VMS
+ HadVMSInterrupt = FALSE;
+#endif /* VMS */
+}
+
+PRIVATE void adjust_search_result ARGS3(
+ document *, doc,
+ int, tentative_result,
+ int, start_line)
+{
+ if (tentative_result > 0) {
+ int anch_line = -1;
+ TextAnchor * a;
+ int nl_closest = -1;
+ int goal = SEARCH_GOAL_LINE;
+ int max_offset;
+ BOOL on_screen = (tentative_result > HTMainText->top_of_screen &&
+ tentative_result <= HTMainText->top_of_screen+display_lines);
+ if (goal < 1)
+ goal = 1;
+ else if (goal > display_lines)
+ goal = display_lines;
+ max_offset = goal - 1;
+
+ if (on_screen && nlinks > 0) {
+ int i;
+ for (i = 0; i < nlinks; i++) {
+ if (doc->line + links[i].ly - 1 <= tentative_result)
+ nl_closest = i;
+ if (doc->line + links[i].ly - 1 >= tentative_result)
+ break;
+ }
+ if (nl_closest >= 0 &&
+ doc->line + links[nl_closest].ly - 1 == tentative_result) {
+ www_search_result = doc->line;
+ doc->link = nl_closest;
+ return;
+ }
+ }
+
+ /* find last anchor before or on target line */
+ for (a = HTMainText->first_anchor;
+ a && a->line_num <= tentative_result-1; a = a->next) {
+ anch_line = a->line_num + 1;
+ }
+ /* position such that the anchor found is on first screen line,
+ if it is not too far above the target line; but also try to
+ make sure we move forward. */
+ if (anch_line >= 0 &&
+ anch_line >= tentative_result - max_offset &&
+ (anch_line > start_line ||
+ tentative_result <= HTMainText->top_of_screen)) {
+ www_search_result = anch_line;
+ } else
+ if (tentative_result - start_line > 0 &&
+ tentative_result - (start_line + 1) <= max_offset) {
+ www_search_result = start_line + 1;
+ } else
+ if (tentative_result > HTMainText->top_of_screen &&
+ tentative_result <= start_line && /* have wrapped */
+ tentative_result <= HTMainText->top_of_screen+goal) {
+ www_search_result = HTMainText->top_of_screen + 1;
+ } else
+ if (tentative_result <= goal)
+ www_search_result = 1;
+ else
+ www_search_result = tentative_result - max_offset;
+ if (www_search_result == doc->line) {
+ if (nl_closest >= 0) {
+ doc->link = nl_closest;
+ return;
+ }
+ }
+ }
+}
+
+PUBLIC void www_user_search ARGS3(
+ int, start_line,
+ document *, doc,
+ char *, target)
+{
+ register HTLine * line;
+ register int count;
+ int tentative_result = -1;
+ TextAnchor *a;
+ OptionType *option;
+ char *stars = NULL, *cp;
+
+ if (!HTMainText) {
+ return;
+ }
+
+ /*
+ * Advance to the start line.
+ */
+ line = HTMainText->last_line->next;
+ for (count = 1; count <= start_line; line = line->next, count++) {
+ if (line == HTMainText->last_line) {
+ line = HTMainText->last_line->next; /* set to first line */
+ count = 1;
+ break;
+ }
+ }
+ a = HTMainText->first_anchor;
+ while (a && a->line_num < count - 1) {
+ a = a->next;
+ }
+
+ for (;;) {
+ while ((a != NULL) && a->line_num == (count - 1)) {
+ if (a->show_anchor &&
+ (a->link_type != INPUT_ANCHOR ||
+ a->input_field->type != F_HIDDEN_TYPE)) {
+ if (((a->hightext != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->hightext, target)) ||
+ ((a->hightext != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->hightext, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ if (((a->hightext2 != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->hightext2, target)) ||
+ ((a->hightext2 != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->hightext2, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+
+ /*
+ * Search the relevant form fields, taking the
+ * case_sensitive setting into account. - FM
+ */
+ if ((a->input_field != NULL && a->input_field->value != NULL) &&
+ a->input_field->type != F_HIDDEN_TYPE) {
+ if (a->input_field->type == F_PASSWORD_TYPE) {
+ /*
+ * Check the actual, hidden password, and then
+ * the displayed string. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->input_field->value,
+ target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->input_field->value,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ StrAllocCopy(stars, a->input_field->value);
+ for (cp = stars; *cp != '\0'; cp++)
+ *cp = '*';
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(stars, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(stars, target))) {
+ FREE(stars);
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ FREE(stars);
+ } else if (a->input_field->type == F_OPTION_LIST_TYPE) {
+ /*
+ * Search the option strings that are displayed
+ * when the popup is invoked. - FM
+ */
+ option = a->input_field->select_list;
+ while (option != NULL) {
+ if (((option->name != NULL &&
+ case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(option->name,
+ target)) ||
+ ((option->name != NULL &&
+ case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(option->name,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ option = option->next;
+ }
+ } else if (a->input_field->type == F_RADIO_TYPE) {
+ /*
+ * Search for checked or unchecked parens. - FM
+ */
+ if (a->input_field->num_value) {
+ cp = checked_radio;
+ } else {
+ cp = unchecked_radio;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ } else if (a->input_field->type == F_CHECKBOX_TYPE) {
+ /*
+ * Search for checked or unchecked
+ * square brackets. - FM
+ */
+ if (a->input_field->num_value) {
+ cp = checked_box;
+ } else {
+ cp = unchecked_box;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ } else {
+ /*
+ * Check the values intended for display.
+ * May have been found already via the
+ * hightext search, but make sure here
+ * that the entire value is searched. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->input_field->value,
+ target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->input_field->value,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ }
+ }
+ }
+ a = a->next;
+ }
+ if (a != NULL && a->line_num <= (count - 1)) {
+ a = a->next;
+ }
+
+ if (case_sensitive && LYno_attr_char_strstr(line->data, target)) {
+ tentative_result = count;
+ break;
+ } else if (!case_sensitive &&
+ LYno_attr_char_case_strstr(line->data, target)) {
+ tentative_result = count;
+ break;
+ } else if (line == HTMainText->last_line) { /* next line */
+ break;
+ } else { /* end */
+ line = line->next;
+ count++;
+ }
+ }
+ if (tentative_result > 0) {
+ adjust_search_result(doc, tentative_result, start_line);
+ return;
+ }
+
+ /*
+ * Search from the beginning.
+ */
+ line = HTMainText->last_line->next; /* set to first line */
+ count = 1;
+ a = HTMainText->first_anchor;
+ while (a && a->line_num < count - 1) {
+ a = a->next;
+ }
+
+ for (;;) {
+ while ((a != NULL) && a->line_num == (count - 1)) {
+ if (a->show_anchor &&
+ (a->link_type != INPUT_ANCHOR ||
+ a->input_field->type != F_HIDDEN_TYPE)) {
+ if (((a->hightext != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->hightext, target)) ||
+ ((a->hightext != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->hightext, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ if (((a->hightext2 != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->hightext2, target)) ||
+ ((a->hightext2 != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->hightext2, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+
+ /*
+ * Search the relevant form fields, taking the
+ * case_sensitive setting into account. - FM
+ */
+ if ((a->input_field != NULL && a->input_field->value != NULL) &&
+ a->input_field->type != F_HIDDEN_TYPE) {
+ if (a->input_field->type == F_PASSWORD_TYPE) {
+ /*
+ * Check the actual, hidden password, and then
+ * the displayed string. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->input_field->value,
+ target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->input_field->value,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ StrAllocCopy(stars, a->input_field->value);
+ for (cp = stars; *cp != '\0'; cp++)
+ *cp = '*';
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(stars, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(stars, target))) {
+ FREE(stars);
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ FREE(stars);
+ } else if (a->input_field->type == F_OPTION_LIST_TYPE) {
+ /*
+ * Search the option strings that are displayed
+ * when the popup is invoked. - FM
+ */
+ option = a->input_field->select_list;
+ while (option != NULL) {
+ if (((option->name != NULL &&
+ case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(option->name,
+ target)) ||
+ ((option->name != NULL &&
+ case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(option->name,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ option = option->next;
+ }
+ } else if (a->input_field->type == F_RADIO_TYPE) {
+ /*
+ * Search for checked or unchecked parens. - FM
+ */
+ if (a->input_field->num_value) {
+ cp = checked_radio;
+ } else {
+ cp = unchecked_radio;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ } else if (a->input_field->type == F_CHECKBOX_TYPE) {
+ /*
+ * Search for checked or unchecked
+ * square brackets. - FM
+ */
+ if (a->input_field->num_value) {
+ cp = checked_box;
+ } else {
+ cp = unchecked_box;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ } else {
+ /*
+ * Check the values intended for display.
+ * May have been found already via the
+ * hightext search, but make sure here
+ * that the entire value is searched. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(a->input_field->value,
+ target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(a->input_field->value,
+ target))) {
+ adjust_search_result(doc, count, start_line);
+ return;
+ }
+ }
+ }
+ }
+ a = a->next;
+ }
+ if (a != NULL && a->line_num <= (count - 1)) {
+ a = a->next;
+ }
+
+ if (case_sensitive && LYno_attr_char_strstr(line->data, target)) {
+ tentative_result=count;
+ break;
+ } else if (!case_sensitive &&
+ LYno_attr_char_case_strstr(line->data, target)) {
+ tentative_result = count;
+ break;
+ } else if (count > start_line) { /* next line */
+ _user_message(STRING_NOT_FOUND, target);
+ sleep(MessageSecs);
+ return; /* end */
+ } else {
+ line = line->next;
+ count++;
+ }
+ }
+ if (tentative_result > 0) {
+ adjust_search_result(doc, tentative_result, start_line);
+ }
+}
+
+PUBLIC void user_message ARGS2(
+ CONST char *, message,
+ CONST char *, argument)
+{
+ char *temp = NULL;
+ char temp_arg[256];
+
+ if (message == NULL) {
+ mustshow = FALSE;
+ return;
+ }
+
+ /*
+ * Make sure we don't overrun any buffers.
+ */
+ LYstrncpy(temp_arg, ((argument == NULL) ? "" : argument), 255);
+ temp_arg[255] = '\0';
+ temp = (char *)malloc(strlen(message) + strlen(temp_arg) + 1);
+ if (temp == NULL)
+ outofmem(__FILE__, "user_message");
+ sprintf(temp, message, temp_arg);
+
+ statusline(temp);
+
+ FREE(temp);
+ return;
+}
+
+/*
+ * HText_getOwner returns the owner of the
+ * current document.
+ */
+PUBLIC char * HText_getOwner NOARGS
+{
+ return(HTMainText ?
+ (char *)HTAnchor_owner(HTMainText->node_anchor) : NULL);
+}
+
+/*
+* HText_setMainTextOwner sets the owner for the
+ * current document.
+ */
+PUBLIC void HText_setMainTextOwner ARGS1(
+ CONST char *, owner)
+{
+ if (!HTMainText)
+ return;
+
+ HTAnchor_setOwner(HTMainText->node_anchor, owner);
+}
+
+/*
+ * HText_getRevTitle returns the RevTitle element of the
+ * current document, used as the subject for mailto comments
+ * to the owner.
+ */
+PUBLIC char * HText_getRevTitle NOARGS
+{
+ return(HTMainText ?
+ (char *)HTAnchor_RevTitle(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HText_getContentBase returns the Content-Base header
+ * of the current document.
+ */
+PUBLIC char * HText_getContentBase NOARGS
+{
+ return(HTMainText ?
+ (char *)HTAnchor_content_base(HTMainText->node_anchor) : NULL);
+}
+
+/*
+ * HText_getContentLocation returns the Content-Location header
+ * of the current document.
+ */
+PUBLIC char * HText_getContentLocation NOARGS
+{
+ return(HTMainText ?
+ (char *)HTAnchor_content_location(HTMainText->node_anchor) : NULL);
+}
+
+PUBLIC void HTuncache_current_document NOARGS
+{
+ /*
+ * Should remove current document from memory.
+ */
+ if (HTMainText) {
+ HTParentAnchor * htmain_anchor = HTMainText->node_anchor;
+
+ if (htmain_anchor) {
+ if (!(HTOutputFormat && HTOutputFormat == WWW_SOURCE)) {
+ FREE(htmain_anchor->UCStages);
+ }
+ }
+ if (TRACE) {
+ fprintf(stderr, "\rHTuncache.. freeing document for '%s'%s\n",
+ ((htmain_anchor &&
+ htmain_anchor->address) ?
+ htmain_anchor->address : "unknown anchor"),
+ ((htmain_anchor &&
+ htmain_anchor->post_data) ?
+ " with POST data" : ""));
+ }
+ HTList_removeObject(loaded_texts, HTMainText);
+ HText_free(HTMainText);
+ HTMainText = NULL;
+ } else {
+ if (TRACE) {
+ fprintf(stderr, "HTuncache.. HTMainText already is NULL!\n");
+ }
+ }
+}
+
+PUBLIC int HTisDocumentSource NOARGS
+{
+ return(HTMainText->source);
+}
+
+PUBLIC char * HTLoadedDocumentURL NOARGS
+{
+ if (!HTMainText)
+ return ("");
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->address)
+ return(HTMainText->node_anchor->address);
+ else
+ return ("");
+}
+
+PUBLIC char * HTLoadedDocumentPost_data NOARGS
+{
+ if (!HTMainText)
+ return ("");
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->post_data)
+ return(HTMainText->node_anchor->post_data);
+ else
+ return ("");
+}
+
+PUBLIC char * HTLoadedDocumentTitle NOARGS
+{
+ if (!HTMainText)
+ return ("");
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->title)
+ return(HTMainText->node_anchor->title);
+ else
+ return ("");
+}
+
+PUBLIC BOOLEAN HTLoadedDocumentIsHEAD NOARGS
+{
+ if (!HTMainText)
+ return (FALSE);
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->isHEAD)
+ return(HTMainText->node_anchor->isHEAD);
+ else
+ return (FALSE);
+}
+
+PUBLIC BOOLEAN HTLoadedDocumentIsSafe NOARGS
+{
+ if (!HTMainText)
+ return (FALSE);
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->safe)
+ return(HTMainText->node_anchor->safe);
+ else
+ return (FALSE);
+}
+
+PUBLIC char * HTLoadedDocumentCharset NOARGS
+{
+ if (!HTMainText)
+ return (NULL);
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->charset)
+ return(HTMainText->node_anchor->charset);
+ else
+ return (NULL);
+}
+
+PUBLIC BOOL HTLoadedDocumentEightbit NOARGS
+{
+ if (!HTMainText)
+ return (NO);
+ else
+ return (HTMainText->have_8bit_chars);
+}
+
+PUBLIC void HText_setNodeAnchorBookmark ARGS1(
+ CONST char *, bookmark)
+{
+ if (!HTMainText)
+ return;
+
+ if (HTMainText->node_anchor)
+ HTAnchor_setBookmark(HTMainText->node_anchor, bookmark);
+}
+
+PUBLIC char * HTLoadedDocumentBookmark NOARGS
+{
+ if (!HTMainText)
+ return (NULL);
+
+ if (HTMainText->node_anchor && HTMainText->node_anchor->bookmark)
+ return(HTMainText->node_anchor->bookmark);
+ else
+ return (NULL);
+}
+
+PUBLIC int HText_LastLineSize ARGS2(
+ HText *, text,
+ BOOL, IgnoreSpaces)
+{
+ if (!text || !text->last_line || !text->last_line->size)
+ return 0;
+ return HText_TrueLineSize(text->last_line, text, IgnoreSpaces);
+}
+
+PUBLIC int HText_PreviousLineSize ARGS2(
+ HText *, text,
+ BOOL, IgnoreSpaces)
+{
+ HTLine * line;
+
+ if (!text || !text->last_line)
+ return 0;
+ if (!(line = text->last_line->prev))
+ return 0;
+ return HText_TrueLineSize(line, text, IgnoreSpaces);
+}
+
+PRIVATE int HText_TrueLineSize ARGS3(
+ HTLine *, line,
+ HText *, text,
+ BOOL, IgnoreSpaces)
+{
+ size_t i;
+ int true_size = 0;
+
+ if (!(line && line->size))
+ return 0;
+
+ if (IgnoreSpaces) {
+ for (i = 0; i < line->size; i++) {
+ if (!IsSpecialAttrChar((unsigned char)line->data[i]) &&
+ (!(text && text->T.output_utf8) ||
+ (unsigned char)line->data[i] < 128 ||
+ ((unsigned char)(line->data[i] & 0xc0) == 0xc0)) &&
+ !isspace((unsigned char)line->data[i]) &&
+ (unsigned char)line->data[i] != HT_NON_BREAK_SPACE &&
+ (unsigned char)line->data[i] != HT_EM_SPACE) {
+ true_size++;
+ }
+ }
+ } else {
+ for (i = 0; i < line->size; i++) {
+ if (!IsSpecialAttrChar(line->data[i]) &&
+ (!(text && text->T.output_utf8) ||
+ (unsigned char)line->data[i] < 128 ||
+ ((unsigned char)(line->data[i] & 0xc0) == 0xc0))) {
+ true_size++;
+ }
+ }
+ }
+ return true_size;
+}
+
+PUBLIC void HText_NegateLineOne ARGS1(
+ HText *, text)
+{
+ if (text) {
+ text->in_line_1 = NO;
+ }
+ return;
+}
+
+/*
+ * This function is for removing the first of two
+ * successive blank lines. It should be called after
+ * checking the situation with HText_LastLineSize()
+ * and HText_PreviousLineSize(). Any characters in
+ * the removed line (i.e., control characters, or it
+ * wouldn't have tested blank) should have been
+ * reiterated by split_line() in the retained blank
+ * line. - FM
+ */
+PUBLIC void HText_RemovePreviousLine ARGS1(
+ HText *, text)
+{
+ HTLine *line, *previous;
+ char *data;
+
+ if (!(text && text->Lines > 1))
+ return;
+
+ line = text->last_line->prev;
+ data = line->data;
+ previous = line->prev;
+ previous->next = text->last_line;
+ text->last_line->prev = previous;
+ text->chars -= ((data && *data == '\0') ?
+ 1 : strlen(line->data) + 1);
+ text->Lines--;
+ FREE(line);
+}
+
+/*
+ * NOTE: This function presently is correct only if the
+ * alignment is HT_LEFT. The offset is still zero,
+ * because that's not determined for HT_CENTER or
+ * HT_RIGHT until subsequent characters are received
+ * and split_line() is called. - FM
+ */
+PUBLIC int HText_getCurrentColumn ARGS1(
+ HText *, text)
+{
+ int column = 0;
+ BOOL IgnoreSpaces = FALSE;
+
+ if (text) {
+ column = (text->in_line_1 ?
+ (int)text->style->indent1st : (int)text->style->leftIndent)
+ + HText_LastLineSize(text, IgnoreSpaces)
+ + (int)text->last_line->offset;
+ }
+ return column;
+}
+
+PUBLIC int HText_getMaximumColumn ARGS1(
+ HText *, text)
+{
+ int column = (LYcols-2);
+ if (text) {
+ column = ((int)text->style->rightIndent ? (LYcols-2) :
+ ((LYcols-1) - (int)text->style->rightIndent));
+ }
+ return column;
+}
+
+/*
+ * NOTE: This function uses HText_getCurrentColumn() which
+ * presently is correct only if the alignment is
+ * HT_LEFT. - FM
+ */
+PUBLIC void HText_setTabID ARGS2(
+ HText *, text,
+ CONST char *, name)
+{
+ HTTabID * Tab = NULL;
+ HTList * cur = text->tabs;
+ HTList * last = NULL;
+
+ if (!text || !name || !*name)
+ return;
+
+ if (!cur) {
+ cur = text->tabs = HTList_new();
+ } else {
+ while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) {
+ if (Tab->name && !strcmp(Tab->name, name))
+ return; /* Already set. Keep the first value. */
+ last = cur;
+ }
+ if (last)
+ cur = last;
+ }
+ if (!Tab) { /* New name. Create a new node */
+ Tab = (HTTabID *)calloc(1, sizeof(HTTabID));
+ if (Tab == NULL)
+ outofmem(__FILE__, "HText_setTabID");
+ HTList_addObject(cur, Tab);
+ StrAllocCopy(Tab->name, name);
+ }
+ Tab->column = HText_getCurrentColumn(text);
+ return;
+}
+
+PUBLIC int HText_getTabIDColumn ARGS2(
+ HText *, text,
+ CONST char *, name)
+{
+ int column = 0;
+ HTTabID * Tab;
+ HTList * cur = text->tabs;
+
+ if (text && name && *name && cur) {
+ while (NULL != (Tab = (HTTabID *)HTList_nextObject(cur))) {
+ if (Tab->name && !strcmp(Tab->name, name))
+ break;
+ }
+ if (Tab)
+ column = Tab->column;
+ }
+ return column;
+}
+
+/*
+ * This function is for saving the address of a link
+ * which had an attribute in the markup that resolved
+ * to a URL (i.e., not just a NAME or ID attribute),
+ * but was found in HText_endAnchor() to have no visible
+ * content for use as a link name. It loads the address
+ * into text->hidden_links, whose count can be determined
+ * via HText_HiddenLinks(), below. The addresses can be
+ * retrieved via HText_HiddenLinkAt(), below, based on
+ * count. - FM
+ */
+PRIVATE void HText_AddHiddenLink ARGS2(
+ HText *, text,
+ TextAnchor *, textanchor)
+{
+ HTAnchor *dest;
+
+ /*
+ * Make sure we have an HText structure and anchor. - FM
+ */
+ if (!(text && textanchor && textanchor->anchor))
+ return;
+
+ /*
+ * Create the hidden links list
+ * if it hasn't been already. - FM
+ */
+ if (text->hidden_links == NULL)
+ text->hidden_links = HTList_new();
+
+ /*
+ * Store the address, in reverse list order
+ * so that first in will be first out on
+ * retrievals. - FM
+ */
+ if ((dest = HTAnchor_followMainLink((HTAnchor *)textanchor->anchor)) &&
+ (text->hiddenlinkflag != HIDDENLINKS_IGNORE ||
+ HTList_isEmpty(text->hidden_links)))
+ HTList_appendObject(text->hidden_links, HTAnchor_address(dest));
+
+ return;
+}
+
+/*
+ * This function returns the number of addresses
+ * that are loaded in text->hidden_links. - FM
+ */
+PUBLIC int HText_HiddenLinkCount ARGS1(
+ HText *, text)
+{
+ int count = 0;
+
+ if (text && text->hidden_links)
+ count = HTList_count((HTList *)text->hidden_links);
+
+ return(count);
+}
+
+/*
+ * This function returns the address, corresponding to
+ * a hidden link, at the position (zero-based) in the
+ * text->hidden_links list of the number argument. - FM
+ */
+PUBLIC char * HText_HiddenLinkAt ARGS2(
+ HText *, text,
+ int, number)
+{
+ char *href = NULL;
+
+ if (text && text->hidden_links && number >= 0)
+ href = (char *)HTList_objectAt((HTList *)text->hidden_links, number);
+
+ return(href);
+}
+
+
+/*
+ * Form methods
+ * These routines are used to build forms consisting
+ * of input fields
+ */
+PRIVATE int HTFormMethod;
+PRIVATE char * HTFormAction = NULL;
+PRIVATE char * HTFormEnctype = NULL;
+PRIVATE char * HTFormTitle = NULL;
+PRIVATE char * HTFormAcceptCharset = NULL;
+PRIVATE BOOLEAN HTFormDisabled = FALSE;
+PRIVATE PerFormInfo * HTCurrentForm;
+
+PUBLIC void HText_beginForm ARGS5(
+ char *, action,
+ char *, method,
+ char *, enctype,
+ char *, title,
+ CONST char *, accept_cs)
+{
+ PerFormInfo * newform;
+ HTFormMethod = URL_GET_METHOD;
+ HTFormNumber++;
+ HTFormFields = 0;
+ HTFormDisabled = FALSE;
+
+ /*
+ * Check the ACTION. - FM
+ */
+ if (action != NULL) {
+ if (!strncmp(action, "mailto:", 7)) {
+ HTFormMethod = URL_MAIL_METHOD;
+ }
+ StrAllocCopy(HTFormAction, action);
+ }
+ else
+ StrAllocCopy(HTFormAction, HTLoadedDocumentURL());
+
+ /*
+ * Check the METHOD. - FM
+ */
+ if (method != NULL && HTFormMethod != URL_MAIL_METHOD)
+ if (!strcasecomp(method,"post") || !strcasecomp(method,"pget"))
+ HTFormMethod = URL_POST_METHOD;
+
+ /*
+ * Check the ENCTYPE. - FM
+ */
+ if ((enctype != NULL) && *enctype) {
+ StrAllocCopy(HTFormEnctype, enctype);
+ if (HTFormMethod != URL_MAIL_METHOD &&
+ !strncasecomp(enctype, "multipart/form-data", 19))
+ HTFormMethod = URL_POST_METHOD;
+ } else {
+ FREE(HTFormEnctype);
+ }
+
+ /*
+ * Check the TITLE. - FM
+ */
+ if ((title != NULL) && *title)
+ StrAllocCopy(HTFormTitle, title);
+ else
+ FREE(HTFormTitle);
+
+ /*
+ * Check for an ACCEPT_CHARSET. If present, store it and
+ * convert to lowercase and collapse spaces. - kw
+ */
+ if (accept_cs != NULL) {
+ int i;
+ StrAllocCopy(HTFormAcceptCharset, accept_cs);
+ collapse_spaces(HTFormAcceptCharset);
+ for (i = 0; HTFormAcceptCharset[i]; i++)
+ HTFormAcceptCharset[i] = TOLOWER(HTFormAcceptCharset[i]);
+ }
+
+ /*
+ * Create a new "PerFormInfo" structure to hold info on the current
+ * form. The HTForm* variables could all migrate there, currently
+ * this isn't done (yet?) but it might be less confusing.
+ * Currently the only data saved in this structure that will actually
+ * be used is the accept_cs string.
+ * This will be appended to the forms list kept by the HText object
+ * if and when we reach a HText_endForm. - kw
+ */
+ newform = (PerFormInfo *)calloc(1, sizeof(PerFormInfo));
+ if (newform == NULL)
+ outofmem(__FILE__,"HText_beginForm");
+ newform->number = HTFormNumber;
+
+ PerFormInfo_free(HTCurrentForm); /* shouldn't happen here - kw */
+ HTCurrentForm = newform;
+
+ if (TRACE)
+ fprintf(stderr,
+ "BeginForm: action:%s Method:%d%s%s%s%s%s%s\n",
+ HTFormAction, HTFormMethod,
+ (HTFormTitle ? " Title:" : ""),
+ (HTFormTitle ? HTFormTitle : ""),
+ (HTFormEnctype ? " Enctype:" : ""),
+ (HTFormEnctype ? HTFormEnctype : ""),
+ (HTFormAcceptCharset ? " Accept-charset:" : ""),
+ (HTFormAcceptCharset ? HTFormAcceptCharset : ""));
+}
+
+PUBLIC void HText_endForm ARGS1(
+ HText *, text)
+{
+ if (HTFormFields == 1 && text && text->first_anchor) {
+ /*
+ * Support submission of a single text input field in
+ * the form via <return> instead of a submit button. - FM
+ */
+ TextAnchor * a = text->first_anchor;
+ /*
+ * Go through list of anchors and get our input field. - FM
+ */
+ while (a) {
+ if (a->link_type == INPUT_ANCHOR &&
+ a->input_field->number == HTFormNumber &&
+ a->input_field->type == F_TEXT_TYPE) {
+ /*
+ * Got it. Make it submitting. - FM
+ */
+ a->input_field->submit_action = NULL;
+ StrAllocCopy(a->input_field->submit_action, HTFormAction);
+ if (HTFormEnctype != NULL)
+ StrAllocCopy(a->input_field->submit_enctype,
+ HTFormEnctype);
+ if (HTFormTitle != NULL)
+ StrAllocCopy(a->input_field->submit_title, HTFormTitle);
+ a->input_field->submit_method = HTFormMethod;
+ a->input_field->type = F_TEXT_SUBMIT_TYPE;
+ if (HTFormDisabled)
+ a->input_field->disabled = TRUE;
+ break;
+ }
+ if (a == text->last_anchor)
+ break;
+ a = a->next;
+ }
+ }
+ /*
+ * Append info on the current form to the HText object's list of
+ * forms.
+ * HText_beginInput call will have set some of the data in the
+ * PerFormInfo structure (if there were any form fields at all),
+ * we also fill in the ACCEPT-CHARSET data now (this could have
+ * been done earlier). - kw
+ */
+ if (HTCurrentForm) {
+ if (HTFormDisabled)
+ HTCurrentForm->disabled = TRUE;
+ HTCurrentForm->accept_cs = HTFormAcceptCharset;
+ HTFormAcceptCharset = NULL;
+ if (!text->forms)
+ text->forms = HTList_new();
+ HTList_appendObject(text->forms, HTCurrentForm);
+ HTCurrentForm = NULL;
+ } else {
+ if (TRACE)
+ fprintf(stderr, "endForm: HTCurrentForm is missing!\n");
+ }
+
+ FREE(HTCurSelectGroup);
+ FREE(HTCurSelectGroupSize);
+ FREE(HTCurSelectedOptionValue);
+ FREE(HTFormAction);
+ FREE(HTFormEnctype);
+ FREE(HTFormTitle);
+ FREE(HTFormAcceptCharset);
+ HTFormFields = 0;
+ HTFormDisabled = FALSE;
+}
+
+PUBLIC void HText_beginSelect ARGS4(
+ char *, name,
+ int, name_cs,
+ BOOLEAN, multiple,
+ char *, size)
+{
+ /*
+ * Save the group name.
+ */
+ StrAllocCopy(HTCurSelectGroup, name);
+ HTCurSelectGroupCharset = name_cs;
+
+ /*
+ * If multiple then all options are actually checkboxes.
+ */
+ if (multiple)
+ HTCurSelectGroupType = F_CHECKBOX_TYPE;
+ /*
+ * If not multiple then all options are radio buttons.
+ */
+ else
+ HTCurSelectGroupType = F_RADIO_TYPE;
+
+ /*
+ * Length of an option list.
+ */
+ StrAllocCopy(HTCurSelectGroupSize, size);
+
+ if (TRACE) {
+ fprintf(stderr,"HText_beginSelect: name=%s type=%d size=%s\n",
+ ((HTCurSelectGroup == NULL) ?
+ "<NULL>" : HTCurSelectGroup),
+ HTCurSelectGroupType,
+ ((HTCurSelectGroupSize == NULL) ?
+ "<NULL>" : HTCurSelectGroupSize));
+ fprintf(stderr,"HText_beginSelect: name_cs=%d \"%s\"\n",
+ HTCurSelectGroupCharset,
+ (HTCurSelectGroupCharset >= 0 ?
+ LYCharSet_UC[HTCurSelectGroupCharset].MIMEname : "<UNKNOWN>"));
+ }
+}
+
+/*
+** This function returns the number of the option whose
+** value currently is being accumulated for a select
+** block. - LE && FM
+*/
+PUBLIC int HText_getOptionNum ARGS1(
+ HText *, text)
+{
+ TextAnchor *a;
+ OptionType *op;
+ int n = 1; /* start count at 1 */
+
+ if (!(text && text->last_anchor))
+ return(0);
+
+ a = text->last_anchor;
+ if (!(a->link_type == INPUT_ANCHOR && a->input_field &&
+ a->input_field->type == F_OPTION_LIST_TYPE))
+ return(0);
+
+ for (op = a->input_field->select_list; op; op = op->next)
+ n++;
+ if (TRACE)
+ fprintf(stderr, "HText_getOptionNum: Got number '%d'.\n", n);
+ return(n);
+}
+
+/*
+** This function checks for a numbered option pattern
+** as the prefix for an option value. If present, and
+** we are in the correct keypad mode, it returns a
+** pointer to the actual value, following that prefix.
+** Otherwise, it returns the original pointer.
+*/
+PRIVATE char * HText_skipOptionNumPrefix ARGS1(
+ char *, opname)
+{
+ /*
+ * Check if we are in the correct keypad mode.
+ */
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+ /*
+ * Skip the option number embedded in the option name so the
+ * extra chars won't mess up cgi scripts processing the value.
+ * The format is (nnn)__ where nnn is a number and there is a
+ * minimum of 5 chars (no underscores if (nnn) exceeds 5 chars).
+ * See HTML.c. If the chars don't exactly match this format,
+ * just use all of opname. - LE
+ */
+ char *cp = opname;
+
+ if ((cp && *cp && *cp++ == '(') &&
+ *cp && isdigit(*cp++)) {
+ while (*cp && isdigit(*cp))
+ ++cp;
+ if (*cp && *cp++ == ')') {
+ int i = (cp - opname);
+
+ while (i < 5) {
+ if (*cp != '_')
+ break;
+ i++;
+ cp++;
+ }
+ if (i < 5 ) {
+ cp = opname;
+ }
+ } else {
+ cp = opname;
+ }
+ } else {
+ cp = opname;
+ }
+ return(cp);
+ }
+
+ return(opname);
+}
+
+/*
+** We couldn't set the value field for the previous option
+** tag so we have to do it now. Assume that the last anchor
+** was the previous options tag.
+*/
+PUBLIC char * HText_setLastOptionValue ARGS7(
+ HText *, text,
+ char *, value,
+ char*, submit_value,
+ int, order,
+ BOOLEAN, checked,
+ int, val_cs,
+ int, submit_val_cs)
+{
+ char *cp, *cp1;
+ char *ret_Value = NULL;
+ unsigned char *tmp = NULL;
+ int number = 0, i, j;
+
+ if (!(text && text->last_anchor &&
+ text->last_anchor->link_type == INPUT_ANCHOR)) {
+ if (TRACE)
+ fprintf(stderr,
+ "HText_setLastOptionValue: invalid call! value:%s!\n",
+ (value ? value : "<NULL>"));
+ return NULL;
+ }
+
+ if (TRACE)
+ fprintf(stderr,
+ "Entering HText_setLastOptionValue: value:%s, checked:%s\n",
+ value, (checked ? "on" : "off"));
+
+ /*
+ * Strip end spaces, newline is also whitespace.
+ */
+ if (*value) {
+ cp = &value[strlen(value)-1];
+ while ((cp >= value) && (isspace((unsigned char)*cp) ||
+ IsSpecialAttrChar((unsigned char)*cp)))
+ cp--;
+ *(cp+1) = '\0';
+ }
+
+ /*
+ * Find first non space
+ */
+ cp = value;
+ while (isspace((unsigned char)*cp) ||
+ IsSpecialAttrChar((unsigned char)*cp))
+ cp++;
+ if (HTCurSelectGroupType == F_RADIO_TYPE &&
+ LYSelectPopups &&
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+ /*
+ * Collapse any space between the popup option
+ * prefix and actual value. - FM
+ */
+ if ((cp1 = HText_skipOptionNumPrefix(cp)) > cp) {
+ i = 0, j = (cp1 - cp);
+ while (isspace((unsigned char)cp1[i]) ||
+ IsSpecialAttrChar((unsigned char)cp1[i])) {
+ i++;
+ }
+ if (i > 0) {
+ while (cp1[i] != '\0')
+ cp[j++] = cp1[i++];
+ cp[j] = '\0';
+ }
+ }
+ }
+
+ if (HTCurSelectGroupType == F_CHECKBOX_TYPE) {
+ StrAllocCopy(text->last_anchor->input_field->value, cp);
+ text->last_anchor->input_field->value_cs = val_cs;
+ /*
+ * Put the text on the screen as well.
+ */
+ HText_appendText(text, cp);
+
+ } else if (LYSelectPopups == FALSE) {
+ StrAllocCopy(text->last_anchor->input_field->value,
+ (submit_value ? submit_value : cp));
+ text->last_anchor->input_field->value_cs = (submit_value ?
+ submit_val_cs : val_cs);
+ /*
+ * Put the text on the screen as well.
+ */
+ HText_appendText(text, cp);
+
+ } else {
+ /*
+ * Create a linked list of option values.
+ */
+ OptionType * op_ptr = text->last_anchor->input_field->select_list;
+ OptionType * new_ptr = NULL;
+ BOOLEAN first_option = FALSE;
+
+ /*
+ * Deal with newlines or tabs.
+ */
+ convert_to_spaces(value, FALSE);
+
+ if (!op_ptr) {
+ /*
+ * No option items yet.
+ */
+ if (text->last_anchor->input_field->type != F_OPTION_LIST_TYPE) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HText_setLastOptionValue: last input_field not F_OPTION_LIST_TYPE (%d)\n",
+ F_OPTION_LIST_TYPE);
+ fprintf(stderr,
+ " but %d, ignoring!\n",
+ text->last_anchor->input_field->type);
+ }
+ return NULL;
+ }
+
+ new_ptr = text->last_anchor->input_field->select_list =
+ (OptionType *)calloc(1, sizeof(OptionType));
+ if (new_ptr == NULL)
+ outofmem(__FILE__, "HText_setLastOptionValue");
+
+ first_option = TRUE;
+ } else {
+ while (op_ptr->next) {
+ number++;
+ op_ptr=op_ptr->next;
+ }
+ number++; /* add one more */
+
+ op_ptr->next = new_ptr =
+ (OptionType *)calloc(1, sizeof(OptionType));
+ if (new_ptr == NULL)
+ outofmem(__FILE__, "HText_setLastOptionValue");
+ }
+
+ new_ptr->name = NULL;
+ new_ptr->cp_submit_value = NULL;
+ new_ptr->next = NULL;
+ for (i = 0, j = 0; cp[i]; i++) {
+ if (cp[i] == HT_NON_BREAK_SPACE ||
+ cp[i] == HT_EM_SPACE) {
+ cp[j++] = ' ';
+ } else if (cp[i] != LY_SOFT_HYPHEN &&
+ !IsSpecialAttrChar((unsigned char)cp[i])) {
+ cp[j++] = cp[i];
+ }
+ }
+ cp[j] = '\0';
+ if (HTCJK != NOCJK) {
+ if (cp &&
+ (tmp = (unsigned char *)calloc(1, strlen(cp)+1))) {
+ if (kanji_code == EUC) {
+ TO_EUC((unsigned char *)cp, tmp);
+ val_cs = current_char_set;
+ } else if (kanji_code == SJIS) {
+ TO_SJIS((unsigned char *)cp, tmp);
+ val_cs = current_char_set;
+ } else {
+ for (i = 0, j = 0; cp[i]; i++) {
+ if (cp[i] != '\033') {
+ tmp[j++] = cp[i];
+ }
+ }
+ }
+ StrAllocCopy(new_ptr->name, (CONST char *)tmp);
+ FREE(tmp);
+ }
+ } else {
+ StrAllocCopy(new_ptr->name, cp);
+ }
+ StrAllocCopy(new_ptr->cp_submit_value,
+ (submit_value ? submit_value :
+ HText_skipOptionNumPrefix(new_ptr->name)));
+ new_ptr->value_cs = (submit_value ? submit_val_cs : val_cs);
+
+ if (first_option) {
+ StrAllocCopy(HTCurSelectedOptionValue, new_ptr->name);
+ text->last_anchor->input_field->num_value = 0;
+ /*
+ * If this is the first option in a popup select list,
+ * HText_beginInput may have allocated the value and
+ * cp_submit_value fields, so free them now to avoid
+ * a memory leak. - kw
+ */
+ FREE(text->last_anchor->input_field->value);
+ FREE(text->last_anchor->input_field->cp_submit_value);
+
+ text->last_anchor->input_field->value =
+ text->last_anchor->input_field->select_list->name;
+ text->last_anchor->input_field->orig_value =
+ text->last_anchor->input_field->select_list->name;
+ text->last_anchor->input_field->cp_submit_value =
+ text->last_anchor->input_field->select_list->cp_submit_value;
+ text->last_anchor->input_field->orig_submit_value =
+ text->last_anchor->input_field->select_list->cp_submit_value;
+ text->last_anchor->input_field->value_cs =
+ new_ptr->value_cs;
+ } else {
+ int newlen = strlen(new_ptr->name);
+ int curlen = strlen(HTCurSelectedOptionValue);
+ /*
+ * Make the selected Option Value as long as
+ * the longest option.
+ */
+ if (newlen > curlen)
+ StrAllocCat(HTCurSelectedOptionValue,
+ UNDERSCORES(newlen-curlen));
+ }
+
+ if (checked) {
+ int curlen = strlen(new_ptr->name);
+ int newlen = strlen(HTCurSelectedOptionValue);
+ /*
+ * Set the default option as this one.
+ */
+ text->last_anchor->input_field->num_value = number;
+ text->last_anchor->input_field->value = new_ptr->name;
+ text->last_anchor->input_field->orig_value = new_ptr->name;
+ text->last_anchor->input_field->cp_submit_value =
+ new_ptr->cp_submit_value;
+ text->last_anchor->input_field->orig_submit_value =
+ new_ptr->cp_submit_value;
+ text->last_anchor->input_field->value_cs =
+ new_ptr->value_cs;
+ StrAllocCopy(HTCurSelectedOptionValue, new_ptr->name);
+ if (newlen > curlen)
+ StrAllocCat(HTCurSelectedOptionValue,
+ UNDERSCORES(newlen-curlen));
+ }
+
+ /*
+ * Return the selected Option value to be sent to the screen.
+ */
+ if (order == LAST_ORDER) {
+ /*
+ * Change the value.
+ */
+ text->last_anchor->input_field->size =
+ strlen(HTCurSelectedOptionValue);
+ ret_Value = HTCurSelectedOptionValue;
+ }
+ }
+
+ if (TRACE) {
+ fprintf(stderr,"HText_setLastOptionValue:%s value=%s",
+ (order == LAST_ORDER) ? " LAST_ORDER" : "",
+ value);
+ fprintf(stderr," val_cs=%d \"%s\"",
+ val_cs,
+ (val_cs >= 0 ?
+ LYCharSet_UC[val_cs].MIMEname : "<UNKNOWN>"));
+ if (submit_value) {
+ fprintf(stderr, " (submit_val_cs %d \"%s\") submit_value%s=%s\n",
+ submit_val_cs,
+ (submit_val_cs >= 0 ?
+ LYCharSet_UC[submit_val_cs].MIMEname : "<UNKNOWN>"),
+ (HTCurSelectGroupType == F_CHECKBOX_TYPE) ?
+ "(ignored)" : "",
+ submit_value);
+ }
+ else {
+ fprintf(stderr,"\n");
+ }
+ }
+ return(ret_Value);
+}
+
+/*
+ * Assign a form input anchor.
+ * Returns the number of characters to leave
+ * blank so that the input field can fit.
+ */
+PUBLIC int HText_beginInput ARGS3(
+ HText *, text,
+ BOOL, underline,
+ InputFieldData *, I)
+{
+
+ TextAnchor * a = (TextAnchor *) calloc(1, sizeof(*a));
+ FormInfo * f = (FormInfo *) calloc(1, sizeof(*f));
+ CONST char *cp_option = NULL;
+ char *IValue = NULL;
+ unsigned char *tmp = NULL;
+ int i, j;
+
+ if (TRACE)
+ fprintf(stderr,"Entering HText_beginInput\n");
+
+ if (a == NULL || f == NULL)
+ outofmem(__FILE__, "HText_beginInput");
+
+ a->start = text->chars + text->last_line->size;
+ a->inUnderline = underline;
+ a->line_pos = text->last_line->size;
+
+
+ /*
+ * If this is a radio button, or an OPTION we're converting
+ * to a radio button, and it's the first with this name, make
+ * sure it's checked by default. Otherwise, if it's checked,
+ * uncheck the default or any preceding radio button with this
+ * name that was checked. - FM
+ */
+ if (I->type != NULL && !strcmp(I->type,"OPTION") &&
+ HTCurSelectGroupType == F_RADIO_TYPE && LYSelectPopups == FALSE) {
+ I->type = "RADIO";
+ I->name = HTCurSelectGroup;
+ I->name_cs = HTCurSelectGroupCharset;
+ }
+ if (I->name && I->type && !strcasecomp(I->type, "radio")) {
+ if (!text->last_anchor) {
+ I->checked = TRUE;
+ } else {
+ TextAnchor * b = text->first_anchor;
+ int i2 = 0;
+ while (b) {
+ if (b->link_type == INPUT_ANCHOR &&
+ b->input_field->type == F_RADIO_TYPE &&
+ b->input_field->number == HTFormNumber) {
+ if (!strcmp(b->input_field->name, I->name)) {
+ if (I->checked && b->input_field->num_value) {
+ b->input_field->num_value = 0;
+ StrAllocCopy(b->input_field->orig_value, "0");
+ break;
+ }
+ i2++;
+ }
+ }
+ if (b == text->last_anchor) {
+ if (i2 == 0)
+ I->checked = TRUE;
+ break;
+ }
+ b = b->next;
+ }
+ }
+ }
+
+ a->next = 0;
+ a->anchor = NULL;
+ a->link_type = INPUT_ANCHOR;
+ a->show_anchor = YES;
+
+ a->hightext = NULL;
+ a->extent = 2;
+
+ a->input_field = f;
+
+ f->select_list = 0;
+ f->number = HTFormNumber;
+ f->disabled = (HTFormDisabled ? TRUE : I->disabled);
+ f->no_cache = NO;
+
+ HTFormFields++;
+
+
+ /*
+ * Set the no_cache flag if the METHOD is POST. - FM
+ */
+ if (HTFormMethod == URL_POST_METHOD)
+ f->no_cache = TRUE;
+
+ /*
+ * Set up VALUE.
+ */
+ if (I->value)
+ StrAllocCopy(IValue, I->value);
+ if (IValue && HTCJK != NOCJK) {
+ if ((tmp = (unsigned char *)calloc(1, (strlen(IValue) + 1)))) {
+ if (kanji_code == EUC) {
+ TO_EUC((unsigned char *)IValue, tmp);
+ I->value_cs = current_char_set;
+ } else if (kanji_code == SJIS) {
+ TO_SJIS((unsigned char *)IValue, tmp);
+ I->value_cs = current_char_set;
+ } else {
+ for (i = 0, j = 0; IValue[i]; i++) {
+ if (IValue[i] != '\033') {
+ tmp[j++] = IValue[i];
+ }
+ }
+ }
+ StrAllocCopy(IValue, (CONST char *)tmp);
+ FREE(tmp);
+ }
+ }
+
+ /*
+ * Special case of OPTION.
+ * Is handled above if radio type and LYSelectPopups is FALSE.
+ */
+ /* set the values and let the parsing below do the work */
+ if (I->type != NULL && !strcmp(I->type,"OPTION")) {
+ cp_option = I->type;
+ if (HTCurSelectGroupType == F_RADIO_TYPE)
+ I->type = "OPTION_LIST";
+ else
+ I->type = "CHECKBOX";
+ I->name = HTCurSelectGroup;
+ I->name_cs = HTCurSelectGroupCharset;
+
+ /*
+ * The option's size parameter actually gives the length and not
+ * the width of the list. Perform the conversion here
+ * and get rid of the allocated HTCurSelect....
+ * 0 is ok as it means any length (arbitrary decision).
+ */
+ if (HTCurSelectGroupSize != NULL) {
+ f->size_l = atoi(HTCurSelectGroupSize);
+ FREE(HTCurSelectGroupSize);
+ }
+ }
+
+ /*
+ * Set SIZE.
+ */
+ if (I->size != NULL) {
+ f->size = atoi(I->size);
+ /*
+ * Leave at zero for option lists.
+ */
+ if (f->size == 0 && cp_option == NULL) {
+ f->size = 20; /* default */
+ }
+ } else {
+ f->size = 20; /* default */
+ }
+
+ /*
+ * Set MAXLENGTH.
+ */
+ if (I->maxlength != NULL) {
+ f->maxlength = atoi(I->maxlength);
+ } else {
+ f->maxlength = 0; /* 0 means infinite */
+ }
+
+ /*
+ * Set CHECKED
+ * (num_value is only relevant to check and radio types).
+ */
+ if (I->checked == TRUE)
+ f->num_value = 1;
+ else
+ f->num_value = 0;
+
+ /*
+ * Set TYPE.
+ */
+ if (I->type != NULL) {
+ if (!strcasecomp(I->type,"password")) {
+ f->type = F_PASSWORD_TYPE;
+ } else if (!strcasecomp(I->type,"checkbox")) {
+ f->type = F_CHECKBOX_TYPE;
+ } else if (!strcasecomp(I->type,"radio")) {
+ f->type = F_RADIO_TYPE;
+ } else if (!strcasecomp(I->type,"submit")) {
+ f->type = F_SUBMIT_TYPE;
+ } else if (!strcasecomp(I->type,"image")) {
+ f->type = F_IMAGE_SUBMIT_TYPE;
+ } else if (!strcasecomp(I->type,"reset")) {
+ f->type = F_RESET_TYPE;
+ } else if (!strcasecomp(I->type,"OPTION_LIST")) {
+ f->type = F_OPTION_LIST_TYPE;
+ } else if (!strcasecomp(I->type,"hidden")) {
+ f->type = F_HIDDEN_TYPE;
+ HTFormFields--;
+ f->size = 0;
+ } else if (!strcasecomp(I->type,"textarea")) {
+ f->type = F_TEXTAREA_TYPE;
+ } else if (!strcasecomp(I->type,"range")) {
+ f->type = F_RANGE_TYPE;
+ } else if (!strcasecomp(I->type,"file")) {
+ f->type = F_FILE_TYPE;
+ } else if (!strcasecomp(I->type,"keygen")) {
+ f->type = F_KEYGEN_TYPE;
+ } else {
+ /*
+ * Note that TYPE="scribble" defaults to TYPE="text". - FM
+ */
+ f->type = F_TEXT_TYPE; /* default */
+ }
+ } else {
+ f->type = F_TEXT_TYPE;
+ }
+
+ /*
+ * Set NAME.
+ */
+ if (I->name != NULL) {
+ StrAllocCopy(f->name,I->name);
+ f->name_cs = I->name_cs;
+ } else {
+ if (f->type == F_RESET_TYPE ||
+ f->type == F_SUBMIT_TYPE ||
+ f->type == F_IMAGE_SUBMIT_TYPE) {
+ /*
+ * Set name to empty string.
+ */
+ StrAllocCopy(f->name, "");
+ } else {
+ /*
+ * Error! NAME must be present.
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "GridText: No name present in input field; not displaying\n");
+ FREE(a);
+ FREE(f);
+ FREE(IValue);
+ return(0);
+ }
+ }
+
+ /*
+ * Add this anchor to the anchor list
+ */
+ if (text->last_anchor) {
+ text->last_anchor->next = a;
+ } else {
+ text->first_anchor = a;
+ }
+
+ /*
+ * Set VALUE, if it exists. Otherwise, if it's not
+ * an option list make it a zero-length string. - FM
+ */
+ if (IValue != NULL) {
+ /*
+ * OPTION VALUE is not actually the value to be seen but is to
+ * be sent....
+ */
+ if (f->type == F_OPTION_LIST_TYPE ||
+ f->type == F_CHECKBOX_TYPE) {
+ /*
+ * Fill both with the value. The f->value may be
+ * overwritten in HText_setLastOptionValue....
+ */
+ StrAllocCopy(f->value, IValue);
+ StrAllocCopy(f->cp_submit_value, IValue);
+ } else {
+ StrAllocCopy(f->value, IValue);
+ }
+ f->value_cs = I->value_cs;
+ } else if (f->type != F_OPTION_LIST_TYPE) {
+ StrAllocCopy(f->value, "");
+ /*
+ * May be an empty INPUT field. The text entered will then
+ * probably be in the current display character set. - kw
+ */
+ f->value_cs = current_char_set;
+ }
+
+ /*
+ * Run checks and fill in necessary values.
+ */
+ if (f->type == F_RESET_TYPE) {
+ if (f->value && *f->value != '\0') {
+ f->size = strlen(f->value);
+ } else {
+ StrAllocCopy(f->value, "Reset");
+ f->size = 5;
+ }
+ } else if (f->type == F_IMAGE_SUBMIT_TYPE ||
+ f->type == F_SUBMIT_TYPE) {
+ if (f->value && *f->value != '\0') {
+ f->size = strlen(f->value);
+ } else if (f->type == F_IMAGE_SUBMIT_TYPE) {
+ StrAllocCopy(f->value, "[IMAGE]-Submit");
+ f->size = 14;
+ } else {
+ StrAllocCopy(f->value, "Submit");
+ f->size = 6;
+ }
+ f->submit_action = NULL;
+ StrAllocCopy(f->submit_action, HTFormAction);
+ if (HTFormEnctype != NULL)
+ StrAllocCopy(f->submit_enctype, HTFormEnctype);
+ if (HTFormTitle != NULL)
+ StrAllocCopy(f->submit_title, HTFormTitle);
+ f->submit_method = HTFormMethod;
+
+ } else if (f->type == F_RADIO_TYPE || f->type == F_CHECKBOX_TYPE) {
+ f->size=3;
+ if (IValue == NULL)
+ StrAllocCopy(f->value, (f->type == F_CHECKBOX_TYPE ? "on" : ""));
+
+ }
+ FREE(IValue);
+
+ /*
+ * Set original values.
+ */
+ if (f->type == F_RADIO_TYPE || f->type == F_CHECKBOX_TYPE ) {
+ if (f->num_value)
+ StrAllocCopy(f->orig_value, "1");
+ else
+ StrAllocCopy(f->orig_value, "0");
+ } else if (f->type == F_OPTION_LIST_TYPE) {
+ f->orig_value = NULL;
+ } else {
+ StrAllocCopy(f->orig_value, f->value);
+ }
+
+ /*
+ * Store accept-charset if present, converting to lowercase
+ * and collapsing spaces. - kw
+ */
+ if (I->accept_cs) {
+ StrAllocCopy(f->accept_cs, I->accept_cs);
+ collapse_spaces(f->accept_cs);
+ for (i = 0; f->accept_cs[i]; i++)
+ f->accept_cs[i] = TOLOWER(f->accept_cs[i]);
+ }
+
+ /*
+ * Add numbers to form fields if needed. - LE & FM
+ */
+ switch (f->type) {
+ /*
+ * Do not supply number for hidden fields, nor
+ * for types that are not yet implemented.
+ */
+ case F_HIDDEN_TYPE:
+ case F_FILE_TYPE:
+ case F_RANGE_TYPE:
+ case F_KEYGEN_TYPE:
+ a->number = 0;
+ break;
+
+ default:
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED)
+ a->number = ++(text->last_anchor_number);
+ else
+ a->number = 0;
+ break;
+ }
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED && a->number > 0) {
+ char marker[16];
+
+ if (f->type != F_OPTION_LIST_TYPE)
+ /*
+ * '[' was already put out for a popup menu
+ * designator. See HTML.c.
+ */
+ HText_appendCharacter(text, '[');
+ sprintf(marker,"%d]", a->number);
+ HText_appendText(text, marker);
+ if (f->type == F_OPTION_LIST_TYPE)
+ /*
+ * Add option list designation char.
+ */
+ HText_appendCharacter(text, '[');
+ a->start = text->chars + text->last_line->size;
+ a->line_pos = text->last_line->size;
+ }
+
+ /*
+ * Restrict SIZE to maximum allowable size.
+ */
+ switch (f->type) {
+ int MaximumSize;
+
+ case F_SUBMIT_TYPE:
+ case F_IMAGE_SUBMIT_TYPE:
+ case F_RESET_TYPE:
+ case F_TEXT_TYPE:
+ case F_TEXTAREA_TYPE:
+ /*
+ * For submit and reset buttons, and for text entry
+ * fields and areas, we limit the size element to that
+ * of one line for the current style because that's
+ * the most we could highlight on overwrites, and/or
+ * handle in the line editor. The actual values for
+ * text entry lines can be long, and will be scrolled
+ * horizontally within the editing window. - FM
+ */
+ MaximumSize = (LYcols - 1) -
+ (int)text->style->leftIndent -
+ (int)text->style->rightIndent;
+
+ /*
+ * If we are numbering form links, take that into
+ * account as well. - FM
+ */
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED)
+ MaximumSize -= ((a->number/10) + 3);
+ if (f->size > MaximumSize)
+ f->size = MaximumSize;
+
+ /*
+ * Save value for submit/reset buttons so they
+ * will be visible when printing the page. - LE
+ */
+ I->value = f->value;
+ break;
+
+
+ default:
+ /*
+ * For all other fields we limit the size element to
+ * 10 less than the screen width, because either they
+ * are types with small placeholders, and/or are a
+ * type which is handled via a popup window. - FM
+ */
+ if (f->size > LYcols-10)
+ f->size = LYcols-10; /* maximum */
+ break;
+ }
+
+ /*
+ * Add this anchor to the anchor list
+ */
+ text->last_anchor = a;
+
+ if (HTCurrentForm) { /* should always apply! - kw */
+ if (!HTCurrentForm->first_field) {
+ HTCurrentForm->first_field = f;
+ }
+ HTCurrentForm->last_field = f;
+ HTCurrentForm->nfields++; /* will count hidden fields - kw */
+ /*
+ * Propagate form field's accept-charset attribute to enclosing
+ * form if the form itself didn't have an accept-charset - kw
+ */
+ if (f->accept_cs && !HTFormAcceptCharset) {
+ StrAllocCopy(HTFormAcceptCharset, f->accept_cs);
+ }
+ if (!text->forms) {
+ text->forms = HTList_new();
+ }
+ } else {
+ if (TRACE)
+ fprintf(stderr, "beginInput: HTCurrentForm is missing!\n");
+ }
+
+ if (TRACE) {
+ fprintf(stderr,"Input link: name=%s\nvalue=%s\nsize=%d\n",
+ f->name,
+ ((f->value != NULL) ? f->value : ""),
+ f->size);
+ fprintf(stderr,"Input link: name_cs=%d \"%s\" (from %d \"%s\")\n",
+ f->name_cs,
+ (f->name_cs >= 0 ?
+ LYCharSet_UC[f->name_cs].MIMEname : "<UNKNOWN>"),
+ I->name_cs,
+ (I->name_cs >= 0 ?
+ LYCharSet_UC[I->name_cs].MIMEname : "<UNKNOWN>"));
+ fprintf(stderr," value_cs=%d \"%s\" (from %d \"%s\")\n",
+ f->value_cs,
+ (f->value_cs >= 0 ?
+ LYCharSet_UC[f->value_cs].MIMEname : "<UNKNOWN>"),
+ I->value_cs,
+ (I->value_cs >= 0 ?
+ LYCharSet_UC[I->value_cs].MIMEname : "<UNKNOWN>"));
+ }
+
+ /*
+ * Return the SIZE of the input field.
+ */
+ return(f->size);
+}
+
+/*
+ * Get a translation (properly: transcoding) quality, factoring in
+ * our ability to translate (an UCTQ_t) and a possible q parameter
+ * on the given charset string, for cs_from -> givenmime.
+ * The parsed input string will be mutilated on exit(!).
+ * Note that results are not normalised to 1.0, but results from
+ * different calls of this function can be compared. - kw
+ *
+ * Obsolete, it was planned to use here a quality parametr UCTQ_t,
+ * which is boolean now.
+ */
+PRIVATE double get_trans_q ARGS2(
+ int, cs_from,
+ char *, givenmime)
+{
+ double df = 1.0;
+ BOOL tq;
+ char *p;
+ if (!givenmime || !(*givenmime))
+ return 0.0;
+ if ((p = strchr(givenmime,';')) != NULL) {
+ *p++ = '\0';
+ }
+ if (!strcmp(givenmime, "*"))
+ tq = UCCanTranslateFromTo(cs_from,
+ UCGetLYhndl_byMIME("utf-8"));
+ else
+ tq = UCCanTranslateFromTo(cs_from,
+ UCGetLYhndl_byMIME(givenmime));
+ if (!tq)
+ return 0.0;
+ if (p && *p) {
+ char *pair, *field = p, *pval, *ptok;
+ /* Get all the parameters to the Charset */
+ while ((pair = HTNextTok(&field, ";", "\"", NULL)) != NULL) {
+ if ((ptok = HTNextTok(&pair, "= ", NULL, NULL)) != NULL &&
+ (pval = HTNextField(&pair)) != NULL) {
+ if (0==strcasecomp(ptok,"q")) {
+ df = strtod(pval, NULL);
+ break;
+ }
+ }
+ }
+ return (df * tq);
+ } else {
+ return tq;
+ }
+}
+
+/*
+ * Find the best charset for submission, if we have an ACCEPT_CHARSET
+ * list. It factors in how well we can translate (just as guess, and
+ * not a very good one..) and possible ";q=" factors. Yes this is
+ * more general than it needs to be here.
+ *
+ * Input is cs_in and acceptstring.
+ *
+ * Will return charset handle as int.
+ * best_csname will point to a newly allocated MIME string for the
+ * charset corresponding to the return value if return value >= 0.
+ * - kw
+ */
+PRIVATE int find_best_target_cs ARGS3(
+ char **, best_csname,
+ int, cs_from,
+ CONST char *, acceptstring)
+{
+ char *paccept = NULL;
+ double bestq = -1.0;
+ char *bestmime = NULL;
+ char *field, *nextfield;
+ StrAllocCopy(paccept, acceptstring);
+ nextfield = paccept;
+ while ((field = HTNextTok(&nextfield, ",", "\"", NULL)) != NULL) {
+ double q;
+ if (*field != '\0') {
+ /* Get the Charset*/
+ q = get_trans_q(cs_from, field);
+ if (q > bestq) {
+ bestq = q;
+ bestmime = field;
+ }
+ }
+ }
+ if (bestmime) {
+ if (!strcmp(bestmime, "*")) /* non-standard for HTML attribute.. */
+ StrAllocCopy(*best_csname, "utf-8");
+ else
+ StrAllocCopy(*best_csname, bestmime);
+ FREE(paccept);
+ if (bestq > 0)
+ return (UCGetLYhndl_byMIME(*best_csname));
+ else
+ return (-1);
+ }
+ FREE(paccept);
+ return (-1);
+}
+
+PUBLIC void HText_SubmitForm ARGS4(
+ FormInfo *, submit_item,
+ document *, doc,
+ char *, link_name,
+ char *, link_value)
+{
+ TextAnchor *anchor_ptr;
+ int form_number = submit_item->number;
+ FormInfo *form_ptr;
+ PerFormInfo *thisform;
+ int len;
+ char *query = NULL;
+ char *escaped1 = NULL, *escaped2 = NULL;
+ int first_one = 1;
+ char *last_textarea_name = NULL;
+ int textarea_lineno = 0;
+ char *previous_blanks = NULL;
+ BOOLEAN PlainText = FALSE;
+ BOOLEAN SemiColon = FALSE;
+ char *Boundary = NULL;
+ char *MultipartContentType = NULL;
+ int target_cs = -1;
+ CONST char *out_csname;
+ CONST char *target_csname = NULL;
+ char *name_used = "";
+ BOOL form_has_8bit = NO, form_has_special = NO;
+ BOOL field_has_8bit = NO, field_has_special = NO;
+ BOOL name_has_8bit = NO, name_has_special = NO;
+ BOOL have_accept_cs = NO;
+ BOOL success;
+ BOOL had_chartrans_warning = NO;
+ char *val_used = "";
+ char *copied_val_used = NULL;
+ char *copied_name_used = NULL;
+
+ if (!HTMainText)
+ return;
+
+ thisform = HTList_objectAt(HTMainText->forms, form_number - 1);
+ /* Sanity check */
+ if (!thisform) {
+ if (TRACE)
+ fprintf(stderr,
+ "SubmitForm: form %d not in HTMainText's list!\n",
+ form_number);
+ } else if (thisform->number != form_number) {
+ if (TRACE)
+ fprintf(stderr,
+ "SubmitForm: failed sanity check, %d!=%d !\n",
+ thisform->number, form_number);
+ thisform = NULL;
+ }
+
+ if (submit_item->submit_action) {
+ /*
+ * If we're mailing, make sure it's a mailto ACTION. - FM
+ */
+ if ((submit_item->submit_method == URL_MAIL_METHOD) &&
+ strncmp(submit_item->submit_action, "mailto:", 7)) {
+ HTAlert(BAD_FORM_MAILTO);
+ return;
+ }
+
+ /*
+ * Set length plus breathing room.
+ */
+ len = strlen(submit_item->submit_action) + 2048;
+ } else {
+ return;
+ }
+
+ /*
+ * Check the ENCTYPE and set up the appropriate variables. - FM
+ */
+ if (submit_item->submit_enctype &&
+ !strncasecomp(submit_item->submit_enctype, "text/plain", 10)) {
+ /*
+ * Do not hex escape, and use physical newlines
+ * to separate name=value pairs. - FM
+ */
+ PlainText = TRUE;
+ } else if (submit_item->submit_enctype &&
+ !strncasecomp(submit_item->submit_enctype,
+ "application/sgml-form-urlencoded", 32)) {
+ /*
+ * Use semicolons instead of ampersands as the
+ * separators for name=value pairs. - FM
+ */
+ SemiColon = TRUE;
+ } else if (submit_item->submit_enctype &&
+ !strncasecomp(submit_item->submit_enctype,
+ "multipart/form-data", 19)) {
+ /*
+ * Use the multipart MIME format. We should generate
+ * a boundary string which we are sure doesn't occur
+ * in the content, but for now we'll just assume that
+ * this string doesn't. - FM
+ */
+ Boundary = "xnyLAaB03X";
+ }
+
+ /*
+ * Determine in what character encoding (aka. charset) we should
+ * submit. We call this target_cs and the MIME name for it
+ * target_csname.
+ * TODO: - actually use ACCEPT-CHARSET stuff from FORM
+ * TODO: - deal with list in ACCEPT-CHARSET, find a "best"
+ * charset to submit
+ */
+
+ /* Look at ACCEPT-CHARSET on the submitting field if we have one. */
+ if (thisform && submit_item->accept_cs &&
+ strcasecomp(submit_item->accept_cs, "UNKNOWN")) {
+ have_accept_cs = YES;
+ target_cs = find_best_target_cs(&thisform->thisacceptcs,
+ current_char_set,
+ submit_item->accept_cs);
+ }
+ /* Look at ACCEPT-CHARSET on form as a whole if submitting field
+ * didn't have one. */
+ if (thisform && !have_accept_cs && thisform->accept_cs &&
+ strcasecomp(thisform->accept_cs, "UNKNOWN")) {
+ have_accept_cs = YES;
+ target_cs = find_best_target_cs(&thisform->thisacceptcs,
+ current_char_set,
+ thisform->accept_cs);
+ }
+ if (have_accept_cs && (target_cs >= 0) && thisform->thisacceptcs) {
+ target_csname = thisform->thisacceptcs;
+ }
+
+ if (target_cs < 0 &&
+ HTMainText->node_anchor->charset &&
+ *HTMainText->node_anchor->charset) {
+ target_cs = UCGetLYhndl_byMIME(HTMainText->node_anchor->charset);
+ if (target_cs >= 0) {
+ target_csname = HTMainText->node_anchor->charset;
+ } else {
+ target_cs = UCLYhndl_for_unspec;
+ if (target_cs >= 0)
+ target_csname = LYCharSet_UC[target_cs].MIMEname;
+ }
+ }
+ if (target_cs < 0) {
+ target_cs = UCLYhndl_for_unspec;
+ }
+
+ /*
+ * Go through list of anchors and get size first.
+ */
+ /*
+ * also get a "max." charset parameter - kw
+ */
+ anchor_ptr = HTMainText->first_anchor;
+ while (anchor_ptr) {
+ if (anchor_ptr->link_type == INPUT_ANCHOR) {
+ if (anchor_ptr->input_field->number == form_number) {
+
+ char *p;
+ char * val;
+ form_ptr = anchor_ptr->input_field;
+ val = form_ptr->cp_submit_value != NULL ?
+ form_ptr->cp_submit_value : form_ptr->value;
+ field_has_8bit = NO;
+ field_has_special = NO;
+
+ len += (strlen(form_ptr->name) + (Boundary ? 100 : 10));
+ /*
+ * Calculate by the option submit value if present.
+ */
+ if (form_ptr->cp_submit_value != NULL) {
+ len += (strlen(form_ptr->cp_submit_value) + 10);
+ } else {
+ len += (strlen(form_ptr->value) + 10);
+ }
+ len += 32; /* plus and ampersand + safety net */
+
+ for (p = val;
+ p && *p && !(field_has_8bit && field_has_special);
+ p++)
+ if ((*p == HT_NON_BREAK_SPACE) ||
+ (*p == HT_EM_SPACE) ||
+ (*p == LY_SOFT_HYPHEN)) {
+ field_has_special = YES;
+ } else if ((*p & 0x80) != 0) {
+ field_has_8bit = YES;
+ }
+ for (p = form_ptr->name;
+ p && *p && !(name_has_8bit && name_has_special);
+ p++)
+ if ((*p == HT_NON_BREAK_SPACE) ||
+ (*p == HT_EM_SPACE) ||
+ (*p == LY_SOFT_HYPHEN)) {
+ name_has_special = YES;
+ } else if ((*p & 0x80) != 0) {
+ name_has_8bit = YES;
+ }
+
+ if (field_has_8bit || name_has_8bit)
+ form_has_8bit = YES;
+ if (field_has_special || name_has_special)
+ form_has_special = YES;
+
+ if (!field_has_8bit && !field_has_special) {
+ /* already ok */
+ } else if (target_cs < 0) {
+ /* already confused */
+ } else if (!field_has_8bit &&
+ (LYCharSet_UC[target_cs].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[target_cs].like8859 & UCT_R_8859SPECL))) {
+ /* those specials will be trivial */
+ } else if (UCNeedNotTranslate(form_ptr->value_cs, target_cs)) {
+ /* already ok */
+ } else if (UCCanTranslateFromTo(form_ptr->value_cs, target_cs)) {
+ /* also ok */
+ } else if (UCCanTranslateFromTo(target_cs, form_ptr->value_cs)) {
+ target_cs = form_ptr->value_cs; /* try this */
+ target_csname = NULL; /* will be set after loop */
+ } else {
+ target_cs = -1; /* don't know what to do */
+ }
+
+ /* Same for name */
+ if (!name_has_8bit && !name_has_special) {
+ /* already ok */
+ } else if (target_cs < 0) {
+ /* already confused */
+ } else if (!name_has_8bit &&
+ (LYCharSet_UC[target_cs].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[target_cs].like8859 & UCT_R_8859SPECL))) {
+ /* those specials will be trivial */
+ } else if (UCNeedNotTranslate(form_ptr->name_cs, target_cs)) {
+ /* already ok */
+ } else if (UCCanTranslateFromTo(form_ptr->name_cs, target_cs)) {
+ /* also ok */
+ } else if (UCCanTranslateFromTo(target_cs, form_ptr->name_cs)) {
+ target_cs = form_ptr->value_cs; /* try this */
+ target_csname = NULL; /* will be set after loop */
+ } else {
+ target_cs = -1; /* don't know what to do */
+ }
+
+ } else if (anchor_ptr->input_field->number > form_number) {
+ break;
+ }
+ }
+
+ if (anchor_ptr == HTMainText->last_anchor)
+ break;
+
+ anchor_ptr = anchor_ptr->next;
+ }
+
+ if (target_csname == NULL && target_cs >= 0) {
+ if (form_has_8bit) {
+ target_csname = LYCharSet_UC[target_cs].MIMEname;
+ } else if (form_has_special) {
+ target_csname = LYCharSet_UC[target_cs].MIMEname;
+ } else {
+ target_csname = "us-ascii";
+ }
+ }
+ /*
+ * Get query ready.
+ */
+ query = (char *)calloc(1, len);
+ if (query == NULL)
+ outofmem(__FILE__, "HText_SubmitForm");
+
+ if (submit_item->submit_method == URL_GET_METHOD && Boundary == NULL) {
+ strcpy (query, submit_item->submit_action);
+ /*
+ * Method is GET. Clip out any anchor in the current URL.
+ */
+ strtok (query, "#");
+ /*
+ * Clip out any old query in the current URL.
+ */
+ strtok (query, "?");
+ /*
+ * Add the lead question mark for the new URL.
+ */
+ strcat(query,"?");
+ } else {
+ query[0] = '\0';
+ /*
+ * We are submitting POST content to a server,
+ * so load the post_content_type element. - FM
+ */
+ if (SemiColon == TRUE) {
+ StrAllocCopy(doc->post_content_type,
+ "application/sgml-form-urlencoded");
+ } else if (PlainText == TRUE) {
+ StrAllocCopy(doc->post_content_type,
+ "text/plain");
+ } else if (Boundary != NULL) {
+ StrAllocCopy(doc->post_content_type,
+ "multipart/form-data; boundary=");
+ StrAllocCat(doc->post_content_type, Boundary);
+ } else {
+ StrAllocCopy(doc->post_content_type,
+ "application/x-www-form-urlencoded");
+ }
+
+ /*
+ * If the ENCTYPE is not multipart/form-data, append the
+ * charset we'll be sending to the post_content_type, IF
+ * (1) there was an explicit accept-charset attribute, OR
+ * (2) we have 8-bit or special chars, AND the document had
+ * an explicit (recognized and accepted) charset parameter,
+ * AND it or target_csname is different from iso-8859-1,
+ * OR
+ * (3) we have 8-bit or special chars, AND the document had
+ * no explicit (recognized and accepted) charset parameter,
+ * AND target_cs is different from the currently effective
+ * assumed charset (which should have been set by the user
+ * so that it reflects what the server is sending, if the
+ * document is rendered correctly).
+ * For multipart/form-data the equivalent will be done later,
+ * separately for each form field. - kw
+ */
+ if (have_accept_cs ||
+ (form_has_8bit || form_has_special)) {
+ if (target_cs >= 0 && target_csname) {
+ if (Boundary == NULL) {
+ if ((HTMainText->node_anchor->charset &&
+ (strcmp(HTMainText->node_anchor->charset,
+ "iso-8859-1") ||
+ strcmp(target_csname, "iso-8859-1"))) ||
+ (!HTMainText->node_anchor->charset &&
+ target_cs != UCLYhndl_for_unspec)) {
+ StrAllocCat(doc->post_content_type, "; charset=");
+ StrAllocCat(doc->post_content_type, target_csname);
+ }
+ }
+ } else {
+ had_chartrans_warning = YES;
+ _user_message(
+ CANNOT_TRANSCODE_FORM,
+ target_csname ? target_csname : "UNKNOWN");
+ sleep(AlertSecs);
+ }
+ }
+ }
+
+
+ out_csname = target_csname;
+
+ /*
+ * Reset anchor->ptr.
+ */
+ anchor_ptr = HTMainText->first_anchor;
+ /*
+ * Go through list of anchors and assemble URL query.
+ */
+ while (anchor_ptr) {
+ if (anchor_ptr->link_type == INPUT_ANCHOR) {
+ if (anchor_ptr->input_field->number == form_number) {
+ char *p;
+ int out_cs;
+ form_ptr = anchor_ptr->input_field;
+
+ if (form_ptr->type != F_TEXTAREA_TYPE)
+ textarea_lineno = 0;
+
+ switch(form_ptr->type) {
+ case F_RESET_TYPE:
+ break;
+ case F_SUBMIT_TYPE:
+ case F_TEXT_SUBMIT_TYPE:
+ case F_IMAGE_SUBMIT_TYPE:
+ if (!(form_ptr->name && *form_ptr->name != '\0' &&
+ !strcmp(form_ptr->name, link_name))) {
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: skipping submit field with ");
+ fprintf(stderr,
+ "name \"%s\" for link_name \"%s\", %s.",
+ form_ptr->name ? form_ptr->name : "???",
+ link_name ? link_name : "???",
+ (form_ptr->name && *form_ptr->name) ?
+ "not current link" : "no field name");
+ }
+ break;
+ }
+ if (!(form_ptr->type == F_TEXT_SUBMIT_TYPE ||
+ (form_ptr->value && *form_ptr->value != '\0' &&
+ !strcmp(form_ptr->value, link_value)))) {
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: skipping submit field with ");
+ fprintf(stderr,
+ "name \"%s\" for link_name \"%s\", %s!",
+ form_ptr->name ? form_ptr->name : "???",
+ link_name ? link_name : "???",
+ "values are different");
+ }
+ break;
+ }
+ /* fall through */
+ case F_RADIO_TYPE:
+ case F_CHECKBOX_TYPE:
+ case F_TEXTAREA_TYPE:
+ case F_PASSWORD_TYPE:
+ case F_TEXT_TYPE:
+ case F_OPTION_LIST_TYPE:
+ case F_HIDDEN_TYPE:
+ /*
+ * Be sure to actually look at the option submit value.
+ */
+ if (form_ptr->cp_submit_value != NULL) {
+ val_used = form_ptr->cp_submit_value;
+ } else {
+ val_used = form_ptr->value;
+ }
+
+ /*
+ * Charset-translate value now, because we need
+ * to know the charset parameter for multipart
+ * bodyparts. - kw
+ */
+ field_has_8bit = NO;
+ field_has_special = NO;
+ for (p = val_used;
+ p && *p && !(field_has_8bit && field_has_special);
+ p++) {
+ if ((*p == HT_NON_BREAK_SPACE) ||
+ (*p == HT_EM_SPACE) ||
+ (*p == LY_SOFT_HYPHEN)) {
+ field_has_special = YES;
+ } else if ((*p & 0x80) != 0) {
+ field_has_8bit = YES;
+ }
+ }
+
+ if (field_has_8bit || field_has_special) {
+ /* We should translate back. */
+ StrAllocCopy(copied_val_used, val_used);
+ success = LYUCTranslateBackFormData(&copied_val_used,
+ form_ptr->value_cs,
+ target_cs, PlainText);
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: field \"%s\" %d %s -> %d %s %s\n",
+ form_ptr->name ? form_ptr->name : "",
+ form_ptr->value_cs,
+ form_ptr->value_cs >= 0 ?
+ LYCharSet_UC[form_ptr->value_cs].MIMEname :
+ "???",
+ target_cs,
+ target_csname ? target_csname : "???",
+ success ? "OK" : "FAILED");
+ }
+ if (success) {
+ val_used = copied_val_used;
+ }
+ } else { /* We can use the value directly. */
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: field \"%s\" %d %s OK\n",
+ form_ptr->name ? form_ptr->name : "",
+ target_cs,
+ target_csname ? target_csname : "???");
+ }
+ success = YES;
+ }
+ if (!success) {
+ if (!had_chartrans_warning) {
+ had_chartrans_warning = YES;
+ _user_message(
+ CANNOT_TRANSCODE_FORM,
+ target_csname ? target_csname : "UNKNOWN");
+ sleep(AlertSecs);
+ }
+ out_cs = form_ptr->value_cs;
+ } else {
+ out_cs = target_cs;
+ }
+ if (out_cs >= 0)
+ out_csname = LYCharSet_UC[out_cs].MIMEname;
+ if (Boundary) {
+ if (!success && form_ptr->value_cs < 0) {
+ /* This is weird. */
+ StrAllocCopy(MultipartContentType,
+ "\r\nContent-Type: text/plain; charset=");
+ StrAllocCat(MultipartContentType, "UNKNOWN-8BIT");
+ } else if (!success) {
+ StrAllocCopy(MultipartContentType,
+ "\r\nContent-Type: text/plain; charset=");
+ StrAllocCat(MultipartContentType, out_csname);
+ target_csname = NULL;
+ } else {
+ if (!target_csname) {
+ target_csname = LYCharSet_UC[target_cs].MIMEname;
+ }
+ StrAllocCopy(MultipartContentType,
+ "\r\nContent-Type: text/plain; charset=");
+ StrAllocCat(MultipartContentType, out_csname);
+ }
+ }
+
+ /*
+ * Charset-translate name now, because we need
+ * to know the charset parameter for multipart
+ * bodyparts. - kw
+ */
+ if (form_ptr->type == F_TEXTAREA_TYPE) {
+ textarea_lineno++;
+ if (textarea_lineno > 1 &&
+ last_textarea_name && form_ptr->name &&
+ !strcmp(last_textarea_name, form_ptr->name)) {
+ break;
+ }
+ }
+ name_used = (form_ptr->name ?
+ form_ptr->name : "");
+
+ name_has_8bit = NO;
+ name_has_special = NO;
+ for (p = name_used;
+ p && *p && !(name_has_8bit && name_has_special);
+ p++) {
+ if ((*p == HT_NON_BREAK_SPACE) ||
+ (*p == HT_EM_SPACE) ||
+ (*p == LY_SOFT_HYPHEN)) {
+ name_has_special = YES;
+ } else if ((*p & 0x80) != 0) {
+ name_has_8bit = YES;
+ }
+ }
+
+ if (name_has_8bit || name_has_special) {
+ /* We should translate back. */
+ StrAllocCopy(copied_name_used, name_used);
+ success = LYUCTranslateBackFormData(&copied_name_used,
+ form_ptr->name_cs,
+ target_cs, PlainText);
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: name \"%s\" %d %s -> %d %s %s\n",
+ form_ptr->name ? form_ptr->name : "",
+ form_ptr->name_cs,
+ form_ptr->name_cs >= 0 ?
+ LYCharSet_UC[form_ptr->name_cs].MIMEname :
+ "???",
+ target_cs,
+ target_csname ? target_csname : "???",
+ success ? "OK" : "FAILED");
+ }
+ if (success) {
+ name_used = copied_name_used;
+ }
+ if (Boundary) {
+ if (!success) {
+ StrAllocCopy(MultipartContentType, "");
+ target_csname = NULL;
+ } else {
+ if (!target_csname)
+ target_csname = LYCharSet_UC[target_cs].MIMEname;
+ }
+ }
+ } else { /* We can use the name directly. */
+ if (TRACE) {
+ fprintf(stderr,
+ "SubmitForm: name \"%s\" %d %s OK\n",
+ form_ptr->name ? form_ptr->name : "",
+ target_cs,
+ target_csname ? target_csname : "???");
+ }
+ success = YES;
+ if (Boundary) {
+ StrAllocCopy(copied_name_used, name_used);
+ }
+ }
+ if (!success) {
+ if (!had_chartrans_warning) {
+ had_chartrans_warning = YES;
+ _user_message(
+ CANNOT_TRANSCODE_FORM,
+ target_csname ? target_csname : "UNKNOWN");
+ sleep(AlertSecs);
+ }
+ }
+ if (Boundary) {
+ /*
+ * According to RFC 1867, Non-ASCII field names
+ * "should be encoded according to the prescriptions
+ * of RFC 1522 [...]. I don't think RFC 1522 actually
+ * is meant to apply to parameters like this, and it
+ * is unknown whether any server would make sense of
+ * it, so for now just use some quoting/escaping and
+ * otherwise leave 8-bit values as they are.
+ * Non-ASCII characters in form field names submitted
+ * as multipart/form-data can only occur if the form
+ * provider specifically asked for it anyway. - kw
+ */
+ HTMake822Word(&copied_name_used);
+ name_used = copied_name_used;
+ }
+
+ break;
+ default:
+ if (TRACE)
+ fprintf(stderr, "SubmitForm: What type is %d?\n",
+ form_ptr->type);
+ }
+
+ switch(form_ptr->type) {
+
+ case F_RESET_TYPE:
+ break;
+
+ case F_SUBMIT_TYPE:
+ case F_TEXT_SUBMIT_TYPE:
+ case F_IMAGE_SUBMIT_TYPE:
+ /*
+ * If it has a non-zero length name (e.g., because
+ * it's IMAGE_SUBMIT_TYPE to be handled homologously
+ * to an image map, or a SUBMIT_TYPE in a set of
+ * multiple submit buttons, or a single type="text"
+ * that's been converted to a TEXT_SUBMIT_TYPE),
+ * include the name=value pair, or fake name.x=0 and
+ * name.y=0 pairs for IMAGE_SUBMIT_TYPE. - FM
+ */
+ if ((form_ptr->name && *form_ptr->name != '\0' &&
+ !strcmp(form_ptr->name, link_name)) &&
+ (form_ptr->type == F_TEXT_SUBMIT_TYPE ||
+ (form_ptr->value && *form_ptr->value != '\0' &&
+ !strcmp(form_ptr->value, link_value)))) {
+ int cdisp_name_startpos = 0;
+ if (first_one) {
+ if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "--%s\r\n", Boundary);
+ }
+ first_one=FALSE;
+ } else {
+ if (PlainText) {
+ strcat(query, "\n");
+ } else if (SemiColon) {
+ strcat(query, ";");
+ } else if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "\r\n--%s\r\n", Boundary);
+ } else {
+ strcat(query, "&");
+ }
+ }
+
+ if (PlainText) {
+ StrAllocCopy(escaped1, name_used);
+ } else if (Boundary) {
+ StrAllocCopy(escaped1,
+ "Content-Disposition: form-data; name=");
+ cdisp_name_startpos = strlen(escaped1);
+ StrAllocCat(escaped1, name_used);
+ if (MultipartContentType)
+ StrAllocCat(escaped1, MultipartContentType);
+ StrAllocCat(escaped1, "\r\n\r\n");
+ } else {
+ escaped1 = HTEscapeSP(name_used, URL_XALPHAS);
+ }
+
+ if (PlainText || Boundary) {
+ StrAllocCopy(escaped2,
+ (val_used ?
+ val_used : ""));
+ } else {
+ escaped2 = HTEscapeSP(val_used, URL_XALPHAS);
+ }
+
+ if (form_ptr->type == F_IMAGE_SUBMIT_TYPE) {
+ /*
+ * It's a clickable image submit button.
+ * Fake a 0,0 coordinate pair, which
+ * typically returns the image's default. - FM
+ */
+ if (Boundary) {
+ escaped1[cdisp_name_startpos] = '\0';
+ sprintf(&query[strlen(query)],
+ "%s.x\r\n\r\n0\r\n--%s\r\n%s.y\r\n\r\n0",
+ escaped1,
+ Boundary,
+ escaped1);
+ } else {
+ sprintf(&query[strlen(query)],
+ "%s.x=0%s%s.y=0%s",
+ escaped1,
+ (PlainText ?
+ "\n" : (SemiColon ?
+ ";" : "&")),
+ escaped1,
+ ((PlainText && *escaped1) ?
+ "\n" : ""));
+ }
+ } else {
+ /*
+ * It's a standard submit button.
+ * Use the name=value pair. = FM
+ */
+ sprintf(&query[strlen(query)],
+ "%s%s%s%s%s",
+ escaped1,
+ (Boundary ?
+ "" : "="),
+ (PlainText ?
+ "\n" : ""),
+ escaped2,
+ ((PlainText && *escaped2) ?
+ "\n" : ""));
+ }
+ FREE(escaped1);
+ FREE(escaped2);
+ }
+ FREE(copied_name_used);
+ FREE(copied_val_used);
+ break;
+
+ case F_RADIO_TYPE:
+ case F_CHECKBOX_TYPE:
+ /*
+ * Only add if selected.
+ */
+ if (form_ptr->num_value) {
+ if (first_one) {
+ if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "--%s\r\n", Boundary);
+ }
+ first_one=FALSE;
+ } else {
+ if (PlainText) {
+ strcat(query, "\n");
+ } else if (SemiColon) {
+ strcat(query, ";");
+ } else if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "\r\n--%s\r\n", Boundary);
+ } else {
+ strcat(query, "&");
+ }
+ }
+
+ if (PlainText) {
+ StrAllocCopy(escaped1, name_used);
+ } else if (Boundary) {
+ StrAllocCopy(escaped1,
+ "Content-Disposition: form-data; name=");
+ StrAllocCat(escaped1,
+ name_used);
+ if (MultipartContentType)
+ StrAllocCat(escaped1, MultipartContentType);
+ StrAllocCat(escaped1, "\r\n\r\n");
+ } else {
+ escaped1 = HTEscapeSP(name_used, URL_XALPHAS);
+ }
+ if (PlainText || Boundary) {
+ StrAllocCopy(escaped2,
+ (val_used ?
+ val_used : ""));
+ } else {
+ escaped2 = HTEscapeSP(val_used, URL_XALPHAS);
+ }
+
+ sprintf(&query[strlen(query)],
+ "%s%s%s%s%s",
+ escaped1,
+ (Boundary ?
+ "" : "="),
+ (PlainText ?
+ "\n" : ""),
+ escaped2,
+ ((PlainText && *escaped2) ?
+ "\n" : ""));
+ FREE(escaped1);
+ FREE(escaped2);
+ }
+ FREE(copied_name_used);
+ FREE(copied_val_used);
+ break;
+
+ case F_TEXTAREA_TYPE:
+ if (PlainText || Boundary) {
+ StrAllocCopy(escaped2,
+ (val_used ?
+ val_used : ""));
+ } else {
+ escaped2 = HTEscapeSP(val_used, URL_XALPHAS);
+ }
+
+ if (!last_textarea_name ||
+ strcmp(last_textarea_name, form_ptr->name)) {
+ textarea_lineno = 1;
+ /*
+ * Names are different so this is the first
+ * textarea or a different one from any before
+ * it.
+ */
+ if (Boundary) {
+ StrAllocCopy(previous_blanks, "\r\n");
+ } else {
+ FREE(previous_blanks);
+ }
+ if (first_one) {
+ if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "--%s\r\n", Boundary);
+ }
+ first_one=FALSE;
+ } else {
+ if (PlainText) {
+ strcat(query, "\n");
+ } else if (SemiColon) {
+ strcat(query, ";");
+ } else if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "\r\n--%s\r\n", Boundary);
+ } else {
+ strcat(query, "&");
+ }
+ }
+ if (PlainText) {
+ StrAllocCopy(escaped1, name_used);
+ } else if (Boundary) {
+ StrAllocCopy(escaped1,
+ "Content-Disposition: form-data; name=");
+ StrAllocCat(escaped1, name_used);
+ if (MultipartContentType)
+ StrAllocCat(escaped1, MultipartContentType);
+ StrAllocCat(escaped1, "\r\n\r\n");
+ } else {
+ escaped1 = HTEscapeSP(name_used, URL_XALPHAS);
+ }
+ sprintf(&query[strlen(query)],
+ "%s%s%s%s%s",
+ escaped1,
+ (Boundary ?
+ "" : "="),
+ (PlainText ?
+ "\n" : ""),
+ escaped2,
+ ((PlainText && *escaped2) ?
+ "\n" : ""));
+ FREE(escaped1);
+ last_textarea_name = form_ptr->name;
+ } else {
+ /*
+ * This is a continuation of a previous textarea
+ * add %0a (\n) and the escaped string.
+ */
+ if (escaped2[0] != '\0') {
+ if (previous_blanks) {
+ strcat(query, previous_blanks);
+ FREE(previous_blanks);
+ }
+ if (PlainText) {
+ sprintf(&query[strlen(query)], "%s\n",
+ escaped2);
+ } else if (Boundary) {
+ sprintf(&query[strlen(query)], "%s\r\n",
+ escaped2);
+ } else {
+ sprintf(&query[strlen(query)], "%%0a%s",
+ escaped2);
+ }
+ } else {
+ if (PlainText) {
+ StrAllocCat(previous_blanks, "\n");
+ } else if (Boundary) {
+ StrAllocCat(previous_blanks, "\r\n");
+ } else {
+ StrAllocCat(previous_blanks, "%0a");
+ }
+ }
+ }
+ FREE(escaped2);
+ FREE(copied_val_used);
+ break;
+
+ case F_PASSWORD_TYPE:
+ case F_TEXT_TYPE:
+ case F_OPTION_LIST_TYPE:
+ case F_HIDDEN_TYPE:
+ if (first_one) {
+ if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "--%s\r\n", Boundary);
+ }
+ first_one=FALSE;
+ } else {
+ if (PlainText) {
+ strcat(query, "\n");
+ } else if (SemiColon) {
+ strcat(query, ";");
+ } else if (Boundary) {
+ sprintf(&query[strlen(query)],
+ "\r\n--%s\r\n", Boundary);
+ } else {
+ strcat(query, "&");
+ }
+ }
+
+ if (PlainText) {
+ StrAllocCopy(escaped1, name_used);
+ } else if (Boundary) {
+ StrAllocCopy(escaped1,
+ "Content-Disposition: form-data; name=");
+ StrAllocCat(escaped1, name_used);
+ if (MultipartContentType)
+ StrAllocCat(escaped1, MultipartContentType);
+ StrAllocCat(escaped1, "\r\n\r\n");
+ } else {
+ escaped1 = HTEscapeSP(name_used, URL_XALPHAS);
+ }
+
+ if (PlainText || Boundary) {
+ StrAllocCopy(escaped2,
+ (val_used ?
+ val_used : ""));
+ } else {
+ escaped2 = HTEscapeSP(val_used, URL_XALPHAS);
+ }
+
+ sprintf(&query[strlen(query)],
+ "%s%s%s%s%s",
+ escaped1,
+ (Boundary ?
+ "" : "="),
+ (PlainText ?
+ "\n" : ""),
+ escaped2,
+ ((PlainText && *escaped2) ?
+ "\n" : ""));
+ FREE(escaped1);
+ FREE(escaped2);
+ FREE(copied_name_used);
+ FREE(copied_val_used);
+ break;
+ }
+ } else if (anchor_ptr->input_field->number > form_number) {
+ break;
+ }
+ }
+
+ if (anchor_ptr == HTMainText->last_anchor)
+ break;
+
+ anchor_ptr = anchor_ptr->next;
+ }
+ FREE(copied_name_used);
+ if (Boundary) {
+ sprintf(&query[strlen(query)], "\r\n--%s--\r\n", Boundary);
+ }
+ FREE(previous_blanks);
+
+ if (submit_item->submit_method == URL_MAIL_METHOD) {
+ _user_message("Submitting %s", submit_item->submit_action);
+ if (TRACE) {
+ fprintf(stderr, "\nGridText - mailto_address: %s\n",
+ (submit_item->submit_action+7));
+ fprintf(stderr, "GridText - mailto_subject: %s\n",
+ ((submit_item->submit_title &&
+ *submit_item->submit_title) ?
+ (submit_item->submit_title) :
+ (HText_getTitle() ?
+ HText_getTitle() : "")));
+ fprintf(stderr,"GridText - mailto_content: %s\n",query);
+ }
+ sleep(MessageSecs);
+ mailform((submit_item->submit_action+7),
+ ((submit_item->submit_title &&
+ *submit_item->submit_title) ?
+ (submit_item->submit_title) :
+ (HText_getTitle() ?
+ HText_getTitle() : "")),
+ query,
+ doc->post_content_type);
+ FREE(query);
+ FREE(doc->post_content_type);
+ return;
+ } else {
+ _statusline(SUBMITTING_FORM);
+ }
+
+ if (submit_item->submit_method == URL_POST_METHOD || Boundary) {
+ StrAllocCopy(doc->post_data, query);
+ if (TRACE)
+ fprintf(stderr,"GridText - post_data: %s\n",doc->post_data);
+ StrAllocCopy(doc->address, submit_item->submit_action);
+ FREE(query);
+ return;
+ } else { /* GET_METHOD */
+ StrAllocCopy(doc->address, query);
+ FREE(doc->post_data);
+ FREE(doc->post_content_type);
+ FREE(query);
+ return;
+ }
+}
+
+PUBLIC void HText_DisableCurrentForm NOARGS
+{
+ TextAnchor * anchor_ptr;
+
+ HTFormDisabled = TRUE;
+ if (!HTMainText)
+ return;
+
+ /*
+ * Go through list of anchors and set the disabled flag.
+ */
+ anchor_ptr = HTMainText->first_anchor;
+ while (anchor_ptr) {
+ if (anchor_ptr->link_type == INPUT_ANCHOR &&
+ anchor_ptr->input_field->number == HTFormNumber) {
+
+ anchor_ptr->input_field->disabled = TRUE;
+ }
+
+ if (anchor_ptr == HTMainText->last_anchor)
+ break;
+
+
+ anchor_ptr = anchor_ptr->next;
+ }
+
+ return;
+}
+
+PUBLIC void HText_ResetForm ARGS1(
+ FormInfo *, form)
+{
+ TextAnchor * anchor_ptr;
+
+ _statusline(RESETTING_FORM);
+ if (!HTMainText)
+ return;
+
+ /*
+ * Go through list of anchors and reset values.
+ */
+ anchor_ptr = HTMainText->first_anchor;
+ while (anchor_ptr) {
+ if (anchor_ptr->link_type == INPUT_ANCHOR) {
+ if (anchor_ptr->input_field->number == form->number) {
+
+ if (anchor_ptr->input_field->type == F_RADIO_TYPE ||
+ anchor_ptr->input_field->type == F_CHECKBOX_TYPE) {
+
+ if (anchor_ptr->input_field->orig_value[0] == '0')
+ anchor_ptr->input_field->num_value = 0;
+ else
+ anchor_ptr->input_field->num_value = 1;
+
+ } else if (anchor_ptr->input_field->type ==
+ F_OPTION_LIST_TYPE) {
+ anchor_ptr->input_field->value =
+ anchor_ptr->input_field->orig_value;
+
+ anchor_ptr->input_field->cp_submit_value =
+ anchor_ptr->input_field->orig_submit_value;
+
+ } else {
+ StrAllocCopy(anchor_ptr->input_field->value,
+ anchor_ptr->input_field->orig_value);
+ }
+ } else if (anchor_ptr->input_field->number > form->number) {
+ break;
+ }
+
+ }
+
+ if (anchor_ptr == HTMainText->last_anchor)
+ break;
+
+
+ anchor_ptr = anchor_ptr->next;
+ }
+}
+
+PUBLIC void HText_activateRadioButton ARGS1(
+ FormInfo *, form)
+{
+ TextAnchor * anchor_ptr;
+ int form_number = form->number;
+
+ if (!HTMainText)
+ return;
+ anchor_ptr = HTMainText->first_anchor;
+ while (anchor_ptr) {
+ if (anchor_ptr->link_type == INPUT_ANCHOR &&
+ anchor_ptr->input_field->type == F_RADIO_TYPE) {
+
+ if (anchor_ptr->input_field->number == form_number) {
+
+ /* if it has the same name and its on */
+ if (!strcmp(anchor_ptr->input_field->name, form->name) &&
+ anchor_ptr->input_field->num_value) {
+ anchor_ptr->input_field->num_value = 0;
+ break;
+ }
+ } else if (anchor_ptr->input_field->number > form_number) {
+ break;
+ }
+
+ }
+
+ if (anchor_ptr == HTMainText->last_anchor)
+ break;
+
+ anchor_ptr = anchor_ptr->next;
+ }
+
+ form->num_value = 1;
+}
+
+/*
+ * Purpose: Free all currently loaded HText objects in memory.
+ * Arguments: void
+ * Return Value: void
+ * Remarks/Portability/Dependencies/Restrictions:
+ * Usage of this function should really be limited to program
+ * termination.
+ * Revision History:
+ * 05-27-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+PRIVATE void free_all_texts NOARGS
+{
+ HText *cur = NULL;
+
+ if (!loaded_texts)
+ return;
+
+ /*
+ * Simply loop through the loaded texts list killing them off.
+ */
+ while (loaded_texts && !HTList_isEmpty(loaded_texts)) {
+ if ((cur = (HText *)HTList_removeLastObject(loaded_texts)) != NULL) {
+ HText_free(cur);
+ }
+ }
+
+ /*
+ * Get rid of the text list.
+ */
+ if (loaded_texts) {
+ HTList_delete(loaded_texts);
+ }
+
+ /*
+ * Insurance for bad HTML.
+ */
+ FREE(HTCurSelectGroup);
+ FREE(HTCurSelectGroupSize);
+ FREE(HTCurSelectedOptionValue);
+ FREE(HTFormAction);
+ FREE(HTFormEnctype);
+ FREE(HTFormTitle);
+ FREE(HTFormAcceptCharset);
+ PerFormInfo_free(HTCurrentForm);
+
+ return;
+}
+
+/*
+** stub_HTAnchor_address is like HTAnchor_address, but it returns the
+** parent address for child links. This is only useful for traversal's
+** where one does not want to index a text file N times, once for each
+** of N internal links. Since the parent link has already been taken,
+** it won't go again, hence the (incorrect) links won't cause problems.
+*/
+PUBLIC char * stub_HTAnchor_address ARGS1(
+ HTAnchor *, me)
+{
+ char *addr = NULL;
+ if (me)
+ StrAllocCopy (addr, me->parent->address);
+ return addr;
+}
+
+PUBLIC void HText_setToolbar ARGS1(
+ HText *, text)
+{
+ if (text)
+ text->toolbar = TRUE;
+ return;
+}
+
+PUBLIC BOOL HText_hasToolbar ARGS1(
+ HText *, text)
+{
+ return ((text && text->toolbar) ? TRUE : FALSE);
+}
+
+PUBLIC void HText_setNoCache ARGS1(
+ HText *, text)
+{
+ if (text)
+ text->no_cache = TRUE;
+ return;
+}
+
+PUBLIC BOOL HText_hasNoCacheSet ARGS1(
+ HText *, text)
+{
+ return ((text && text->no_cache) ? TRUE : FALSE);
+}
+
+PUBLIC BOOL HText_hasUTF8OutputSet ARGS1(
+ HText *, text)
+{
+ return ((text && text->T.output_utf8) ? TRUE : FALSE);
+}
+
+/*
+** Check charset and set the kcode element. - FM
+** Info on the input charset may be passed in in two forms,
+** as a string (if given explicitly) and as a pointer to
+** a LYUCcharset (from chartrans mechanism); either can be NULL.
+** For Japanese the kcode will be reset at a space or explicit
+** line or paragraph break, so what we set here may not last for
+** long. It's potentially more important not to set HTCJK to
+** NOCJK unless we are sure. - kw
+*/
+PUBLIC void HText_setKcode ARGS3(
+ HText *, text,
+ CONST char *, charset,
+ LYUCcharset *, p_in)
+{
+ if (!text)
+ return;
+
+ /*
+ ** Check whether we have some kind of info. - kw
+ */
+ if (!charset && !p_in) {
+ return;
+ }
+ /*
+ ** If no explicit charset string, use the implied one. - kw
+ */
+ if (!charset || *charset == '\0') {
+ charset = p_in->MIMEname;
+ }
+ /*
+ ** Check whether we have a specified charset. - FM
+ */
+ if (!charset || *charset == '\0') {
+ return;
+ }
+
+ /*
+ ** We've included the charset, and not forced a download offer,
+ ** only if the currently selected character set can handle it,
+ ** so check the charset value and set the text->kcode element
+ ** appropriately. - FM
+ */
+ if (!strcmp(charset, "shift_jis") ||
+ !strcmp(charset, "x-shift-jis")) {
+ text->kcode = SJIS;
+ } else if ((p_in && (p_in->enc == UCT_ENC_CJK)) ||
+ !strcmp(charset, "euc-jp") ||
+ !strncmp(charset, "x-euc-", 6) ||
+ !strcmp(charset, "iso-2022-jp") ||
+ !strcmp(charset, "iso-2022-jp-2") ||
+ !strcmp(charset, "euc-kr") ||
+ !strcmp(charset, "iso-2022-kr") ||
+ !strcmp(charset, "big5") ||
+ !strcmp(charset, "cn-big5") ||
+ !strcmp(charset, "euc-cn") ||
+ !strcmp(charset, "gb2312") ||
+ !strncmp(charset, "cn-gb", 5) ||
+ !strcmp(charset, "iso-2022-cn")) {
+ text->kcode = EUC;
+ } else {
+ /*
+ ** If we get to here, it's not CJK, so disable that if
+ ** it is enabled. But only if we are quite sure. - FM & kw
+ */
+ text->kcode = NOKANJI;
+ if (HTCJK != NOCJK) {
+ if (!p_in || p_in->enc != UCT_ENC_CJK)
+ HTCJK = NOCJK;
+ }
+ }
+
+ return;
+}
+
+/*
+** Set a permissible split at the current end of the last line. - FM
+*/
+PUBLIC void HText_setBreakPoint ARGS1(
+ HText *, text)
+{
+ if (!text)
+ return;
+
+ /*
+ * Can split here. - FM
+ */
+ text->permissible_split = (int)text->last_line->size;
+
+ return;
+}
+
+/*
+** This function determines whether a document which
+** would be sought via the a URL that has a fragment
+** directive appended is otherwise identical to the
+** currently loaded document, and if so, returns
+** FALSE, so that any no_cache directives can be
+** overridden "safely", on the grounds that we are
+** simply acting on the equivalent of a paging
+** command. Otherwise, it returns TRUE, i.e, that
+** the target document might differ from the current,
+** based on any caching directives or analyses which
+** claimed or suggested this. - FM
+*/
+PUBLIC BOOL HText_AreDifferent ARGS2(
+ HTParentAnchor *, anchor,
+ CONST char *, full_address)
+{
+ HTParentAnchor *MTanc;
+ char *MTaddress;
+ char *MTpound;
+ char *TargetPound;
+
+ /*
+ * Do we have a loaded document and both
+ * arguments for this function?
+ */
+ if (!(HTMainText && anchor && full_address))
+ return TRUE;
+
+ /*
+ * Do we have both URLs?
+ */
+ MTanc = HTMainText->node_anchor;
+ if (!(MTanc->address && anchor->address))
+ return (TRUE);
+
+ /*
+ * Do we have a fragment associated with the target?
+ */
+ if ((TargetPound = strchr(full_address, '#')) == NULL)
+ return (TRUE);
+
+ /*
+ * Always treat client-side image map menus
+ * as potentially stale, so we'll create a
+ * fresh menu from the LynxMaps HTList.
+ */
+ if (!strncasecomp(anchor->address, "LYNXIMGMAP:", 11))
+ return (TRUE);
+
+ /*
+ * Do the docs differ in the type of request?
+ */
+ if (MTanc->isHEAD != anchor->isHEAD)
+ return (TRUE);
+
+ /*
+ * Are the actual URLs different, after factoring
+ * out a "LYNXIMGMAP:" leader in the MainText URL
+ * and its fragment, if present?
+ */
+ MTaddress = (strncasecomp(MTanc->address,
+ "LYNXIMGMAP:", 11) ?
+ MTanc->address : (MTanc->address + 11));
+ if ((MTpound = strchr(MTaddress, '#')) != NULL)
+ *MTpound = '\0';
+ if (strcmp(MTaddress, anchor->address)) {
+ if (MTpound != NULL) {
+ *MTpound = '#';
+ }
+ return(TRUE);
+ }
+ if (MTpound != NULL) {
+ *MTpound = '#';
+ }
+
+ /*
+ * If the MainText is not an image map menu,
+ * do the docs have different POST contents?
+ */
+ if (MTaddress == MTanc->address) {
+ if (MTanc->post_data) {
+ if (anchor->post_data) {
+ if (strcmp(MTanc->post_data, anchor->post_data)) {
+ /*
+ * Both have contents, and they differ.
+ */
+ return(TRUE);
+ }
+ } else {
+ /*
+ * The loaded document has content, but the
+ * target doesn't, so they're different.
+ */
+ return(TRUE);
+ }
+ } else if (anchor->post_data) {
+ /*
+ * The loaded document does not have content, but
+ * the target does, so they're different.
+ */
+ return(TRUE);
+ }
+ }
+
+ /*
+ * We'll assume the target is a position in the currently
+ * displayed document, and thus can ignore any header, META,
+ * or other directives not to use a cached rendition. - FM
+ */
+ return(FALSE);
+}
diff --git a/gnu/usr.bin/lynx/src/GridText.h b/gnu/usr.bin/lynx/src/GridText.h
new file mode 100644
index 00000000000..42a50c0c7b5
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/GridText.h
@@ -0,0 +1,206 @@
+
+/* Specialities of GridText as subclass of HText
+*/
+#ifndef LYGRIDTEXT_H
+#define LYGRIDTEXT_H
+
+#include "HText.h" /* Superclass */
+
+#ifndef HTFORMS_H
+#include "HTForms.h"
+#endif /* HTFORMS_H */
+
+#define LY_UNDERLINE_START_CHAR '\003'
+#define LY_UNDERLINE_END_CHAR '\004'
+#define LY_BOLD_START_CHAR '\005'
+#define LY_BOLD_END_CHAR '\006'
+#ifndef LY_SOFT_HYPHEN
+#define LY_SOFT_HYPHEN ((char)7)
+#endif /* !LY_SOFT_HYPHEN */
+#define IsSpecialAttrChar(a) ((a > '\002') && (a < '\010'))
+
+extern int HTCurSelectGroupType;
+extern char * HTCurSelectGroupSize;
+extern HText * HTMainText; /* Equivalent of main window */
+extern HTParentAnchor * HTMainAnchor; /* Anchor for HTMainText */
+
+#ifdef SHORT_NAMES
+#define HText_childNumber HTGTChNu
+#define HText_canScrollUp HTGTCaUp
+#define HText_canScrollDown HTGTCaDo
+#define HText_scrollUp HTGTScUp
+#define HText_scrollDown HTGTScDo
+#define HText_scrollTop HTGTScTo
+#define HText_scrollBottom HTGTScBo
+#define HText_sourceAnchors HTGTSoAn
+#define HText_setStale HTGTStal
+#define HText_refresh HTGTRefr
+#endif /* SHORT_NAMES */
+
+extern int WWW_TraceFlag;
+extern int HTCacheSize;
+
+extern BOOLEAN mustshow;
+
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+extern int HTVirtualMemorySize;
+#endif /* VMS && VAXC && !__DECC */
+extern HTChildAnchor * HText_childNumber PARAMS((int n));
+extern void HText_FormDescNumber PARAMS((int n, char **desc));
+
+/* Is there any file left?
+*/
+extern BOOL HText_canScrollUp PARAMS((HText * text));
+extern BOOL HText_canScrollDown NOPARAMS;
+
+/* Move display within window
+*/
+extern void HText_scrollUp PARAMS((HText * text)); /* One page */
+extern void HText_scrollDown PARAMS((HText * text)); /* One page */
+extern void HText_scrollTop PARAMS((HText * text));
+extern void HText_scrollBottom PARAMS((HText * text));
+extern void HText_pageDisplay PARAMS((int line_num, char *target));
+extern BOOL HText_pageHasPrevTarget NOPARAMS;
+
+extern int HText_LinksInLines PARAMS((HText *text, int line_num, int Lines));
+
+extern void HText_setLastChar PARAMS((HText *text, char ch));
+extern char HText_getLastChar PARAMS((HText *text));
+extern void HText_setIgnoreExcess PARAMS((HText *text, BOOL ignore));
+
+extern int HText_sourceAnchors PARAMS((HText * text));
+extern void HText_setStale PARAMS((HText * text));
+extern void HText_refresh PARAMS((HText * text));
+extern char * HText_getTitle NOPARAMS;
+extern char * HText_getSugFname NOPARAMS;
+extern void HTCheckFnameForCompression PARAMS((
+ char ** fname,
+ HTParentAnchor * anchor,
+ BOOLEAN strip_ok));
+extern char * HText_getLastModified NOPARAMS;
+extern char * HText_getDate NOPARAMS;
+extern char * HText_getServer NOPARAMS;
+extern char * HText_getOwner NOPARAMS;
+extern char * HText_getContentBase NOPARAMS;
+extern char * HText_getContentLocation NOPARAMS;
+#ifdef USE_HASH
+extern char * HText_getStyle NOPARAMS;
+#endif
+extern void HText_setMainTextOwner PARAMS((CONST char * owner));
+extern char * HText_getRevTitle NOPARAMS;
+extern void print_wwwfile_to_fd PARAMS((FILE * fp, int is_reply));
+extern BOOL HText_select PARAMS((HText *text));
+extern BOOL HText_POSTReplyLoaded PARAMS((document *doc));
+extern BOOL HTFindPoundSelector PARAMS((char *selector));
+extern int HTGetLinkInfo PARAMS((
+ int number,
+ int want_go,
+ int * go_line,
+ int * linknum,
+ char ** hightext,
+ char ** lname));
+extern BOOL HText_getFirstTargetInLine PARAMS((
+ HText * text,
+ int line_num,
+ BOOL utf_flag,
+ int * offset,
+ int * tLen,
+ char ** data,
+ char * target));
+extern int HTisDocumentSource NOPARAMS;
+extern void HTuncache_current_document NOPARAMS;
+extern int HText_getTopOfScreen NOPARAMS;
+extern int HText_getLines PARAMS((HText * text));
+extern int HText_getNumOfLines NOPARAMS;
+extern int do_www_search PARAMS((document *doc));
+extern char * HTLoadedDocumentURL NOPARAMS;
+extern char * HTLoadedDocumentPost_data NOPARAMS;
+extern char * HTLoadedDocumentTitle NOPARAMS;
+extern BOOLEAN HTLoadedDocumentIsHEAD NOPARAMS;
+extern BOOLEAN HTLoadedDocumentIsSafe NOPARAMS;
+extern char * HTLoadedDocumentCharset NOPARAMS;
+extern BOOL HTLoadedDocumentEightbit NOPARAMS;
+extern void HText_setNodeAnchorBookmark PARAMS((CONST char *bookmark));
+extern char * HTLoadedDocumentBookmark NOPARAMS;
+extern int HText_LastLineSize PARAMS((HText *me, BOOL IgnoreSpaces));
+extern int HText_PreviousLineSize PARAMS((HText *me, BOOL IgnoreSpaces));
+extern void HText_NegateLineOne PARAMS((HText *text));
+extern void HText_RemovePreviousLine PARAMS((HText *text));
+extern int HText_getCurrentColumn PARAMS((HText *text));
+extern int HText_getMaximumColumn PARAMS((HText *text));
+extern void HText_setTabID PARAMS((HText *text, CONST char *name));
+extern int HText_getTabIDColumn PARAMS((HText *text, CONST char *name));
+extern int HText_HiddenLinkCount PARAMS((HText *text));
+extern char * HText_HiddenLinkAt PARAMS((HText *text, int number));
+
+/* forms stuff */
+extern void HText_beginForm PARAMS((
+ char * action,
+ char * method,
+ char * enctype,
+ char * title,
+ CONST char * accept_cs));
+extern void HText_endForm PARAMS((HText *text));
+extern void HText_beginSelect PARAMS((char *name,
+ int name_cs,
+ BOOLEAN multiple,
+ char *len));
+extern int HText_getOptionNum PARAMS((HText *text));
+extern char * HText_setLastOptionValue PARAMS((
+ HText * text,
+ char * value,
+ char * submit_value,
+ int order,
+ BOOLEAN checked,
+ int val_cs,
+ int submit_val_cs));
+extern int HText_beginInput PARAMS((
+ HText * text,
+ BOOL underline,
+ InputFieldData *I));
+extern void HText_SubmitForm PARAMS((
+ FormInfo * submit_item,
+ document * doc,
+ char * link_name,
+ char * link_value));
+extern void HText_DisableCurrentForm NOPARAMS;
+extern void HText_ResetForm PARAMS((FormInfo *form));
+extern void HText_activateRadioButton PARAMS((FormInfo *form));
+
+extern HTList * search_queries; /* Previous isindex and whereis queries */
+extern void HTSearchQueries_free NOPARAMS;
+extern void HTAddSearchQuery PARAMS((char *query));
+
+extern void user_message PARAMS((
+ CONST char * message,
+ CONST char * argument));
+
+#define _user_message(msg, arg) mustshow = TRUE, user_message(msg, arg)
+
+extern void www_user_search PARAMS((int start_line, document *doc, char *target));
+
+extern void print_crawl_to_fd PARAMS((
+ FILE * fp,
+ char * thelink,
+ char * thetitle));
+extern char * stub_HTAnchor_address PARAMS((HTAnchor *me));
+
+extern void HText_setToolbar PARAMS((HText *text));
+extern BOOL HText_hasToolbar PARAMS((HText *text));
+
+extern void HText_setNoCache PARAMS((HText *text));
+extern BOOL HText_hasNoCacheSet PARAMS((HText *text));
+
+extern BOOL HText_hasUTF8OutputSet PARAMS((HText *text));
+extern void HText_setKcode PARAMS((
+ HText * text,
+ CONST char * charset,
+ LYUCcharset * p_in));
+
+extern void HText_setBreakPoint PARAMS((HText *text));
+
+extern BOOL HText_AreDifferent PARAMS((
+ HTParentAnchor * anchor,
+ CONST char * full_address));
+
+#endif /* LYGRIDTEXT_H */
diff --git a/gnu/usr.bin/lynx/src/HTAlert.c b/gnu/usr.bin/lynx/src/HTAlert.c
new file mode 100644
index 00000000000..0886d81eae5
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTAlert.c
@@ -0,0 +1,573 @@
+/* Displaying messages and getting input for Lynx Browser
+** ==========================================================
+**
+** REPLACE THIS MODULE with a GUI version in a GUI environment!
+**
+** History:
+** Jun 92 Created May 1992 By C.T. Barker
+** Feb 93 Simplified, portablised TBL
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "LYGlobalDefs.h"
+#include "LYCurses.h"
+#include "LYStrings.h"
+#include "LYUtils.h"
+#include "LYSignal.h"
+#include "GridText.h"
+#include "LYCookie.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+
+/* Issue a message about a problem. HTAlert()
+** --------------------------------
+*/
+PUBLIC void HTAlert ARGS1(
+ CONST char *, Msg)
+{
+ if (TRACE) {
+ fprintf(stderr, "\nAlert!: %s", Msg);
+ fflush(stderr);
+ _user_message("Alert!: %s", Msg);
+ fprintf(stderr, "\n\n");
+ fflush(stderr);
+ } else
+ _user_message("Alert!: %s", Msg);
+
+ sleep(AlertSecs);
+}
+
+/* Issue a progress message. HTProgress()
+** -------------------------
+*/
+PUBLIC void HTProgress ARGS1(
+ CONST char *, Msg)
+{
+ if (TRACE)
+ fprintf(stderr, "%s\n", Msg);
+ else
+ statusline(Msg);
+}
+
+PRIVATE BOOL conf_cancelled = NO; /* used by HTConfirm only - kw */
+
+PUBLIC BOOL HTLastConfirmCancelled NOARGS
+{
+ if (conf_cancelled) {
+ conf_cancelled = NO; /* reset */
+ return(YES);
+ } else {
+ return(NO);
+ }
+}
+
+/* Seek confirmation. HTConfirm()
+** ------------------
+*/
+PUBLIC BOOL HTConfirm ARGS1(CONST char *, Msg)
+{
+ conf_cancelled = NO;
+ if (dump_output_immediately) { /* Non-interactive, can't respond */
+ return(NO);
+ } else {
+ int c;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ _user_message("%s (y/n) ", Msg);
+
+ while (1) {
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ c = 'N';
+ }
+#endif /* VMS */
+ if (TOUPPER(c) == 'Y')
+ return(YES);
+ if (c == 7 || c == 3) /* remember we had ^G or ^C */
+ conf_cancelled = YES;
+ if (TOUPPER(c) == 'N' || c == 7 || c == 3) /* ^G or ^C cancels */
+ return(NO);
+ }
+ }
+}
+
+/* Prompt for answer and get text back. HTPrompt()
+** ------------------------------------
+*/
+PUBLIC char * HTPrompt ARGS2(
+ CONST char *, Msg,
+ CONST char *, deflt)
+{
+ char * rep = NULL;
+ char Tmp[200];
+
+ Tmp[0] = '\0';
+ Tmp[199] = '\0';
+
+ _statusline(Msg);
+ if (deflt)
+ strncpy(Tmp, deflt, 199);
+
+ if (!dump_output_immediately)
+ LYgetstr(Tmp, VISIBLE, sizeof(Tmp), NORECALL);
+
+ StrAllocCopy(rep, Tmp);
+
+ return rep;
+}
+
+/*
+** Prompt for password without echoing the reply. HTPromptPassword()
+** ----------------------------------------------
+*/
+PUBLIC char * HTPromptPassword ARGS1(
+ CONST char *, Msg)
+{
+ char *result = NULL;
+ char pw[120];
+
+ pw[0] = '\0';
+
+ if (!dump_output_immediately) {
+ _statusline(Msg ? Msg : PASSWORD_PROMPT);
+ LYgetstr(pw, HIDDEN, sizeof(pw), NORECALL); /* hidden */
+ StrAllocCopy(result, pw);
+ } else {
+ printf("\n%s\n", PASSWORD_REQUIRED);
+ StrAllocCopy(result, "");
+ }
+ return result;
+}
+
+/* Prompt both username and password. HTPromptUsernameAndPassword()
+** ----------------------------------
+**
+** On entry,
+** Msg is the prompting message.
+** *username and
+** *password are char pointers which contain default
+** or zero-length strings; they are changed
+** to point to result strings.
+** IsProxy should be TRUE if this is for
+** proxy authentication.
+**
+** If *username is not NULL, it is taken
+** to point to a default value.
+** Initial value of *password is
+** completely discarded.
+**
+** On exit,
+** *username and *password point to newly allocated
+** strings -- original strings pointed to by them
+** are NOT freed.
+**
+*/
+PUBLIC void HTPromptUsernameAndPassword ARGS4(
+ CONST char *, Msg,
+ char **, username,
+ char **, password,
+ BOOL, IsProxy)
+{
+ if ((IsProxy == FALSE &&
+ authentication_info[0] && authentication_info[1]) ||
+ (IsProxy == TRUE &&
+ proxyauth_info[0] && proxyauth_info[1])) {
+ /*
+ ** The -auth or -pauth parameter gave us both the username
+ ** and password to use for the first realm or proxy server,
+ ** respectively, so just use them without any prompting. - FM
+ */
+ StrAllocCopy(*username, (IsProxy ?
+ proxyauth_info[0] : authentication_info[0]));
+ if (IsProxy) {
+ FREE(proxyauth_info[0]);
+ } else {
+ FREE(authentication_info[0]);
+ }
+ StrAllocCopy(*password, (IsProxy ?
+ proxyauth_info[1] : authentication_info[1]));
+ if (IsProxy) {
+ FREE(proxyauth_info[1]);
+ } else {
+ FREE(authentication_info[1]);
+ }
+ } else if (dump_output_immediately) {
+ /*
+ * We are not interactive and don't have both the
+ * username and password from the command line,
+ * but might have one or the other. - FM
+ */
+ if ((IsProxy == FALSE && authentication_info[0]) ||
+ (IsProxy == TRUE && proxyauth_info[0])) {
+ /*
+ ** Use the command line username. - FM
+ */
+ StrAllocCopy(*username, (IsProxy ?
+ proxyauth_info[0] : authentication_info[0]));
+ if (IsProxy) {
+ FREE(proxyauth_info[0]);
+ } else {
+ FREE(authentication_info[0]);
+ }
+ } else {
+ /*
+ ** Default to "WWWuser". - FM
+ */
+ StrAllocCopy(*username, "WWWuser");
+ }
+ if ((IsProxy == FALSE && authentication_info[1]) ||
+ (IsProxy == TRUE && proxyauth_info[1])) {
+ /*
+ ** Use the command line password. - FM
+ */
+ StrAllocCopy(*password, (IsProxy ?
+ proxyauth_info[1] : authentication_info[1]));
+ if (IsProxy) {
+ FREE(proxyauth_info[1]);
+ } else {
+ FREE(authentication_info[1]);
+ }
+ } else {
+ /*
+ ** Default to a zero-length string. - FM
+ */
+ StrAllocCopy(*password, "");
+ }
+ printf("\n%s\n", USERNAME_PASSWORD_REQUIRED);
+
+ } else {
+ /*
+ * We are interactive and don't have both the
+ * username and password from the command line,
+ * but might have one or the other. - FM
+ */
+ if ((IsProxy == FALSE && authentication_info[0]) ||
+ (IsProxy == TRUE && proxyauth_info[0])) {
+ /*
+ ** Offer the command line username in the
+ ** prompt for the first realm. - FM
+ */
+ StrAllocCopy(*username, (IsProxy ?
+ proxyauth_info[0] : authentication_info[0]));
+ if (IsProxy) {
+ FREE(proxyauth_info[0]);
+ } else {
+ FREE(authentication_info[0]);
+ }
+ }
+ /*
+ * Prompt for confirmation or entry of the username. - FM
+ */
+ if (Msg != NULL) {
+ *username = HTPrompt(Msg, *username);
+ } else {
+ *username = HTPrompt(USERNAME_PROMPT, *username);
+ }
+ if ((IsProxy == FALSE && authentication_info[1]) ||
+ (IsProxy == TRUE && proxyauth_info[1])) {
+ /*
+ ** Use the command line password for the first realm. - FM
+ */
+ StrAllocCopy(*password, (IsProxy ?
+ proxyauth_info[1] : authentication_info[1]));
+ if (IsProxy) {
+ FREE(proxyauth_info[1]);
+ } else {
+ FREE(authentication_info[1]);
+ }
+ } else if (*username != NULL && *username[0] != '\0') {
+ /*
+ ** We have a non-zero length username,
+ ** so prompt for the password. - FM
+ */
+ *password = HTPromptPassword(PASSWORD_PROMPT);
+ } else {
+ /*
+ ** Return a zero-length password. - FM
+ */
+ StrAllocCopy(*password, "");
+ }
+ }
+}
+
+/* Confirm a cookie operation. HTConfirmCookie()
+** ---------------------------
+**
+** On entry,
+** server is the server sending the Set-Cookie.
+** domain is the domain of the cookie.
+** path is the path of the cookie.
+** name is the name of the cookie.
+** value is the value of the cookie.
+**
+** On exit,
+** Returns FALSE on cancel,
+** TRUE if the cookie should be set.
+*/
+PUBLIC BOOL HTConfirmCookie ARGS6(
+ void *, dp,
+ CONST char *, server,
+ CONST char *, domain,
+ CONST char *, path,
+ CONST char *, name,
+ CONST char *, value)
+{
+ char message[256];
+ domain_entry *de;
+ int ch, namelen, valuelen, space_free;
+
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ if ((de = (domain_entry *)dp) == NULL)
+ return FALSE;
+
+ /*
+ ** If the user has specified a constant action, don't prompt at all.
+ */
+ if (de->bv == ACCEPT_ALWAYS)
+ return TRUE;
+ if (de->bv == REJECT_ALWAYS)
+ return FALSE;
+
+ if (dump_output_immediately) {
+ /*
+ ** Non-interactive, can't respond. Use the LYSetCookies value
+ * based on its compilation or configuration setting, or on the
+ ** command line toggle. - FM
+ */
+ return LYSetCookies;
+ }
+
+ /*
+ ** Figure out how much of the cookie we can show.
+ ** The '37' is the length of ADVANCED_COOKIE_CONFIRMATION,
+ ** minus the length of the %s directives (10 chars)
+ */
+ if (de != NULL) {
+ if (de->bv == ACCEPT_ALWAYS)
+ return TRUE;
+ if (de->bv == REJECT_ALWAYS)
+ return FALSE;
+ }
+ space_free = (((LYcols - 1) - 37) - strlen(server));
+ if (space_free < 0)
+ space_free = 0;
+ namelen = strlen(name);
+ valuelen = strlen(value);
+ if ((namelen + valuelen) > space_free) {
+ /*
+ ** Argh... there isn't enough space on our single line for
+ ** the whole cookie. Reduce them both by a percentage.
+ ** This should be smarter.
+ */
+ float percentage;
+ percentage = (float)space_free/(float)(namelen + valuelen);
+ namelen = (int)(percentage*(float)namelen);
+ valuelen = (int)(percentage*(float)valuelen);
+ }
+ sprintf(message, ADVANCED_COOKIE_CONFIRMATION,
+ server, namelen, name, valuelen, value);
+ _statusline(message);
+ while (1) {
+ ch = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ ch = 'N';
+ }
+#endif /* VMS */
+ switch(TOUPPER(ch)) {
+ case 'A':
+ /*
+ ** Set to accept all cookies for this domain.
+ */
+ de->bv = ACCEPT_ALWAYS;
+ _user_message(ALWAYS_ALLOWING_COOKIES, de->domain);
+ sleep(MessageSecs);
+ return TRUE;
+
+ case 'N':
+ case 7: /* Ctrl-G */
+ case 3: /* Ctrl-C */
+ /*
+ ** Reject the cookie.
+ */
+ _statusline(REJECTING_COOKIE);
+ sleep(MessageSecs);
+ return FALSE;
+
+ case 'V':
+ /*
+ ** Set to reject all cookies from this domain.
+ */
+ de->bv = REJECT_ALWAYS;
+ _user_message(NEVER_ALLOWING_COOKIES, de->domain);
+ sleep(MessageSecs);
+ return FALSE;
+
+ case 'Y':
+ /*
+ ** Accept the cookie.
+ */
+ _statusline(ALLOWING_COOKIE);
+ sleep(InfoSecs);
+ return TRUE;
+
+ default:
+ continue;
+ }
+ }
+}
+
+/* Confirm redirection of POST. HTConfirmPostRedirect()
+** ----------------------------
+**
+** On entry,
+** Redirecting_url is the Location.
+** server_status is the server status code.
+**
+** On exit,
+** Returns 0 on cancel,
+** 1 for redirect of POST with content,
+** 303 for redirect as GET without content
+*/
+PUBLIC int HTConfirmPostRedirect ARGS2(
+ CONST char *, Redirecting_url,
+ int, server_status)
+{
+ char *show_POST_url = NULL;
+ char StatusInfo[256];
+ char url[256];
+ int on_screen = 0; /* 0 - show menu
+ * 1 - show url
+ * 2 - menu is already on screen */
+
+ if (server_status == 303 ||
+ server_status == 302) {
+ /*
+ * HTTP.c should not have called us for either of
+ * these because we're treating 302 as historical,
+ * so just return 303. - FM
+ */
+ return 303;
+ }
+
+ if (dump_output_immediately)
+ if (server_status == 301) {
+ /*
+ ** Treat 301 as historical, i.e., like 303 (GET
+ ** without content), when not interactive. - FM
+ */
+ return 303;
+ } else {
+ /*
+ ** Treat anything else (e.g., 305, 306 or 307) as too
+ ** dangerous to redirect without confirmation, and thus
+ ** cancel when not interactive. - FM
+ */
+ return 0;
+ }
+
+ StatusInfo[254] = StatusInfo[255] = '\0';
+ url[254] = url[(LYcols < 250 ? LYcols-1 : 255)] = '\0';
+ if (user_mode == NOVICE_MODE) {
+ on_screen = 2;
+ move(LYlines-2, 0);
+ sprintf(StatusInfo, SERVER_ASKED_FOR_REDIRECTION, server_status);
+ addstr(StatusInfo);
+ clrtoeol();
+ move(LYlines-1, 0);
+ sprintf(url, "URL: %.*s",
+ (LYcols < 250 ? LYcols-6 : 250), Redirecting_url);
+ addstr(url);
+ clrtoeol();
+ if (server_status == 301) {
+ _statusline(PROCEED_GET_CANCEL);
+ } else {
+ _statusline(PROCEED_OR_CANCEL);
+ }
+ } else {
+ sprintf(StatusInfo, "%d %.*s",
+ server_status,
+ 251,
+ ((server_status == 301) ?
+ ADVANCED_POST_GET_REDIRECT :
+ ADVANCED_POST_REDIRECT));
+ StrAllocCopy(show_POST_url, LOCATION_HEADER);
+ StrAllocCat(show_POST_url, Redirecting_url);
+ }
+ while (1) {
+ int c;
+
+ switch (on_screen) {
+ case 0:
+ _statusline(StatusInfo);
+ break;
+ case 1:
+ _statusline(show_POST_url);
+ }
+ c = LYgetch();
+ switch (TOUPPER(c)) {
+ case 'P':
+ /*
+ ** Proceed with 301 or 307 redirect of POST
+ ** with same method and POST content. - FM
+ */
+ FREE(show_POST_url);
+ return 1;
+
+ case 7:
+ case 'C':
+ /*
+ ** Cancel request.
+ */
+ FREE(show_POST_url);
+ return 0;
+
+ case 'U':
+ /*
+ ** Show URL for intermediate or advanced mode.
+ */
+ if (user_mode != NOVICE_MODE) {
+ if (on_screen == 1) {
+ on_screen = 0;
+ } else {
+ on_screen = 1;
+ }
+ }
+ break;
+
+ case 'G':
+ if (server_status == 301) {
+ /*
+ ** Treat as 303 (GET without content).
+ */
+ FREE(show_POST_url);
+ return 303;
+ }
+ /* fall through to default */
+
+ default:
+ /*
+ ** Get another character.
+ */
+ if (on_screen == 1) {
+ on_screen = 0;
+ } else {
+ on_screen = 2;
+ }
+ }
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/HTAlert.h b/gnu/usr.bin/lynx/src/HTAlert.h
new file mode 100644
index 00000000000..ce40afb5c45
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTAlert.h
@@ -0,0 +1,133 @@
+/* */
+
+/* Displaying messages and getting input for WWW Library
+** =====================================================
+**
+** May 92 Created By C.T. Barker
+** Feb 93 Portablized etc TBL
+*/
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "tcp.h"
+
+/* Display a message and get the input
+**
+** On entry,
+** Msg is the message.
+**
+** On exit,
+** Return value is malloc'd string which must be freed.
+*/
+extern char * HTPrompt PARAMS((CONST char * Msg, CONST char * deflt));
+
+
+/* Display a message, don't wait for input
+**
+** On entry,
+** The input is a list of parameters for printf.
+*/
+extern void HTAlert PARAMS((CONST char * Msg));
+
+
+/* Display a progress message for information (and diagnostics) only
+**
+** On entry,
+** The input is a list of parameters for printf.
+*/
+extern void HTProgress PARAMS((CONST char * Msg));
+extern BOOLEAN mustshow;
+#define _HTProgress(msg) mustshow = TRUE, HTProgress(msg)
+
+/*
+ * Indicates whether last HTConfirm was cancelled (^G or ^C) and
+ * resets flag. (so only call once!) - kw
+ */
+extern BOOL HTLastConfirmCancelled NOPARAMS;
+
+/* Display a message, then wait for 'yes' or 'no'.
+**
+** On entry,
+** Takes a list of parameters for printf.
+**
+** On exit,
+** If the user enters 'YES', returns TRUE, returns FALSE
+** otherwise.
+*/
+extern BOOL HTConfirm PARAMS ((CONST char * Msg));
+
+
+/* Prompt for password without echoing the reply
+*/
+extern char * HTPromptPassword PARAMS((CONST char * Msg));
+
+/* Prompt both username and password HTPromptUsernameAndPassword()
+** ---------------------------------
+** On entry,
+** Msg is the prompting message.
+** *username and
+** *password are char pointers; they are changed
+** to point to result strings.
+** IsProxy should be TRUE if this is for
+** proxy authentication.
+**
+** If *username is not NULL, it is taken
+** to point to a default value.
+** Initial value of *password is
+** completely discarded.
+**
+** On exit,
+** *username and *password point to newly allocated
+** strings -- original strings pointed to by them
+** are NOT freed.
+**
+*/
+extern void HTPromptUsernameAndPassword PARAMS((
+ CONST char * Msg,
+ char ** username,
+ char ** password,
+ BOOL IsProxy));
+
+
+/* Confirm a cookie operation. HTConfirmCookie()
+** ---------------------------
+**
+** On entry,
+** server is the server sending the Set-Cookie.
+** domain is the domain of the cookie.
+** path is the path of the cookie.
+** name is the name of the cookie.
+** value is the value of the cookie.
+**
+** On exit,
+** Returns FALSE on cancel,
+** TRUE if the cookie should be set.
+*/
+extern BOOL HTConfirmCookie PARAMS((
+ void * dp,
+ CONST char * server,
+ CONST char * domain,
+ CONST char * path,
+ CONST char * name,
+ CONST char * value));
+
+
+/* Confirm redirection of POST. HTConfirmPostRedirect()
+** ----------------------------
+** On entry,
+** Redirecting_url is the Location.
+** server_status is the server status code.
+**
+** On exit,
+** Returns 0 on cancel,
+** 1 for redirect of POST with content,
+** 303 for redirect as GET without content
+*/
+extern int HTConfirmPostRedirect PARAMS((
+ CONST char * Redirecting_url,
+ int server_status));
+
+/*
+
+ */
diff --git a/gnu/usr.bin/lynx/src/HTFWriter.c b/gnu/usr.bin/lynx/src/HTFWriter.c
new file mode 100644
index 00000000000..a5390387019
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTFWriter.c
@@ -0,0 +1,1294 @@
+/* FILE WRITER HTFWrite.h
+** ===========
+**
+** This version of the stream object just writes to a C file.
+** The file is assumed open and left open.
+**
+** Bugs:
+** strings written must be less than buffer size.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYCurses.h"
+#include "HTFWriter.h"
+#include "HTSaveToFile.h"
+
+#include "HTFormat.h"
+#include "UCDefs.h"
+#include "HTAlert.h"
+#include "HTFile.h"
+#include "HTPlain.h"
+#include "HTFile.h"
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#include "LYStrings.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYSystem.h"
+#include "GridText.h"
+#include "LYexit.h"
+#include "LYLeaks.h"
+#include "LYKeymap.h"
+
+PUBLIC char * WWW_Download_File=NULL; /* contains the name of the temp file
+ ** which is being downloaded into
+ */
+PUBLIC char LYCancelDownload=FALSE; /* exported to HTFormat.c in libWWW */
+
+#ifdef VMS
+extern BOOLEAN HadVMSInterrupt; /* flag from cleanup_sig() */
+PRIVATE char * FIXED_RECORD_COMMAND = NULL;
+#ifdef USE_COMMAND_FILE /* Keep this as an option. - FM */
+#define FIXED_RECORD_COMMAND_MASK "@Lynx_Dir:FIXED512 %s"
+#else
+#define FIXED_RECORD_COMMAND_MASK "%s"
+PUBLIC unsigned long LYVMS_FixedLengthRecords PARAMS((char *filename));
+#endif /* USE_COMMAND_FILE */
+#endif /* VMS */
+
+PUBLIC HTStream* HTSaveToFile PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+
+/* Stream Object
+** -------------
+*/
+struct _HTStream {
+ CONST HTStreamClass * isa;
+
+ FILE * fp; /* The file we've opened */
+ char * end_command; /* What to do on _free. */
+ char * remove_command; /* What to do on _abort. */
+ char * viewer_command; /* Saved external viewer */
+ HTFormat input_format; /* Original pres->rep */
+ HTFormat output_format; /* Original pres->rep_out */
+ HTParentAnchor * anchor; /* Original stream's anchor. */
+ HTStream * sink; /* Original stream's sink. */
+#ifdef FNAMES_8_3
+ int idash; /* remember position to become '.'*/
+#endif
+};
+
+
+/*_________________________________________________________________________
+**
+** A C T I O N R O U T I N E S
+** Bug:
+** All errors are ignored.
+*/
+
+/* Character handling
+** ------------------
+*/
+PRIVATE void HTFWriter_put_character ARGS2(HTStream *, me, char, c)
+{
+ putc(c, me->fp);
+}
+
+/* String handling
+** ---------------
+**
+** Strings must be smaller than this buffer size.
+*/
+PRIVATE void HTFWriter_put_string ARGS2(HTStream *, me, CONST char*, s)
+{
+ fputs(s, me->fp);
+}
+
+/* Buffer write. Buffers can (and should!) be big.
+** ------------
+*/
+PRIVATE void HTFWriter_write ARGS3(HTStream *, me, CONST char*, s, int, l)
+{
+ fwrite(s, 1, l, me->fp);
+}
+
+
+
+
+/* Free an HTML object
+** -------------------
+**
+** Note that the SGML parsing context is freed, but the created
+** object is not,
+** as it takes on an existence of its own unless explicitly freed.
+*/
+PRIVATE void HTFWriter_free ARGS1(HTStream *, me)
+{
+ FILE *fp = NULL;
+ int len;
+ char *path = NULL;
+ char *addr = NULL;
+ int status;
+ BOOL use_gzread = NO;
+
+ fflush(me->fp);
+ if (me->end_command) { /* Temp file */
+ fclose(me->fp);
+#ifdef VMS
+ if (0 == strcmp(me->end_command, "SaveVMSBinaryFile")) {
+ /*
+ * It's a binary file saved to disk on VMS, which
+ * we want to convert to fixed records format. - FM
+ */
+#ifdef USE_COMMAND_FILE
+ system(FIXED_RECORD_COMMAND);
+#else
+ LYVMS_FixedLengthRecords(FIXED_RECORD_COMMAND);
+#endif /* USE_COMMAND_FILE */
+ FREE(FIXED_RECORD_COMMAND);
+
+ if (me->remove_command) {
+ /* NEVER REMOVE THE FILE unless during an abort!*/
+ /* system(me->remove_command); */
+ FREE(me->remove_command);
+ }
+ } else
+#endif /* VMS */
+ if (me->input_format == HTAtom_for("www/compressed")) {
+ /*
+ * It's a compressed file supposedly cached to
+ * a temporary file for uncompression. - FM
+ */
+ if (me->anchor->FileCache != NULL) {
+ BOOL skip_loadfile = (me->viewer_command != NULL);
+ /*
+ * Save the path with the "gz" or "Z" suffix trimmed,
+ * and remove any previous uncompressed copy. - FM
+ */
+ StrAllocCopy(path, me->anchor->FileCache);
+ if ((len = strlen(path)) > 2) {
+ if (!strcasecomp((char *)&path[len-2], "gz")) {
+#ifdef USE_ZLIB
+ if (!skip_loadfile) {
+ use_gzread = YES;
+ } else
+#endif /* USE_ZLIB */
+ {
+ path[len-3] = '\0';
+ remove(path);
+ }
+ } else if (!strcasecomp((char *)&path[len-1], "Z")) {
+ path[len-2] = '\0';
+ remove(path);
+ }
+ }
+ if (!use_gzread) {
+ if (!dump_output_immediately) {
+ /*
+ * Tell user what's happening. - FM
+ */
+ _HTProgress(me->end_command);
+ }
+ /*
+ * Uncompress it. - FM
+ */
+ if (me->end_command && me->end_command[0])
+ system(me->end_command);
+ fp = fopen(me->anchor->FileCache, "r");
+ }
+ if (fp != NULL) {
+ /*
+ * It's still there with the "gz" or "Z" suffix,
+ * so the uncompression failed. - FM
+ */
+ fclose(fp);
+ fp = NULL;
+ if (!dump_output_immediately) {
+ lynx_force_repaint();
+ refresh();
+ }
+ HTAlert(ERROR_UNCOMPRESSING_TEMP);
+ remove(me->anchor->FileCache);
+ FREE(me->anchor->FileCache);
+ } else {
+ /*
+ * Succeeded! Create a complete address
+ * for the uncompressed file and invoke
+ * HTLoadFile() to handle it. - FM
+ */
+#ifdef FNAMES_8_3
+ /*
+ * Assuming we have just uncompressed e.g.
+ * FILE-mpeg.gz -> FILE-mpeg, restore/shorten
+ * the name to be fit for passing to an external
+ * viewer, by renaming FILE-mpeg -> FILE.mpe - kw
+ */
+ if (skip_loadfile) {
+ char *new_path = NULL;
+ if (me->idash > 1 && path[me->idash] == '-') {
+ StrAllocCopy(new_path, path);
+ new_path[me->idash] = '.';
+ if (strlen(new_path + me->idash) > 4)
+ new_path[me->idash + 4] = '\0';
+ if (rename(path, new_path) == 0) {
+ FREE(path);
+ path = new_path;
+ } else {
+ FREE(new_path);
+ }
+ }
+ }
+#endif /* FNAMES_8_3 */
+ StrAllocCopy(addr, "file://localhost");
+#ifdef DOSPATH
+ StrAllocCat(addr, "/");
+ StrAllocCat(addr, HTDOS_wwwName(path));
+#else
+#ifdef VMS
+ StrAllocCat(addr, HTVMS_wwwName(path));
+#else
+ StrAllocCat(addr, path);
+#endif /* VMS */
+#endif /* DOSPATH */
+ if (!use_gzread) {
+ StrAllocCopy(me->anchor->FileCache, path);
+ StrAllocCopy(me->anchor->content_encoding, "binary");
+ }
+ FREE(path);
+ if (!skip_loadfile) {
+ /*
+ * Lock the chartrans info we may possibly have,
+ * so HTCharsetFormat() will not apply the default
+ * for local files. - KW
+ */
+ if (HTAnchor_getUCLYhndl(me->anchor,
+ UCT_STAGE_PARSER) < 0 ) {
+ /*
+ * If not yet set - KW
+ */
+ HTAnchor_copyUCInfoStage(me->anchor,
+ UCT_STAGE_PARSER,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT+1);
+ }
+ HTAnchor_copyUCInfoStage(me->anchor,
+ UCT_STAGE_PARSER,
+ UCT_STAGE_MIME, -1);
+ }
+ /*
+ * Create a complete address for
+ * the uncompressed file. - FM
+ */
+ if (!dump_output_immediately) {
+ /*
+ * Tell user what's happening. - FM
+ */
+ _user_message(WWW_USING_MESSAGE, addr);
+ }
+
+ if (skip_loadfile) {
+ /*
+ * It's a temporary file we're passing to a
+ * viewer or helper application.
+ * Loading the temp file through HTLoadFile()
+ * would result in yet another HTStream (created
+ * with HTSaveAndExecute()) which would just
+ * copy the temp file to another temp file
+ * (or even the same!). We can skip this
+ * needless duplication by using the
+ * viewer_command which has already been
+ * determind when the HTCompressed stream was
+ * created. - kw
+ */
+ FREE(me->end_command);
+ me->end_command = (char *)calloc (
+ (strlen (me->viewer_command) + 10 +
+ strlen(me->anchor->FileCache))
+ * sizeof (char),1);
+ if (me->end_command == NULL)
+ outofmem(__FILE__, "HTFWriter_free (HTCompressed)");
+
+ sprintf(me->end_command,
+ me->viewer_command, me->anchor->FileCache,
+ "", "", "", "", "", "");
+ if (!dump_output_immediately) {
+ /*
+ * Tell user what's happening. - FM
+ */
+ HTProgress(me->end_command);
+ stop_curses();
+ }
+ system(me->end_command);
+
+ if (me->remove_command) {
+ /* NEVER REMOVE THE FILE unless during an abort!!!*/
+ /* system(me->remove_command); */
+ FREE(me->remove_command);
+ }
+ if (!dump_output_immediately)
+ start_curses();
+ } else
+ status = HTLoadFile(addr,
+ me->anchor,
+ me->output_format,
+ me->sink);
+ if (dump_output_immediately &&
+ me->output_format == HTAtom_for("www/present")) {
+ FREE(addr);
+ remove(me->anchor->FileCache);
+ FREE(me->anchor->FileCache);
+ FREE(me->remove_command);
+ FREE(me->end_command);
+ FREE(me->viewer_command);
+ FREE(me);
+ return;
+ }
+ }
+ FREE(addr);
+ }
+ if (me->remove_command) {
+ /* NEVER REMOVE THE FILE unless during an abort!!!*/
+ /* system(me->remove_command); */
+ FREE(me->remove_command);
+ }
+ } else if (strcmp(me->end_command, "SaveToFile")) {
+ /*
+ * It's a temporary file we're passing to a
+ * viewer or helper application. - FM
+ */
+ if (!dump_output_immediately) {
+ /*
+ * Tell user what's happening. - FM
+ */
+ _HTProgress(me->end_command);
+ stop_curses();
+ }
+ system(me->end_command);
+
+ if (me->remove_command) {
+ /* NEVER REMOVE THE FILE unless during an abort!!!*/
+ /* system(me->remove_command); */
+ FREE(me->remove_command);
+ }
+ if (!dump_output_immediately)
+ start_curses();
+ } else {
+ /*
+ * It's a file we saved to disk for handling
+ * via a menu. - FM
+ */
+ if (me->remove_command) {
+ /* NEVER REMOVE THE FILE unless during an abort!!!*/
+ /* system(me->remove_command); */
+ FREE(me->remove_command);
+ }
+ }
+ FREE(me->end_command);
+ }
+ FREE(me->viewer_command);
+
+ if (dump_output_immediately) {
+ if (me->anchor->FileCache)
+ remove(me->anchor->FileCache);
+ FREE(me);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(0);
+ }
+
+ FREE(me);
+ return;
+}
+
+/* Abort writing
+** -------------
+*/
+PRIVATE void HTFWriter_abort ARGS2(
+ HTStream *, me,
+ HTError, e GCC_UNUSED)
+{
+ if (TRACE)
+ fprintf(stderr,"HTFWriter_abort called\n");
+
+ fclose(me->fp);
+ FREE(me->viewer_command);
+ if (me->end_command) { /* Temp file */
+ if (TRACE)
+ fprintf(stderr, "HTFWriter: Aborting: file not executed.\n");
+ FREE(me->end_command);
+ if (me->remove_command) {
+ system(me->remove_command);
+ FREE(me->remove_command);
+ }
+ }
+
+ FREE(WWW_Download_File);
+
+ FREE(me);
+}
+
+/* Structured Object Class
+** -----------------------
+*/
+PRIVATE CONST HTStreamClass HTFWriter = /* As opposed to print etc */
+{
+ "FileWriter",
+ HTFWriter_free,
+ HTFWriter_abort,
+ HTFWriter_put_character, HTFWriter_put_string,
+ HTFWriter_write
+};
+
+/* Subclass-specific Methods
+** -------------------------
+*/
+PUBLIC HTStream* HTFWriter_new ARGS1(FILE *, fp)
+{
+ HTStream* me;
+
+ if (!fp)
+ return NULL;
+
+ me = (HTStream*)calloc(sizeof(*me),1);
+ if (me == NULL)
+ outofmem(__FILE__, "HTFWriter_new");
+ me->isa = &HTFWriter;
+
+ me->fp = fp;
+ me->end_command = NULL;
+ me->remove_command = NULL;
+ me->anchor = NULL;
+ me->sink = NULL;
+
+ return me;
+}
+
+/* Make system command from template
+** ---------------------------------
+**
+** See mailcap spec for description of template.
+*/
+/* @@ to be written. sprintfs will do for now. */
+
+#ifndef VMS
+#define REMOVE_COMMAND "/bin/rm -f %s"
+#else
+#define REMOVE_COMMAND "delete/noconfirm/nolog %s;"
+#endif /* VMS */
+
+/* Take action using a system command
+** ----------------------------------
+**
+** originally from Ghostview handling by Marc Andreseen.
+** Creates temporary file, writes to it, executes system command
+** on end-document. The suffix of the temp file can be given
+** in case the application is fussy, or so that a generic opener can
+** be used.
+*/
+PUBLIC HTStream* HTSaveAndExecute ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ char fnam[256];
+ CONST char *suffix;
+ char *cp;
+ HTStream* me;
+ FILE *fp = NULL;
+
+ if (traversal) {
+ LYCancelledFetch = TRUE;
+ return(NULL);
+ }
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ if (pres->quality == 999.0) { /* exec link */
+ if (dump_output_immediately) {
+ LYCancelledFetch = TRUE;
+ return(NULL);
+ }
+ if (no_exec) {
+ _statusline(EXECUTION_DISABLED);
+ sleep(AlertSecs);
+ return HTPlainPresent(pres, anchor, sink);
+ }
+ if (!local_exec)
+ if (local_exec_on_local_files &&
+ (LYJumpFileURL ||
+ !strncmp(anchor->address,"file://localhost",16))) {
+ /* allow it to continue */
+ } else {
+ char buf[512];
+
+ sprintf(buf, EXECUTION_DISABLED_FOR_FILE,
+ key_for_func(LYK_OPTIONS));
+ _statusline(buf);
+ sleep(AlertSecs);
+ return HTPlainPresent(pres, anchor, sink);
+ }
+ }
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+ if (dump_output_immediately) {
+ return(HTSaveToFile(pres, anchor, sink));
+ }
+
+ me = (HTStream*)calloc(sizeof(*me),1);
+ if (me == NULL)
+ outofmem(__FILE__, "HTSaveAndExecute");
+ me->isa = &HTFWriter;
+ me->input_format = pres->rep;
+ me->output_format = pres->rep_out;
+ me->anchor = anchor;
+ me->sink = sink;
+
+ if (anchor->FileCache) {
+ strcpy(fnam, anchor->FileCache);
+ FREE(anchor->FileCache);
+ if ((fp = fopen(fnam, "r")) != NULL) {
+ fclose(fp);
+ fp = NULL;
+ remove(fnam);
+ }
+ } else {
+ /*
+ * Lynx routine to create a temporary filename
+ */
+SaveAndExecute_tempname:
+ tempname (fnam, NEW_FILE);
+ /*
+ * Check for a suffix.
+ */
+ if (((cp = strrchr(fnam, '.')) != NULL) &&
+#ifdef VMS
+ NULL == strchr(cp, ']') &&
+#endif /* VMS */
+ NULL == strchr(cp, '/')) {
+ /*
+ * Save the file under a suitably suffixed name.
+ */
+ *cp = '\0';
+ if (!strcasecomp(pres->rep->name, "text/html")) {
+ strcat(fnam, HTML_SUFFIX);
+ } else if (!strcasecomp(pres->rep->name, "text/plain")) {
+ strcat(fnam, ".txt");
+ } else if (!strcasecomp(pres->rep->name,
+ "application/octet-stream")) {
+ strcat(fnam, ".bin");
+ } else if ((suffix = HTFileSuffix(pres->rep, anchor->content_encoding))
+ && *suffix == '.') {
+ strcat(fnam, suffix);
+ /*
+ * It's not one of the suffixes checked for a
+ * spoof in tempname(), so check it now. - FM
+ */
+ if (strcmp(suffix, HTML_SUFFIX) &&
+ strcmp(suffix, ".txt") &&
+ strcmp(suffix, ".bin") &&
+ (fp = fopen(fnam, "r")) != NULL) {
+ fclose(fp);
+ fp = NULL;
+ goto SaveAndExecute_tempname;
+ }
+ } else {
+ *cp = '.';
+ }
+ }
+ }
+
+ me->fp = LYNewBinFile (fnam);
+ if (!me->fp) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ FREE(me);
+ return NULL;
+ }
+
+ StrAllocCopy(me->viewer_command, pres->command);
+ /*
+ * Make command to process file.
+ */
+ me->end_command = (char *)calloc (
+ (strlen (pres->command) + 10 + strlen(fnam))
+ * sizeof (char),1);
+ if (me->end_command == NULL)
+ outofmem(__FILE__, "HTSaveAndExecute");
+
+ sprintf(me->end_command, pres->command, fnam, "", "", "", "", "", "");
+
+ /*
+ * Make command to delete file.
+ */
+ me->remove_command = (char *)calloc (
+ (strlen (REMOVE_COMMAND) + 10 + strlen(fnam))
+ * sizeof (char),1);
+ if (me->remove_command == NULL)
+ outofmem(__FILE__, "HTSaveAndExecute");
+
+ sprintf(me->remove_command, REMOVE_COMMAND, fnam);
+
+ StrAllocCopy(anchor->FileCache, fnam);
+ return me;
+}
+
+
+/* Format Converter using system command
+** -------------------------------------
+*/
+
+/* @@@@@@@@@@@@@@@@@@@@@@ */
+
+/* Save to a local file LJM!!!
+** --------------------
+**
+** usually a binary file that can't be displayed
+**
+** originally from Ghostview handling by Marc Andreseen.
+** Asks the user if he wants to continue, creates a temporary
+** file, and writes to it. In HTSaveToFile_Free
+** the user will see a list of choices for download
+*/
+PUBLIC HTStream* HTSaveToFile ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream * ret_obj;
+ char fnam[256];
+ CONST char * suffix;
+ char *cp;
+ int c=0;
+ BOOL IsBinary = TRUE;
+ FILE *fp = NULL;
+
+ ret_obj = (HTStream*)calloc(sizeof(* ret_obj),1);
+ if (ret_obj == NULL)
+ outofmem(__FILE__, "HTSaveToFile");
+ ret_obj->isa = &HTFWriter;
+ ret_obj->remove_command = NULL;
+ ret_obj->end_command = NULL;
+ ret_obj->input_format = pres->rep;
+ ret_obj->output_format = pres->rep_out;
+ ret_obj->anchor = anchor;
+ ret_obj->sink = sink;
+
+ if (dump_output_immediately) {
+ ret_obj->fp = stdout; /* stdout*/
+ if (HTOutputFormat == HTAtom_for("www/download"))
+ goto Prepend_BASE;
+ return ret_obj;
+ }
+
+ LYCancelDownload = FALSE;
+ if (HTOutputFormat != HTAtom_for("www/download")) {
+ if (traversal ||
+ (no_download && !override_no_download && no_disk_save)) {
+ if (!traversal) {
+ _statusline(CANNOT_DISPLAY_FILE);
+ sleep(AlertSecs);
+ }
+ LYCancelDownload = TRUE;
+ if (traversal)
+ LYCancelledFetch = TRUE;
+ FREE(ret_obj);
+ return(NULL);
+ }
+
+ if (((cp=strchr((char *)pres->rep->name, ';')) != NULL) &&
+ strstr((cp+1), "charset") != NULL) {
+ _user_message(WRONG_CHARSET_D_OR_C, (char *)pres->rep->name);
+ } else if (*((char *)pres->rep->name) != '\0') {
+ _user_message(UNMAPPED_TYPE_D_OR_C, (char *)pres->rep->name);
+ } else {
+ _statusline(CANNOT_DISPLAY_FILE_D_OR_C);
+ }
+
+ while(TOUPPER(c)!='C' && TOUPPER(c)!='D' && c!=7) {
+ c=LYgetch();
+#ifdef VMS
+ /*
+ * 'C'ancel on Control-C or Control-Y and
+ * a 'N'o to the "really exit" query. - FM
+ */
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ c = 'C';
+ }
+#endif /* VMS */
+ }
+
+ /*
+ * Cancel on 'C', 'c' or Control-G or Control-C.
+ */
+ if (TOUPPER(c)=='C' || c==7 || c==3) {
+ _statusline(CANCELLING_FILE);
+ LYCancelDownload = TRUE;
+ FREE(ret_obj);
+ return(NULL);
+ }
+ }
+
+ /*
+ * Set up a 'D'ownload.
+ */
+ if (anchor->FileCache) {
+ strcpy(fnam, anchor->FileCache);
+ FREE(anchor->FileCache);
+ if ((fp = fopen(fnam, "r")) != NULL) {
+ fclose(fp);
+ fp = NULL;
+ remove(fnam);
+ }
+ } else {
+ /*
+ * Lynx routine to create a temporary filename
+ */
+SaveToFile_tempname:
+ tempname(fnam, NEW_FILE);
+ /*
+ * Check for a suffix.
+ */
+ if (((cp=strrchr(fnam, '.')) != NULL) &&
+#ifdef VMS
+ NULL == strchr(cp, ']') &&
+#endif /* VMS */
+ NULL == strchr(cp, '/')) {
+ /*
+ * Save the file under a suitably suffixed name.
+ */
+ *cp = '\0';
+ if (!strcasecomp(pres->rep->name, "text/html")) {
+ strcat(fnam, HTML_SUFFIX);
+ } else if (!strcasecomp(pres->rep->name, "text/plain")) {
+ strcat(fnam, ".txt");
+ } else if (!strcasecomp(pres->rep->name,
+ "application/octet-stream")) {
+ strcat(fnam, ".bin");
+ } else if ((suffix = HTFileSuffix(pres->rep,
+ anchor->content_encoding)) && *suffix == '.') {
+ strcat(fnam, suffix);
+ /*
+ * It's not one of the suffixes checked for a
+ * spoof in tempname(), so check it now. - FM
+ */
+ if (strcmp(suffix, HTML_SUFFIX) &&
+ strcmp(suffix, ".txt") &&
+ strcmp(suffix, ".bin") &&
+ (fp = fopen(fnam, "r")) != NULL) {
+ fclose(fp);
+ fp = NULL;
+ goto SaveToFile_tempname;
+ }
+ } else {
+ *cp = '.';
+ }
+ }
+ }
+
+ if (0==strncasecomp(pres->rep->name, "text/", 5) ||
+ 0==strcasecomp(pres->rep->name, "application/postscript") ||
+ 0==strcasecomp(pres->rep->name, "application/x-RUNOFF-MANUAL"))
+ /*
+ * It's a text file requested via 'd'ownload.
+ * Keep adding others to the above list, 'til
+ * we add a configurable procedure. - FM
+ */
+ IsBinary = FALSE;
+
+ ret_obj->fp = LYNewBinFile (fnam);
+ if (!ret_obj->fp) {
+ HTAlert(CANNOT_OPEN_OUTPUT);
+ FREE(ret_obj);
+ return NULL;
+ }
+
+ /*
+ * Any "application/foo" or other non-"text/foo" types that
+ * are actually text but not checked, above, will be treated
+ * as binary, so show the type to help sort that out later.
+ * Unix folks don't need to know this, but we'll show it to
+ * them, too. - FM
+ */
+ user_message("Content-type: %s", pres->rep->name);
+ sleep(MessageSecs);
+
+ StrAllocCopy(WWW_Download_File,fnam);
+
+ /*
+ * Make command to delete file.
+ */
+ ret_obj->remove_command = (char *)calloc (
+ (strlen (REMOVE_COMMAND) + 10+ strlen(fnam))
+ * sizeof (char),1);
+ if (ret_obj->remove_command == NULL)
+ outofmem(__FILE__, "HTSaveToFile");
+
+ sprintf(ret_obj->remove_command, REMOVE_COMMAND, fnam);
+
+#ifdef VMS
+ if (IsBinary && UseFixedRecords) {
+ ret_obj->end_command = (char *)calloc (sizeof(char)*20,1);
+ if (ret_obj->end_command == NULL)
+ outofmem(__FILE__, "HTSaveToFile");
+ sprintf(ret_obj->end_command, "SaveVMSBinaryFile");
+ FIXED_RECORD_COMMAND = (char *)calloc (
+ (strlen (FIXED_RECORD_COMMAND_MASK) + 10 + strlen(fnam))
+ * sizeof (char),1);
+ if (FIXED_RECORD_COMMAND == NULL)
+ outofmem(__FILE__, "HTSaveToFile");
+ sprintf(FIXED_RECORD_COMMAND,
+ FIXED_RECORD_COMMAND_MASK, fnam, "", "", "", "", "", "");
+ } else {
+#endif /* VMS */
+ ret_obj->end_command = (char *)calloc (sizeof(char)*12,1);
+ if (ret_obj->end_command == NULL)
+ outofmem(__FILE__, "HTSaveToFile");
+ sprintf(ret_obj->end_command, "SaveToFile");
+#ifdef VMS
+ }
+#endif /* VMS */
+
+ _statusline(RETRIEVING_FILE);
+
+ StrAllocCopy(anchor->FileCache, fnam);
+Prepend_BASE:
+ if (LYPrependBaseToSource &&
+ !strncasecomp(pres->rep->name, "text/html", 9) &&
+ !anchor->content_encoding) {
+ /*
+ * Add the document's base as a BASE tag at the top of the file,
+ * so that any partial or relative URLs within it will be resolved
+ * relative to that if no BASE tag is present and replaces it.
+ * Note that the markup will be technically invalid if a DOCTYPE
+ * declaration, or HTML or HEAD tags, are present, and thus the
+ * file may need editing for perfection. - FM
+ */
+ char *temp = NULL;
+
+ if (anchor->content_base && *anchor->content_base) {
+ StrAllocCopy(temp, anchor->content_base);
+ } else if (anchor->content_location && *anchor->content_location) {
+ StrAllocCopy(temp, anchor->content_location);
+ }
+ if (temp) {
+ collapse_spaces(temp);
+ if (!is_url(temp)) {
+ FREE(temp);
+ }
+ }
+
+ fprintf(ret_obj->fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n",
+ anchor->address, (temp ? temp : anchor->address));
+ FREE(temp);
+ }
+ if (LYPrependCharsetToSource &&
+ !strncasecomp(pres->rep->name, "text/html", 9) &&
+ !anchor->content_encoding) {
+ /*
+ * Add the document's charset as a META CHARSET tag
+ * at the top of the file, so HTTP charset header
+ * will not be forgotten when a document saved as local file.
+ * We add this line only(!) if HTTP charset present. - LP
+ * Note that the markup will be technically invalid if a DOCTYPE
+ * declaration, or HTML or HEAD tags, are present, and thus the
+ * file may need editing for perfection. - FM
+ */
+ char *temp = NULL;
+
+ if (anchor->charset && *anchor->charset) {
+ StrAllocCopy(temp, anchor->charset);
+ collapse_spaces(temp);
+ fprintf(ret_obj->fp,
+ "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=%s\">\n\n",
+ temp);
+ }
+ FREE(temp);
+ }
+ return ret_obj;
+}
+
+/* Set up stream for uncompressing - FM
+** -------------------------------
+*/
+PUBLIC HTStream* HTCompressed ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream* me;
+ HTFormat format;
+ char *type = NULL;
+ HTPresentation *Pres = NULL;
+ int n, i;
+ BOOL can_present = FALSE;
+ char fnam[256];
+ CONST char *suffix;
+ char *uncompress_mask = NULL;
+ char *compress_suffix = "";
+ char *cp;
+ CONST char *middle;
+ FILE *fp = NULL;
+
+ /*
+ * Deal with any inappropriate invokations of this function,
+ * or a download request, in which case we won't bother to
+ * uncompress the file. - FM
+ */
+ if (!(anchor && anchor->content_encoding && anchor->content_type)) {
+ /*
+ * We have no idea what we're dealing with,
+ * so treat it as a binary stream. - FM
+ */
+ format = HTAtom_for("application/octet-stream");
+ me = HTStreamStack(format, pres->rep_out, sink, anchor);
+ return me;
+ }
+ n = HTList_count(HTPresentations);
+ for (i = 0; i < n; i++) {
+ Pres = (HTPresentation *)HTList_objectAt(HTPresentations, i);
+ if (!strcasecomp(Pres->rep->name, anchor->content_type) &&
+ Pres->rep_out == WWW_PRESENT) {
+ /*
+ * We have a presentation mapping for it. - FM
+ */
+ can_present = TRUE;
+ if (!strcasecomp(anchor->content_encoding, "x-gzip") ||
+ !strcasecomp(anchor->content_encoding, "gzip")) {
+ /*
+ * It's compressed with the modern gzip. - FM
+ */
+ StrAllocCopy(uncompress_mask, GZIP_PATH);
+ StrAllocCat(uncompress_mask, " -d --no-name %s");
+ compress_suffix = "gz";
+ } else if (!strcasecomp(anchor->content_encoding, "x-compress") ||
+ !strcasecomp(anchor->content_encoding, "compress")) {
+ /*
+ * It's compressed the old fashioned Unix way. - FM
+ */
+ StrAllocCopy(uncompress_mask, UNCOMPRESS_PATH);
+ StrAllocCat(uncompress_mask, " %s");
+ compress_suffix = "Z";
+ }
+ break;
+ }
+ }
+ if (can_present == FALSE || /* no presentation mapping */
+ uncompress_mask == NULL || /* not gzip or compress */
+ strchr(anchor->content_type, ';') || /* wrong charset */
+ HTOutputFormat == HTAtom_for("www/download") || /* download */
+ !strcasecomp(pres->rep_out->name, "www/download") || /* download */
+ (traversal && /* only handle html or plain text for traversals */
+ strcasecomp(anchor->content_type, "text/html") &&
+ strcasecomp(anchor->content_type, "text/plain"))) {
+ /*
+ * Cast the Content-Encoding to a Content-Type
+ * and pass it back to be handled as that type. - FM
+ */
+ if (strchr(anchor->content_encoding, '/') == NULL) {
+ StrAllocCopy(type, "application/");
+ StrAllocCat(type, anchor->content_encoding);
+ } else {
+ StrAllocCopy(type, anchor->content_encoding);
+ }
+ format = HTAtom_for(type);
+ FREE(type)
+ FREE(uncompress_mask);
+ me = HTStreamStack(format, pres->rep_out, sink, anchor);
+ return me;
+ }
+
+ /*
+ * Set up the stream structure for uncompressing and then
+ * handling based on the uncompressed Content-Type.- FM
+ */
+ me = (HTStream*)calloc(sizeof(*me),1);
+ if (me == NULL)
+ outofmem(__FILE__, "HTCompressed");
+ me->isa = &HTFWriter;
+ me->input_format = pres->rep;
+ me->output_format = pres->rep_out;
+ me->anchor = anchor;
+ me->sink = sink;
+
+ /*
+ * Remove any old versions of the file. - FM
+ */
+ if (anchor->FileCache) {
+ while ((fp = fopen(anchor->FileCache, "r")) != NULL) {
+ fclose(fp);
+ remove(anchor->FileCache);
+ }
+ FREE(anchor->FileCache);
+ }
+
+ /*
+ * Get a new temporary filename and substitute a suitable suffix. - FM
+ */
+Compressed_tempname:
+ tempname(fnam, NEW_FILE);
+ if ((cp = strrchr(fnam, '.')) != NULL) {
+ middle = NULL;
+ if (!strcasecomp(anchor->content_type, "text/html")) {
+ middle = HTML_SUFFIX;
+ middle++; /* point to 'h' of .htm(l) - kw */
+ } else if (!strcasecomp(anchor->content_type, "text/plain")) {
+ middle = "txt";
+ } else if (!strcasecomp(anchor->content_type,
+ "application/octet-stream")) {
+ middle = "bin";
+ } else if ((suffix =
+ HTFileSuffix(HTAtom_for(anchor->content_type), NULL)) &&
+ *suffix == '.') {
+#if defined(VMS) || defined(FNAMES_8_3)
+ if (strchr(suffix + 1, '.') == NULL)
+#endif
+ middle = suffix + 1;
+ }
+ if (middle) {
+ *cp = '\0';
+#ifdef FNAMES_8_3
+ me->idash = strlen(fnam); /* remember position of '-' - kw */
+ strcat(fnam, "-"); /* NAME-htm, NAME-txt, etc. - hack for DOS */
+#else
+ strcat(fnam, "."); /* NAME.html, NAME-txt etc. */
+#endif /* FNAMES_8_3 */
+ strcat(fnam, middle);
+#ifdef VMS
+ strcat(fnam, "-"); /* NAME.html-gz, NAME.txt-gz, NAME.txt-Z etc.*/
+#else
+ strcat(fnam, "."); /* NAME-htm.gz (DOS), NAME.html.gz (UNIX)etc.*/
+#endif /* VMS */
+ } else {
+ *(cp + 1) = '\0';
+ }
+ } else {
+ strcat(fnam, ".");
+ }
+ strcat(fnam, compress_suffix);
+ /*
+ * It's not one of the suffixes checked for a
+ * spoof in tempname(), so check it now. - FM
+ */
+ if ((fp = fopen(fnam, "r")) != NULL) {
+ fclose(fp);
+ fp = NULL;
+ goto Compressed_tempname;
+ }
+
+ /*
+ * Open the file for receiving the compressed input stream. - FM
+ */
+ me->fp = LYNewBinFile (fnam);
+ if (!me->fp) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ FREE(uncompress_mask);
+ FREE(me);
+ return NULL;
+ }
+
+ /*
+ * me->viewer_command will be NULL if the converter Pres found above
+ * is not for an external viewer but an internal HTStream converter.
+ * We also don't set it under conditions where HTSaveAndExecute would
+ * disallow execution of the command. - KW
+ */
+ if (!dump_output_immediately && !traversal
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ && (Pres->quality != 999.0 ||
+ (!no_exec && /* allowed exec link or script ? */
+ (local_exec ||
+ (local_exec_on_local_files &&
+ (LYJumpFileURL ||
+ !strncmp(anchor->address,"file://localhost",16))))))
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+ ) {
+ StrAllocCopy(me->viewer_command, Pres->command);
+ }
+
+ /*
+ * Make command to process file. - FM
+ */
+#ifdef USE_ZLIB
+ if (compress_suffix[0] == 'g' && /* must be gzip */
+ !me->viewer_command) {
+ /*
+ * We won't call gzip externally, so we don't need to supply
+ * a command for it. - kw
+ */
+ StrAllocCopy(me->end_command, "");
+ } else
+#endif /* USE_ZLIB */
+ {
+ me->end_command = (char *)calloc(1, (strlen(uncompress_mask) + 10 +
+ strlen(fnam)) * sizeof(char));
+ if (me->end_command == NULL)
+ outofmem(__FILE__, "HTCompressed");
+ sprintf(me->end_command, uncompress_mask, fnam, "", "", "", "", "", "");
+ }
+ FREE(uncompress_mask);
+
+ /*
+ * Make command to delete file. - FM
+ */
+ me->remove_command = (char *)calloc(1, (strlen(REMOVE_COMMAND) + 10 +
+ strlen(fnam)) * sizeof(char));
+ if (me->remove_command == NULL)
+ outofmem(__FILE__, "HTCompressed");
+ sprintf(me->remove_command, REMOVE_COMMAND, fnam);
+
+ /*
+ * Save the filename and return the structure. - FM
+ */
+ StrAllocCopy(anchor->FileCache, fnam);
+ return me;
+}
+
+/* Dump output to stdout - LJM & FM
+** ---------------------
+**
+*/
+PUBLIC HTStream* HTDumpToStdout ARGS3(
+ HTPresentation *, pres GCC_UNUSED,
+ HTParentAnchor *, anchor,
+ HTStream *, sink GCC_UNUSED)
+{
+ HTStream * ret_obj;
+ ret_obj = (HTStream*)calloc(sizeof(* ret_obj),1);
+ if (ret_obj == NULL)
+ outofmem(__FILE__, "HTDumpToStdout");
+ ret_obj->isa = &HTFWriter;
+ ret_obj->remove_command = NULL;
+ ret_obj->end_command = NULL;
+ ret_obj->anchor = anchor;
+
+ ret_obj->fp = stdout; /* stdout*/
+ return ret_obj;
+}
+
+#if defined(VMS) && !defined(USE_COMMAND_FILE)
+#include <fab.h>
+#include <rmsdef.h> /* RMS status codes */
+#include <iodef.h> /* I/O function codes */
+#include <fibdef.h> /* file information block defs */
+#include <atrdef.h> /* attribute request codes */
+#ifdef NOTDEFINED /*** Not all versions of VMS compilers have these. ***/
+#include <fchdef.h> /* file characteristics */
+#include <fatdef.h> /* file attribute defs */
+#else /*** So we'll define what we need from them ourselves. ***/
+#define FCH$V_CONTIGB 0x005 /* pos of cont best try bit */
+#define FCH$M_CONTIGB (1 << FCH$V_CONTIGB) /* contig best try bit mask */
+/* VMS I/O User's Reference Manual: Part I (V5.x doc set) */
+struct fatdef {
+ unsigned char fat$b_rtype, fat$b_rattrib;
+ unsigned short fat$w_rsize;
+ unsigned long fat$l_hiblk, fat$l_efblk;
+ unsigned short fat$w_ffbyte;
+ unsigned char fat$b_bktsize, fat$b_vfcsize;
+ unsigned short fat$w_maxrec, fat$w_defext, fat$w_gbc;
+ unsigned : 16, : 32, : 16; /* 6 bytes reserved, 2 bytes not used */
+ unsigned short fat$w_versions;
+};
+#endif /* NOTDEFINED */
+
+/* arbitrary descriptor without type and class info */
+typedef struct dsc { unsigned short len, mbz; void *adr; } Desc;
+
+extern unsigned long sys$open(), sys$qiow(), sys$dassgn();
+
+#define syswork(sts) ((sts) & 1)
+#define sysfail(sts) (!syswork(sts))
+
+
+/*
+ * 25-Jul-1995 - Pat Rankin (rankin@eql.caltech.edu)
+ *
+ * Force a file to be marked as having fixed-length, 512 byte records
+ * without implied carriage control, and with best_try_contiguous set.
+ */
+PUBLIC unsigned long LYVMS_FixedLengthRecords ARGS1(char *, filename)
+{
+ struct FAB fab; /* RMS file access block */
+ struct fibdef fib; /* XQP file information block */
+ struct fatdef recattr; /* XQP file "record" attributes */
+ struct atrdef attr_rqst_list[3]; /* XQP attribute request itemlist */
+
+ Desc fib_dsc;
+ unsigned short channel, iosb[4];
+ unsigned long fchars, sts, tmp;
+
+ /* initialize file access block */
+ fab = cc$rms_fab;
+ fab.fab$l_fna = filename;
+ fab.fab$b_fns = (unsigned char) strlen(filename);
+ fab.fab$l_fop = FAB$M_UFO; /* user file open; no further RMS processing */
+ fab.fab$b_fac = FAB$M_PUT; /* need write access */
+ fab.fab$b_shr = FAB$M_NIL; /* exclusive access */
+
+ sts = sys$open(&fab); /* channel in stv; $dassgn to close */
+ if (sts == RMS$_FLK) {
+ /* For MultiNet, at least, if the file was just written by a remote
+ NFS client, the local NFS server might still have it open, and the
+ failed access attempt will provoke it to be closed, so try again. */
+ sts = sys$open(&fab);
+ }
+ if (sysfail(sts)) return sts;
+
+ /* RMS supplies a user-mode channel (see FAB$L_FOP FAB$V_UFO doc) */
+ channel = (unsigned short) fab.fab$l_stv;
+
+ /* set up ACP interface strutures */
+ /* file information block, passed by descriptor; it's okay to start with
+ an empty FIB after RMS has accessed the file for us */
+ fib_dsc.len = sizeof fib;
+ fib_dsc.mbz = 0;
+ fib_dsc.adr = &fib;
+ memset((void *)&fib, 0, sizeof fib);
+ /* attribute request list */
+ attr_rqst_list[0].atr$w_size = sizeof recattr;
+ attr_rqst_list[0].atr$w_type = ATR$C_RECATTR;
+ *(void **)&attr_rqst_list[0].atr$l_addr = (void *)&recattr;
+ attr_rqst_list[1].atr$w_size = sizeof fchars;
+ attr_rqst_list[1].atr$w_type = ATR$C_UCHAR;
+ *(void **)&attr_rqst_list[1].atr$l_addr = (void *)&fchars;
+ attr_rqst_list[2].atr$w_size = attr_rqst_list[2].atr$w_type = 0;
+ attr_rqst_list[2].atr$l_addr = 0;
+ /* file "record" attributes */
+ memset((void *)&recattr, 0, sizeof recattr);
+ fchars = 0; /* file characteristics */
+
+ /* get current attributes */
+ sts = sys$qiow(0, channel, IO$_ACCESS, iosb, (void(*)())0, 0,
+ &fib_dsc, 0, 0, 0, attr_rqst_list, 0);
+ if (syswork(sts))
+ sts = iosb[0];
+
+ /* set desired attributes */
+ if (syswork(sts)) {
+ recattr.fat$b_rtype = FAB$C_SEQ | FAB$C_FIX; /* org=seq, rfm=fix */
+ recattr.fat$w_rsize = recattr.fat$w_maxrec = 512; /* lrl=mrs=512 */
+ recattr.fat$b_rattrib = 0; /* rat=none */
+ fchars |= FCH$M_CONTIGB; /* contiguous-best-try */
+ sts = sys$qiow(0, channel, IO$_DEACCESS, iosb, (void(*)())0, 0,
+ &fib_dsc, 0, 0, 0, attr_rqst_list, 0);
+ if (syswork(sts))
+ sts = iosb[0];
+ }
+
+ /* all done */
+ tmp = sys$dassgn(channel);
+ if (syswork(sts))
+ sts = tmp;
+ return sts;
+}
+#endif /* VMS && !USE_COMMAND_FILE */
diff --git a/gnu/usr.bin/lynx/src/HTFont.h b/gnu/usr.bin/lynx/src/HTFont.h
new file mode 100644
index 00000000000..61ece860392
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTFont.h
@@ -0,0 +1,29 @@
+/* The portable font concept (!?*)
+*/
+
+/* Line mode browser version:
+*/
+#ifndef HTFONT_H
+#define HTFONT_H
+
+typedef long int HTMLFont; /* For now */
+
+#ifndef HT_NON_BREAK_SPACE
+#define HT_NON_BREAK_SPACE ((char)1) /* For now */
+#endif /* !HT_NON_BREAK_SPACE */
+#ifndef HT_EM_SPACE
+#define HT_EM_SPACE ((char)2) /* For now */
+#endif /* !HT_EM_SPACE */
+
+
+#define HT_FONT 0
+#define HT_CAPITALS 1
+#define HT_BOLD 2
+#define HT_UNDERLINE 4
+#define HT_INVERSE 8
+#define HT_DOUBLE 0x10
+
+#define HT_BLACK 0
+#define HT_WHITE 1
+
+#endif /* HTFONT_H */
diff --git a/gnu/usr.bin/lynx/src/HTForms.h b/gnu/usr.bin/lynx/src/HTForms.h
new file mode 100644
index 00000000000..3d6f608d0fb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTForms.h
@@ -0,0 +1,140 @@
+
+#ifndef HTFORMS_H
+#define HTFORMS_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+/* in LYForms.c */
+extern int change_form_link PARAMS((struct link *form_link, int mode,
+ document *newdoc, BOOLEAN *refresh_screen,
+ char *link_name, char *link_value));
+
+/* InputFieldData is used to pass the info between
+ * HTML.c and Gridtext.c in HText_beginInput()
+ */
+typedef struct _InputFieldData {
+ CONST char *accept;
+ CONST char *align;
+ int checked;
+ CONST char *class;
+ int disabled;
+ CONST char *error;
+ CONST char *height;
+ CONST char *id;
+ CONST char *lang;
+ CONST char *max;
+ CONST char *maxlength;
+ CONST char *md;
+ CONST char *min;
+ CONST char *name;
+ CONST char *size;
+ CONST char *src;
+ CONST char *type;
+ char *value;
+ CONST char *width;
+ int name_cs; /* charset handle for name */
+ int value_cs; /* charset handle for value */
+ CONST char *accept_cs;
+} InputFieldData;
+
+/* The OptionType structure is for a linked list of option entries
+ */
+typedef struct _OptionType {
+ char * name; /* the name of the entry */
+ char * cp_submit_value; /* the value to submit */
+ int value_cs; /* charset value is in */
+ struct _OptionType * next; /* the next entry */
+} OptionType;
+
+/* the FormInfo structure is used to contain the form field
+ * data within each anchor
+ * A pointer to this structure is in the TextAnchor struct.
+ */
+typedef struct _FormInfo {
+ char * name; /* the name of the link */
+ int number; /* which form is the link within */
+ int type; /* string, int, etc. */
+ char * value; /* user entered string data */
+ char * orig_value;/* the original value */
+ int size; /* width on the screen */
+ int maxlength; /* max width of data */
+ int group; /* a group associated with the link
+ * this is used for select's
+ */
+ int num_value; /* value of the numerical fields */
+ int hrange; /* high numerical range */
+ int lrange; /* low numerical range */
+ OptionType * select_list; /* array of option choices */
+ char * submit_action; /* form's action */
+ int submit_method; /* form's method */
+ char * submit_enctype; /* form's entype */
+ char * submit_title; /* form's title */
+ BOOL no_cache; /* Always resubmit? */
+ char * cp_submit_value; /* option value to submit */
+ char * orig_submit_value; /* original submit value */
+ int size_l; /* The length of the option list */
+ int disabled; /* If YES, can't change values */
+ int name_cs;
+ int value_cs;
+ char * accept_cs;
+} FormInfo;
+
+/*
+ * As structure for info associated with a form.
+ * There is some redundancy here, this shouldn't waste too much memory
+ * since the total number of forms (as opposed to form fields) per doc
+ * is expected to be rather small.
+ * More things which are per form rather than per field could be moved
+ * here. - kw
+ */
+typedef struct _PerFormInfo
+{
+ int number; /* form number, see GridText.c */
+ /* except for the last two, the followign fields aren't actually used.. */
+ int disabled; /* If YES, can't change values */
+ struct _PerFormInfo * next; /* pointer to next form in doc */
+ int nfields; /* number of fields */
+ FormInfo * first_field;
+ FormInfo * last_field; /* pointer to last field in form */
+ char * accept_cs;
+ char * thisacceptcs; /* used during submit */
+} PerFormInfo;
+
+#define HYPERTEXT_ANCHOR 1
+#define INPUT_ANCHOR 2 /* forms mode input fields */
+#define INTERNAL_LINK_ANCHOR 5 /* 1+4, can be used as bitflag... - kw */
+
+#define F_TEXT_TYPE 1
+#define F_PASSWORD_TYPE 2
+#define F_CHECKBOX_TYPE 3
+#define F_RADIO_TYPE 4
+#define F_SUBMIT_TYPE 5
+#define F_RESET_TYPE 6
+#define F_OPTION_LIST_TYPE 7
+#define F_HIDDEN_TYPE 8
+#define F_TEXTAREA_TYPE 9
+#define F_RANGE_TYPE 10
+#define F_FILE_TYPE 11
+#define F_TEXT_SUBMIT_TYPE 12
+#define F_IMAGE_SUBMIT_TYPE 13
+#define F_KEYGEN_TYPE 14
+
+#define WWW_FORM_LINK_TYPE 1
+#define WWW_LINK_TYPE 2
+#define WWW_INTERN_LINK_TYPE 6 /* can be used as a bitflag... - kw */
+#define LINK_LINE_FOUND 8 /* used in follow_link_number - kw */
+
+/* #define different lynx modes */
+#define NORMAL_LYNX_MODE 1
+#define FORMS_LYNX_MODE 2
+
+#define FORM_UP 1
+#define FORM_DOWN 2
+
+#define FIRST_ORDER 1
+#define MIDDLE_ORDER 2
+#define LAST_ORDER 3
+
+#endif /* HTFORMS_H */
diff --git a/gnu/usr.bin/lynx/src/HTInit.c b/gnu/usr.bin/lynx/src/HTInit.c
new file mode 100644
index 00000000000..3b15191c4ee
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTInit.c
@@ -0,0 +1,1063 @@
+/* Configuration-specific Initialialization HTInit.c
+** ----------------------------------------
+*/
+
+/* Define a basic set of suffixes and presentations
+** ------------------------------------------------
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+/* Implements:
+*/
+#include "HTInit.h"
+
+#include "HTML.h"
+#include "HTPlain.h"
+#include "HTMLGen.h"
+#include "HTFile.h"
+#include "HTFormat.h"
+#include "HTMIME.h"
+#include "HTWSRC.h"
+
+#include "HTSaveToFile.h" /* LJM */
+#include "userdefs.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYSystem.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+PRIVATE int HTLoadTypesConfigFile PARAMS((char *fn));
+PRIVATE int HTLoadExtensionsConfigFile PARAMS((char *fn));
+
+PUBLIC void HTFormatInit NOARGS
+{
+ FILE *fp = NULL;
+ char *cp = NULL;
+
+#ifdef NeXT
+ HTSetPresentation("application/postscript", "open %s", 1.0, 2.0, 0.0, 0);
+ HTSetPresentation("image/x-tiff", "open %s", 2.0, 2.0, 0.0, 0);
+ HTSetPresentation("image/tiff", "open %s", 1.0, 2.0, 0.0, 0);
+ HTSetPresentation("audio/basic", "open %s", 1.0, 2.0, 0.0, 0);
+ HTSetPresentation("*", "open %s", 1.0, 0.0, 0.0, 0);
+#else
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') { /* Must have X11 */
+ HTSetPresentation("application/postscript", "ghostview %s&",
+ 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/gif", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-xbm", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-xbitmap", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-png", XLoadImageCommand, 2.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/png", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-rgb", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/x-tiff", XLoadImageCommand, 2.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/tiff", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("image/jpeg", XLoadImageCommand, 1.0, 3.0, 0.0, 0);
+ HTSetPresentation("video/mpeg", "mpeg_play %s &", 1.0, 3.0, 0.0, 0);
+
+ }
+#endif
+
+#ifdef EXEC_SCRIPTS
+ /* set quality to 999.0 for protected exec applications */
+#ifndef VMS
+ HTSetPresentation("application/x-csh", "csh %s", 999.0, 3.0, 0.0, 0);
+ HTSetPresentation("application/x-sh", "sh %s", 999.0, 3.0, 0.0, 0);
+ HTSetPresentation("application/x-ksh", "ksh %s", 999.0, 3.0, 0.0, 0);
+#else
+ HTSetPresentation("application/x-VMS_script", "@%s", 999.0, 3.0, 0.0, 0);
+#endif /* not VMS */
+#endif /* EXEC_SCRIPTS */
+
+/*
+ * Add our header handlers.
+ */
+ HTSetConversion("www/mime", "www/present", HTMIMEConvert, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/mime", "www/download", HTMIMEConvert, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/mime", "www/source", HTMIMEConvert, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/mime", "www/dump", HTMIMEConvert, 1.0, 0.0, 0.0, 0);
+
+/*
+ * Add our compressed file handlers.
+ */
+ HTSetConversion("www/compressed", "www/present",
+ HTCompressed, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/compressed", "www/download",
+ HTCompressed, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/compressed", "www/present",
+ HTCompressed, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/compressed", "www/source",
+ HTCompressed, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("www/compressed", "www/dump",
+ HTCompressed, 1.0, 0.0, 0.0, 0);
+
+ /*
+ * Added the following to support some content types beginning to surface.
+ */
+ HTSetConversion("application/html", "text/x-c",
+ HTMLToC, 0.5, 0.0, 0.0, 0);
+ HTSetConversion("application/html", "text/plain",
+ HTMLToPlain, 0.5, 0.0, 0.0, 0);
+ HTSetConversion("application/html", "www/present",
+ HTMLPresent, 2.0, 0.0, 0.0, 0);
+ HTSetConversion("application/html", "www/source",
+ HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("application/x-wais-source", "www/source",
+ HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("application/x-wais-source", "www/present",
+ HTWSRCConvert, 2.0, 0.0, 0.0, 0);
+ HTSetConversion("application/x-wais-source", "www/download",
+ HTWSRCConvert, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("application/x-wais-source", "www/dump",
+ HTWSRCConvert, 1.0, 0.0, 0.0, 0);
+
+ /*
+ * Save all unknown mime types to disk.
+ */
+ HTSetConversion("www/source", "www/present",
+ HTSaveToFile, 1.0, 3.0, 0.0, 0);
+ HTSetConversion("www/source", "www/source",
+ HTSaveToFile, 1.0, 3.0, 0.0, 0);
+ HTSetConversion("www/source", "www/download",
+ HTSaveToFile, 1.0, 3.0, 0.0, 0);
+ HTSetConversion("www/source", "*", HTSaveToFile, 1.0, 3.0, 0.0, 0);
+
+ /*
+ * Output all www/dump presentations to stdout.
+ */
+ HTSetConversion("www/source", "www/dump",
+ HTDumpToStdout, 1.0, 3.0, 0.0, 0);
+
+/*
+ * Now add our basic conversions.
+ */
+ HTSetConversion("text/x-sgml",
+ "www/source", HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/x-sgml",
+ "www/present", HTMLPresent, 2.0, 0.0, 0.0, 0);
+ HTSetConversion("text/sgml", "www/source", HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/sgml", "www/present", HTMLPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/plain","www/present", HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/plain","www/source", HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "www/source", HTPlainPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "text/x-c", HTMLToC, 0.5, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "text/plain", HTMLToPlain, 0.5, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "www/present", HTMLPresent, 1.0, 0.0, 0.0, 0);
+
+ /*
+ * These should override the default types as necessary.
+ */
+ HTLoadTypesConfigFile(global_type_map);
+
+ /*
+ * Load the local maps.
+ */
+ if ((fp = fopen(personal_type_map,"r")) != NULL) {
+ fclose(fp);
+ /* These should override everything else. */
+ HTLoadTypesConfigFile(personal_type_map);
+ } else {
+ char buffer[256];
+#ifdef VMS
+ sprintf(buffer, "sys$login:%s", personal_type_map);
+#else
+ sprintf(buffer, "%s/%s", (Home_Dir() ? Home_Dir() : ""),
+ personal_type_map);
+#endif
+ HTLoadTypesConfigFile(buffer);
+ }
+
+ /*
+ * Put text/html and text/plain at beginning of list. - kw
+ */
+ HTReorderPresentation(WWW_PLAINTEXT, WWW_PRESENT);
+ HTReorderPresentation(WWW_HTML, WWW_PRESENT);
+}
+
+PUBLIC void HTPreparsedFormatInit NOARGS
+{
+ if (LYPreparsedSource) {
+ HTSetConversion("text/html", "www/source", HTMLParsedPresent, 1.0, 0.0, 0.0, 0);
+ HTSetConversion("text/html", "www/dump", HTMLParsedPresent, 1.0, 0.0, 0.0, 0);
+ }
+}
+
+/* Some of the following is taken from: */
+
+/*
+Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
+
+Permission to use, copy, modify, and distribute this material
+for any purpose and without fee is hereby granted, provided
+that the above copyright notice and this permission notice
+appear in all copies, and that the name of Bellcore not be
+used in advertising or publicity pertaining to this
+material without the specific, prior written permission
+of an authorized representative of Bellcore. BELLCORE
+MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY
+OF THIS MATERIAL FOR ANY PURPOSE. IT IS PROVIDED "AS IS",
+WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
+*/
+/******************************************************
+ Metamail -- A tool to help diverse mail readers
+ cope with diverse multimedia mail formats.
+
+ Author: Nathaniel S. Borenstein, Bellcore
+
+ ******************************************************* */
+
+struct MailcapEntry {
+ char *contenttype;
+ char *command;
+ char *testcommand;
+ int needsterminal;
+ int copiousoutput;
+ int needtofree;
+ char *label;
+ char *printcommand;
+ float quality;
+ long int maxbytes;
+};
+
+
+PRIVATE int ExitWithError PARAMS((char *txt));
+PRIVATE int PassesTest PARAMS((struct MailcapEntry *mc));
+
+#define LINE_BUF_SIZE 2048
+#define TMPFILE_NAME_SIZE 256
+
+PRIVATE char *GetCommand ARGS2(
+ char *, s,
+ char **, t)
+{
+ char *s2;
+ int quoted = 0;
+
+ /* marca -- added + 1 for error case -- oct 24, 1993. */
+ s2 = malloc(strlen(s)*2 + 1); /* absolute max, if all % signs */
+ if (!s2)
+ ExitWithError("Out of memory");
+
+ *t = s2;
+ while (s && *s) {
+ if (quoted) {
+ if (*s == '%') *s2++ = '%'; /* Quote through next level, ugh! */
+
+ *s2++ = *s++;
+ quoted = 0;
+ } else {
+ if (*s == ';') {
+ *s2 = '\0';
+ return(++s);
+ }
+ if (*s == '\\') {
+ quoted = 1;
+ ++s;
+ } else {
+ *s2++ = *s++;
+ }
+ }
+ }
+ *s2 = '\0';
+ return(NULL);
+}
+
+/* no leading or trailing space, all lower case */
+PRIVATE char *Cleanse ARGS1(
+ char *, s)
+{
+ char *tmp, *news;
+
+ /* strip leading white space */
+ while (*s && isspace((unsigned char) *s))
+ ++s;
+ news = s;
+ /* put in lower case */
+ for (tmp=s; *tmp; ++tmp) {
+ *tmp = TOLOWER ((unsigned char)*tmp);
+ }
+ /* strip trailing white space */
+ while ((tmp > news) && *--tmp && isspace((unsigned char) *tmp))
+ *tmp = '\0';
+ return(news);
+}
+
+PRIVATE int ProcessMailcapEntry ARGS2(
+ FILE *, fp,
+ struct MailcapEntry *, mc)
+{
+ int i, j;
+ size_t rawentryalloc = 2000, len;
+ char *rawentry, *s, *t, *LineBuf;
+
+ LineBuf = (char *)malloc(LINE_BUF_SIZE);
+ if (!LineBuf)
+ ExitWithError("Out of memory");
+ rawentry = (char *)malloc(1 + rawentryalloc);
+ if (!rawentry)
+ ExitWithError("Out of memory");
+ *rawentry = '\0';
+ while (fgets(LineBuf, LINE_BUF_SIZE, fp)) {
+ if (LineBuf[0] == '#')
+ continue;
+ len = strlen(LineBuf);
+ if (len == 0)
+ continue;
+ if (LineBuf[len-1] == '\n')
+ LineBuf[--len] = '\0';
+ if ((len + strlen(rawentry)) > rawentryalloc) {
+ rawentryalloc += 2000;
+ rawentry = realloc(rawentry, rawentryalloc+1);
+ if (!rawentry)
+ ExitWithError("Out of memory");
+ }
+ if (len > 0 && LineBuf[len-1] == '\\') {
+ LineBuf[len-1] = '\0';
+ strcat(rawentry, LineBuf);
+ } else {
+ strcat(rawentry, LineBuf);
+ break;
+ }
+ }
+
+ FREE(LineBuf);
+
+ for (s = rawentry; *s && isspace((unsigned char) *s); ++s)
+ ;
+ if (!*s) {
+ /* totally blank entry -- quietly ignore */
+ FREE(rawentry);
+ return(0);
+ }
+ s = strchr(rawentry, ';');
+ if (s == NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "ProcessMailcapEntry: Ignoring invalid mailcap entry: %s\n",
+ rawentry);
+ }
+ FREE(rawentry);
+ return(0);
+ }
+ *s++ = '\0';
+ if (!strncasecomp(rawentry, "text/html", 9) ||
+ !strncasecomp(rawentry, "text/plain", 10)) {
+ --s;
+ *s = ';';
+ if (TRACE) {
+ fprintf(stderr,
+ "ProcessMailcapEntry: Ignoring mailcap entry: %s\n",
+ rawentry);
+ }
+ FREE(rawentry);
+ return(0);
+ }
+ for (i = 0, j = 0; rawentry[i]; i++) {
+ if (rawentry[i] != ' ') {
+ rawentry[j++] = TOLOWER(rawentry[i]);
+ }
+ }
+ rawentry[j] = '\0';
+ mc->needsterminal = 0;
+ mc->copiousoutput = 0;
+ mc->needtofree = 1;
+ mc->testcommand = NULL;
+ mc->label = NULL;
+ mc->printcommand = NULL;
+ mc->contenttype = (char *)malloc(1 + strlen(rawentry));
+ if (!mc->contenttype)
+ ExitWithError("Out of memory");
+ strcpy(mc->contenttype, rawentry);
+ mc->quality = 1.0;
+ mc->maxbytes = 0;
+ t = GetCommand(s, &mc->command);
+ if (!t) {
+ goto assign_presentation;
+ }
+ s = t;
+ while (s && *s && isspace((unsigned char) *s)) ++s;
+ while (s) {
+ char *arg, *eq, *mallocd_string;
+
+ t = GetCommand(s, &mallocd_string);
+ arg = mallocd_string;
+ eq = strchr(arg, '=');
+ if (eq) {
+ *eq++ = '\0';
+ }
+ if (arg && *arg) {
+ arg = Cleanse(arg);
+ if (!strcmp(arg, "needsterminal")) {
+ mc->needsterminal = 1;
+ } else if (!strcmp(arg, "copiousoutput")) {
+ mc->copiousoutput = 1;
+ } else if (eq && !strcmp(arg, "test")) {
+ mc->testcommand = NULL;
+ StrAllocCopy(mc->testcommand, eq);
+ if (TRACE)
+ fprintf(stderr,
+ "ProcessMailcapEntry: Found testcommand:%s\n",
+ mc->testcommand);
+ } else if (eq && !strcmp(arg, "description")) {
+ mc->label = eq;
+ } else if (eq && !strcmp(arg, "label")) {
+ mc->label = eq; /* bogus old name for description */
+ } else if (eq && !strcmp(arg, "print")) {
+ mc->printcommand = eq;
+ } else if (eq && !strcmp(arg, "textualnewlines")) {
+ /* no support for now. What does this do anyways? */
+ /* ExceptionalNewline(mc->contenttype, atoi(eq)); */
+ } else if (eq && !strcmp(arg, "q")) {
+ mc->quality = atof(eq);
+ if (mc->quality > 0.000 && mc->quality < 0.001)
+ mc->quality = 0.001;
+ } else if (eq && !strcmp(arg, "mxb")) {
+ mc->maxbytes = atol(eq);
+ if (mc->maxbytes < 0)
+ mc->maxbytes = 0;
+ } else if (strcmp(arg, "notes")) { /* IGNORE notes field */
+ if (*arg && TRACE)
+ fprintf(stderr,
+ "ProcessMailcapEntry: Ignoring mailcap flag '%s'.\n",
+ arg);
+ }
+
+ }
+ FREE(mallocd_string);
+ s = t;
+ }
+
+assign_presentation:
+ FREE(rawentry);
+
+ if (PassesTest(mc)) {
+ if (TRACE)
+ fprintf(stderr,
+ "ProcessMailcapEntry Setting up conversion %s : %s\n",
+ mc->contenttype, mc->command);
+ HTSetPresentation(mc->contenttype, mc->command,
+ mc->quality, 3.0, 0.0, mc->maxbytes);
+ }
+ FREE(mc->command);
+ FREE(mc->contenttype);
+
+ return(1);
+}
+
+PRIVATE void BuildCommand ARGS5(
+ char **, pBuf,
+ size_t, Bufsize,
+ char *, controlstring,
+ char *, TmpFileName,
+ size_t, TmpFileLen)
+{
+ char *from, *to;
+ int prefixed = 0;
+
+ for (from = controlstring, to = *pBuf; *from != '\0'; from++) {
+ if (prefixed) {
+ prefixed = 0;
+ switch(*from) {
+ case '%':
+ *to++ = '%';
+ break;
+ case 'n':
+ case 'F':
+ if (TRACE) {
+ fprintf(stderr,
+ "BuildCommand: Bad mailcap \"test\" clause: %s\n",
+ controlstring);
+ }
+ case 's':
+ if (TmpFileLen && TmpFileName) {
+ if ((to - *pBuf) + TmpFileLen + 1 > Bufsize) {
+ *to = '\0';
+ if (TRACE) {
+ fprintf(stderr,
+ "BuildCommand: Too long mailcap \"test\" clause,\n");
+ fprintf(stderr,
+ " ignoring: %s%s...\n",
+ *pBuf, TmpFileName);
+ }
+ **pBuf = '\0';
+ return;
+ }
+ strcpy(to, TmpFileName);
+ to += strlen(TmpFileName);
+ }
+ break;
+ default:
+ if (TRACE) {
+ fprintf(stderr,
+ "BuildCommand: Ignoring unrecognized format code in mailcap file '%%%c'.\n",
+ *from);
+ }
+ break;
+ }
+ } else if (*from == '%') {
+ prefixed = 1;
+ } else {
+ *to++ = *from;
+ }
+ if (to >= *pBuf + Bufsize) {
+ (*pBuf)[Bufsize - 1] = '\0';
+ if (TRACE) {
+ fprintf(stderr,
+ "BuildCommand: Too long mailcap \"test\" clause,\n");
+ fprintf(stderr,
+ " ignoring: %s...\n",
+ *pBuf);
+ }
+ **pBuf = '\0';
+ return;
+ }
+ }
+ *to = '\0';
+}
+
+PRIVATE int PassesTest ARGS1(
+ struct MailcapEntry *, mc)
+{
+ int result;
+ char *cmd, TmpFileName[TMPFILE_NAME_SIZE];
+ char *cp = NULL;
+
+ /*
+ * Make sure we have a command
+ */
+ if (!mc->testcommand)
+ return(1);
+
+ /*
+ * Save overhead of system() calls by faking these. - FM
+ */
+ if (0 == strcasecomp(mc->testcommand, "test -n \"$DISPLAY\"")) {
+ FREE(mc->testcommand);
+ if (TRACE)
+ fprintf(stderr,
+ "PassesTest: Testing for XWINDOWS environment.\n");
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
+ if (TRACE)
+ fprintf(stderr,"PassesTest: Test passed!\n");
+ return(0 == 0);
+ } else {
+ if (TRACE)
+ fprintf(stderr,"PassesTest: Test failed!\n");
+ return(-1 == 0);
+ }
+ }
+ if (0 == strcasecomp(mc->testcommand, "test -z \"$DISPLAY\"")) {
+ FREE(mc->testcommand);
+ if (TRACE)
+ fprintf(stderr,
+ "PassesTest: Testing for NON_XWINDOWS environment.\n");
+ if (!((cp = getenv(DISPLAY)) != NULL && *cp != '\0')) {
+ if (TRACE)
+ fprintf(stderr,"PassesTest: Test passed!\n");
+ return(0 == 0);
+ } else {
+ if (TRACE)
+ fprintf(stderr,"PassesTest: Test failed!\n");
+ return(-1 == 0);
+ }
+ }
+
+ /*
+ * Why do anything but return success for this one! - FM
+ */
+ if (0 == strcasecomp(mc->testcommand, "test -n \"$LYNX_VERSION\"")){
+ FREE(mc->testcommand);
+ if (TRACE) {
+ fprintf(stderr,
+ "PassesTest: Testing for LYNX environment.\n");
+ fprintf(stderr,"PassesTest: Test passed!\n");
+ }
+ return(0 == 0);
+ } else
+ /*
+ * ... or failure for this one! - FM
+ */
+ if (0 == strcasecomp(mc->testcommand, "test -z \"$LYNX_VERSION\"")) {
+ FREE(mc->testcommand);
+ if (TRACE) {
+ fprintf(stderr,
+ "PassesTest: Testing for non-LYNX environment.\n");
+ fprintf(stderr,"PassesTest: Test failed!\n");
+ }
+ return(-1 == 0);
+ }
+
+ /*
+ * Build the command and execute it.
+ */
+ tempname(TmpFileName, NEW_FILE);
+ cmd = (char *)malloc(1024);
+ if (!cmd)
+ ExitWithError("Out of memory");
+ BuildCommand(&cmd, 1024,
+ mc->testcommand,
+ TmpFileName,
+ strlen(TmpFileName));
+ if (TRACE)
+ fprintf(stderr,"PassesTest: Executing test command: %s\n", cmd);
+ result = system(cmd);
+ FREE(cmd);
+
+ /*
+ * Free the test command as well since
+ * we wont be needing it anymore.
+ */
+ FREE(mc->testcommand);
+
+ if (TRACE && result)
+ fprintf(stderr,"PassesTest: Test failed!\n");
+ else if (TRACE)
+ fprintf(stderr,"PassesTest: Test passed!\n");
+
+ return(result == 0);
+}
+
+PRIVATE int ProcessMailcapFile ARGS1(
+ char *, file)
+{
+ struct MailcapEntry mc;
+ FILE *fp;
+
+ if (TRACE)
+ fprintf(stderr,
+ "ProcessMailcapFile: Loading file '%s'.\n",
+ file);
+ if ((fp = fopen(file, "r")) == NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "ProcessMailcapFile: Could not open '%s'.\n",
+ file);
+ return(-1 == 0);
+ }
+
+ while (fp && !feof(fp)) {
+ ProcessMailcapEntry(fp, &mc);
+ }
+ fclose(fp);
+ return(0 == 0);
+}
+
+PRIVATE int ExitWithError ARGS1(
+ char *, txt)
+{
+ if (txt)
+ fprintf(stderr, "metamail: %s\n", txt);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ return(-1);
+}
+
+
+PRIVATE int HTLoadTypesConfigFile ARGS1(
+ char *, fn)
+{
+ return ProcessMailcapFile(fn);
+}
+
+
+
+
+/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------------------ */
+/* ------------------------------------------------------------------------ */
+
+/* Define a basic set of suffixes
+** ------------------------------
+**
+** The LAST suffix for a type is that used for temporary files
+** of that type.
+** The quality is an apriori bias as to whether the file should be
+** used. Not that different suffixes can be used to represent files
+** which are of the same format but are originals or regenerated,
+** with different values.
+*/
+
+PUBLIC void HTFileInit NOARGS
+{
+ FILE *fp;
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTFileInit: Loading default (HTInit) extension maps.\n");
+
+ /* default suffix interpretation */
+ HTSetSuffix("*", "text/plain", "7bit", 1.0);
+ HTSetSuffix("*.*", "text/plain", "7bit", 1.0);
+
+#ifdef EXEC_SCRIPTS
+ /*
+ * define these extentions for exec scripts.
+ */
+#ifndef VMS
+ /* for csh exec links */
+ HTSetSuffix(".csh", "application/x-csh", "8bit", 0.8);
+ HTSetSuffix(".sh", "application/x-sh", "8bit", 0.8);
+ HTSetSuffix(".ksh", "application/x-ksh", "8bit", 0.8);
+#else
+ HTSetSuffix(".com", "application/x-VMS_script", "8bit", 0.8);
+#endif /* !VMS */
+#endif /* EXEC_SCRIPTS */
+
+
+ HTSetSuffix(".saveme", "application/x-Binary", "binary", 1.0);
+ HTSetSuffix(".dump", "application/x-Binary", "binary", 1.0);
+ HTSetSuffix(".bin", "application/x-Binary", "binary", 1.0);
+
+ HTSetSuffix(".arc", "application/x-Compressed", "binary", 1.0);
+
+ HTSetSuffix(".alpha-exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".alpha_exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".AXP-exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".AXP_exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".VAX-exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".VAX_exe", "application/x-Executable", "binary", 1.0);
+ HTSetSuffix(".exe", "application/x-Executable", "binary", 1.0);
+
+ HTSetSuffix(".exe.Z", "application/x-Comp. Executable",
+ "binary", 1.0);
+
+ HTSetSuffix(".Z", "application/UNIX Compressed", "binary", 1.0);
+
+ HTSetSuffix(".tar_Z", "application/UNIX Compr. Tar", "binary", 1.0);
+ HTSetSuffix(".tar.Z", "application/UNIX Compr. Tar", "binary", 1.0);
+
+ HTSetSuffix("-gz", "application/GNU Compressed", "binary", 1.0);
+ HTSetSuffix("_gz", "application/GNU Compressed", "binary", 1.0);
+ HTSetSuffix(".gz", "application/GNU Compressed", "binary", 1.0);
+
+ HTSetSuffix5(".tar.gz", "application/x-tar", "binary", "GNU Compr. Tar", 1.0);
+ HTSetSuffix5(".tgz", "application/x-tar", "gzip", "GNU Compr. Tar", 1.0);
+
+ HTSetSuffix(".src", "application/x-WAIS-source", "8bit", 1.0);
+ HTSetSuffix(".wsrc", "application/x-WAIS-source", "8bit", 1.0);
+
+ HTSetSuffix(".zip", "application/x-Zip File", "binary", 1.0);
+
+ HTSetSuffix(".uu", "application/x-UUencoded", "8bit", 1.0);
+
+ HTSetSuffix(".hqx", "application/x-Binhex", "8bit", 1.0);
+
+ HTSetSuffix(".o", "application/x-Prog. Object", "binary", 1.0);
+ HTSetSuffix(".a", "application/x-Prog. Library", "binary", 1.0);
+
+ HTSetSuffix5(".oda", "application/oda", "binary", "ODA", 1.0);
+
+ HTSetSuffix5(".pdf", "application/pdf", "binary", "PDF", 1.0);
+
+ HTSetSuffix(".eps", "application/Postscript", "8bit", 1.0);
+ HTSetSuffix(".ai", "application/Postscript", "8bit", 1.0);
+ HTSetSuffix(".ps", "application/Postscript", "8bit", 1.0);
+
+ HTSetSuffix(".rtf", "application/RTF", "8bit", 1.0);
+
+ HTSetSuffix(".dvi", "application/x-DVI", "8bit", 1.0);
+
+ HTSetSuffix(".hdf", "application/x-HDF", "8bit", 1.0);
+
+ HTSetSuffix(".cdf", "application/x-netcdf", "8bit", 1.0);
+ HTSetSuffix(".nc", "application/x-netcdf", "8bit", 1.0);
+
+ HTSetSuffix(".latex", "application/x-Latex", "8bit", 1.0);
+ HTSetSuffix(".tex", "application/x-Tex", "8bit", 1.0);
+ HTSetSuffix(".texinfo", "application/x-Texinfo", "8bit", 1.0);
+ HTSetSuffix(".texi", "application/x-Texinfo", "8bit", 1.0);
+
+ HTSetSuffix(".t", "application/x-Troff", "8bit", 1.0);
+ HTSetSuffix(".tr", "application/x-Troff", "8bit", 1.0);
+ HTSetSuffix(".roff", "application/x-Troff", "8bit", 1.0);
+
+ HTSetSuffix(".man", "application/x-Troff-man", "8bit", 1.0);
+ HTSetSuffix(".me", "application/x-Troff-me", "8bit", 1.0);
+ HTSetSuffix(".ms", "application/x-Troff-ms", "8bit", 1.0);
+
+ HTSetSuffix(".zoo", "application/x-Zoo File", "binary", 1.0);
+
+ HTSetSuffix(".bak", "application/x-VMS BAK File", "binary", 1.0);
+ HTSetSuffix(".bkp", "application/x-VMS BAK File", "binary", 1.0);
+ HTSetSuffix(".bck", "application/x-VMS BAK File", "binary", 1.0);
+
+ HTSetSuffix(".bkp_gz", "application/x-GNU BAK File", "binary", 1.0);
+ HTSetSuffix(".bkp-gz", "application/x-GNU BAK File", "binary", 1.0);
+ HTSetSuffix(".bck_gz", "application/x-GNU BAK File", "binary", 1.0);
+ HTSetSuffix(".bck-gz", "application/x-GNU BAK File", "binary", 1.0);
+
+ HTSetSuffix(".bkp-Z", "application/x-Comp. BAK File", "binary", 1.0);
+ HTSetSuffix(".bkp_Z", "application/x-Comp. BAK File", "binary", 1.0);
+ HTSetSuffix(".bck-Z", "application/x-Comp. BAK File", "binary", 1.0);
+ HTSetSuffix(".bck_Z", "application/x-Comp. BAK File", "binary", 1.0);
+
+ HTSetSuffix(".hlb", "application/x-VMS Help Libr.", "binary", 1.0);
+ HTSetSuffix(".olb", "application/x-VMS Obj. Libr.", "binary", 1.0);
+ HTSetSuffix(".tlb", "application/x-VMS Text Libr.", "binary", 1.0);
+ HTSetSuffix(".obj", "application/x-VMS Prog. Obj.", "binary", 1.0);
+ HTSetSuffix(".decw$book", "application/x-DEC BookReader", "binary", 1.0);
+ HTSetSuffix(".mem", "application/x-RUNOFF-MANUAL", "8bit", 1.0);
+
+ HTSetSuffix(".vsd", "application/visio", "binary", 1.0);
+
+ HTSetSuffix(".lha", "application/x-lha File", "binary", 1.0);
+ HTSetSuffix(".lzh", "application/x-lzh File", "binary", 1.0);
+
+ HTSetSuffix(".sea", "application/x-sea File", "binary", 1.0);
+ HTSetSuffix(".sit", "application/x-sit File", "binary", 1.0);
+
+ HTSetSuffix(".dms", "application/x-dms File", "binary", 1.0);
+
+ HTSetSuffix(".iff", "application/x-iff File", "binary", 1.0);
+
+ HTSetSuffix(".bcpio", "application/x-bcpio", "binary", 1.0);
+ HTSetSuffix(".cpio", "application/x-cpio", "binary", 1.0);
+
+ HTSetSuffix(".gtar", "application/x-gtar", "binary", 1.0);
+
+ HTSetSuffix(".shar", "application/x-shar", "8bit", 1.0);
+ HTSetSuffix(".share", "application/x-share", "8bit", 1.0);
+
+ HTSetSuffix(".sh", "application/x-sh", "8bit", 1.0); /* xtra */
+
+ HTSetSuffix(".sv4cpio", "application/x-sv4cpio", "binary", 1.0);
+ HTSetSuffix(".sv4crc", "application/x-sv4crc", "binary", 1.0);
+
+ HTSetSuffix5(".tar", "application/x-tar", "binary", "Tar File", 1.0);
+ HTSetSuffix(".ustar", "application/x-ustar", "binary", 1.0);
+
+ HTSetSuffix(".snd", "audio/basic", "binary", 1.0);
+ HTSetSuffix(".au", "audio/basic", "binary", 1.0);
+
+ HTSetSuffix(".aifc", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".aif", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".aiff", "audio/x-aiff", "binary", 1.0);
+ HTSetSuffix(".wav", "audio/x-wav", "binary", 1.0);
+ HTSetSuffix(".midi", "audio/midi", "binary", 1.0);
+ HTSetSuffix(".mod", "audio/mod", "binary", 1.0);
+
+ HTSetSuffix(".gif", "image/gif", "binary", 1.0);
+ HTSetSuffix(".ief", "image/ief", "binary", 1.0);
+ HTSetSuffix(".jfif", "image/jpeg", "binary", 1.0); /* xtra */
+ HTSetSuffix(".jfif-tbnl", "image/jpeg", "binary", 1.0); /* xtra */
+ HTSetSuffix(".jpe", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".jpg", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".jpeg", "image/jpeg", "binary", 1.0);
+ HTSetSuffix(".tif", "image/tiff", "binary", 1.0);
+ HTSetSuffix(".tiff", "image/tiff", "binary", 1.0);
+ HTSetSuffix(".ham", "image/ham", "binary", 1.0);
+ HTSetSuffix(".ras", "image/x-cmu-rast", "binary", 1.0);
+ HTSetSuffix(".pnm", "image/x-portable-anymap", "binary", 1.0);
+ HTSetSuffix(".pbm", "image/x-portable-bitmap", "binary", 1.0);
+ HTSetSuffix(".pgm", "image/x-portable-graymap", "binary", 1.0);
+ HTSetSuffix(".ppm", "image/x-portable-pixmap", "binary", 1.0);
+ HTSetSuffix(".png", "image/png", "binary", 1.0);
+ HTSetSuffix(".rgb", "image/x-rgb", "binary", 1.0);
+ HTSetSuffix(".xbm", "image/x-xbitmap", "binary", 1.0);
+ HTSetSuffix(".xpm", "image/x-xpixmap", "binary", 1.0);
+ HTSetSuffix(".xwd", "image/x-xwindowdump", "binary", 1.0);
+
+ HTSetSuffix(".rtx", "text/richtext", "8bit", 1.0);
+ HTSetSuffix(".tsv", "text/tab-separated-values", "8bit", 1.0);
+ HTSetSuffix(".etx", "text/x-setext", "8bit", 1.0);
+
+ HTSetSuffix(".mpg", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".mpe", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".mpeg", "video/mpeg", "binary", 1.0);
+ HTSetSuffix(".mov", "video/quicktime", "binary", 1.0);
+ HTSetSuffix(".qt", "video/quicktime", "binary", 1.0);
+ HTSetSuffix(".avi", "video/x-msvideo", "binary", 1.0);
+ HTSetSuffix(".movie", "video/x-sgi-movie", "binary", 1.0);
+ HTSetSuffix(".mv", "video/x-sgi-movie", "binary", 1.0);
+
+ HTSetSuffix(".mime", "message/rfc822", "8bit", 1.0);
+
+ HTSetSuffix(".c", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".cc", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".c++", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".h", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".pl", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".text", "text/plain", "8bit", 1.0);
+ HTSetSuffix(".txt", "text/plain", "8bit", 1.0);
+
+ HTSetSuffix(".html3", "text/html", "8bit", 1.0);
+ HTSetSuffix(".ht3", "text/html", "8bit", 1.0);
+ HTSetSuffix(".phtml", "text/html", "8bit", 1.0);
+ HTSetSuffix(".shtml", "text/html", "8bit", 1.0);
+ HTSetSuffix(".htmlx", "text/html", "8bit", 1.0);
+ HTSetSuffix(".htm", "text/html", "8bit", 1.0);
+ HTSetSuffix(".html", "text/html", "8bit", 1.0);
+
+ /* These should override the default extensions as necessary. */
+ HTLoadExtensionsConfigFile(global_extension_map);
+
+ if ((fp = fopen(personal_extension_map,"r")) != NULL) {
+ fclose(fp);
+ /* These should override everything else. */
+ HTLoadExtensionsConfigFile(personal_extension_map);
+ } else {
+ char buffer[256];
+#ifdef VMS
+ sprintf(buffer, "sys$login:%s", personal_extension_map);
+#else
+ sprintf(buffer, "%s/%s", (Home_Dir() ? Home_Dir() : ""),
+ personal_extension_map);
+#endif /* VMS */
+ /* These should override everything else. */
+ HTLoadExtensionsConfigFile(buffer);
+ }
+}
+
+
+/* -------------------- Extension config file reading --------------------- */
+
+/*
+ * The following is lifted from NCSA httpd 1.0a1, by Rob McCool;
+ * NCSA httpd is in the public domain, as is this code.
+ *
+ * Modified Oct 97 - KW
+ */
+
+#define MAX_STRING_LEN 256
+
+PRIVATE int HTGetLine ARGS3(
+ char *, s,
+ int, n,
+ FILE *, f)
+{
+ register int i = 0, r;
+
+ if (!f)
+ return(1);
+
+ while (1) {
+ r = fgetc(f);
+ s[i] = (char)r;
+
+ if (s[i] == CR) {
+ r = fgetc(f);
+ if (r == LF)
+ s[i] = r;
+ else if (r != EOF)
+ ungetc(r, f);
+ }
+
+ if ((r == EOF) || (s[i] == LF) || (s[i] == CR) || (i == (n-1))) {
+ s[i] = '\0';
+ return (feof(f) ? 1 : 0);
+ }
+ ++i;
+ }
+}
+
+PRIVATE void HTGetWord ARGS4(
+ char *, word,
+ char *, line,
+ char , stop,
+ char , stop2)
+{
+ int x = 0, y;
+
+ for (x = 0; line[x] && line[x] != stop && line[x] != stop2; x++) {
+ word[x] = line[x];
+ }
+
+ word[x] = '\0';
+ if (line[x])
+ ++x;
+ y=0;
+
+ while ((line[y++] = line[x++]))
+ ;
+
+ return;
+}
+
+PRIVATE int HTLoadExtensionsConfigFile ARGS1(
+ char *, fn)
+{
+ char l[MAX_STRING_LEN],w[MAX_STRING_LEN],*ct;
+ FILE *f;
+ int x, count = 0;
+
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadExtensionsConfigFile: Loading file '%s'.\n", fn);
+
+ if ((f = fopen(fn,"r")) == NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTLoadExtensionsConfigFile: Could not open '%s'.\n", fn);
+ return count;
+ }
+
+ while (!(HTGetLine(l,MAX_STRING_LEN,f))) {
+ HTGetWord(w, l, ' ', '\t');
+ if (l[0] == '\0' || w[0] == '#')
+ continue;
+ ct = (char *)malloc(sizeof(char) * (strlen(w) + 1));
+ if (!ct)
+ outofmem(__FILE__, "HTLoadExtensionsConfigFile");
+ strcpy(ct,w);
+ for (x = 0; ct[x]; x++)
+ ct[x] = TOLOWER(ct[x]);
+
+ while(l[0]) {
+ HTGetWord(w, l, ' ', '\t');
+ if (w[0] && (w[0] != ' ')) {
+ char *ext = (char *)malloc(sizeof(char) * (strlen(w)+1+1));
+ if (!ct)
+ outofmem(__FILE__, "HTLoadExtensionsConfigFile");
+
+ for (x = 0; w[x]; x++)
+ ext[x+1] = TOLOWER(w[x]);
+ ext[0] = '.';
+ ext[strlen(w)+1] = '\0';
+
+ if (TRACE) {
+ fprintf (stderr,
+ "SETTING SUFFIX '%s' to '%s'.\n", ext, ct);
+ }
+
+ if (strstr(ct, "tex") != NULL ||
+ strstr(ct, "postscript") != NULL ||
+ strstr(ct, "sh") != NULL ||
+ strstr(ct, "troff") != NULL ||
+ strstr(ct, "rtf") != NULL)
+ HTSetSuffix (ext, ct, "8bit", 1.0);
+ else
+ HTSetSuffix (ext, ct, "binary", 1.0);
+ count++;
+
+ FREE(ext);
+ }
+ }
+ FREE(ct);
+ }
+ fclose(f);
+
+ return count;
+}
diff --git a/gnu/usr.bin/lynx/src/HTML.c b/gnu/usr.bin/lynx/src/HTML.c
new file mode 100644
index 00000000000..14a11eff81f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTML.c
@@ -0,0 +1,7491 @@
+/* Structured stream to Rich hypertext converter
+** ============================================
+**
+** This generates a hypertext object. It converts from the
+** structured stream interface of HTML events into the style-
+** oriented interface of the HText.h interface. This module is
+** only used in clients and should not be linked into servers.
+**
+** Override this module if making a new GUI browser.
+**
+** Being Overidden
+**
+*/
+#include "HTUtils.h"
+#include "tcp.h"
+
+#define Lynx_HTML_Handler
+#include "HTChunk.h"
+#include "HText.h"
+#include "HTStyle.h"
+#include "HTML.h"
+
+#include "HTCJK.h"
+#include "HTAtom.h"
+#include "HTAnchor.h"
+#include "HTMLGen.h"
+#include "HTParse.h"
+#include "HTList.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include "LYGlobalDefs.h"
+#include "LYCharUtils.h"
+#include "LYCharSets.h"
+
+#include "HTAlert.h"
+#include "HTFont.h"
+#include "HTForms.h"
+#include "HTNestedList.h"
+#include "GridText.h"
+#include "LYSignal.h"
+#include "LYUtils.h"
+#include "LYMap.h"
+#include "LYList.h"
+#include "LYBookmark.h"
+
+#ifdef VMS
+#include "LYCurses.h"
+#include "HTVMSUtils.h"
+#endif /* VMS */
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+#include "LYHash.h"
+#include "LYStyle.h"
+#undef SELECTED_STYLES
+#define pHText_changeStyle(X,Y,Z) {}
+char Style_className[16384];
+#endif
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern BOOL HTPassEightBitRaw;
+extern HTCJKlang HTCJK;
+
+extern BOOLEAN HT_Is_Gopher_URL;
+
+/* from Curses.h */
+extern int LYcols;
+
+struct _HTStream {
+ CONST HTStreamClass * isa;
+ /* .... */
+};
+
+PRIVATE HTStyleSheet * styleSheet; /* Application-wide */
+
+/* Module-wide style cache
+*/
+PUBLIC HTStyle *styles[HTML_ELEMENTS+31]; /* adding 24 nested list styles */
+ /* and 3 header alignment styles */
+ /* and 3 div alignment styles */
+PRIVATE HTStyle *default_style;
+
+PUBLIC char *LYToolbarName = "LynxPseudoToolbar";
+
+/* used to turn off a style if the HTML author forgot to
+PRIVATE int i_prior_style = -1;
+ */
+
+/*
+ * Private function....
+ */
+PRIVATE void HTML_end_element PARAMS((HTStructured *me,
+ int element_number,
+ char **include));
+
+/* Forward declarations of routines
+*/
+PRIVATE void get_styles NOPARAMS;
+PRIVATE void change_paragraph_style PARAMS((HTStructured * me,
+ HTStyle * style));
+
+/* Set an internal flag that the next call to a stack-affecting method
+** is only internal and the stack manipulation should be skipped. - kw
+*/
+#define SET_SKIP_STACK(el_num) if (HTML_dtd.tags[el_num].contents != SGML_EMPTY) \
+ { me->skip_stack++; }
+
+extern int hash_code PARAMS((char* i));
+
+PUBLIC void strtolower ARGS1(char*, i)
+{
+ if (!i) return;
+ while (*i) { *i=tolower(*i); i++; }
+}
+
+/* Flattening the style structure
+** ------------------------------
+**
+On the NeXT, and on any read-only browser, it is simpler for the text to have
+a sequence of styles, rather than a nested tree of styles. In this
+case we have to flatten the structure as it arrives from SGML tags into
+a sequence of styles.
+*/
+
+/*
+** If style really needs to be set, call this.
+*/
+PUBLIC void actually_set_style ARGS1(HTStructured *, me)
+{
+ if (!me->text) { /* First time through */
+ LYGetChartransInfo(me);
+ UCSetTransParams(&me->T,
+ me->UCLYhndl, me->UCI,
+ HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_HTEXT),
+ HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_HTEXT));
+ me->text = HText_new2(me->node_anchor, me->target);
+ HText_beginAppend(me->text);
+ HText_setStyle(me->text, me->new_style);
+ me->in_word = NO;
+ LYCheckForContentBase(me);
+ } else {
+ HText_setStyle(me->text, me->new_style);
+ }
+
+ me->old_style = me->new_style;
+ me->style_change = NO;
+}
+
+/*
+** If you THINK you need to change style, call this.
+*/
+PRIVATE void change_paragraph_style ARGS2(HTStructured *, me, HTStyle *,style)
+{
+ if (me->new_style != style) {
+ me->style_change = YES;
+ me->new_style = style;
+ }
+ me->in_word = NO;
+}
+
+/*_________________________________________________________________________
+**
+** A C T I O N R O U T I N E S
+*/
+
+/* Character handling
+** ------------------
+*/
+PUBLIC void HTML_put_character ARGS2(HTStructured *, me, char, c)
+{
+ /*
+ * Ignore all non-MAP content when just
+ * scanning a document for MAPs. - FM
+ */
+ if (LYMapsOnly)
+ return;
+
+ /*
+ * Do EOL conversion if needed. - FM
+ *
+ * Convert EOL styles:
+ * macintosh: cr --> lf
+ * ascii: cr-lf --> lf
+ * unix: lf --> lf
+ */
+ if ((me->lastraw == '\r') && c == '\n') {
+ me->lastraw = -1;
+ return;
+ }
+ me->lastraw = c;
+ if (c == '\r')
+ c = '\n';
+
+ /*
+ * Handle SGML_LITTERAL tags that have HTChunk elements. - FM
+ */
+ switch (me->sp[0].tag_number) {
+
+ case HTML_COMMENT:
+ return; /* Do Nothing */
+
+ case HTML_TITLE:
+ if (c == LY_SOFT_HYPHEN)
+ return;
+ if (c != '\n' && c != '\t' && c != '\r')
+ HTChunkPutc(&me->title, c);
+ else
+ HTChunkPutc(&me->title, ' ');
+ return;
+
+ case HTML_STYLE:
+ HTChunkPutc(&me->style_block, c);
+ return;
+
+ case HTML_SCRIPT:
+ HTChunkPutc(&me->script, c);
+ return;
+
+ case HTML_OBJECT:
+ HTChunkPutc(&me->object, c);
+ return;
+
+ case HTML_TEXTAREA:
+ HTChunkPutc(&me->textarea, c);
+ return;
+
+ case HTML_SELECT:
+ case HTML_OPTION:
+ HTChunkPutc(&me->option, c);
+ return;
+
+ case HTML_MATH:
+ HTChunkPutc(&me->math, c);
+ return;
+
+ default:
+ if (me->inSELECT) {
+ /*
+ * If we are within a SELECT not caught by the cases
+ * above - HTML_SELECT or HTML_OPTION may not be the
+ * last element pushed on the style stack if there were
+ * invalid markup tags within a SELECT element. For error
+ * recovery, treat text as part of the OPTION text, it is
+ * probably meant to show up as user-visible text.
+ * Having A as an open element while in SELECT is really sick,
+ * don't make anchor text part of the option text in that case
+ * since the option text will probably just be discarded. - kw
+ */
+ if (me->sp[0].tag_number == HTML_A)
+ break;
+ HTChunkPutc(&me->option, c);
+ return;
+ }
+ break;
+ } /* end first switch */
+
+ /*
+ * Handle all other tag content. - FM
+ */
+ switch (me->sp[0].tag_number) {
+
+ case HTML_PRE: /* Formatted text */
+ /*
+ * We guarantee that the style is up-to-date in begin_litteral
+ * But we still want to strip \r's
+ */
+ if (c != '\r' &&
+ !(c == '\n' && me->inLABEL && !me->inP) &&
+ !(c == '\n' && !me->inPRE)) {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, c);
+ }
+ me->inPRE = TRUE;
+ break;
+
+ case HTML_LISTING: /* Literal text */
+ case HTML_XMP:
+ case HTML_PLAINTEXT:
+ /*
+ * We guarantee that the style is up-to-date in begin_litteral
+ * But we still want to strip \r's
+ */
+ if (c != '\r') {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, c);
+ }
+ break;
+
+ default:
+ /*
+ * Free format text.
+ */
+ if (!strcmp(me->sp->style->name,"Preformatted")) {
+ if (c != '\r' &&
+ !(c == '\n' && me->inLABEL && !me->inP) &&
+ !(c == '\n' && !me->inPRE)) {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, c);
+ }
+ me->inPRE = TRUE;
+
+ } else if (!strcmp(me->sp->style->name,"Listing") ||
+ !strcmp(me->sp->style->name,"Example")) {
+ if (c != '\r') {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, c);
+ }
+
+ } else {
+ if (me->style_change) {
+ if ((c == '\n') || (c == ' '))
+ return; /* Ignore it */
+ UPDATE_STYLE;
+ }
+ if (c == '\n') {
+ if (me->in_word) {
+ if (HText_getLastChar(me->text) != ' ') {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, ' ');
+ }
+ me->in_word = NO;
+ }
+
+ } else if (c == ' ' || c == '\t') {
+ if (HText_getLastChar(me->text) != ' ') {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, ' ');
+ }
+
+ } else if (c == '\r') {
+ /* ignore */
+
+ } else {
+ me->inP = TRUE;
+ me->inLABEL = FALSE;
+ HText_appendCharacter(me->text, c);
+ me->in_word = YES;
+ }
+ }
+ } /* end second switch */
+
+ if (c == '\n' || c == '\t') {
+ HText_setLastChar(me->text, ' '); /* set it to a generic seperater */
+
+ /*
+ * \r's are ignored. In order to keep collapsing spaces
+ * correctly we must default back to the previous
+ * seperater if there was one
+ */
+ } else if (c == '\r' && HText_getLastChar(me->text) == ' ') {
+ HText_setLastChar(me->text, ' '); /* set it to a generic seperater */
+ } else {
+ HText_setLastChar(me->text, c);
+ }
+}
+
+/* String handling
+** ---------------
+**
+** This is written separately from put_character because the loop can
+** in some cases be promoted to a higher function call level for speed.
+*/
+PUBLIC void HTML_put_string ARGS2(HTStructured *, me, CONST char *, s)
+{
+ if (LYMapsOnly || s == NULL)
+ return;
+
+ switch (me->sp[0].tag_number) {
+
+ case HTML_COMMENT:
+ break; /* Do Nothing */
+
+ case HTML_TITLE:
+ HTChunkPuts(&me->title, s);
+ break;
+
+ case HTML_STYLE:
+ HTChunkPuts(&me->style_block, s);
+ break;
+
+ case HTML_SCRIPT:
+ HTChunkPuts(&me->script, s);
+ break;
+
+ case HTML_PRE: /* Formatted text */
+ case HTML_LISTING: /* Literal text */
+ case HTML_XMP:
+ case HTML_PLAINTEXT:
+ /*
+ * We guarantee that the style is up-to-date in begin_litteral
+ */
+ HText_appendText(me->text, s);
+ break;
+
+ case HTML_OBJECT:
+ HTChunkPuts(&me->object, s);
+ break;
+
+ case HTML_TEXTAREA:
+ HTChunkPuts(&me->textarea, s);
+ break;
+
+ case HTML_SELECT:
+ case HTML_OPTION:
+ HTChunkPuts(&me->option, s);
+ break;
+
+ case HTML_MATH:
+ HTChunkPuts(&me->math, s);
+ break;
+
+ default: /* Free format text? */
+ if (!me->sp->style->freeFormat) {
+ /*
+ * If we are within a preformatted text style not caught
+ * by the cases above (HTML_PRE or similar may not be the
+ * last element pushed on the style stack). - kw
+ */
+ HText_appendText(me->text, s);
+ break;
+ } else {
+ CONST char *p = s;
+ char c;
+ if (me->style_change) {
+ for (; *p && ((*p == '\n') || (*p == '\r') ||
+ (*p == ' ') || (*p == '\t')); p++)
+ ; /* Ignore leaders */
+ if (!*p)
+ return;
+ UPDATE_STYLE;
+ }
+ for (; *p; p++) {
+ if (*p == 13 && p[1] != 10) {
+ /*
+ * Treat any '\r' which is not followed by '\n'
+ * as '\n', to account for macintosh lineend in
+ * ALT attributes etc. - kw
+ */
+ c = '\n';
+ } else {
+ c = *p;
+ }
+ if (me->style_change) {
+ if ((c == '\n') || (c == ' ') || (c == '\t'))
+ continue; /* Ignore it */
+ UPDATE_STYLE;
+ }
+ if (c == '\n') {
+ if (me->in_word) {
+ if (HText_getLastChar(me->text) != ' ')
+ HText_appendCharacter(me->text, ' ');
+ me->in_word = NO;
+ }
+
+ } else if (c == ' ' || c == '\t') {
+ if (HText_getLastChar(me->text) != ' ')
+ HText_appendCharacter(me->text, ' ');
+
+ } else if (c == '\r') {
+ /* ignore */
+ } else {
+ HText_appendCharacter(me->text, c);
+ me->in_word = YES;
+ }
+
+ /* set the Last Character */
+ if (c == '\n' || c == '\t') {
+ /* set it to a generic seperater */
+ HText_setLastChar(me->text, ' ');
+ } else if (c == '\r' &&
+ HText_getLastChar(me->text) == ' ') {
+ /*
+ * \r's are ignored. In order to keep collapsing
+ * spaces correctly, we must default back to the
+ * previous seperator, if there was one. So we
+ * set LastChar to a generic seperater.
+ */
+ HText_setLastChar(me->text, ' ');
+ } else {
+ HText_setLastChar(me->text, c);
+ }
+
+ } /* for */
+ }
+ } /* end switch */
+}
+
+/* Buffer write
+** ------------
+*/
+PUBLIC void HTML_write ARGS3(HTStructured *, me, CONST char*, s, int, l)
+{
+ CONST char* p;
+ CONST char* e = s+l;
+
+ if (LYMapsOnly)
+ return;
+
+ for (p = s; s < e; p++)
+ HTML_put_character(me, *p);
+}
+
+/*
+ * "Internal links" are hyperlinks whose source and destination are
+ * within the same document, and for which the destination is given
+ * as a URL Reference with an empty URL, but possibly with a non-empty
+ * #fragment. (This terminology re URL-Reference vs. URL follows the
+ * Fielding URL syntax and semantics drafts).
+ * Differences:
+ * (1) The document's base (in whatever way it is given) is not used for
+ * resolving internal link references.
+ * (2) Activating an internal link should not result in a new retrieval
+ * of a copy of the document.
+ * (3) Internal links are the only way to refer with a hyperlink to a document
+ * (or a location in it) which is only known as the result of a POST
+ * request (doesn't have a URL from which the document can be retrieved
+ * with GET), and can only be used from within that document.
+ *
+ * *If DONT_TRACK_INTERNAL_LINKS is not defined, we keep track of whether a
+ * link destination was given as an internal link. This information is
+ * recorded in the type of the link between anchor objects, and is available
+ * to the HText object and the mainloop from there. URL References to
+ * internal destinations are still resolved into an absolute form before
+ * being passed on, but using the current stream's retrieval address instead
+ * of the base URL.
+ * Examples: (replace [...] to have a valid absolute URL)
+ * In document retrieved from [...]/mypath/mydoc.htm w/ base [...]/otherpath/
+ * a. HREF="[...]/mypath/mydoc.htm" -> [...]/mypath/mydoc.htm
+ * b. HREF="[...]/mypath/mydoc.htm#frag" -> [...]/mypath/mydoc.htm#frag
+ * c. HREF="mydoc.htm" -> [...]/otherpath/mydoc.htm
+ * d. HREF="mydoc.htm#frag" -> [...]/otherpath/mydoc.htm#frag
+ * e. HREF="" -> [...]/mypath/mydoc.htm (marked internal)
+ * f. HREF="#frag" -> [...]/mypath/mydoc.htm#frag (marked internal)
+ *
+ * *If DONT_TRACK_INTERNAL_LINKS is defined, URL-less URL-References are
+ * resolved differently from URL-References with a non-empty URL (using the
+ * current stream's retrieval address instead of the base), but we make no
+ * further distinction. Resolution is then as in the examples above, execept
+ * that there is no "(marked internal)".
+ *
+ * *Note that this doesn't apply to form ACTIONs (always resolved using base,
+ * never marked internal). Also other references encountered or generated
+ * are not marked internal, whether they have a URL or not, if in a given
+ * context an internal link makes no sense (e.g. IMG SRC=).
+ */
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+/* A flag is used to keep track of whether an "URL reference" encountered
+ had a real "URL" or not. In the latter case, it will be marked as
+ "internal". The flag is set before we start messing around with the
+ string (resolution of relative URLs etc.). This variable only used
+ locally here, don't confuse with LYinternal_flag which is for
+ for overriding non-caching similar to LYoverride_no_cache. - kw */
+#define CHECK_FOR_INTERN(s) intern_flag = (s && (*s=='#' || *s=='\0')) ? TRUE : FALSE;
+
+/* Last argument to pass to HTAnchor_findChildAndLink() calls,
+ just an abbreviation. - kw */
+#define INTERN_LT (HTLinkType *)(intern_flag ? LINK_INTERNAL : NULL)
+
+#else /* !DONT_TRACK_INTERNAL_LINKS */
+
+#define CHECK_FOR_INTERN(s) /* do nothing */ ;
+#define INTERN_LT (HTLinkType *)NULL
+
+#endif /* DONT_TRACK_INTERNAL_LINKS */
+
+#ifdef USE_COLOR_STYLE
+char class_string[TEMPSTRINGSIZE];
+char prevailing_class[TEMPSTRINGSIZE];
+#endif
+
+#ifdef USE_COLOR_STYLE
+ char myHash[128];
+ int hcode;
+#endif
+
+/* Start Element
+** -------------
+*/
+PRIVATE void HTML_start_element ARGS6(
+ HTStructured *, me,
+ int, element_number,
+ CONST BOOL*, present,
+ CONST char **, value,
+ int, tag_charset,
+ char **, include)
+{
+ char *alt_string = NULL;
+ char *id_string = NULL;
+ char *href = NULL;
+ char *map_href = NULL;
+ char *title = NULL;
+ char *I_value = NULL;
+ char *I_name = NULL;
+ char *temp = NULL;
+ int dest_char_set = -1;
+ HTParentAnchor *dest = NULL; /* An anchor's destination */
+ BOOL dest_ismap = FALSE; /* Is dest an image map script? */
+ BOOL UseBASE = TRUE; /* Resoved vs. BASE if present? */
+ HTChildAnchor *ID_A = NULL; /* HTML_foo_ID anchor */
+ int url_type = 0, i = 0;
+ char *cp = NULL;
+ int ElementNumber = element_number;
+ BOOL intern_flag = FALSE;
+
+ if (LYMapsOnly) {
+ if (!(ElementNumber == HTML_MAP || ElementNumber == HTML_AREA ||
+ ElementNumber == HTML_BASE)) {
+ return;
+ }
+ } else if (!me->text) {
+ UPDATE_STYLE;
+ }
+
+ if (tag_charset < 0)
+ me->tag_charset = me->UCLYhndl;
+ else
+ me->tag_charset = tag_charset;
+
+/* this should be done differently */
+#if defined(USE_COLOR_STYLE)
+ strcat (Style_className, ";");
+ strcat (Style_className, HTML_dtd.tags[element_number].name);
+ strcpy (myHash, HTML_dtd.tags[element_number].name);
+ if (class_string[0])
+ {
+ strcat (Style_className, ".");
+ strcat (Style_className, class_string);
+ strcat (myHash, ".");
+ strcat (myHash, class_string);
+#ifdef PREVAIL
+ strcpy (prevailing_class, class_string);
+#endif
+ }
+#ifdef PREVAIL
+ else if (prevailing_class[0])
+ {
+ strcat (Style_className, ".");
+ strcat (Style_className, prevailing_class);
+ strcat (myHash, ".");
+ strcat (myHash, prevailing_class);
+ }
+#endif /* PREVAIL */
+ class_string[0]='\0';
+ strtolower(myHash);
+ hcode=hash_code(myHash);
+ strtolower(Style_className);
+
+ if (TRACE)
+ {
+ fprintf(stderr, "CSSTRIM:%s -> %d", myHash, hcode);
+ if (hashStyles[hcode].code!=hcode)
+ {
+ char *rp=strrchr(myHash, '.');
+ fprintf(stderr, " (undefined) %s\n", myHash);
+ if (rp)
+ {
+ int hcd;
+ *rp='\0'; /* trim the class */
+ hcd = hash_code(myHash);
+ fprintf(stderr, "CSS:%s -> %d", myHash, hcd);
+ if (hashStyles[hcd].code!=hcd)
+ fprintf(stderr, " (undefined) %s\n", myHash);
+ else
+ fprintf(stderr, " ca=%d\n", hashStyles[hcd].color);
+ }
+ }
+ else
+ fprintf(stderr, " ca=%d\n", hashStyles[hcode].color);
+ }
+
+ if (displayStyles[element_number + STARTAT].color > -2) /* actually set */
+ {
+ if (TRACE)
+ fprintf(stderr, "CSSTRIM: start_element: top <%s>\n", HTML_dtd.tags[element_number].name);
+ HText_characterStyle(me->text, hcode, 1);
+ }
+#endif /* USE_COLOR_STYLE */
+
+ /*
+ * Handle the start tag. - FM
+ */
+ switch (ElementNumber) {
+
+ case HTML_HTML:
+ break;
+
+ case HTML_HEAD:
+ break;
+
+ case HTML_BASE:
+ if (present && present[HTML_BASE_HREF] && !local_host_only &&
+ value[HTML_BASE_HREF] && *value[HTML_BASE_HREF]) {
+ char *base = NULL;
+ char *related = NULL;
+
+ StrAllocCopy(base, value[HTML_BASE_HREF]);
+ if (!(url_type = LYLegitimizeHREF(me, (char**)&base,
+ TRUE, TRUE))) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: BASE '%s' is not an absolute URL.\n",
+ (base ? base : ""));
+ if (me->inBadBASE == FALSE)
+ HTAlert(BASE_NOT_ABSOLUTE);
+ me->inBadBASE = TRUE;
+ }
+
+ if (url_type == LYNXIMGMAP_URL_TYPE) {
+ /*
+ * These have a are non-standard form, basically
+ * strip the prefix or the code below would insert
+ * a nonsense host into the pseudo URL. These
+ * should never occur where they would used for
+ * resolution of relative URLs anyway. We can
+ * also strip the #map part. - kw
+ */
+ temp = HTParse(base + 11, "",
+ PARSE_ACCESS+PARSE_HOST+PARSE_PATH
+ +PARSE_PUNCTUATION);
+ if (temp) {
+ FREE(base);
+ base = temp;
+ temp = NULL;
+ }
+ }
+
+ /*
+ * Get parent's address for defaulted fields.
+ */
+ StrAllocCopy(related, me->node_anchor->address);
+
+ /*
+ * Create the access field.
+ */
+ if ((temp = HTParse(base, related,
+ PARSE_ACCESS+PARSE_PUNCTUATION)) &&
+ *temp != '\0') {
+ StrAllocCopy(me->base_href, temp);
+ } else {
+ FREE(temp);
+ StrAllocCopy(me->base_href, (temp = HTParse(related, "",
+ PARSE_ACCESS+PARSE_PUNCTUATION)));
+ }
+ FREE(temp);
+
+ /*
+ * Create the host[:port] field.
+ */
+ if ((temp = HTParse(base, "",
+ PARSE_HOST+PARSE_PUNCTUATION)) &&
+ !strncmp(temp, "//", 2)) {
+ StrAllocCat(me->base_href, temp);
+ if (!strcmp(me->base_href, "file://")) {
+ StrAllocCat(me->base_href, "localhost");
+ }
+ } else {
+ if (!strcmp(me->base_href, "file:")) {
+ StrAllocCat(me->base_href, "//localhost");
+ } else if (strcmp(me->base_href, "news:")) {
+ FREE(temp);
+ StrAllocCat(me->base_href, (temp = HTParse(related, "",
+ PARSE_HOST+PARSE_PUNCTUATION)));
+ }
+ }
+ FREE(temp);
+ FREE(related);
+
+ /*
+ * Create the path field.
+ */
+ if ((temp = HTParse(base, "",
+ PARSE_PATH+PARSE_PUNCTUATION)) &&
+ *temp != '\0') {
+ StrAllocCat(me->base_href, temp);
+ } else if (!strcmp(me->base_href, "news:")) {
+ StrAllocCat(me->base_href, "*");
+ } else if (!strncmp(me->base_href, "news:", 5) ||
+ !strncmp(me->base_href, "nntp:", 5) ||
+ !strncmp(me->base_href, "snews:", 6)) {
+ StrAllocCat(me->base_href, "/*");
+ } else {
+ StrAllocCat(me->base_href, "/");
+ }
+ FREE(temp);
+ FREE(base);
+
+ me->inBASE = TRUE;
+ StrAllocCopy(me->node_anchor->content_base, me->base_href);
+ }
+ break;
+
+ case HTML_META:
+ if (present)
+ LYHandleMETA(me, present, value, (char **)&include);
+ break;
+
+ case HTML_TITLE:
+ HTChunkClear(&me->title);
+ break;
+
+ case HTML_LINK:
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ intern_flag = FALSE;
+#endif
+ if (present && present[HTML_LINK_HREF]) {
+ CHECK_FOR_INTERN(value[HTML_LINK_HREF]);
+ /*
+ * Prepare to do housekeeping on the reference. - FM
+ */
+ if (!value[HTML_LINK_HREF]) {
+ if (me->inBASE && me->base_href && *me->base_href) {
+ StrAllocCopy(href, me->base_href);
+ } else {
+ StrAllocCopy(href, me->node_anchor->address);
+ }
+ } else {
+ StrAllocCopy(href, value[HTML_LINK_HREF]);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ }
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '\0' && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '\0' && *href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ /*
+ * Handle links with a REV attribute. - FM
+ */
+ if (present &&
+ present[HTML_LINK_REV] && value[HTML_LINK_REV]) {
+ /*
+ * Handle REV="made" or REV="owner". - LM & FM
+ */
+ if (!strcasecomp("made", value[HTML_LINK_REV]) ||
+ !strcasecomp("owner", value[HTML_LINK_REV])) {
+ /*
+ * Load the owner element. - FM
+ */
+ if (!is_url(href)) {
+ temp = HTParse(href,
+ (me->inBASE ?
+ me->base_href : me->node_anchor->address),
+ PARSE_ALL);
+ StrAllocCopy(href, temp);
+ FREE(temp);
+ LYFillLocalFileURL((char **)&href,
+ (me->inBASE ?
+ me->base_href :
+ me->node_anchor->address));
+ }
+ HTAnchor_setOwner(me->node_anchor, href);
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: DOC OWNER '%s' found\n", href);
+ FREE(href);
+
+ /*
+ * Load the RevTitle element if a TITLE attribute
+ * and value are present. - FM
+ */
+ if (present && present[HTML_LINK_TITLE] &&
+ value[HTML_LINK_TITLE] &&
+ *value[HTML_LINK_TITLE] != '\0') {
+ StrAllocCopy(title, value[HTML_LINK_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ if (*title != '\0')
+ HTAnchor_setRevTitle(me->node_anchor, title);
+ FREE(title);
+ }
+ break;
+ }
+ }
+
+ /*
+ * Handle REL links. - FM
+ */
+ if (present &&
+ present[HTML_LINK_REL] && value[HTML_LINK_REL]) {
+ /*
+ * Ignore style sheets, for now. - FM
+ */
+ if (!strcasecomp(value[HTML_LINK_REL], "StyleSheet") ||
+ !strcasecomp(value[HTML_LINK_REL], "Style")) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML: StyleSheet link found.\n");
+ }
+#ifdef LINKEDSTYLES
+ if (href && *href != '\0')
+ {
+ int res = -999;
+ if ((url_type = is_url(href)) == 0 ||
+ (url_type == FILE_URL_TYPE && LYisLocalFile(href))) {
+ if (url_type == FILE_URL_TYPE) {
+ temp = HTParse(href, "", PARSE_PATH+PARSE_PUNCTUATION);
+ HTUnEscape(temp);
+ if (temp && *temp != '\0') {
+ res = style_readFromFile(temp);
+ if (res != 0)
+ StrAllocCopy(href, temp);
+ }
+ FREE(temp);
+ } else {
+ res = style_readFromFile(href);
+ }
+ }
+ if (TRACE)
+ fprintf(stderr, "CSS: StyleSheet=%s %d\n", href, res);
+ if (res == 0)
+ HTAnchor_setStyle (me->node_anchor, href);
+ }
+ else
+ if (TRACE)
+ fprintf(stderr,
+ " non-local StyleSheets not yet implemented.\n");
+#else
+ if (TRACE)
+ fprintf(stderr,
+ " StyleSheets not yet implemented.\n");
+#endif
+ FREE(href);
+ break;
+ }
+
+ /*
+ * Ignore anything not registered in the the 28-Mar-95
+ * IETF HTML 3.0 draft and W3C HTML 3.2 draft, or not
+ * appropriate for Lynx banner links in the expired
+ * Maloney and Quin relrev draft. We'll make this more
+ * efficient when the situation stabilizes, and for now,
+ * we'll treat "Banner" as another toolbar element. - FM
+ */
+ if (!strcasecomp(value[HTML_LINK_REL], "Home") ||
+ !strcasecomp(value[HTML_LINK_REL], "ToC") ||
+ !strcasecomp(value[HTML_LINK_REL], "Contents") ||
+ !strcasecomp(value[HTML_LINK_REL], "Index") ||
+ !strcasecomp(value[HTML_LINK_REL], "Glossary") ||
+ !strcasecomp(value[HTML_LINK_REL], "Copyright") ||
+ !strcasecomp(value[HTML_LINK_REL], "Up") ||
+ !strcasecomp(value[HTML_LINK_REL], "Next") ||
+ !strcasecomp(value[HTML_LINK_REL], "Previous") ||
+ !strcasecomp(value[HTML_LINK_REL], "Prev") ||
+ !strcasecomp(value[HTML_LINK_REL], "Help") ||
+ !strcasecomp(value[HTML_LINK_REL], "Search") ||
+ !strcasecomp(value[HTML_LINK_REL], "Bookmark") ||
+ !strcasecomp(value[HTML_LINK_REL], "Banner") ||
+ !strcasecomp(value[HTML_LINK_REL], "Top") ||
+ !strcasecomp(value[HTML_LINK_REL], "Origin") ||
+ !strcasecomp(value[HTML_LINK_REL], "Navigator") ||
+ !strcasecomp(value[HTML_LINK_REL], "Child") ||
+ !strcasecomp(value[HTML_LINK_REL], "Disclaimer") ||
+ !strcasecomp(value[HTML_LINK_REL], "Sibling") ||
+ !strcasecomp(value[HTML_LINK_REL], "Parent") ||
+ !strcasecomp(value[HTML_LINK_REL], "Author") ||
+ !strcasecomp(value[HTML_LINK_REL], "Editor") ||
+ !strcasecomp(value[HTML_LINK_REL], "Publisher") ||
+ !strcasecomp(value[HTML_LINK_REL], "Trademark") ||
+ !strcasecomp(value[HTML_LINK_REL], "Meta") ||
+ !strcasecomp(value[HTML_LINK_REL], "URC") ||
+ !strcasecomp(value[HTML_LINK_REL], "Hotlist") ||
+ !strcasecomp(value[HTML_LINK_REL], "Begin") ||
+ !strcasecomp(value[HTML_LINK_REL], "First") ||
+ !strcasecomp(value[HTML_LINK_REL], "End") ||
+ !strcasecomp(value[HTML_LINK_REL], "Last") ||
+ !strcasecomp(value[HTML_LINK_REL], "Pointer") ||
+ !strcasecomp(value[HTML_LINK_REL], "Translation") ||
+ !strcasecomp(value[HTML_LINK_REL], "Definition") ||
+ !strcasecomp(value[HTML_LINK_REL], "Chapter") ||
+ !strcasecomp(value[HTML_LINK_REL], "Documentation") ||
+ !strcasecomp(value[HTML_LINK_REL], "Biblioentry") ||
+ !strcasecomp(value[HTML_LINK_REL], "Bibliography")) {
+ StrAllocCopy(title, value[HTML_LINK_REL]);
+ } else {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML: LINK with REL=\"%s\" ignored.\n",
+ value[HTML_LINK_REL]);
+ }
+ FREE(href);
+ break;
+ }
+ }
+ } else if (present &&
+ present[HTML_LINK_REL] && value[HTML_LINK_REL]) {
+ /*
+ * If no HREF was specified, handle special REL links
+ * with self-designated HREFs. - FM
+ */
+ if (!strcasecomp(value[HTML_LINK_REL], "Home")) {
+ StrAllocCopy(href, LynxHome);
+ } else if (!strcasecomp(value[HTML_LINK_REL], "Help")) {
+ StrAllocCopy(href, helpfile);
+ } else if (!strcasecomp(value[HTML_LINK_REL], "Index")) {
+ StrAllocCopy(href, indexfile);
+ } else {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML: LINK with REL=\"%s\" and no HREF ignored.\n",
+ value[HTML_LINK_REL]);
+ }
+ break;
+ }
+ StrAllocCopy(title, value[HTML_LINK_REL]);
+ }
+ if (href) {
+ /*
+ * Create a title (link name) from the TITLE value,
+ * if present, or default to the REL value that was
+ * loaded into title. - FM
+ */
+ if (present && present[HTML_LINK_TITLE] &&
+ value[HTML_LINK_TITLE] && *value[HTML_LINK_TITLE] != '\0') {
+ StrAllocCopy(title, value[HTML_LINK_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ }
+ if (!(title && *title)) {
+ FREE(href);
+ FREE(title);
+ break;
+ }
+
+ if (me->inA) {
+ /*
+ * Ugh! The LINK tag, which is a HEAD element,
+ * is in an Anchor, which is BODY element. All
+ * we can do is close the Anchor and cross our
+ * fingers. - FM
+ */
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+
+ /*
+ * Create anchors for the links that simulate
+ * a toolbar. - FM
+ */
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ if ((dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ )) != NULL) {
+ if (!HTAnchor_title(dest))
+ HTAnchor_setTitle(dest, title);
+ dest = NULL;
+ if (present[HTML_LINK_CHARSET] &&
+ value[HTML_LINK_CHARSET] && *value[HTML_LINK_CHARSET] != '\0') {
+ dest_char_set = UCGetLYhndl_byMIME(value[HTML_LINK_CHARSET]);
+ if (dest_char_set < 0)
+ dest_char_set = UCLYhndl_for_unrec;
+ }
+ if (dest && dest_char_set >= 0)
+ HTAnchor_setUCInfoStage(dest, dest_char_set,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_LINK);
+ dest_char_set = -1;
+ }
+ UPDATE_STYLE;
+ if (!HText_hasToolbar(me->text) &&
+ (ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ LYToolbarName, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0))) { /* Type */
+ HText_appendCharacter(me->text, '#');
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ HText_setToolbar(me->text);
+ }
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+#ifdef USE_COLOR_STYLE
+ if (present && present[HTML_LINK_CLASS] &&
+ value && *value[HTML_LINK_CLASS]!='\0')
+ {
+ char tmp[1024];
+ sprintf(tmp, "link.%s.%s.%s", value[HTML_LINK_CLASS], title, value[HTML_LINK_CLASS]);
+ if (TRACE)
+ fprintf(stderr, "CSSTRIM:link=%s\n", tmp);
+
+ HText_characterStyle(me->text, hash_code(tmp), 1);
+ HTML_put_string(me, title);
+ HTML_put_string(me, " (");
+ HTML_put_string(me, value[HTML_LINK_CLASS]);
+ HTML_put_string(me, ")");
+ HText_characterStyle(me->text, hash_code(tmp), 0);
+ }
+ else
+#endif
+ HTML_put_string(me, title);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ }
+ FREE(href);
+ FREE(title);
+ break;
+
+ case HTML_ISINDEX:
+ if (((present)) &&
+ ((present[HTML_ISINDEX_HREF] && value[HTML_ISINDEX_HREF]) ||
+ (present[HTML_ISINDEX_ACTION] && value[HTML_ISINDEX_ACTION]))) {
+ char * action = NULL;
+ char * isindex_href = NULL;
+
+ /*
+ * Lynx was supporting ACTION, which never made it into
+ * the HTML 2.0 specs. HTML 3.0 uses HREF, so we'll
+ * use that too, but allow use of ACTION as an alternate
+ * until people have fully switched over. - FM
+ */
+ if (present[HTML_ISINDEX_HREF] && value[HTML_ISINDEX_HREF])
+ StrAllocCopy(isindex_href, value[HTML_ISINDEX_HREF]);
+ else
+ StrAllocCopy(isindex_href, value[HTML_ISINDEX_ACTION]);
+ url_type = LYLegitimizeHREF(me, (char**)&isindex_href,
+ TRUE, TRUE);
+
+ /*
+ * Check whether a base tag is in effect.
+ */
+ if (me->inBASE && *isindex_href != '\0' && *isindex_href != '#')
+ action = HTParse(isindex_href, me->base_href, PARSE_ALL);
+ if (!(action && *action))
+ action = HTParse(isindex_href,
+ me->node_anchor->address, PARSE_ALL);
+ FREE(isindex_href);
+
+ if (action && *action) {
+ HTAnchor_setIndex(me->node_anchor, action);
+ } else {
+ HTAnchor_setIndex(me->node_anchor, me->node_anchor->address);
+ }
+ FREE(action);
+
+ } else {
+ if (me->inBASE)
+ /*
+ * Use base.
+ */
+ HTAnchor_setIndex(me->node_anchor, me->base_href);
+ else
+ /*
+ * Use index's address.
+ */
+ HTAnchor_setIndex(me->node_anchor, me->node_anchor->address);
+ }
+ /*
+ * Support HTML 3.0 PROMPT attribute. - FM
+ */
+ if (present &&
+ present[HTML_ISINDEX_PROMPT] &&
+ value[HTML_ISINDEX_PROMPT] && *value[HTML_ISINDEX_PROMPT]) {
+ StrAllocCopy(temp, value[HTML_ISINDEX_PROMPT]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&temp, TRUE, FALSE);
+ LYTrimHead(temp);
+ LYTrimTail(temp);
+ if (*temp != '\0') {
+ StrAllocCat(temp, " ");
+ HTAnchor_setPrompt(me->node_anchor, temp);
+ } else {
+ HTAnchor_setPrompt(me->node_anchor,
+ "Enter a database query: ");
+ }
+ FREE(temp);
+ } else {
+ HTAnchor_setPrompt(me->node_anchor, "Enter a database query: ");
+ }
+ break;
+
+ case HTML_NEXTID:
+ /* if (present && present[NEXTID_N] && value[NEXTID_N])
+ HText_setNextId(me->text, atoi(value[NEXTID_N])); */
+ break;
+
+ case HTML_STYLE:
+ /*
+ * We're getting it as Literal text, which, for now,
+ * we'll just ignore. - FM
+ */
+ HTChunkClear(&me->style_block);
+ break;
+
+ case HTML_SCRIPT:
+ /*
+ * We're getting it as Literal text, which, for now,
+ * we'll just ignore. - FM
+ */
+ HTChunkClear(&me->script);
+ break;
+
+ case HTML_BODY:
+ CHECK_ID(HTML_BODY_ID);
+ if (HText_hasToolbar(me->text))
+ HText_appendParagraph(me->text);
+ break;
+
+ case HTML_FRAMESET:
+ break;
+
+ case HTML_FRAME:
+ if (present && present[HTML_FRAME_NAME] &&
+ value[HTML_FRAME_NAME] && *value[HTML_FRAME_NAME]) {
+ StrAllocCopy(id_string, value[HTML_FRAME_NAME]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&id_string, TRUE, FALSE);
+ LYTrimHead(id_string);
+ LYTrimTail(id_string);
+ }
+ if (present && present[HTML_FRAME_SRC] &&
+ value[HTML_FRAME_SRC] && *value[HTML_FRAME_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_FRAME_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '\0' && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '\0' && *href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ LYEnsureSingleSpace(me);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "FRAME:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ CHECK_ID(HTML_FRAME_ID);
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, (id_string ? id_string : href));
+ FREE(href);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ LYEnsureSingleSpace(me);
+ } else {
+ CHECK_ID(HTML_FRAME_ID);
+ }
+ FREE(id_string);
+ break;
+
+ case HTML_NOFRAMES:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ break;
+
+ case HTML_IFRAME:
+ if (present && present[HTML_IFRAME_NAME] &&
+ value[HTML_IFRAME_NAME] && *value[HTML_IFRAME_NAME]) {
+ StrAllocCopy(id_string, value[HTML_IFRAME_NAME]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&id_string, TRUE, FALSE);
+ LYTrimHead(id_string);
+ LYTrimTail(id_string);
+ }
+ if (present && present[HTML_IFRAME_SRC] &&
+ value[HTML_IFRAME_SRC] && *value[HTML_IFRAME_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_IFRAME_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '\0' && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '\0' && *href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ if (me->inA)
+ HTML_end_element(me, HTML_A, (char **)&include);
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "IFRAME:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ CHECK_ID(HTML_IFRAME_ID);
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, (id_string ? id_string : href));
+ FREE(href);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ LYEnsureSingleSpace(me);
+ } else {
+ CHECK_ID(HTML_IFRAME_ID);
+ }
+ FREE(id_string);
+ break;
+
+ case HTML_BANNER:
+ case HTML_MARQUEE:
+ change_paragraph_style(me, styles[HTML_BANNER]);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == ElementNumber)
+ LYEnsureDoubleSpace(me);
+ /*
+ * Treat this as a toolbar if we don't have one
+ * yet, and we are in the first half of the
+ * first page. - FM
+ */
+ if ((!HText_hasToolbar(me->text) &&
+ HText_getLines(me->text) < (display_lines/2)) &&
+ (ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ LYToolbarName, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0))) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ HText_setToolbar(me->text);
+ }
+ CHECK_ID(HTML_GEN_ID);
+ break;
+
+ case HTML_CENTER:
+ case HTML_DIV:
+ if (me->Division_Level < (MAX_NESTING - 1)) {
+ me->Division_Level++;
+ } else if (TRACE) {
+ fprintf(stderr,
+ "HTML: ****** Maximum nesting of %d divisions exceeded!\n",
+ MAX_NESTING);
+ }
+ if (ElementNumber == HTML_CENTER) {
+ me->DivisionAlignments[me->Division_Level] = HT_CENTER;
+ change_paragraph_style(me, styles[HTML_DCENTER]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DCENTER]->alignment;
+ } else if (present && present[HTML_DIV_ALIGN] &&
+ value[HTML_DIV_ALIGN] && *value[HTML_DIV_ALIGN]) {
+ if (!strcasecomp(value[HTML_DIV_ALIGN], "center")) {
+ me->DivisionAlignments[me->Division_Level] = HT_CENTER;
+ change_paragraph_style(me, styles[HTML_DCENTER]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DCENTER]->alignment;
+ } else if (!strcasecomp(value[HTML_DIV_ALIGN], "right")) {
+ me->DivisionAlignments[me->Division_Level] = HT_RIGHT;
+ change_paragraph_style(me, styles[HTML_DRIGHT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DRIGHT]->alignment;
+ } else {
+ me->DivisionAlignments[me->Division_Level] = HT_LEFT;
+ change_paragraph_style(me, styles[HTML_DLEFT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DLEFT]->alignment;
+ }
+ } else {
+ me->DivisionAlignments[me->Division_Level] = HT_LEFT;
+ change_paragraph_style(me, styles[HTML_DLEFT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DLEFT]->alignment;
+ }
+ CHECK_ID(HTML_DIV_ID);
+ break;
+
+ case HTML_H1:
+ case HTML_H2:
+ case HTML_H3:
+ case HTML_H4:
+ case HTML_H5:
+ case HTML_H6:
+ /*
+ * Close the previous style if not done by HTML doc.
+ * Added to get rid of core dumps in BAD HTML on the net.
+ * GAB 07-07-94
+ * But then again, these are actually allowed to nest. I guess
+ * I have to depend on the HTML writers correct style.
+ * GAB 07-12-94
+ if (i_prior_style != -1) {
+ HTML_end_element(me, i_prior_style);
+ }
+ i_prior_style = ElementNumber;
+ */
+
+ /*
+ * Check whether we have an H# in a list,
+ * and if so, treat it as an LH. - FM
+ */
+ if ((me->List_Nesting_Level >= 0) &&
+ (me->sp[0].tag_number == HTML_UL ||
+ me->sp[0].tag_number == HTML_OL ||
+ me->sp[0].tag_number == HTML_MENU ||
+ me->sp[0].tag_number == HTML_DIR)) {
+ if (HTML_dtd.tags[HTML_LH].contents == SGML_EMPTY) {
+ ElementNumber = HTML_LH;
+ } else {
+ me->new_style = me->sp[0].style;
+ ElementNumber = me->sp[0].tag_number;
+ UPDATE_STYLE;
+ }
+ /*
+ * Some authors use H# headers as a substitute for
+ * FONT, so check if this one immediately followed
+ * an LI. If so, both me->inP and me->in_word will
+ * be FALSE (though the line might not be empty due
+ * to a bullet and/or nbsp) and we can assume it is
+ * just for a FONT change. We thus will not create
+ * another line break nor add to the current left
+ * indentation. - FM
+ */
+ if (!(me->inP == FALSE && me->in_word == NO)) {
+ HText_appendParagraph(me->text);
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HText_setLastChar(me->text, ' ');
+ me->in_word = NO;
+ me->inP = FALSE;
+ }
+ CHECK_ID(HTML_H_ID);
+ break;
+ }
+
+ if (present && present[HTML_H_ALIGN] &&
+ value[HTML_H_ALIGN] && *value[HTML_H_ALIGN]) {
+ if (!strcasecomp(value[HTML_H_ALIGN], "center"))
+ change_paragraph_style(me, styles[HTML_HCENTER]);
+ else if (!strcasecomp(value[HTML_H_ALIGN], "right"))
+ change_paragraph_style(me, styles[HTML_HRIGHT]);
+ else if (!strcasecomp(value[HTML_H_ALIGN], "left") ||
+ !strcasecomp(value[HTML_H_ALIGN], "justify"))
+ change_paragraph_style(me, styles[HTML_HLEFT]);
+ else
+ change_paragraph_style(me, styles[ElementNumber]);
+ } else if (me->Division_Level >= 0) {
+ if (me->DivisionAlignments[me->Division_Level] == HT_CENTER) {
+ change_paragraph_style(me, styles[HTML_HCENTER]);
+ } else if (me->DivisionAlignments[me->Division_Level] == HT_LEFT) {
+ change_paragraph_style(me, styles[HTML_HLEFT]);
+ } else if (me->DivisionAlignments[me->Division_Level] == HT_RIGHT) {
+ change_paragraph_style(me, styles[HTML_HRIGHT]);
+ }
+ } else {
+ change_paragraph_style(me, styles[ElementNumber]);
+ }
+ UPDATE_STYLE;
+ CHECK_ID(HTML_H_ID);
+
+ if ((bold_headers == TRUE ||
+ (ElementNumber == HTML_H1 && bold_H1 == TRUE)) &&
+ (styles[ElementNumber]->font&HT_BOLD)) {
+ if (me->inBoldA == FALSE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ }
+ me->inBoldH = TRUE;
+ }
+ break;
+
+ case HTML_P:
+ LYHandleP(me, present, value, (char **)&include, TRUE);
+ break;
+
+ case HTML_BR:
+ UPDATE_STYLE;
+ CHECK_ID(HTML_GEN_ID);
+ if ((LYCollapseBRs == FALSE) ||
+ HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ }
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_WBR:
+ UPDATE_STYLE;
+ CHECK_ID(HTML_GEN_ID);
+ HText_setBreakPoint(me->text);
+ break;
+
+ case HTML_HY:
+ case HTML_SHY:
+ UPDATE_STYLE;
+ CHECK_ID(HTML_GEN_ID);
+ HText_appendCharacter(me->text, LY_SOFT_HYPHEN);
+ break;
+
+ case HTML_HR:
+ {
+ int width;
+
+ /*
+ * Start a new line only if we had printable
+ * characters following the previous newline,
+ * or remove the previous line if both it and
+ * the last line are blank. - FM
+ */
+ UPDATE_STYLE;
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ } else if (!HText_PreviousLineSize(me->text, FALSE)) {
+ HText_RemovePreviousLine(me->text);
+ }
+ me->in_word = NO;
+ me->inP = FALSE;
+
+ /*
+ * Add an ID link if needed. - FM
+ */
+ CHECK_ID(HTML_HR_ID);
+
+ /*
+ * Center lines within the current margins, if
+ * a right or left ALIGNment is not specified.
+ * If WIDTH="#%" is given and not garbage,
+ * use that to calculate the width, otherwise
+ * use the default width. - FM
+ */
+ if (present && present[HTML_HR_ALIGN] && value[HTML_HR_ALIGN]) {
+ if (!strcasecomp(value[HTML_HR_ALIGN], "right")) {
+ me->sp->style->alignment = HT_RIGHT;
+ } else if (!strcasecomp(value[HTML_HR_ALIGN], "left")) {
+ me->sp->style->alignment = HT_LEFT;
+ } else {
+ me->sp->style->alignment = HT_CENTER;
+ }
+ } else {
+ me->sp->style->alignment = HT_CENTER;
+ }
+ width = LYcols - 1 -
+ me->new_style->leftIndent - me->new_style->rightIndent;
+ if (present && present[HTML_HR_WIDTH] && value[HTML_HR_WIDTH] &&
+ isdigit(*value[HTML_HR_WIDTH]) &&
+ value[HTML_HR_WIDTH][strlen(value[HTML_HR_WIDTH])-1] == '%') {
+ char *percent = NULL;
+ int Percent, Width;
+ StrAllocCopy(percent, value[HTML_HR_WIDTH]);
+ percent[strlen(percent)-1] = '\0';
+ Percent = atoi(percent);
+ if (Percent > 100 || Percent < 1)
+ width -= 5;
+ else {
+ Width = (width * Percent) / 100;
+ if (Width < 1)
+ width = 1;
+ else
+ width = Width;
+ }
+ FREE(percent);
+ } else {
+ width -= 5;
+ }
+ for (i = 0; i < width; i++)
+ HTML_put_character(me, '_');
+ HText_appendCharacter(me->text, '\r');
+ me->in_word = NO;
+ me->inP = FALSE;
+
+ /*
+ * Reset the alignment appropriately
+ * for the division and/or block. - FM
+ */
+ if (me->List_Nesting_Level < 0 &&
+ me->Division_Level >= 0) {
+ me->sp->style->alignment =
+ me->DivisionAlignments[me->Division_Level];
+ } else if (!strcmp(me->sp->style->name, "HeadingCenter") ||
+ !strcmp(me->sp->style->name, "Heading1")) {
+ me->sp->style->alignment = HT_CENTER;
+ } else if (!strcmp(me->sp->style->name, "HeadingRight")) {
+ me->sp->style->alignment = HT_RIGHT;
+ } else {
+ me->sp->style->alignment = HT_LEFT;
+ }
+
+ /*
+ * Add a blank line and set the second line
+ * indentation for lists and addresses, or a
+ * paragraph separator for other blocks. - FM
+ */
+ if (me->List_Nesting_Level >= 0 ||
+ me->sp[0].tag_number == HTML_ADDRESS) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ } else {
+ HText_appendParagraph(me->text);
+ }
+ }
+ break;
+
+ case HTML_TAB:
+ if (!present) { /* Bad tag. Must have at least one attribute. - FM */
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: TAB tag has no attributes. Ignored.\n");
+ break;
+ }
+ UPDATE_STYLE;
+
+ if (present[HTML_TAB_ALIGN] && value[HTML_TAB_ALIGN] &&
+ (strcasecomp(value[HTML_TAB_ALIGN], "left") ||
+ !(present[HTML_TAB_TO] || present[HTML_TAB_INDENT]))) {
+ /*
+ * Just ensure a collapsible space, until we have
+ * the ALIGN and DP attributes implemented. - FM
+ */
+ HTML_put_character(me, ' ');
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: ALIGN not 'left'. Using space instead of TAB.\n");
+
+ } else if (!LYoverride_default_alignment(me) &&
+ me->current_default_alignment != HT_LEFT) {
+ /*
+ * Just ensure a collapsible space, until we
+ * can replace HText_getCurrentColumn() in
+ * GridText.c with code which doesn't require
+ * that the alignment be HT_LEFT. - FM
+ */
+ HTML_put_character(me, ' ');
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: Not HT_LEFT. Using space instead of TAB.\n");
+
+ } else if ((present[HTML_TAB_TO] &&
+ value[HTML_TAB_TO] && *value[HTML_TAB_TO]) ||
+ (present[HTML_TAB_INDENT] &&
+ value[HTML_TAB_INDENT] &&
+ isdigit(*value[HTML_TAB_INDENT]))) {
+ int column, target = -1;
+ int enval = 2;
+
+ column = HText_getCurrentColumn(me->text);
+ if (present[HTML_TAB_TO]) {
+ /*
+ * TO has priority over INDENT if both are present. - FM
+ */
+ StrAllocCopy(temp, value[HTML_TAB_TO]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&temp);
+ if (*temp) {
+ target = HText_getTabIDColumn(me->text, temp);
+ }
+ } else if (!(temp && *temp) && present[HTML_TAB_INDENT] &&
+ value[HTML_TAB_INDENT] &&
+ isdigit(*value[HTML_TAB_INDENT])) {
+ /*
+ * The INDENT value is in "en" (enval per column) units.
+ * Divide it by enval, rounding odd values up. - FM
+ */
+ target =
+ (int)(((1.0 * atoi(value[HTML_TAB_INDENT]))/enval)+(0.5));
+ }
+ FREE(temp);
+ /*
+ * If we are being directed to a column too far to the left
+ * or right, just add a collapsible space, otherwise, add the
+ * appropriate number of spaces. - FM
+ */
+ if (target < column ||
+ target > HText_getMaximumColumn(me->text)) {
+ HTML_put_character(me, ' ');
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: Column out of bounds. Using space instead of TAB.\n");
+ } else {
+ for (i = column; i < target; i++)
+ HText_appendCharacter(me->text, ' ');
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ }
+ }
+ me->in_word = NO;
+
+ /*
+ * If we have an ID attribute, save it together
+ * with the value of the column we've reached. - FM
+ */
+ if (present[HTML_TAB_ID] &&
+ value[HTML_TAB_ID] && *value[HTML_TAB_ID]) {
+ StrAllocCopy(temp, value[HTML_TAB_ID]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&temp);
+ if (*temp)
+ HText_setTabID(me->text, temp);
+ FREE(temp);
+ }
+ break;
+
+ case HTML_BASEFONT:
+ break;
+
+ case HTML_FONT:
+
+ /*
+ * FONT *may* have been declared SGML_EMPTY in HTMLDTD.c, and
+ * SGML_character() in SGML.c *may* check for a FONT end
+ * tag to call HTML_end_element() directly (with a
+ * check in that to bypass decrementing of the HTML
+ * parser's stack). Or this may have been really a </FONT>
+ * end tag, for which some incarnations of SGML.c would fake
+ * a <FONT> start tag instead. - fm & kw
+ *
+ * But if we have an open FONT, DON'T close that one now,
+ * since FONT tags can be legally nested AFAIK, and Lynx
+ * currently doesn't do anything with them anyway... - kw
+ */
+#ifdef NOTUSED_FOTEMODS
+ if (me->inFONT == TRUE)
+ HTML_end_element(me, HTML_FONT, (char **)&include);
+#endif /* NOTUSED_FOTEMODS */
+
+ /*
+ * Set flag to know we are in a FONT container, and
+ * add code to do something about it, someday. - FM
+ */
+ me->inFONT = TRUE;
+ break;
+
+ case HTML_B: /* Physical character highlighting */
+ case HTML_BLINK:
+ case HTML_I:
+ case HTML_U:
+
+ case HTML_CITE: /* Logical character highlighting */
+ case HTML_EM:
+ case HTML_STRONG:
+ UPDATE_STYLE;
+ me->Underline_Level++;
+ CHECK_ID(HTML_GEN_ID);
+ /*
+ * Ignore this if inside of a bold anchor or header.
+ * Can't display both underline and bold at same time.
+ */
+ if (me->inBoldA == TRUE || me->inBoldH == TRUE) {
+ if (TRACE)
+ fprintf(stderr,"Underline Level is %d\n", me->Underline_Level);
+ break;
+ }
+ if (me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ me->inUnderline = TRUE;
+ if (TRACE)
+ fprintf(stderr,"Beginning underline\n");
+ } else {
+ if (TRACE)
+ fprintf(stderr,"Underline Level is %d\n", me->Underline_Level);
+ }
+ break;
+
+ case HTML_ABBREV: /* Miscellaneous character containers */
+ case HTML_ACRONYM:
+ case HTML_AU:
+ case HTML_AUTHOR:
+ case HTML_BIG:
+ case HTML_CODE:
+ case HTML_DFN:
+ case HTML_KBD:
+ case HTML_SAMP:
+ case HTML_SMALL:
+ case HTML_SUB:
+ case HTML_SUP:
+ case HTML_TT:
+ case HTML_VAR:
+ CHECK_ID(HTML_GEN_ID);
+ break; /* ignore */
+
+ case HTML_DEL:
+ case HTML_S:
+ case HTML_STRIKE:
+ CHECK_ID(HTML_GEN_ID);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "[DEL:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_INS:
+ CHECK_ID(HTML_GEN_ID);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "[INS:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_Q:
+ CHECK_ID(HTML_GEN_ID);
+ /*
+ * Should check LANG and/or DIR attributes, and the
+ * me->node_anchor->charset and/or yet to be added
+ * structure elements, to determine whether we should
+ * use chevrons, but for now we'll always use double-
+ * or single-quotes. - FM
+ */
+ if (!(me->Quote_Level & 1))
+ HTML_put_character(me, '"');
+ else
+ HTML_put_character(me, '`');
+ me->Quote_Level++;
+ break;
+
+ case HTML_PRE: /* Formatted text */
+ /*
+ ** Set our inPRE flag to FALSE so that a newline
+ ** immediately following the PRE start tag will
+ ** be ignored. HTML_put_character() will set it
+ ** to TRUE when the first character within the
+ ** PRE block is received. - FM
+ */
+ me->inPRE = FALSE;
+ case HTML_LISTING: /* Literal text */
+ case HTML_XMP:
+ case HTML_PLAINTEXT:
+ change_paragraph_style(me, styles[ElementNumber]);
+ UPDATE_STYLE;
+ CHECK_ID(HTML_GEN_ID);
+ if (me->comment_end)
+ HText_appendText(me->text, me->comment_end);
+ break;
+
+ case HTML_BLOCKQUOTE:
+ case HTML_BQ:
+ change_paragraph_style(me, styles[ElementNumber]);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == ElementNumber)
+ LYEnsureDoubleSpace(me);
+ CHECK_ID(HTML_BQ_ID);
+ break;
+
+ case HTML_NOTE:
+ change_paragraph_style(me, styles[ElementNumber]);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == ElementNumber)
+ LYEnsureDoubleSpace(me);
+ CHECK_ID(HTML_NOTE_ID);
+ {
+ char *note = NULL;
+
+ /*
+ * Indicate the type of NOTE.
+ */
+ if (present && present[HTML_NOTE_CLASS] &&
+ value[HTML_NOTE_CLASS] &&
+ (!strcasecomp(value[HTML_NOTE_CLASS], "CAUTION") ||
+ !strcasecomp(value[HTML_NOTE_CLASS], "WARNING"))) {
+ StrAllocCopy(note, value[HTML_NOTE_CLASS]);
+ for (i = 0; note[i] != '\0'; i++)
+ note[i] = TOUPPER(note[i]);
+ StrAllocCat(note, ":");
+ } else if (present && present[HTML_NOTE_ROLE] &&
+ value[HTML_NOTE_ROLE] &&
+ (!strcasecomp(value[HTML_NOTE_ROLE], "CAUTION") ||
+ !strcasecomp(value[HTML_NOTE_ROLE], "WARNING"))) {
+ StrAllocCopy(note, value[HTML_NOTE_ROLE]);
+ for (i = 0; note[i] != '\0'; i++)
+ note[i] = TOUPPER(note[i]);
+ StrAllocCat(note, ":");
+ } else {
+ StrAllocCopy(note, "NOTE:");
+ }
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, note);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ FREE(note);
+ }
+ me->inLABEL = TRUE;
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_ADDRESS:
+ change_paragraph_style(me, styles[ElementNumber]);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == ElementNumber)
+ LYEnsureDoubleSpace(me);
+ CHECK_ID(HTML_ADDRESS_ID);
+ break;
+
+ case HTML_DL:
+ me->List_Nesting_Level++; /* increment the List nesting level */
+ if (me->List_Nesting_Level <= 0) {
+ change_paragraph_style(me, present && present[HTML_DL_COMPACT]
+ ? styles[HTML_DLC] : styles[HTML_DL]);
+
+ } else if (me->List_Nesting_Level >= 6) {
+ change_paragraph_style(me, present && present[HTML_DL_COMPACT]
+ ? styles[HTML_DLC6] : styles[HTML_DL6]);
+
+ } else {
+ change_paragraph_style(me, present && present[HTML_DL_COMPACT]
+ ? styles[(HTML_DLC1 - 1) + me->List_Nesting_Level]
+ : styles[(HTML_DL1 - 1) + me->List_Nesting_Level]);
+ }
+ UPDATE_STYLE; /* update to the new style */
+ CHECK_ID(HTML_DL_ID);
+ break;
+
+ case HTML_DLC:
+ me->List_Nesting_Level++; /* increment the List nesting level */
+ if (me->List_Nesting_Level <= 0) {
+ change_paragraph_style(me, styles[HTML_DLC]);
+
+ } else if (me->List_Nesting_Level >= 6) {
+ change_paragraph_style(me, styles[HTML_DLC6]);
+
+ } else {
+ change_paragraph_style(me,
+ styles[(HTML_DLC1 - 1) + me->List_Nesting_Level]);
+ }
+ UPDATE_STYLE; /* update to the new style */
+ CHECK_ID(HTML_DL_ID);
+ break;
+
+ case HTML_DT:
+ CHECK_ID(HTML_GEN_ID);
+ if (!me->style_change) {
+ HText_appendParagraph(me->text);
+ me->in_word = NO;
+ me->sp->style->alignment = HT_LEFT;
+ }
+ me->inP = FALSE;
+ break;
+
+ case HTML_DD:
+ CHECK_ID(HTML_GEN_ID);
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ if (!me->style_change) {
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_appendCharacter(me->text, '\r');
+ }
+ } else {
+ UPDATE_STYLE;
+ HText_appendCharacter(me->text, '\t');
+ }
+ me->sp->style->alignment = HT_LEFT;
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_OL:
+ /*
+ * Set the default TYPE.
+ */
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = '1';
+
+ /*
+ * Check whether we have a starting sequence number,
+ * or want to continue the numbering from a previous
+ * OL in this nest. - FM
+ */
+ if (present && (present[HTML_OL_SEQNUM] || present[HTML_OL_START])) {
+ int seqnum;
+
+ /*
+ * Give preference to the valid HTML 3.0 SEQNUM attribute name
+ * over the Netscape START attribute name (too bad the Netscape
+ * developers didn't read the HTML 3.0 specs before re-inventing
+ * the "wheel" as "we'll"). - FM
+ */
+ if (present[HTML_OL_SEQNUM] &&
+ value[HTML_OL_SEQNUM] && *value[HTML_OL_SEQNUM]) {
+ seqnum = atoi(value[HTML_OL_SEQNUM]);
+ } else if (present[HTML_OL_START] &&
+ value[HTML_OL_START] && *value[HTML_OL_START]) {
+ seqnum = atoi(value[HTML_OL_START]);
+ } else {
+ seqnum = 1;
+ }
+
+ /*
+ * Don't allow negative numbers less than
+ * or equal to our flags, or numbers less
+ * than 1 if an Alphabetic or Roman TYPE. - FM
+ */
+ if (present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) {
+ if (*value[HTML_OL_TYPE] == 'A') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'A';
+ if (seqnum < 1)
+ seqnum = 1;
+ } else if (*value[HTML_OL_TYPE] == 'a') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'a';
+ if (seqnum < 1)
+ seqnum = 1;
+ } else if (*value[HTML_OL_TYPE] == 'I') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'I';
+ if (seqnum < 1)
+ seqnum = 1;
+ } else if (*value[HTML_OL_TYPE] == 'i') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'i';
+ if (seqnum < 1)
+ seqnum = 1;
+ } else {
+ if (seqnum <= OL_VOID)
+ seqnum = OL_VOID + 1;
+ }
+ } else if (seqnum <= OL_VOID) {
+ seqnum = OL_VOID + 1;
+ }
+
+ me->OL_Counter[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = seqnum;
+
+ } else if (present && present[HTML_OL_CONTINUE]) {
+ me->OL_Counter[me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11] = OL_CONTINUE;
+
+ } else {
+ me->OL_Counter[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 1;
+ if (present && present[HTML_OL_TYPE] && value[HTML_OL_TYPE]) {
+ if (*value[HTML_OL_TYPE] == 'A') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'A';
+ } else if (*value[HTML_OL_TYPE] == 'a') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'a';
+ } else if (*value[HTML_OL_TYPE] == 'I') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'I';
+ } else if (*value[HTML_OL_TYPE] == 'i') {
+ me->OL_Type[(me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level+1 : 11)] = 'i';
+ }
+ }
+ }
+ me->List_Nesting_Level++;
+
+ if (me->List_Nesting_Level <= 0) {
+ change_paragraph_style(me, styles[ElementNumber]);
+
+ } else if (me->List_Nesting_Level >= 6) {
+ change_paragraph_style(me, styles[HTML_OL6]);
+
+ } else {
+ change_paragraph_style(me,
+ styles[HTML_OL1 + me->List_Nesting_Level - 1]);
+ }
+ UPDATE_STYLE; /* update to the new style */
+ CHECK_ID(HTML_OL_ID);
+ break;
+
+ case HTML_UL:
+ me->List_Nesting_Level++;
+
+ if (me->List_Nesting_Level <= 0) {
+ if (!(present && present[HTML_UL_PLAIN]) &&
+ !(present && present[HTML_UL_TYPE] &&
+ value[HTML_UL_TYPE] &&
+ 0==strcasecomp(value[HTML_UL_TYPE], "PLAIN"))) {
+ change_paragraph_style(me, styles[ElementNumber]);
+ } else {
+ change_paragraph_style(me, styles[HTML_DIR]);
+ ElementNumber = HTML_DIR;
+ }
+
+ } else if (me->List_Nesting_Level >= 6) {
+ if (!(present && present[HTML_UL_PLAIN]) &&
+ !(present && present[HTML_UL_TYPE] &&
+ value[HTML_UL_TYPE] &&
+ 0==strcasecomp(value[HTML_UL_TYPE], "PLAIN"))) {
+ change_paragraph_style(me, styles[HTML_OL6]);
+ } else {
+ change_paragraph_style(me, styles[HTML_MENU6]);
+ ElementNumber = HTML_DIR;
+ }
+
+ } else {
+ if (!(present && present[HTML_UL_PLAIN]) &&
+ !(present && present[HTML_UL_TYPE] &&
+ value[HTML_UL_TYPE] &&
+ 0==strcasecomp(value[HTML_UL_TYPE], "PLAIN"))) {
+ change_paragraph_style(me,
+ styles[HTML_OL1 + me->List_Nesting_Level - 1]);
+ } else {
+ change_paragraph_style(me,
+ styles[HTML_MENU1 + me->List_Nesting_Level - 1]);
+ ElementNumber = HTML_DIR;
+ }
+ }
+ UPDATE_STYLE; /* update to the new style */
+ CHECK_ID(HTML_UL_ID);
+ break;
+
+ case HTML_MENU:
+ case HTML_DIR:
+ me->List_Nesting_Level++;
+
+ if (me->List_Nesting_Level <= 0) {
+ change_paragraph_style(me, styles[ElementNumber]);
+
+ } else if (me->List_Nesting_Level >= 6) {
+ change_paragraph_style(me, styles[HTML_MENU6]);
+
+ } else {
+ change_paragraph_style(me,
+ styles[HTML_MENU1 + me->List_Nesting_Level - 1]);
+ }
+ UPDATE_STYLE; /* update to the new style */
+ CHECK_ID(HTML_UL_ID);
+ break;
+
+ case HTML_LH:
+ UPDATE_STYLE; /* update to the new style */
+ HText_appendParagraph(me->text);
+ CHECK_ID(HTML_GEN_ID);
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HText_setLastChar(me->text, ' ');
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_LI:
+ UPDATE_STYLE; /* update to the new style */
+ HText_appendParagraph(me->text);
+ me->sp->style->alignment = HT_LEFT;
+ CHECK_ID(HTML_LI_ID);
+ if (me->sp[0].tag_number == HTML_OL) {
+ char number_string[20];
+ int counter, seqnum;
+ char seqtype;
+
+ counter = me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level : 11;
+ if (present && present[HTML_LI_TYPE] && value[HTML_LI_TYPE]) {
+ if (*value[HTML_LI_TYPE] == '1') {
+ me->OL_Type[counter] = '1';
+ } else if (*value[HTML_LI_TYPE] == 'A') {
+ me->OL_Type[counter] = 'A';
+ } else if (*value[HTML_LI_TYPE] == 'a') {
+ me->OL_Type[counter] = 'a';
+ } else if (*value[HTML_LI_TYPE] == 'I') {
+ me->OL_Type[counter] = 'I';
+ } else if (*value[HTML_LI_TYPE] == 'i') {
+ me->OL_Type[counter] = 'i';
+ }
+ }
+ if (present && present[HTML_LI_VALUE] &&
+ ((value[HTML_LI_VALUE] != NULL) &&
+ (*value[HTML_LI_VALUE] != '\0')) &&
+ ((isdigit(*value[HTML_LI_VALUE])) ||
+ (*value[HTML_LI_VALUE] == '-' &&
+ isdigit(*(value[HTML_LI_VALUE] + 1))))) {
+ seqnum = atoi(value[HTML_LI_VALUE]);
+ if (seqnum <= OL_VOID)
+ seqnum = OL_VOID + 1;
+ seqtype = me->OL_Type[counter];
+ if (seqtype != '1' && seqnum < 1)
+ seqnum = 1;
+ me->OL_Counter[counter] = seqnum + 1;
+ } else if (me->OL_Counter[counter] >= OL_VOID) {
+ seqnum = me->OL_Counter[counter]++;
+ seqtype = me->OL_Type[counter];
+ if (seqtype != '1' && seqnum < 1) {
+ seqnum = 1;
+ me->OL_Counter[counter] = seqnum + 1;
+ }
+ } else {
+ seqnum = me->Last_OL_Count + 1;
+ seqtype = me->Last_OL_Type;
+ for (i = (counter - 1); i >= 0; i--) {
+ if (me->OL_Counter[i] > OL_VOID) {
+ seqnum = me->OL_Counter[i]++;
+ seqtype = me->OL_Type[i];
+ i = 0;
+ }
+ }
+ }
+ if (seqtype == 'A') {
+ sprintf(number_string, LYUppercaseA_OL_String(seqnum));
+ } else if (seqtype == 'a') {
+ sprintf(number_string, LYLowercaseA_OL_String(seqnum));
+ } else if (seqtype == 'I') {
+ sprintf(number_string, LYUppercaseI_OL_String(seqnum));
+ } else if (seqtype == 'i') {
+ sprintf(number_string, LYLowercaseI_OL_String(seqnum));
+ } else {
+ sprintf(number_string, "%2d.", seqnum);
+ }
+ me->Last_OL_Count = seqnum;
+ me->Last_OL_Type = seqtype;
+ /*
+ * Hack, because there is no append string!
+ */
+ for (i = 0; number_string[i] != '\0'; i++)
+ if (number_string[i] == ' ')
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ else
+ HTML_put_character(me, number_string[i]);
+
+ /*
+ * Use HTML_put_character so that any other spaces
+ * coming through will be collapsed. We'll use
+ * nbsp, so it won't break at the spacing character
+ * if there are no spaces in the subsequent text up
+ * to the right margin, but will declare it as a
+ * normal space to ensure collapsing if a normal
+ * space does immediately follow it. - FM
+ */
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HText_setLastChar(me->text, ' ');
+ } else if (me->sp[0].tag_number == HTML_UL) {
+ /*
+ * Hack, because there is no append string!
+ */
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ switch(me->List_Nesting_Level % 7) {
+ case 0:
+ HTML_put_character(me, '*');
+ break;
+ case 1:
+ HTML_put_character(me, '+');
+ break;
+ case 2:
+ HTML_put_character(me, 'o');
+ break;
+ case 3:
+ HTML_put_character(me, '#');
+ break;
+ case 4:
+ HTML_put_character(me, '@');
+ break;
+ case 5:
+ HTML_put_character(me, '-');
+ break;
+ case 6:
+ HTML_put_character(me, '=');
+ break;
+
+ }
+ /*
+ * Keep using HTML_put_character so that any other
+ * spaces coming through will be collapsed. We use
+ * nbsp, so we won't wrap at the spacing character
+ * if there are no spaces in the subsequent text up
+ * to the right margin, but will declare it as a
+ * normal space to ensure collapsing if a normal
+ * space does immediately follow it. - FM
+ */
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HText_setLastChar(me->text, ' ');
+ } else {
+ /*
+ * Hack, because there is no append string!
+ */
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ HText_setLastChar(me->text, ' ');
+ }
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_SPAN:
+ CHECK_ID(HTML_GEN_ID);
+ /*
+ * Should check LANG and/or DIR attributes, and the
+ * me->node_anchor->charset and/or yet to be added
+ * structure elements, and do something here. - FM
+ */
+ break;
+
+ case HTML_BDO:
+ CHECK_ID(HTML_GEN_ID);
+ /*
+ * Should check DIR (and LANG) attributes, and the
+ * me->node_anchor->charset and/or yet to be added
+ * structure elements, and do something here. - FM
+ */
+ break;
+
+ case HTML_SPOT:
+ CHECK_ID(HTML_GEN_ID);
+ break;
+
+ case HTML_FN:
+ change_paragraph_style(me, styles[ElementNumber]);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == ElementNumber)
+ LYEnsureDoubleSpace(me);
+ CHECK_ID(HTML_FN_ID);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "FOOTNOTE:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->inLABEL = TRUE;
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_A:
+ /*
+ * A may have been declared SGML_EMPTY in HTMLDTD.c, and
+ * SGML_character() in SGML.c may check for an A end
+ * tag to call HTML_end_element() directly (with a
+ * check in that to bypass decrementing of the HTML
+ * parser's stack), so if we have an open A, close
+ * that one now. - FM & kw
+ */
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ /*
+ * Set to know we are in an anchor.
+ */
+ me->inA = TRUE;
+
+ /*
+ * Load id_string if we have an ID or NAME. - FM
+ */
+ if (present && present[HTML_A_ID] &&
+ value[HTML_A_ID] && *value[HTML_A_ID]) {
+ StrAllocCopy(id_string, value[HTML_A_ID]);
+ } else if (present && present[HTML_A_NAME] &&
+ value[HTML_A_NAME] && *value[HTML_A_NAME]) {
+ StrAllocCopy(id_string, value[HTML_A_NAME]);
+ }
+ if (id_string) {
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ if (*id_string == '\0') {
+ FREE(id_string);
+ }
+ }
+
+ /*
+ * Handle the reference. - FM
+ */
+ if (present && present[HTML_A_HREF]) {
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (present[HTML_A_ISMAP])
+ intern_flag = FALSE;
+ else
+ CHECK_FOR_INTERN(value[HTML_A_HREF]);
+#endif
+ /*
+ * Prepare to do housekeeping on the reference. - FM
+ */
+ if (!value[HTML_A_HREF] || *value[HTML_A_HREF] == '\0') {
+ StrAllocCopy(href, me->node_anchor->address);
+ } else if (*value[HTML_A_HREF] == '#') {
+ StrAllocCopy(href, me->node_anchor->address);
+ if (strlen(value[HTML_A_HREF]) > 1) {
+ StrAllocCat(href, value[HTML_A_HREF]);
+ }
+ } else {
+ StrAllocCopy(href, value[HTML_A_HREF]);
+ }
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+
+ /*
+ * Deal with our ftp gateway kludge. - FM
+ */
+ if (!url_type && !strncmp(href, "/foo/..", 7) &&
+ (!strncmp(me->node_anchor->address, "ftp:", 4) ||
+ !strncmp(me->node_anchor->address, "file:", 5))) {
+ for (i = 0; href[i]; i++)
+ href[i] = href[i+7];
+ }
+
+ /*
+ * Set to know we are making the content bold.
+ */
+ me->inBoldA = TRUE;
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '\0' && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '\0' && *href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+ } else {
+ if (bold_name_anchors == TRUE) {
+ me->inBoldA = TRUE;
+ }
+ }
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (present && present[HTML_A_TYPE] && value[HTML_A_TYPE]) {
+ StrAllocCopy(temp, value[HTML_A_TYPE]);
+ if (!intern_flag && href &&
+ !strcasecomp(value[HTML_A_TYPE], HTAtom_name(LINK_INTERNAL)) &&
+ 0 != strcmp(me->node_anchor->address, LYlist_temp_url()) &&
+ 0 != strncmp(me->node_anchor->address, "LYNXIMGMAP:", 11)) {
+ /* Some kind of spoof?
+ ** Found TYPE="internal link" but not in a valid context
+ ** where we have written it. - kw
+ */
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: Found invalid HREF=\"%s\" TYPE=\"%s\"!\n",
+ href, temp);
+ FREE(temp);
+ }
+ }
+#endif /* DONT_TRACK_INTERNAL_LINKS */
+
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ href, /* Address */
+ temp ?
+ (HTLinkType*)HTAtom_for(temp) : INTERN_LT); /* Type */
+ FREE(temp);
+ FREE(id_string);
+
+ if (me->CurrentA && present) {
+ if (present[HTML_A_TITLE] &&
+ value[HTML_A_TITLE] && *value[HTML_A_TITLE] != '\0') {
+ StrAllocCopy(title, value[HTML_A_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ if (*title == '\0') {
+ FREE(title);
+ }
+ }
+ if (present[HTML_A_ISMAP])
+ dest_ismap = TRUE;
+ if (present[HTML_A_CHARSET] &&
+ value[HTML_A_CHARSET] && *value[HTML_A_CHARSET] != '\0') {
+ /*
+ ** Set up to load the anchor's chartrans structures
+ ** appropriately for the current display character
+ ** set if it can handle what's claimed. - FM
+ */
+ StrAllocCopy(temp, value[HTML_A_CHARSET]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&temp);
+ dest_char_set = UCGetLYhndl_byMIME(temp);
+ if (dest_char_set < 0) {
+ dest_char_set = UCLYhndl_for_unrec;
+ }
+ }
+ if (title != NULL || dest_ismap == TRUE || dest_char_set >= 0) {
+ dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ );
+ }
+ if (dest && title != NULL && HTAnchor_title(dest) == NULL)
+ HTAnchor_setTitle(dest, title);
+ if (dest && dest_ismap)
+ dest->isISMAPScript = TRUE;
+ if (dest && dest_char_set >= 0) {
+ /*
+ ** Load the anchor's chartrans structures.
+ ** This should be done more intelligently
+ ** when setting up the structured object,
+ ** but it gets the job done for now. - FM
+ */
+ HTAnchor_setUCInfoStage(dest, dest_char_set,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_setUCInfoStage(dest, dest_char_set,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_LINK);
+ }
+ FREE(temp);
+ dest = NULL;
+ dest_ismap = FALSE;
+ dest_char_set = -1;
+ FREE(title);
+ }
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline, me->CurrentA);
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+#ifdef NOTUSED_FOTEMODS
+ /*
+ * Close an HREF-less NAMED-ed now if we aren't making their
+ * content bold, and let the check in HTML_end_element() deal
+ * with any dangling end tag this creates. - FM
+ */
+ if (href == NULL && me->inBoldA == FALSE) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+#endif /* NOTUSED_FOTEMODS */
+ FREE(href);
+ break;
+
+ case HTML_IMG: /* Images */
+ /*
+ * If we're in an anchor, get the destination, and if it's a
+ * clickable image for the current anchor, set our flags for
+ * faking a 0,0 coordinate pair, which typically returns the
+ * image's default. - FM
+ */
+ if (me->inA && me->CurrentA) {
+ if ((dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ )) != NULL) {
+ if (dest->isISMAPScript == TRUE) {
+ dest_ismap = TRUE;
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: '%s' is an ISMAP script\n",
+ dest->address);
+ } else if (present && present[HTML_IMG_ISMAP]) {
+ dest_ismap = TRUE;
+ dest->isISMAPScript = TRUE;
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: Designating '%s' as an ISMAP script\n",
+ dest->address);
+ }
+ }
+ }
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ intern_flag = FALSE; /* unless set below - kw */
+#endif
+ /*
+ * If there's a USEMAP, resolve it. - FM
+ */
+ if (present && present[HTML_IMG_USEMAP] &&
+ value[HTML_IMG_USEMAP] && *value[HTML_IMG_USEMAP]) {
+ StrAllocCopy(map_href, value[HTML_IMG_USEMAP]);
+ CHECK_FOR_INTERN(map_href);
+ url_type = LYLegitimizeHREF(me, (char**)&map_href, TRUE, TRUE);
+ /*
+ * If map_href ended up zero-length or otherwise doesn't
+ * have a hash, it can't be valid, so ignore it. - FM
+ */
+ if (strchr(map_href, '#') == NULL) {
+ FREE(map_href);
+ }
+ }
+
+ /*
+ * Handle a MAP reference if we have one at this point. - FM
+ */
+ if (map_href) {
+ /*
+ * If the MAP reference doesn't yet begin with a scheme,
+ * check whether a base tag is in effect. - FM
+ */
+ if (!url_type && me->inBASE) {
+ /*
+ * If the
+ * USEMAP value is a lone fragment and LYSeekFragMAPinCur
+ * is set, we'll use the current document's URL for
+ * resolving. Otherwise use the BASE. - kw
+ */
+ if ((*map_href == '#' &&
+ LYSeekFragMAPinCur == TRUE)) {
+ /*
+ * Use reference related to the current stream. - FM
+ */
+ temp = HTParse(map_href, me->node_anchor->address,
+ PARSE_ALL);
+ StrAllocCopy(map_href, temp);
+ UseBASE = FALSE;
+ } else {
+ /*
+ * Use reference related to the base. - FM
+ */
+ temp = HTParse(map_href, me->base_href, PARSE_ALL);
+ StrAllocCopy(map_href, temp);
+ UseBASE = TRUE;
+ }
+ FREE(temp);
+ }
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&map_href,
+ ((UseBASE && me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+ UseBASE = TRUE;
+
+ /*
+ * If it's not yet a URL, resolve versus
+ * the current document's address. - FM
+ */
+ if (!(url_type = is_url(map_href))) {
+ temp = HTParse(map_href, me->node_anchor->address, PARSE_ALL);
+ StrAllocCopy(map_href, temp);
+ FREE(temp);
+ }
+
+ /*
+ * Prepend our client-side MAP access field. - FM
+ */
+ StrAllocCopy(temp, "LYNXIMGMAP:");
+ StrAllocCat(temp, map_href);
+ StrAllocCopy(map_href, temp);
+ FREE(temp);
+ }
+
+ /*
+ * Check whether we want to suppress the server-side
+ * ISMAP link if a client-side MAP is present. - FM
+ */
+ if (LYNoISMAPifUSEMAP && map_href && dest_ismap) {
+ dest_ismap = FALSE;
+ dest = NULL;
+ }
+
+ /*
+ * Check for a TITLE attribute. - FM
+ */
+ if (present && present[HTML_IMG_TITLE] &&
+ value[HTML_IMG_TITLE] && *value[HTML_IMG_TITLE]) {
+ StrAllocCopy(title, value[HTML_IMG_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ if (*title == '\0') {
+ FREE(title);
+ }
+ }
+
+ /*
+ * If there's an ALT string, use it, unless the ALT string
+ * is zero-length or just spaces and we are making all SRCs
+ * links or have a USEMAP link. - FM
+ */
+ if (((present) &&
+ (present[HTML_IMG_ALT] && value[HTML_IMG_ALT])) &&
+ (!clickable_images ||
+ ((clickable_images || map_href) &&
+ *value[HTML_IMG_ALT] != '\0'))) {
+ StrAllocCopy(alt_string, value[HTML_IMG_ALT]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&alt_string,
+ me->UsePlainSpace, me->HiddenValue);
+ /*
+ * If it's all spaces and we are making SRC or
+ * USEMAP links, treat it as zero-length. - FM
+ */
+ if (clickable_images || map_href) {
+ LYTrimHead(alt_string);
+ LYTrimTail(alt_string);
+ if (*alt_string == '\0') {
+ if (map_href) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[USEMAP]"));
+ } else if (dest_ismap) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[ISMAP]"));
+ } else if (me->inA == TRUE && dest) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[LINK]"));
+ } else {
+ StrAllocCopy(alt_string,
+ (title ? title :
+ (present[HTML_IMG_ISOBJECT] ?
+ "(OBJECT)" : "[INLINE]")));
+ }
+ }
+ }
+
+ } else if (map_href) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[USEMAP]"));
+
+ } else if ((dest_ismap == TRUE) ||
+ (me->inA && present && present[HTML_IMG_ISMAP])) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[ISMAP]"));
+
+ } else if (me->inA == TRUE && dest) {
+ StrAllocCopy(alt_string, (title ?
+ title : "[LINK]"));
+
+ } else {
+ if (pseudo_inline_alts || clickable_images)
+ StrAllocCopy(alt_string, (title ? title :
+ ((present &&
+ present[HTML_IMG_ISOBJECT]) ?
+ "(OBJECT)" : "[INLINE]")));
+ else
+ StrAllocCopy(alt_string, (title ?
+ title : ""));
+ }
+ if (*alt_string == '\0' && map_href) {
+ StrAllocCopy(alt_string, "[USEMAP]");
+ }
+
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML IMG: USEMAP=%d ISMAP=%d ANCHOR=%d PARA=%d\n",
+ map_href ? 1 : 0,
+ (dest_ismap == TRUE) ? 1 : 0,
+ me->inA, me->inP);
+ }
+
+ /*
+ * Check for an ID attribute. - FM
+ */
+ if (present && present[HTML_IMG_ID] &&
+ value[HTML_IMG_ID] && *value[HTML_IMG_ID]) {
+ StrAllocCopy(id_string, value[HTML_IMG_ID]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ if (*id_string == '\0') {
+ FREE(id_string);
+ }
+ }
+
+ /*
+ * Create links to the SRC for all images, if desired. - FM
+ */
+ if (clickable_images &&
+ present && present[HTML_IMG_SRC] &&
+ value[HTML_IMG_SRC] && *value[HTML_IMG_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_IMG_SRC]);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '\0' && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '\0' && *href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ /*
+ * If it's an ISMAP and/or USEMAP, or graphic for an
+ * anchor, end that anchor and start one for the SRC. - FM
+ */
+ if (me->inA) {
+ /*
+ * If we have a USEMAP, end this anchor and
+ * start a new one for the client-side MAP. - FM
+ */
+ if (map_href) {
+ if (dest_ismap) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ HTML_put_string(me, "[ISMAP]");
+ } else if (dest) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ HTML_put_string(me, "[LINK]");
+ }
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ if (dest_ismap || dest)
+ HTML_put_character(me, '-');
+ if (id_string) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ map_href, /* Addresss */
+ INTERN_LT); /* Type */
+ if (me->CurrentA && title) {
+ if ((dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ )) != NULL) {
+ if (!HTAnchor_title(dest))
+ HTAnchor_setTitle(dest, title);
+ }
+ }
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldA == FALSE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ }
+ me->inBoldA = TRUE;
+ } else {
+ HTML_put_character(me, ' ');/* space char may be ignored */
+ me->in_word = NO;
+ }
+ HTML_put_string(me, alt_string);
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ HTML_put_character(me, '-');
+ StrAllocCopy(alt_string,
+ ((present &&
+ present[HTML_IMG_ISOBJECT]) ?
+ ((map_href || dest_ismap) ?
+ "(IMAGE)" : "(OBJECT)") : "[IMAGE]"));
+ if (id_string && !map_href) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ }
+ } else if (map_href) {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ if (id_string) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ map_href, /* Addresss */
+ INTERN_LT); /* Type */
+ if (me->CurrentA && title) {
+ if ((dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ )) != NULL) {
+ if (!HTAnchor_title(dest))
+ HTAnchor_setTitle(dest, title);
+ }
+ }
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldA == FALSE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ me->inBoldA = TRUE;
+ HTML_put_string(me, alt_string);
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ HTML_put_character(me, '-');
+ StrAllocCopy(alt_string,
+ ((present &&
+ present[HTML_IMG_ISOBJECT]) ?
+ "(IMAGE)" : "[IMAGE]"));
+ } else {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ if (id_string) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ }
+ }
+
+ /*
+ * Create the link to the SRC. - FM
+ */
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ (HTLinkType*)0); /* Type */
+ FREE(href);
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, alt_string);
+ if (!me->inA) {
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ } else {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ me->inBoldA = TRUE;
+ }
+ } else if (map_href) {
+ if (me->inA) {
+ /*
+ * We're in an anchor and have a USEMAP, so end the anchor
+ * and start a new one for the client-side MAP. - FM
+ */
+ if (dest_ismap) {
+ HTML_put_character(me, ' ');/* space char may be ignored */
+ me->in_word = NO;
+ HTML_put_string(me, "[ISMAP]");
+ } else if (dest) {
+ HTML_put_character(me, ' ');/* space char may be ignored */
+ me->in_word = NO;
+ HTML_put_string(me, "[LINK]");
+ }
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ if (dest_ismap || dest) {
+ HTML_put_character(me, '-');
+ }
+ } else {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ map_href, /* Addresss */
+ INTERN_LT); /* Type */
+ if (me->CurrentA && title) {
+ if ((dest = HTAnchor_parent(
+ HTAnchor_followMainLink((HTAnchor*)me->CurrentA)
+ )) != NULL) {
+ if (!HTAnchor_title(dest))
+ HTAnchor_setTitle(dest, title);
+ }
+ }
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldA == FALSE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ }
+ me->inBoldA = TRUE;
+ HTML_put_string(me, alt_string);
+ if (!me->inA) {
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ }
+ } else {
+ /*
+ * Just put in the ALT or pseudo-ALT string
+ * for the current anchor or inline, with an
+ * ID link if indicated. - FM
+ */
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ if (id_string) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ }
+ HTML_put_string(me, alt_string);
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ FREE(map_href);
+ FREE(alt_string);
+ FREE(id_string);
+ FREE(title);
+ dest = NULL;
+ dest_ismap = FALSE;
+ break;
+
+ case HTML_MAP:
+ /*
+ * Load id_string if we have a NAME or ID. - FM
+ */
+ if (present && present[HTML_MAP_NAME] &&
+ value[HTML_MAP_NAME] && *value[HTML_MAP_NAME]) {
+ StrAllocCopy(id_string, value[HTML_MAP_NAME]);
+ } else if (present && present[HTML_MAP_ID] &&
+ value[HTML_MAP_ID] && *value[HTML_MAP_ID]) {
+ StrAllocCopy(id_string, value[HTML_MAP_ID]);
+ }
+ if (id_string) {
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ if (*id_string == '\0') {
+ FREE(id_string);
+ }
+ }
+
+ /*
+ * Load map_address. - FM
+ */
+ if (id_string) {
+ /*
+ * The MAP must be in the current stream, even if it
+ * had a BASE tag, so we'll use its address here, but
+ * still use the BASE, if present, when resolving the
+ * AREA elements in it's content, unless the AREA's
+ * HREF is a lone fragment and LYSeekFragAREAinCur is
+ * set. - FM && KW
+ */
+ StrAllocCopy(me->map_address, me->node_anchor->address);
+ if ((cp = strrchr(me->map_address, '#')) != NULL)
+ *cp = '\0';
+ StrAllocCat(me->map_address, "#");
+ StrAllocCat(me->map_address, id_string);
+ FREE(id_string);
+ if (present && present[HTML_MAP_TITLE] &&
+ value[HTML_MAP_TITLE] && *value[HTML_MAP_TITLE] != '\0') {
+ StrAllocCopy(title, value[HTML_MAP_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ if (*title == '\0') {
+ FREE(title);
+ }
+ }
+ LYAddImageMap(me->map_address, title, me->node_anchor);
+ FREE(title);
+ }
+ break;
+
+ case HTML_AREA:
+ if (me->map_address &&
+ present && present[HTML_AREA_HREF] &&
+ value[HTML_AREA_HREF] && *value[HTML_AREA_HREF]) {
+ /*
+ * Resolve the HREF. - FM
+ */
+ StrAllocCopy(href, value[HTML_AREA_HREF]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+
+ /*
+ * Check whether a BASE tag is in effect, and use it
+ * for resolving, even though we used this stream's
+ * address for locating the MAP itself, unless the
+ * HREF is a lone fragment and LYSeekFragAREAinCur
+ * is set. - FM
+ */
+ if (((me->inBASE && *href != '\0') &&
+ !(*href == '#' && LYSeekFragAREAinCur == TRUE)) &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((((me->inBASE && *href != '\0') &&
+ !(*href == '#' &&
+ LYSeekFragAREAinCur == TRUE)))
+ ?
+ me->base_href : me->node_anchor->address));
+ if (!(url_type = is_url(href))) {
+ temp = HTParse(href, me->node_anchor->address, PARSE_ALL);
+ if (!(temp && *temp)) {
+ FREE(href);
+ FREE(temp);
+ break;
+ }
+ StrAllocCopy(href, temp);
+ FREE(temp);
+ }
+
+ /*
+ * Check for an ALT. - FM
+ */
+ if (present[HTML_AREA_ALT] &&
+ value[HTML_AREA_ALT] && *value[HTML_AREA_ALT]) {
+ StrAllocCopy(alt_string, value[HTML_AREA_ALT]);
+ } else if (present[HTML_AREA_TITLE] &&
+ value[HTML_AREA_TITLE] && *value[HTML_AREA_TITLE]) {
+ /*
+ * Use the TITLE as an ALT. - FM
+ */
+ StrAllocCopy(alt_string, value[HTML_AREA_TITLE]);
+ }
+ if (alt_string != NULL) {
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&alt_string,
+ me->UsePlainSpace, me->HiddenValue);
+ /*
+ * Make sure it's not just space(s). - FM
+ */
+ LYTrimHead(alt_string);
+ LYTrimTail(alt_string);
+ if (*alt_string == '\0') {
+ StrAllocCopy(alt_string, href);
+ }
+ } else {
+ /*
+ * Use the HREF as an ALT. - FM
+ */
+ StrAllocCopy(alt_string, href);
+ }
+
+ LYAddMapElement(me->map_address, href, alt_string,
+ me->node_anchor, intern_flag);
+ FREE(href);
+ FREE(alt_string);
+ }
+ break;
+
+ case HTML_PARAM:
+ /*
+ * We may need to look at this someday to deal with
+ * MAPs, OBJECTs or APPLETs optimally, but just ignore
+ * it for now. - FM
+ */
+ break;
+
+ case HTML_BODYTEXT:
+ CHECK_ID(HTML_BODYTEXT_ID);
+ /*
+ * We may need to look at this someday to deal with
+ * OBJECTs optimally, but just ignore it for now. - FM
+ */
+ break;
+
+ case HTML_TEXTFLOW:
+ CHECK_ID(HTML_BODYTEXT_ID);
+ /*
+ * We may need to look at this someday to deal with
+ * APPLETs optimally, but just ignore it for now. - FM
+ */
+ break;
+
+ case HTML_FIG:
+ me->inFIG = TRUE;
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (!present ||
+ (present && !present[HTML_FIG_ISOBJECT])) {
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ me->inFIGwithP = TRUE;
+ } else {
+ me->inFIGwithP = FALSE;
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ }
+ CHECK_ID(HTML_FIG_ID);
+ me->in_word = NO;
+ me->inP = FALSE;
+
+ if (clickable_images && present && present[HTML_FIG_SRC] &&
+ value[HTML_FIG_SRC] && *value[HTML_FIG_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_FIG_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ if (*href) {
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, (present[HTML_FIG_ISOBJECT] ?
+ (present[HTML_FIG_IMAGEMAP] ?
+ "(IMAGE)" : "(OBJECT)") : "[FIGURE]"));
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ HTML_put_character(me, '-');
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ FREE(href);
+ }
+ break;
+
+ case HTML_OBJECT:
+ if (!me->object_started) {
+ /*
+ * This is an outer OBJECT start tag,
+ * i.e., not a nested OBJECT, so save
+ * it's relevant attributes. - FM
+ */
+ if (present) {
+ if (present[HTML_OBJECT_DECLARE])
+ me->object_declare = TRUE;
+ if (present[HTML_OBJECT_SHAPES])
+ me->object_shapes = TRUE;
+ if (present[HTML_OBJECT_ISMAP])
+ me->object_ismap = TRUE;
+ if (present[HTML_OBJECT_USEMAP] &&
+ value[HTML_OBJECT_USEMAP] && *value[HTML_OBJECT_USEMAP]) {
+ StrAllocCopy(me->object_usemap, value[HTML_OBJECT_USEMAP]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&me->object_usemap);
+ if (*me->object_usemap == '\0') {
+ FREE(me->object_usemap);
+ }
+ }
+ if (present[HTML_OBJECT_ID] &&
+ value[HTML_OBJECT_ID] && *value[HTML_OBJECT_ID]) {
+ StrAllocCopy(me->object_id, value[HTML_OBJECT_ID]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&me->object_id);
+ if (*me->object_id == '\0') {
+ FREE(me->object_id);
+ }
+ }
+ if (present[HTML_OBJECT_TITLE] &&
+ value[HTML_OBJECT_TITLE] && *value[HTML_OBJECT_TITLE]) {
+ StrAllocCopy(me->object_title, value[HTML_OBJECT_TITLE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&me->object_title, TRUE, FALSE);
+ LYTrimHead(me->object_title);
+ LYTrimTail(me->object_title);
+ if (me->object_title == '\0') {
+ FREE(me->object_title);
+ }
+ }
+ if (present[HTML_OBJECT_DATA] &&
+ value[HTML_OBJECT_DATA] && *value[HTML_OBJECT_DATA]) {
+ StrAllocCopy(me->object_data, value[HTML_OBJECT_DATA]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&me->object_data);
+ if (*me->object_data == '\0') {
+ FREE(me->object_data);
+ }
+ }
+ if (present[HTML_OBJECT_TYPE] &&
+ value[HTML_OBJECT_TYPE] && *value[HTML_OBJECT_TYPE]) {
+ StrAllocCopy(me->object_type, value[HTML_OBJECT_TYPE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&me->object_type, TRUE, FALSE);
+ LYTrimHead(me->object_type);
+ LYTrimTail(me->object_type);
+ if (me->object_type == '\0') {
+ FREE(me->object_type);
+ }
+ }
+ if (present[HTML_OBJECT_CLASSID] &&
+ value[HTML_OBJECT_CLASSID] &&
+ *value[HTML_OBJECT_CLASSID]) {
+ StrAllocCopy(me->object_classid,
+ value[HTML_OBJECT_CLASSID]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&me->object_classid, TRUE, FALSE);
+ LYTrimHead(me->object_classid);
+ LYTrimTail(me->object_classid);
+ if (me->object_classid == '\0') {
+ FREE(me->object_classid);
+ }
+ }
+ if (present[HTML_OBJECT_CODEBASE] &&
+ value[HTML_OBJECT_CODEBASE] &&
+ *value[HTML_OBJECT_CODEBASE]) {
+ StrAllocCopy(me->object_codebase,
+ value[HTML_OBJECT_CODEBASE]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&me->object_codebase);
+ if (*me->object_codebase == '\0') {
+ FREE(me->object_codebase);
+ }
+ }
+ if (present[HTML_OBJECT_CODETYPE] &&
+ value[HTML_OBJECT_CODETYPE] &&
+ *value[HTML_OBJECT_CODETYPE]) {
+ StrAllocCopy(me->object_codetype,
+ value[HTML_OBJECT_CODETYPE]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&me->object_codetype, TRUE, FALSE);
+ LYTrimHead(me->object_codetype);
+ LYTrimTail(me->object_codetype);
+ if (me->object_codetype == '\0') {
+ FREE(me->object_codetype);
+ }
+ }
+ if (present[HTML_OBJECT_NAME] &&
+ value[HTML_OBJECT_NAME] && *value[HTML_OBJECT_NAME]) {
+ StrAllocCopy(me->object_name, value[HTML_OBJECT_NAME]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&me->object_name, TRUE, FALSE);
+ LYTrimHead(me->object_name);
+ LYTrimTail(me->object_name);
+ if (me->object_name == '\0') {
+ FREE(me->object_name);
+ }
+ }
+ }
+ /*
+ * Set flag that we are accumulating OBJECT content. - FM
+ */
+ me->object_started = TRUE;
+ }
+ break;
+
+ case HTML_OVERLAY:
+ if (clickable_images && me->inFIG &&
+ present && present[HTML_OVERLAY_SRC] &&
+ value[HTML_OVERLAY_SRC] && *value[HTML_OVERLAY_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_OVERLAY_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ if (*href) {
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ HTML_put_character(me, ' ');
+ HText_appendCharacter(me->text, '+');
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, "[OVERLAY]");
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ FREE(href);
+ }
+ break;
+
+ case HTML_APPLET:
+ me->inAPPLET = TRUE;
+ me->inAPPLETwithP = FALSE;
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ /*
+ * Load id_string if we have an ID or NAME. - FM
+ */
+ if (present && present[HTML_APPLET_ID] &&
+ value[HTML_APPLET_ID] && *value[HTML_APPLET_ID]) {
+ StrAllocCopy(id_string, value[HTML_APPLET_ID]);
+ } else if (present && present[HTML_APPLET_NAME] &&
+ value[HTML_APPLET_NAME] && *value[HTML_APPLET_NAME]) {
+ StrAllocCopy(id_string, value[HTML_APPLET_NAME]);
+ }
+ if (id_string) {
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ LYHandleID(me, id_string);
+ FREE(id_string);
+ }
+ me->in_word = NO;
+
+ /*
+ * If there's an ALT string, use it, unless the ALT string
+ * is zero-length and we are making all sources links. - FM
+ */
+ if (present && present[HTML_APPLET_ALT] && value[HTML_APPLET_ALT] &&
+ (!clickable_images ||
+ (clickable_images && *value[HTML_APPLET_ALT] != '\0'))) {
+ StrAllocCopy(alt_string, value[HTML_APPLET_ALT]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&alt_string,
+ me->UsePlainSpace, me->HiddenValue);
+ /*
+ * If it's all spaces and we are making sources links,
+ * treat it as zero-length. - FM
+ */
+ if (clickable_images) {
+ LYTrimHead(alt_string);
+ LYTrimTail(alt_string);
+ if (*alt_string == '\0') {
+ StrAllocCopy(alt_string, "[APPLET]");
+ }
+ }
+
+ } else {
+ if (clickable_images)
+ StrAllocCopy(alt_string, "[APPLET]");
+ else
+ StrAllocCopy(alt_string, "");
+ }
+
+ /*
+ * If we're making all sources links, get the source. - FM
+ */
+ if (clickable_images && present && present[HTML_APPLET_CODE] &&
+ value[HTML_APPLET_CODE] && *value[HTML_APPLET_CODE] != '\0') {
+ char * base = NULL;
+ char * code = NULL;
+
+ /*
+ * Check for a CODEBASE attribute. - FM
+ */
+ if (present[HTML_APPLET_CODEBASE] &&
+ value[HTML_APPLET_CODEBASE] && *value[HTML_APPLET_CODEBASE]) {
+ StrAllocCopy(base, value[HTML_APPLET_CODEBASE]);
+ collapse_spaces(base);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&base);
+ /*
+ * Force it to be a directory. - FM
+ */
+ if (*base == '\0')
+ StrAllocCopy(base, "/");
+ if (base[strlen(base)-1] != '/')
+ StrAllocCat(base, "/");
+ url_type = LYLegitimizeHREF(me, (char**)&base, TRUE, FALSE);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&base,
+ (me->inBASE ?
+ me->base_href : me->node_anchor->address));
+
+ if (!(url_type = is_url(base))) {
+ /*
+ * Check whether a base tag is in effect.
+ */
+ if (me->inBASE) {
+ temp = HTParse(base, me->base_href, PARSE_ALL);
+ } else {
+ temp = HTParse(base, me->node_anchor->address,
+ PARSE_ALL);
+ }
+ StrAllocCopy(base, temp);
+ FREE(temp);
+ }
+ } else {
+ if (me->inBASE) {
+ StrAllocCopy(base, me->base_href);
+ } else {
+ StrAllocCopy(base, me->node_anchor->address);
+ }
+ }
+
+ StrAllocCopy(code, value[HTML_APPLET_CODE]);
+ url_type = LYLegitimizeHREF(me, (char**)&code, TRUE, FALSE);
+ href = HTParse(code, base, PARSE_ALL);
+ FREE(base);
+ FREE(code);
+
+ if (href && *href) {
+ if (me->inA) {
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ HTML_put_character(me, '-');
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ (HTLinkType*)0); /* Type */
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, alt_string);
+ if (me->inA == FALSE) {
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ }
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ FREE(href);
+ } else if (*alt_string) {
+ /*
+ * Just put up the ALT string, if non-zero. - FM
+ */
+ HTML_put_string(me, alt_string);
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ FREE(alt_string);
+ FREE(id_string);
+ break;
+
+ case HTML_BGSOUND:
+ /*
+ * If we're making all sources links, get the source. - FM
+ */
+ if (clickable_images && present && present[HTML_BGSOUND_SRC] &&
+ value[HTML_BGSOUND_SRC] && *value[HTML_BGSOUND_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_BGSOUND_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ if (*href == '\0') {
+ FREE(href);
+ break;
+ }
+
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ if (me->inA) {
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ HTML_put_character(me, '-');
+ } else {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, "[BGSOUND]");
+ if (me->inA == FALSE) {
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ }
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ FREE(href);
+ }
+ break;
+
+ case HTML_EMBED:
+ if (pseudo_inline_alts || clickable_images)
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ /*
+ * Load id_string if we have an ID or NAME. - FM
+ */
+ if (present && present[HTML_EMBED_ID] &&
+ value[HTML_EMBED_ID] && *value[HTML_EMBED_ID]) {
+ StrAllocCopy(id_string, value[HTML_EMBED_ID]);
+ } else if (present && present[HTML_EMBED_NAME] &&
+ value[HTML_EMBED_NAME] && *value[HTML_EMBED_NAME]) {
+ StrAllocCopy(id_string, value[HTML_EMBED_NAME]);
+ }
+ if (id_string) {
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ LYHandleID(me, id_string);
+ FREE(id_string);
+ }
+ if (pseudo_inline_alts || clickable_images)
+ me->in_word = NO;
+
+ /*
+ * If there's an ALT string, use it, unless the ALT string
+ * is zero-length and we are making all sources links. - FM
+ */
+ if (present && present[HTML_EMBED_ALT] && value[HTML_EMBED_ALT] &&
+ (!clickable_images ||
+ (clickable_images && *value[HTML_EMBED_ALT] != '\0'))) {
+ StrAllocCopy(alt_string, value[HTML_EMBED_ALT]);
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&alt_string,
+ me->UsePlainSpace, me->HiddenValue);
+ /*
+ * If it's all spaces and we are making sources links,
+ * treat it as zero-length. - FM
+ */
+ if (clickable_images) {
+ LYTrimHead(alt_string);
+ LYTrimTail(alt_string);
+ if (*alt_string == '\0') {
+ StrAllocCopy(alt_string, "[EMBED]");
+ }
+ }
+ } else {
+ if (pseudo_inline_alts || clickable_images)
+ StrAllocCopy(alt_string, "[EMBED]");
+ else
+ StrAllocCopy(alt_string, "");
+ }
+
+ /*
+ * If we're making all sources links, get the source. - FM
+ */
+ if (clickable_images && present && present[HTML_EMBED_SRC] &&
+ value[HTML_EMBED_SRC] && *value[HTML_EMBED_SRC] != '\0') {
+ StrAllocCopy(href, value[HTML_EMBED_SRC]);
+ CHECK_FOR_INTERN(href);
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ if (*href != '\0') {
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '#' &&
+ me->inBASE) ?
+ me->base_href : me->node_anchor->address));
+
+ if (me->inA) {
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ HTML_put_character(me, '-');
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ INTERN_LT); /* Type */
+ me->CurrentANum = HText_beginAnchor(me->text,
+ me->inUnderline,
+ me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, alt_string);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ if (me->inA == FALSE) {
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ }
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ FREE(href);
+ } else if (*alt_string) {
+ /*
+ * Just put up the ALT string, if non-zero. - FM
+ */
+ HTML_put_string(me, alt_string);
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ me->in_word = NO;
+ }
+ FREE(alt_string);
+ FREE(id_string);
+ break;
+
+ case HTML_CREDIT:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ me->inCREDIT = TRUE;
+ CHECK_ID(HTML_CREDIT_ID);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "CREDIT:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+
+ if (me->inFIG)
+ /*
+ * Assume all text in the FIG container is intended
+ * to be paragraphed. - FM
+ */
+ me->inFIGwithP = TRUE;
+
+ if (me->inAPPLET)
+ /*
+ * Assume all text in the APPLET container is intended
+ * to be paragraphed. - FM
+ */
+ me->inAPPLETwithP = TRUE;
+
+ me->inLABEL = TRUE;
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_CAPTION:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ me->inCAPTION = TRUE;
+ CHECK_ID(HTML_CAPTION_ID);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "CAPTION:");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+
+ if (me->inFIG)
+ /*
+ * Assume all text in the FIG container is intended
+ * to be paragraphed. - FM
+ */
+ me->inFIGwithP = TRUE;
+
+ if (me->inAPPLET)
+ /*
+ * Assume all text in the APPLET container is intended
+ * to be paragraphed. - FM
+ */
+ me->inAPPLETwithP = TRUE;
+
+ me->inLABEL = TRUE;
+ me->in_word = NO;
+ me->inP = FALSE;
+ break;
+
+ case HTML_FORM:
+ {
+ char * action = NULL;
+ char * method = NULL;
+ char * enctype = NULL;
+ CONST char * accept_cs = NULL;
+
+ HTChildAnchor * source;
+ HTAnchor *link_dest;
+
+ /*
+ * FORM may have been declared SGML_EMPTY in HTMLDTD.c, and
+ * SGML_character() in SGML.c may check for a FORM end
+ * tag to call HTML_end_element() directly (with a
+ * check in that to bypass decrementing of the HTML
+ * parser's stack), so if we have an open FORM, close
+ * that one now. - FM
+ */
+ if (me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML: Missing FORM end tag. Faking it!\n");
+ }
+ SET_SKIP_STACK(HTML_FORM);
+ HTML_end_element(me, HTML_FORM, (char **)&include);
+ }
+
+ /*
+ * Set to know we are in a new form.
+ */
+ me->inFORM = TRUE;
+
+ if (present && present[HTML_FORM_ACCEPT_CHARSET]) {
+ accept_cs = value[HTML_FORM_ACCEPT_CHARSET] ?
+ value[HTML_FORM_ACCEPT_CHARSET] : "UNKNOWN";
+ }
+ if (present && present[HTML_FORM_ACTION] &&
+ value[HTML_FORM_ACTION]) {
+ /*
+ * Prepare to do housekeeping on the reference. - FM
+ */
+ StrAllocCopy(action, value[HTML_FORM_ACTION]);
+ url_type = LYLegitimizeHREF(me, (char**)&action, TRUE, TRUE);
+
+ /*
+ * Check whether a base tag is in effect. Note that
+ * actions always are resolved w.r.t. to the base,
+ * even if the action is empty. - FM
+ */
+ if ((me->inBASE && me->base_href && *me->base_href) &&
+ (temp = HTParse(action, me->base_href, PARSE_ALL)) &&
+ *temp != '\0') {
+ /*
+ * Use action related to the base.
+ */
+ StrAllocCopy(action, temp);
+ } else if ((temp = HTParse(action,
+ me->node_anchor->address,
+ PARSE_ALL)) &&
+ *temp != '\0') {
+ /*
+ * Use action related to the current document.
+ */
+ StrAllocCopy(action, temp);
+ } else {
+ FREE(action);
+ }
+ FREE(temp);
+ }
+ if (!(action && *action)) {
+ if (me->inBASE && me->base_href && *me->base_href) {
+ StrAllocCopy(action, me->base_href);
+ } else {
+ StrAllocCopy(action, me->node_anchor->address);
+ }
+ }
+ if (action) {
+ source = HTAnchor_findChildAndLink(me->node_anchor,
+ NULL,
+ action,
+ (HTLinkType*)0);
+ if ((link_dest = HTAnchor_followMainLink((HTAnchor *)source)) != NULL) {
+ /*
+ * Memory leak fixed.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ auto char *cp_freeme = HTAnchor_address(link_dest);
+ if (cp_freeme != NULL) {
+ StrAllocCopy(action, cp_freeme);
+ FREE(cp_freeme);
+ } else {
+ StrAllocCopy(action, "");
+ }
+ }
+ }
+
+ if (present && present[HTML_FORM_METHOD])
+ StrAllocCopy(method, value[HTML_FORM_METHOD] ?
+ value[HTML_FORM_METHOD] : "GET");
+
+ if (present && present[HTML_FORM_ENCTYPE] &&
+ value[HTML_FORM_ENCTYPE] && *value[HTML_FORM_ENCTYPE]) {
+ StrAllocCopy(enctype, value[HTML_FORM_ENCTYPE]);
+ /*
+ * Force the enctype value to all lower case. - FM
+ */
+ for (cp = enctype; *cp; cp++)
+ *cp = TOLOWER(*cp);
+ }
+
+ if (present) {
+ /*
+ * Check for a TITLE attribute, and if none is present,
+ * check for a SUBJECT attribute as a synonym. - FM
+ */
+ if (present[HTML_FORM_TITLE] &&
+ value[HTML_FORM_TITLE] &&
+ *value[HTML_FORM_TITLE] != '\0') {
+ StrAllocCopy(title, value[HTML_FORM_TITLE]);
+ } else if (present[HTML_FORM_SUBJECT] &&
+ value[HTML_FORM_SUBJECT] &&
+ *value[HTML_FORM_SUBJECT] != '\0') {
+ StrAllocCopy(title, value[HTML_FORM_SUBJECT]);
+ }
+ if (title != NULL && *title != '\0') {
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&title, TRUE, FALSE);
+ LYTrimHead(title);
+ LYTrimTail(title);
+ if (*title == '\0') {
+ FREE(title);
+ }
+ }
+ }
+
+ HText_beginForm(action, method, enctype, title, accept_cs);
+
+ FREE(action);
+ FREE(method);
+ FREE(enctype);
+ FREE(title);
+ }
+ CHECK_ID(HTML_FORM_ID);
+ break;
+
+ case HTML_FIELDSET:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ CHECK_ID(HTML_FIELDSET_ID);
+ break;
+
+ case HTML_LEGEND:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ CHECK_ID(HTML_LEGEND_ID);
+ break;
+
+ case HTML_LABEL:
+ CHECK_ID(HTML_LABEL_ID);
+ break;
+
+ case HTML_KEYGEN:
+ CHECK_ID(HTML_KEYGEN_ID);
+ break;
+
+ case HTML_BUTTON:
+ {
+ InputFieldData I;
+ int chars;
+
+ /* init */
+ I.align=NULL; I.accept=NULL; I.checked=NO; I.class=NULL;
+ I.disabled=NO; I.error=NULL; I.height= NULL; I.id=NULL;
+ I.lang=NULL; I.max=NULL; I.maxlength=NULL; I.md=NULL;
+ I.min=NULL; I.name=NULL; I.size=NULL; I.src=NULL;
+ I.type=NULL; I.value=NULL; I.width=NULL;
+ I.accept_cs = NULL;
+ I.name_cs = ATTR_CS_IN;
+ I.value_cs = ATTR_CS_IN;
+
+ UPDATE_STYLE;
+ if ((present && present[HTML_BUTTON_TYPE] &&
+ value[HTML_BUTTON_TYPE]) &&
+ (!strcasecomp(value[HTML_BUTTON_TYPE], "submit") ||
+ !strcasecomp(value[HTML_BUTTON_TYPE], "reset"))) {
+ /*
+ * It's a button for submitting or resetting a form. - FM
+ */
+ I.type = value[HTML_BUTTON_TYPE];
+ } else {
+ /*
+ * Ugh, it's a button for a script. - FM
+ */
+ HTML_put_string(me," [BUTTON] ");
+ break;
+ }
+
+ /*
+ * Make sure we're in a form.
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: BUTTON tag not within FORM tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ /*
+ * We'll process it, since the chances of a crash are
+ * small, and we probably do have a form started. - FM
+ *
+ break;
+ */
+ }
+
+ /*
+ * Before any input field, add a collapsible space if
+ * we're not in a PRE block, to promote a wrap there
+ * for any long values that would extent past the right
+ * margin from our current position in the line. If
+ * we are in a PRE block, start a new line if the last
+ * line already is within 6 characters of the wrap point
+ * for PRE blocks. - FM
+ */
+ if (me->sp[0].tag_number != HTML_PRE && !me->inPRE &&
+ me->sp->style->freeFormat) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ } else if (HText_LastLineSize(me->text, FALSE) > (LYcols - 7)) {
+ HTML_put_character(me, '\n');
+ me->in_word = NO;
+ }
+ HTML_put_character(me, '(');
+
+ if (!(present && present[HTML_BUTTON_NAME] &&
+ value[HTML_BUTTON_NAME])) {
+ I.name = "";
+ } else if (strchr(value[HTML_BUTTON_NAME], '&') == NULL) {
+ I.name = value[HTML_BUTTON_NAME];
+ } else {
+ StrAllocCopy(I_name, value[HTML_BUTTON_NAME]);
+ UNESCAPE_FIELDNAME_TO_STD(&I_name);
+ I.name = I_name;
+ }
+
+ if (present && present[HTML_BUTTON_VALUE] &&
+ value[HTML_BUTTON_VALUE] && *value[HTML_BUTTON_VALUE]) {
+ /*
+ * Convert any HTML entities or decimal escaping. - FM
+ */
+ int len;
+
+ StrAllocCopy(I_value, value[HTML_BUTTON_VALUE]);
+ me->UsePlainSpace = TRUE;
+ TRANSLATE_AND_UNESCAPE_ENTITIES(&I_value, TRUE, me->HiddenValue);
+ me->UsePlainSpace = FALSE;
+ I.value = I_value;
+ /*
+ * Convert any newlines or tabs to spaces,
+ * and trim any lead or trailing spaces. - FM
+ */
+ convert_to_spaces(I.value, FALSE);
+ while (I.value && I.value[0] == ' ')
+ I.value++;
+ len = strlen(I.value) - 1;
+ while (len > 0 && I.value[len] == ' ')
+ I.value[len--] = '\0';
+ }
+
+ if (present && present[HTML_BUTTON_DISABLED])
+ I.disabled = YES;
+
+ if (present && present[HTML_BUTTON_CLASS] && /* Not yet used. */
+ value[HTML_BUTTON_CLASS] && *value[HTML_BUTTON_CLASS])
+ I.class = value[HTML_BUTTON_CLASS];
+
+ if (present && present[HTML_BUTTON_ID] &&
+ value[HTML_BUTTON_ID] && *value[HTML_BUTTON_ID]) {
+ I.id = value[HTML_BUTTON_ID];
+ CHECK_ID(HTML_BUTTON_ID);
+ }
+
+ if (present && present[HTML_BUTTON_LANG] && /* Not yet used. */
+ value[HTML_BUTTON_LANG] && *value[HTML_BUTTON_LANG])
+ I.lang = value[HTML_BUTTON_LANG];
+
+ chars = HText_beginInput(me->text, me->inUnderline, &I);
+ /*
+ * Submit and reset buttons have values which don't change,
+ * so HText_beginInput() sets I.value to the string which
+ * should be displayed, and we'll enter that instead of
+ * underscore placeholders into the HText structure to
+ * see it instead of underscores when dumping or printing.
+ * We also won't worry about a wrap in PRE blocks, because
+ * the line editor never is invoked for submit or reset
+ * buttons. - LE & FM
+ */
+ if (me->sp[0].tag_number == HTML_PRE ||
+ !me->sp->style->freeFormat) {
+ /*
+ * We have a submit or reset button in a PRE block,
+ * so output the entire value from the markup. If
+ * it extends to the right margin, it will wrap
+ * there, and only the portion before that wrap will
+ * be hightlighted on screen display (Yuk!) but we
+ * may as well show the rest of the full value on
+ * the next or more lines. - FM
+ */
+ while (I.value[i])
+ HTML_put_character(me, I.value[i++]);
+ } else {
+ /*
+ * The submit or reset button is not in a PRE block.
+ * Note that if a wrap occurs before outputting the
+ * entire value, the wrapped portion will not be
+ * highlighted or clearly indicated as part of the
+ * link for submission or reset (Yuk!).
+ * We'll replace any spaces in the submit or reset
+ * button value with nbsp, to promote a wrap at the
+ * space we ensured would be present before the start
+ * of the string, as when we use all underscores
+ * instead of the INPUT's actual value, but we could
+ * still get a wrap at the right margin, instead, if
+ * the value is greater than a line width for the
+ * current style. Also, if chars somehow ended up
+ * longer than the length of the actual value
+ * (shouldn't have), we'll continue padding with nbsp
+ * up to the length of chars. - FM
+ */
+ for (i = 0; I.value[i]; i++) {
+ HTML_put_character(me,
+ (I.value[i] == ' ' ?
+ HT_NON_BREAK_SPACE : I.value[i]));
+ }
+ while (i < chars) {
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ }
+ }
+ HTML_put_character(me, ')');
+ if (me->sp[0].tag_number != HTML_PRE &&
+ me->sp->style->freeFormat) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ FREE(I_value);
+ FREE(I_name);
+ }
+ break;
+
+ case HTML_INPUT:
+ {
+ InputFieldData I;
+ int chars;
+ BOOL UseALTasVALUE = FALSE;
+ BOOL HaveSRClink = FALSE;
+ BOOL IsSubmitOrReset = FALSE;
+
+ /* init */
+ I.align=NULL; I.accept=NULL; I.checked=NO; I.class=NULL;
+ I.disabled=NO; I.error=NULL; I.height= NULL; I.id=NULL;
+ I.lang=NULL; I.max=NULL; I.maxlength=NULL; I.md=NULL;
+ I.min=NULL; I.name=NULL; I.size=NULL; I.src=NULL;
+ I.type=NULL; I.value=NULL; I.width=NULL;
+ I.accept_cs = NULL;
+ I.name_cs = ATTR_CS_IN;
+ I.value_cs = ATTR_CS_IN;
+
+ UPDATE_STYLE;
+
+ /*
+ * Before any input field, add a collapsible space if
+ * we're not in a PRE block, to promote a wrap there
+ * for any long values that would extent past the right
+ * margin from our current position in the line. If
+ * we are in a PRE block, start a new line if the last
+ * line already is within 6 characters of the wrap point
+ * for PRE blocks. - FM
+ */
+ if (me->sp[0].tag_number != HTML_PRE && !me->inPRE &&
+ me->sp->style->freeFormat) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ } else if (HText_LastLineSize(me->text, FALSE) > (LYcols - 7)) {
+ HTML_put_character(me, '\n');
+ me->in_word = NO;
+ }
+
+ /*
+ * Get the TYPE and make sure we can handle it. - FM
+ */
+ if (present && present[HTML_INPUT_TYPE] &&
+ value[HTML_INPUT_TYPE] && *value[HTML_INPUT_TYPE]) {
+ I.type = value[HTML_INPUT_TYPE];
+
+ if (!strcasecomp(I.type, "range")) {
+ if (present[HTML_INPUT_MIN])
+ I.min = value[HTML_INPUT_MIN];
+ if (present[HTML_INPUT_MAX])
+ I.max = value[HTML_INPUT_MAX];
+ /*
+ * Not yet implemented.
+ */
+ HTML_put_string(me,"[RANGE Input] (Not yet implemented.)");
+#ifdef NOTDEFINED
+ if (me->inFORM)
+ HText_DisableCurrentForm();
+#endif /* NOTDEFINED */
+ if (TRACE)
+ fprintf(stderr, "HTML: Ignoring TYPE=\"range\"\n");
+ break;
+
+ } else if (!strcasecomp(I.type, "file")) {
+ if (present[HTML_INPUT_ACCEPT])
+ I.accept = value[HTML_INPUT_ACCEPT];
+ /*
+ * Not yet implemented.
+ */
+ if (me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text,
+ LY_UNDERLINE_START_CHAR);
+ }
+ HTML_put_string(me,"[FILE Input] (Not yet implemented.)");
+ if (me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text,
+ LY_UNDERLINE_END_CHAR);
+ }
+#ifdef NOTDEFINED
+ if (me->inFORM)
+ HText_DisableCurrentForm();
+#endif /* NOTDEFINED */
+ if (TRACE)
+ fprintf(stderr, "HTML: Ignoring TYPE=\"file\"\n");
+ break;
+
+ } else if (!strcasecomp(I.type, "button")) {
+ /*
+ * Ugh, a button for a script.
+ */
+ HTML_put_string(me,"[BUTTON] ");
+ break;
+ }
+ }
+
+ /*
+ * Check if we're in a form. - FM
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: INPUT tag not within FORM tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ /*
+ * We'll process it, since the chances of a crash are
+ * small, and we probably do have a form started. - FM
+ *
+ break;
+ */
+ }
+
+ /*
+ * Check for an unclosed TEXTAREA.
+ */
+ if (me->inTEXTAREA) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: Missing TEXTAREA end tag.\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * Check for an unclosed SELECT, try to close it if found.
+ */
+ if (me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr, "HTML: Missing SELECT end tag, faking it...\n");
+ }
+ if (me->sp->tag_number != HTML_SELECT) {
+ SET_SKIP_STACK(HTML_SELECT);
+ }
+ HTML_end_element(me, HTML_SELECT, (char **)&include);
+ }
+
+ /*
+ * Handle the INPUT as for a FORM. - FM
+ */
+ if (!(present && present[HTML_INPUT_NAME] &&
+ value[HTML_INPUT_NAME])) {
+ I.name = "";
+ } else if (strchr(value[HTML_INPUT_NAME], '&') == NULL) {
+ I.name = value[HTML_INPUT_NAME];
+ } else {
+ StrAllocCopy(I_name, value[HTML_INPUT_NAME]);
+ UNESCAPE_FIELDNAME_TO_STD(&I_name);
+ I.name = I_name;
+ }
+ if ((present && present[HTML_INPUT_ALT] &&
+ value[HTML_INPUT_ALT] && *value[HTML_INPUT_ALT] &&
+ I.type && !strcasecomp(I.type, "image")) &&
+ !(present && present[HTML_INPUT_VALUE] &&
+ value[HTML_INPUT_VALUE] && *value[HTML_INPUT_VALUE])) {
+ /*
+ * This is a TYPE="image" using an ALT rather than
+ * VALUE attribute to indicate the link string for
+ * text clients or GUIs with image loading off, so
+ * set the flag to use that as if it were a VALUE
+ * attribute. - FM
+ */
+ UseALTasVALUE = TRUE;
+ }
+ if (clickable_images == TRUE &&
+ present && present[HTML_INPUT_SRC] &&
+ value[HTML_INPUT_SRC] && *value[HTML_INPUT_SRC] &&
+ I.type && !strcasecomp(I.type, "image")) {
+ StrAllocCopy(href, value[HTML_INPUT_SRC]);
+ /*
+ * We have a TYPE="image" with a non-zero-length SRC
+ * attribute and want clickable images. Make the
+ * SRC's value a link if it's still not zero-length
+ * legitiimizing it. - FM
+ */
+ url_type = LYLegitimizeHREF(me, (char**)&href, TRUE, TRUE);
+ if (*href) {
+ /*
+ * Check whether a base tag is in effect. - FM
+ */
+ if ((me->inBASE && *href != '#') &&
+ (temp = HTParse(href, me->base_href, PARSE_ALL)) &&
+ *temp != '\0')
+ /*
+ * Use reference related to the base.
+ */
+ StrAllocCopy(href, temp);
+ FREE(temp);
+
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ ((*href != '#' &&
+ me->inBASE) ?
+ me->base_href :
+ me->node_anchor->address));
+
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ NULL, /* Tag */
+ href, /* Addresss */
+ (HTLinkType*)0); /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, "[IMAGE]");
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ HTML_put_character(me, '-');
+ HaveSRClink = TRUE;
+ }
+ FREE(href);
+ }
+ if ((UseALTasVALUE == TRUE) ||
+ (present && present[HTML_INPUT_VALUE] &&
+ value[HTML_INPUT_VALUE] && *value[HTML_INPUT_VALUE])) {
+ /*
+ * Convert any HTML entities or decimal escaping. - FM
+ */
+ int CurrentCharSet = current_char_set;
+ BOOL CurrentEightBitRaw = HTPassEightBitRaw;
+ BOOLEAN CurrentUseDefaultRawMode = LYUseDefaultRawMode;
+ HTCJKlang CurrentHTCJK = HTCJK;
+ int len;
+
+ if (I.type && !strcasecomp(I.type, "hidden")) {
+ me->HiddenValue = TRUE;
+ current_char_set = 0; /* Default ISO-Latin1 */
+ LYUseDefaultRawMode = TRUE;
+ HTMLSetCharacterHandling(current_char_set);
+ }
+
+ if (!I.type)
+ me->UsePlainSpace = TRUE;
+ else if (!strcasecomp(I.type, "text") ||
+ !strcasecomp(I.type, "submit") ||
+ !strcasecomp(I.type, "image") ||
+ !strcasecomp(I.type, "reset"))
+ me->UsePlainSpace = TRUE;
+ StrAllocCopy(I_value,
+ ((UseALTasVALUE == TRUE) ?
+ value[HTML_INPUT_ALT] :
+ value[HTML_INPUT_VALUE]));
+ if (me->UsePlainSpace && !me->HiddenValue) {
+ I.value_cs = current_char_set;
+ }
+ TRANSLATE_AND_UNESCAPE_ENTITIES6(
+ &I_value,
+ ATTR_CS_IN,
+ I.value_cs,
+ (me->UsePlainSpace && !me->HiddenValue),
+ me->UsePlainSpace, me->HiddenValue);
+ I.value = I_value;
+ if (me->UsePlainSpace == TRUE) {
+ /*
+ * Convert any newlines or tabs to spaces,
+ * and trim any lead or trailing spaces. - FM
+ */
+ convert_to_spaces(I.value, FALSE);
+ while (I.value && I.value[0] == ' ')
+ I.value++;
+ len = strlen(I.value) - 1;
+ while (len > 0 && I.value[len] == ' ')
+ I.value[len--] = '\0';
+ }
+ me->UsePlainSpace = FALSE;
+
+
+ if (I.type && !strcasecomp(I.type, "hidden")) {
+ me->HiddenValue = FALSE;
+ current_char_set = CurrentCharSet;
+ LYUseDefaultRawMode = CurrentUseDefaultRawMode;
+ HTMLSetCharacterHandling(current_char_set);
+ HTPassEightBitRaw = CurrentEightBitRaw;
+ HTCJK = CurrentHTCJK;
+ }
+ } else if (HaveSRClink == TRUE) {
+ /*
+ * We put up an [IMAGE] link and '-' for a TYPE="image"
+ * and didn't get a VALUE or ALT string, so fake a
+ * "Submit" value. If we didn't put up a link, then
+ * HText_beginInput() will use "[IMAGE]-Submit". - FM
+ */
+ StrAllocCopy(I_value, "Submit");
+ I.value = I_value;
+ }
+ if (present && present[HTML_INPUT_CHECKED])
+ I.checked = YES;
+ if (present && present[HTML_INPUT_SIZE] &&
+ value[HTML_INPUT_SIZE] && *value[HTML_INPUT_SIZE])
+ I.size = value[HTML_INPUT_SIZE];
+ if (present && present[HTML_INPUT_MAXLENGTH] &&
+ value[HTML_INPUT_MAXLENGTH] && *value[HTML_INPUT_MAXLENGTH])
+ I.maxlength = value[HTML_INPUT_MAXLENGTH];
+ if (present && present[HTML_INPUT_DISABLED])
+ I.disabled = YES;
+
+ if (present && present[HTML_INPUT_ACCEPT_CHARSET]) { /* Not yet used. */
+ I.accept_cs = value[HTML_INPUT_ACCEPT_CHARSET] ?
+ value[HTML_INPUT_ACCEPT_CHARSET] : "UNKNOWN";
+ }
+ if (present && present[HTML_INPUT_ALIGN] && /* Not yet used. */
+ value[HTML_INPUT_ALIGN] && *value[HTML_INPUT_ALIGN])
+ I.align = value[HTML_INPUT_ALIGN];
+ if (present && present[HTML_INPUT_CLASS] && /* Not yet used. */
+ value[HTML_INPUT_CLASS] && *value[HTML_INPUT_CLASS])
+ I.class = value[HTML_INPUT_CLASS];
+ if (present && present[HTML_INPUT_ERROR] && /* Not yet used. */
+ value[HTML_INPUT_ERROR] && *value[HTML_INPUT_ERROR])
+ I.error = value[HTML_INPUT_ERROR];
+ if (present && present[HTML_INPUT_HEIGHT] && /* Not yet used. */
+ value[HTML_INPUT_HEIGHT] && *value[HTML_INPUT_HEIGHT])
+ I.height = value[HTML_INPUT_HEIGHT];
+ if (present && present[HTML_INPUT_WIDTH] && /* Not yet used. */
+ value[HTML_INPUT_WIDTH] && *value[HTML_INPUT_WIDTH])
+ I.width = value[HTML_INPUT_WIDTH];
+ if (present && present[HTML_INPUT_ID] &&
+ value[HTML_INPUT_ID] && *value[HTML_INPUT_ID]) {
+ I.id = value[HTML_INPUT_ID];
+ CHECK_ID(HTML_INPUT_ID);
+ }
+ if (present && present[HTML_INPUT_LANG] && /* Not yet used. */
+ value[HTML_INPUT_LANG] && *value[HTML_INPUT_LANG])
+ I.lang = value[HTML_INPUT_LANG];
+ if (present && present[HTML_INPUT_MD] && /* Not yet used. */
+ value[HTML_INPUT_MD] && *value[HTML_INPUT_MD])
+ I.md = value[HTML_INPUT_MD];
+
+ chars = HText_beginInput(me->text, me->inUnderline, &I);
+ /*
+ * Submit and reset buttons have values which don't change,
+ * so HText_beginInput() sets I.value to the string which
+ * should be displayed, and we'll enter that instead of
+ * underscore placeholders into the HText structure to
+ * see it instead of underscores when dumping or printing.
+ * We also won't worry about a wrap in PRE blocks, because
+ * the line editor never is invoked for submit or reset
+ * buttons. - LE & FM
+ */
+ if (I.type &&
+ (!strcasecomp(I.type,"submit") ||
+ !strcasecomp(I.type,"reset") ||
+ !strcasecomp(I.type,"image")))
+ IsSubmitOrReset = TRUE;
+
+ if (I.type && chars == 3 &&
+ !strcasecomp(I.type, "radio")) {
+ /*
+ * Put a (_) placeholder, and one space
+ * (collapsible) before the label that is
+ * expected to follow. - FM
+ */
+ HTML_put_string(me, "(_)");
+ chars = 0;
+ me->in_word = YES;
+ if (me->sp[0].tag_number != HTML_PRE &&
+ me->sp->style->freeFormat) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ } else if (I.type && chars == 3 &&
+ !strcasecomp(I.type, "checkbox")) {
+ /*
+ * Put a [_] placeholder, and one space
+ * (collapsible) before the label that is
+ * expected to follow. - FM
+ */
+ HTML_put_string(me, "[_]");
+ chars = 0;
+ me->in_word = YES;
+ if (me->sp[0].tag_number != HTML_PRE &&
+ me->sp->style->freeFormat) {
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ }
+ } else if ((me->sp[0].tag_number == HTML_PRE ||
+ !me->sp->style->freeFormat)
+ && chars > 6 &&
+ IsSubmitOrReset == FALSE) {
+ /*
+ * This is not a submit or reset button, and we are
+ * in a PRE block with a field intended to exceed 6
+ * character widths. The code inadequately handles
+ * INPUT fields in PRE tags if wraps occur (at the
+ * right margin) for the underscore placeholders.
+ * We'll put up a minimum of 6 underscores, since we
+ * should have wrapped artificially, above, if the
+ * INPUT begins within 6 columns of the right margin,
+ * and if any more would exceed the wrap column, we'll
+ * ignore them. Note that if we somehow get tripped
+ * up and a wrap still does occur before all 6 of the
+ * underscores are output, the wrapped ones won't be
+ * treated as part of the editing window, nor be
+ * highlighted when not editing (Yuk!). - FM
+ */
+ for (i = 0; i < 6; i++) {
+ HTML_put_character(me, '_');
+ chars--;
+ }
+ HText_setIgnoreExcess(me->text, TRUE);
+ }
+ if (IsSubmitOrReset == FALSE) {
+ /*
+ * This is not a submit or reset button,
+ * so output the rest of the underscore
+ * placeholders, if any more are needed. - FM
+ */
+ for (; chars > 0; chars--)
+ HTML_put_character(me, '_');
+ } else {
+ if (me->sp[0].tag_number == HTML_PRE ||
+ !me->sp->style->freeFormat) {
+ /*
+ * We have a submit or reset button in a PRE block,
+ * so output the entire value from the markup. If
+ * it extends to the right margin, it will wrap
+ * there, and only the portion before that wrap will
+ * be hightlighted on screen display (Yuk!) but we
+ * may as well show the rest of the full value on
+ * the next or more lines. - FM
+ */
+ while (I.value[i])
+ HTML_put_character(me, I.value[i++]);
+ } else {
+ /*
+ * The submit or reset button is not in a PRE block.
+ * Note that if a wrap occurs before outputting the
+ * entire value, the wrapped portion will not be
+ * highlighted or clearly indicated as part of the
+ * link for submission or reset (Yuk!).
+ * We'll replace any spaces in the submit or reset
+ * button value with nbsp, to promote a wrap at the
+ * space we ensured would be present before the start
+ * of the string, as when we use all underscores
+ * instead of the INPUT's actual value, but we could
+ * still get a wrap at the right margin, instead, if
+ * the value is greater than a line width for the
+ * current style. Also, if chars somehow ended up
+ * longer than the length of the actual value
+ * (shouldn't have), we'll continue padding with nbsp
+ * up to the length of chars. - FM
+ */
+ for (i = 0; I.value[i]; i++)
+ HTML_put_character(me,
+ (I.value[i] == ' ' ?
+ HT_NON_BREAK_SPACE : I.value[i]));
+ while (i < chars)
+ HTML_put_character(me, HT_NON_BREAK_SPACE);
+ }
+ }
+ HText_setIgnoreExcess(me->text, FALSE);
+ FREE(I_value);
+ FREE(I_name);
+ }
+ break;
+
+ case HTML_TEXTAREA:
+ /*
+ * Make sure we're in a form.
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: TEXTAREA start tag not within FORM tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ /*
+ * Too likely to cause a crash, so we'll ignore it. - FM
+ */
+ break;
+ }
+
+ /*
+ * Set to know we are in a textarea.
+ */
+ me->inTEXTAREA = TRUE;
+
+ /*
+ * Get ready for the value.
+ */
+ HTChunkClear(&me->textarea);
+ if (present && present[HTML_TEXTAREA_NAME] &&
+ value[HTML_TEXTAREA_NAME]) {
+ StrAllocCopy(me->textarea_name, value[HTML_TEXTAREA_NAME]);
+ me->textarea_name_cs = ATTR_CS_IN;
+ if (strchr(value[HTML_TEXTAREA_NAME], '&') != NULL) {
+ UNESCAPE_FIELDNAME_TO_STD(&me->textarea_name);
+ }
+ } else {
+ StrAllocCopy(me->textarea_name, "");
+ }
+
+ if (present && present[HTML_TEXTAREA_ACCEPT_CHARSET]) {
+ if (value[HTML_TEXTAREA_ACCEPT_CHARSET]) {
+ StrAllocCopy(me->textarea_accept_cs, value[HTML_TEXTAREA_ACCEPT_CHARSET]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&me->textarea_accept_cs);
+ } else {
+ StrAllocCopy(me->textarea_accept_cs, "UNKNOWN");
+ }
+ } else {
+ FREE(me->textarea_accept_cs);
+ }
+
+ if (present && present[HTML_TEXTAREA_COLS] &&
+ value[HTML_TEXTAREA_COLS] &&
+ isdigit((unsigned char)*value[HTML_TEXTAREA_COLS]))
+ StrAllocCopy(me->textarea_cols, value[HTML_TEXTAREA_COLS]);
+ else
+ StrAllocCopy(me->textarea_cols, "60");
+
+ if (present && present[HTML_TEXTAREA_ROWS] &&
+ value[HTML_TEXTAREA_ROWS] &&
+ isdigit((unsigned char)*value[HTML_TEXTAREA_ROWS]))
+ me->textarea_rows = atoi(value[HTML_TEXTAREA_ROWS]);
+ else
+ me->textarea_rows = 4;
+
+ if (present && present[HTML_TEXTAREA_DISABLED])
+ me->textarea_disabled = YES;
+ else
+ me->textarea_disabled = NO;
+
+ if (present && present[HTML_TEXTAREA_ID]
+ && value[HTML_TEXTAREA_ID] && *value[HTML_TEXTAREA_ID]) {
+ StrAllocCopy(id_string, value[HTML_TEXTAREA_ID]);
+ TRANSLATE_AND_UNESCAPE_TO_STD(&id_string);
+ if ((id_string != '\0') &&
+ (ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0))) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ StrAllocCopy(me->textarea_id, id_string);
+ } else {
+ FREE(me->textarea_id);
+ }
+ FREE(id_string);
+ } else {
+ FREE(me->textarea_id);
+ }
+ break;
+
+ case HTML_SELECT:
+ /*
+ * Check for an already open SELECT block. - FM
+ */
+ if (me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: SELECT start tag in SELECT element. Faking SELECT end tag. *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ if (me->sp->tag_number != HTML_SELECT) {
+ SET_SKIP_STACK(HTML_SELECT);
+ }
+ HTML_end_element(me, HTML_SELECT, (char **)&include);
+ }
+
+ /*
+ * Start a new SELECT block. - FM
+ */
+ LYHandleSELECT(me,
+ present, (CONST char **)value,
+ (char **)&include,
+ TRUE);
+ break;
+
+ case HTML_OPTION:
+ {
+ /*
+ * An option is a special case of an input field.
+ */
+ InputFieldData I;
+
+ /*
+ * Make sure we're in a select tag.
+ */
+ if (!me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: OPTION tag not within SELECT tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+
+ /*
+ * Too likely to cause a crash, so we'll ignore it. - FM
+ */
+ break;
+ }
+
+ if (!me->first_option) {
+ /*
+ * Finish the data off.
+ */
+ HTChunkTerminate(&me->option);
+
+ /*
+ * Finish the previous option @@@@@
+ */
+ HText_setLastOptionValue(me->text,
+ me->option.data,
+ me->LastOptionValue,
+ MIDDLE_ORDER,
+ me->LastOptionChecked,
+ me->UCLYhndl,
+ ATTR_CS_IN);
+ }
+
+ /*
+ * If its not a multiple option list and select popups
+ * are enabled, then don't use the checkbox/button method,
+ * and don't put anything on the screen yet.
+ */
+ if (me->first_option ||
+ HTCurSelectGroupType == F_CHECKBOX_TYPE ||
+ LYSelectPopups == FALSE) {
+ if (HTCurSelectGroupType == F_CHECKBOX_TYPE ||
+ LYSelectPopups == FALSE) {
+ /*
+ * Start a newline before each option.
+ */
+ LYEnsureSingleSpace(me);
+ } else {
+ /*
+ * Add option list designation character.
+ */
+ HText_appendCharacter(me->text, '[');
+ me->in_word = YES;
+ }
+
+ /*
+ * Inititialize.
+ */
+ I.align=NULL; I.accept=NULL; I.checked=NO; I.class=NULL;
+ I.disabled=NO; I.error=NULL; I.height= NULL; I.id=NULL;
+ I.lang=NULL; I.max=NULL; I.maxlength=NULL; I.md=NULL;
+ I.min=NULL; I.name=NULL; I.size=NULL; I.src=NULL;
+ I.type=NULL; I.value=NULL; I.width=NULL;
+ I.accept_cs = NULL;
+ I.name_cs = -1;
+ I.value_cs = current_char_set;
+
+ I.type = "OPTION";
+
+ if ((present && present[HTML_OPTION_SELECTED]) ||
+ (me->first_option && LYSelectPopups == FALSE &&
+ HTCurSelectGroupType == F_RADIO_TYPE))
+ I.checked=YES;
+
+ if (present && present[HTML_OPTION_VALUE] &&
+ value[HTML_OPTION_VALUE]) {
+ /*
+ * Convert any HTML entities or decimal escaping. - FM
+ */
+ StrAllocCopy(I_value, value[HTML_OPTION_VALUE]);
+ me->HiddenValue = TRUE;
+ TRANSLATE_AND_UNESCAPE_ENTITIES6(&I_value,
+ ATTR_CS_IN,
+ ATTR_CS_IN,
+ NO,
+ me->UsePlainSpace, me->HiddenValue);
+ I.value_cs = ATTR_CS_IN;
+ me->HiddenValue = FALSE;
+
+ I.value = I_value;
+ }
+
+ if (me->select_disabled ||
+ (present && present[HTML_OPTION_DISABLED]))
+ I.disabled=YES;
+
+ if (present && present[HTML_OPTION_ID]
+ && value[HTML_OPTION_ID] && *value[HTML_OPTION_ID]) {
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ value[HTML_OPTION_ID], /* Tag */
+ NULL, /* Addresss */
+ (HTLinkType*)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ I.id = value[HTML_OPTION_ID];
+ }
+ }
+
+ HText_beginInput(me->text, me->inUnderline, &I);
+
+ if (HTCurSelectGroupType == F_CHECKBOX_TYPE) {
+ /*
+ * Put a "[_]" placeholder, and one space
+ * (collapsible) before the label that is
+ * expected to follow. - FM
+ */
+ HText_appendCharacter(me->text, '[');
+ HText_appendCharacter(me->text, '_');
+ HText_appendCharacter(me->text, ']');
+ HText_appendCharacter(me->text, ' ');
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ me->in_word = NO;
+ } else if (LYSelectPopups == FALSE) {
+ /*
+ * Put a "(_)" placeholder, and one space
+ * (collapsible) before the label that is
+ * expected to follow. - FM
+ */
+ HText_appendCharacter(me->text, '(');
+ HText_appendCharacter(me->text, '_');
+ HText_appendCharacter(me->text, ')');
+ HText_appendCharacter(me->text, ' ');
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ me->in_word = NO;
+ }
+ }
+
+ /*
+ * Get ready for the next value.
+ */
+ HTChunkClear(&me->option);
+ if ((present && present[HTML_OPTION_SELECTED]) ||
+ (me->first_option && LYSelectPopups == FALSE &&
+ HTCurSelectGroupType == F_RADIO_TYPE))
+ me->LastOptionChecked = TRUE;
+ else
+ me->LastOptionChecked = FALSE;
+ me->first_option = FALSE;
+
+
+ if (present && present[HTML_OPTION_VALUE] &&
+ value[HTML_OPTION_VALUE]) {
+ if (!I_value) {
+ /*
+ * Convert any HTML entities or decimal escaping. - FM
+ */
+ StrAllocCopy(I_value, value[HTML_OPTION_VALUE]);
+ me->HiddenValue = TRUE;
+ TRANSLATE_AND_UNESCAPE_ENTITIES6(&I_value,
+ ATTR_CS_IN,
+ ATTR_CS_IN,
+ NO,
+ me->UsePlainSpace, me->HiddenValue);
+ me->HiddenValue = FALSE;
+ }
+ StrAllocCopy(me->LastOptionValue, I_value);
+ } else {
+ StrAllocCopy(me->LastOptionValue, me->option.data);
+ }
+
+ /*
+ * If this is a popup option, print its option
+ * for use in selecting option by number. - LE
+ */
+ if (HTCurSelectGroupType == F_RADIO_TYPE &&
+ LYSelectPopups &&
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+ char marker[8];
+ int opnum = HText_getOptionNum(me->text);
+
+ if (opnum > 0 && opnum < 100000) {
+ sprintf(marker,"(%d)", opnum);
+ HTML_put_string(me, marker);
+ for (i = strlen(marker); i < 5; ++i) {
+ HTML_put_character(me, '_');
+ }
+ }
+ }
+ FREE(I_value);
+ }
+ break;
+
+ case HTML_TABLE:
+ /*
+ * Not implemented. Just treat as a division
+ * with respect to any ALIGN attribute, with
+ * a default of HT_LEFT, or leave as a PRE
+ * block if we are presently in one. - FM
+ */
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ me->inTABLE = TRUE;
+ if (!strcmp(me->sp->style->name, "Preformatted")) {
+ UPDATE_STYLE;
+ CHECK_ID(HTML_TABLE_ID);
+ break;
+ }
+ if (me->Division_Level < (MAX_NESTING - 1)) {
+ me->Division_Level++;
+ } else if (TRACE) {
+ fprintf(stderr,
+ "HTML: ****** Maximum nesting of %d divisions/tables exceeded!\n",
+ MAX_NESTING);
+ }
+ if (present && present[HTML_TABLE_ALIGN] &&
+ value[HTML_TABLE_ALIGN] && *value[HTML_TABLE_ALIGN]) {
+ if (!strcasecomp(value[HTML_TABLE_ALIGN], "center")) {
+ me->DivisionAlignments[me->Division_Level] = HT_CENTER;
+ change_paragraph_style(me, styles[HTML_DCENTER]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DCENTER]->alignment;
+ } else if (!strcasecomp(value[HTML_TABLE_ALIGN], "right")) {
+ me->DivisionAlignments[me->Division_Level] = HT_RIGHT;
+ change_paragraph_style(me, styles[HTML_DRIGHT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DRIGHT]->alignment;
+ } else {
+ me->DivisionAlignments[me->Division_Level] = HT_LEFT;
+ change_paragraph_style(me, styles[HTML_DLEFT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DLEFT]->alignment;
+ }
+ } else {
+ me->DivisionAlignments[me->Division_Level] = HT_LEFT;
+ change_paragraph_style(me, styles[HTML_DLEFT]);
+ UPDATE_STYLE;
+ me->current_default_alignment = styles[HTML_DLEFT]->alignment;
+ }
+ CHECK_ID(HTML_TABLE_ID);
+ break;
+
+ case HTML_TR:
+ /*
+ * Not yet implemented. Just start a new row,
+ * if needed, act on an ALIGN attribute if present,
+ * and check for an ID link. - FM
+ */
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ UPDATE_STYLE;
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ }
+ me->in_word = NO;
+
+ if (!strcmp(me->sp->style->name, "Preformatted")) {
+ CHECK_ID(HTML_TR_ID);
+ me->inP = FALSE;
+ break;
+ }
+ if (LYoverride_default_alignment(me)) {
+ me->sp->style->alignment = styles[me->sp[0].tag_number]->alignment;
+ } else if (me->List_Nesting_Level >= 0 ||
+ ((me->Division_Level < 0) &&
+ (!strcmp(me->sp->style->name, "Normal") ||
+ !strcmp(me->sp->style->name, "Preformatted")))) {
+ me->sp->style->alignment = HT_LEFT;
+ } else {
+ me->sp->style->alignment = me->current_default_alignment;
+ }
+ if (present && present[HTML_TR_ALIGN] && value[HTML_TR_ALIGN]) {
+ if (!strcasecomp(value[HTML_TR_ALIGN], "center") &&
+ !(me->List_Nesting_Level >= 0 && !me->inP))
+ me->sp->style->alignment = HT_CENTER;
+ else if (!strcasecomp(value[HTML_TR_ALIGN], "right") &&
+ !(me->List_Nesting_Level >= 0 && !me->inP))
+ me->sp->style->alignment = HT_RIGHT;
+ else if (!strcasecomp(value[HTML_TR_ALIGN], "left") ||
+ !strcasecomp(value[HTML_TR_ALIGN], "justify"))
+ me->sp->style->alignment = HT_LEFT;
+ }
+
+ CHECK_ID(HTML_TR_ID);
+ me->inP = FALSE;
+ break;
+
+ case HTML_THEAD:
+ case HTML_TFOOT:
+ case HTML_TBODY:
+ /*
+ * Not yet implemented. Just check for an ID link. - FM
+ */
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ UPDATE_STYLE;
+ CHECK_ID(HTML_TR_ID);
+ break;
+
+ case HTML_COL:
+ case HTML_COLGROUP:
+ /*
+ * Not yet implemented. Just check for an ID link. - FM
+ */
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ UPDATE_STYLE;
+ CHECK_ID(HTML_COL_ID);
+ break;
+
+ case HTML_TH:
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ UPDATE_STYLE;
+ CHECK_ID(HTML_TD_ID);
+ /*
+ * Not yet implemented. Just add a collapsible space and break. - FM
+ */
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_TD:
+ if (me->inA) {
+ SET_SKIP_STACK(HTML_A);
+ HTML_end_element(me, HTML_A, (char **)&include);
+ }
+ if (me->Underline_Level > 0) {
+ SET_SKIP_STACK(HTML_U);
+ HTML_end_element(me, HTML_U, (char **)&include);
+ }
+ UPDATE_STYLE;
+ CHECK_ID(HTML_TD_ID);
+ /*
+ * Not yet implemented. Just add a collapsible space and break. - FM
+ */
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_MATH:
+ /*
+ * We're getting it as Literal text, which, until we can process
+ * it, we'll display as is, within brackets to alert the user. - FM
+ */
+ HTChunkClear(&me->math);
+ CHECK_ID(HTML_GEN_ID);
+ break;
+
+ default:
+ break;
+
+ } /* end switch */
+
+ if (HTML_dtd.tags[ElementNumber].contents != SGML_EMPTY) {
+ if (me->skip_stack > 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTML:begin_element: internal call (level %d), leaving on stack - %s\n",
+ me->skip_stack, me->sp->style->name);
+ me->skip_stack--;
+ return;
+ }
+ if (me->sp == me->stack) {
+ if (me->stack_overrun == FALSE) {
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML: ****** Maximum nesting of %d tags exceeded!\n",
+ MAX_NESTING);
+
+ } else {
+ HTAlert(HTML_STACK_OVERRUN);
+ }
+ me->stack_overrun = TRUE;
+ }
+ return;
+ }
+
+ (me->sp)--;
+ me->sp[0].style = me->new_style; /* Stack new style */
+ me->sp[0].tag_number = ElementNumber;
+
+ if (TRACE)
+ fprintf(stderr,"HTML:begin_element: adding style to stack - %s\n",
+ me->new_style->name);
+ }
+
+#if defined(USE_COLOR_STYLE)
+/* end empty tags straight away */
+ if (HTML_dtd.tags[ElementNumber].contents == SGML_EMPTY)
+ {
+ if (TRACE)
+ fprintf(stderr, "STYLE:begin_element:ending EMPTY element style\n");
+#if !defined(USE_HASH)
+ HText_characterStyle(me->text, element_number+STARTAT, STACK_OFF);
+#else
+ HText_characterStyle(me->text, hcode, STACK_OFF);
+#endif /* USE_HASH */
+ {
+ char *end, *start=NULL, *lookfrom;
+ char tmp[64];
+ sprintf(tmp, ";%s", HTML_dtd.tags[element_number].name);
+ strtolower(tmp);
+
+ lookfrom = Style_className;
+ do
+ {
+ end = start;
+ start = strstr(lookfrom, tmp);
+ if (start)
+ lookfrom = start + 1;
+ }
+ while (start);
+ if (end)
+ *end='\0';
+
+#if defined(PREVAIL)
+ start=strrchr(Style_className, '.');
+ if (start)
+ strcpy(prevailing_class, (char*)(start+1));
+ else
+ strcpy(prevailing_class, "");
+#endif
+
+
+ if (TRACE)
+ fprintf(stderr, "CSS:%s (trimmed %s, SGML_EMPTY)\n", Style_className, tmp);
+ }
+ }
+#endif /* USE_COLOR_STYLE */
+}
+
+/* End Element
+** -----------
+**
+** When we end an element, the style must be returned to that
+** in effect before that element. Note that anchors (etc?)
+** don't have an associated style, so that we must scan down the
+** stack for an element with a defined style. (In fact, the styles
+** should be linked to the whole stack not just the top one.)
+** TBL 921119
+**
+** We don't turn on "CAREFUL" check because the parser produces
+** (internal code errors apart) good nesting. The parser checks
+** incoming code errors, not this module.
+*/
+PRIVATE void HTML_end_element ARGS3(
+ HTStructured *, me,
+ int, element_number,
+ char **, include)
+{
+ int i = 0;
+ char *temp = NULL, *cp = NULL;
+ BOOL BreakFlag = FALSE;
+
+#ifdef CAREFUL /* parser assumed to produce good nesting */
+ if (element_number != me->sp[0].tag_number &&
+ HTML_dtd.tags[element_number].contents != SGML_EMPTY) {
+ fprintf(stderr,
+ "HTMLText: end of element %s when expecting end of %s\n",
+ HTML_dtd.tags[element_number].name,
+ HTML_dtd.tags[me->sp->tag_number].name);
+ /* panic */
+ }
+#endif /* CAREFUL */
+
+ /*
+ * If we're seeking MAPs, skip everything that's
+ * not a MAP or AREA tag. - FM
+ */
+ if (LYMapsOnly) {
+ if (!(element_number == HTML_MAP || element_number == HTML_AREA)) {
+ return;
+ }
+ }
+
+ /*
+ * Pop state off stack if we didn't declare the element
+ * SGML_EMPTY in HTMLDTD.c. - FM & KW
+ */
+ if (HTML_dtd.tags[element_number].contents != SGML_EMPTY) {
+ if ((element_number != me->sp[0].tag_number) &&
+ me->skip_stack <= 0 &&
+ HTML_dtd.tags[HTML_LH].contents != SGML_EMPTY &&
+ (me->sp[0].tag_number == HTML_UL ||
+ me->sp[0].tag_number == HTML_OL ||
+ me->sp[0].tag_number == HTML_MENU ||
+ me->sp[0].tag_number == HTML_DIR) &&
+ (element_number == HTML_H1 ||
+ element_number == HTML_H2 ||
+ element_number == HTML_H3 ||
+ element_number == HTML_H4 ||
+ element_number == HTML_H6 ||
+ element_number == HTML_H6)) {
+ /*
+ * Set the break flag if we're popping
+ * a dummy HTML_LH substituted for an
+ * HTML_H# encountered in a list.
+ */
+ BreakFlag = TRUE;
+ }
+ if (me->skip_stack > 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTML:end_element: Internal call (level %d), leaving on stack - %s\n",
+ me->skip_stack, me->sp->style->name);
+ me->skip_stack--;
+ } else if (me->stack_overrun == TRUE &&
+ element_number != me->sp[0].tag_number) {
+ /*
+ * Ignore non-corresponding tags if we had
+ * a stack overrun. This is not a completely
+ * fail-safe strategy for protection against
+ * any seriously adverse consequences of a
+ * stack overrun, and the rendering of the
+ * document will not be as intended, but we
+ * expect overruns to be rare, and this should
+ * offer reasonable protection against crashes
+ * if an overrun does occur. - FM
+ */
+ return;
+ } else if (element_number == HTML_SELECT &&
+ me->sp[0].tag_number != HTML_SELECT) {
+ /*
+ * Ignore non-corresponding SELECT tags, since we
+ * probably popped it and closed the SELECT block
+ * to deal with markup which amounts to a nested
+ * SELECT, or an out of order FORM end tag. - FM
+ */
+ return;
+ } else if ((element_number != me->sp[0].tag_number) &&
+ HTML_dtd.tags[HTML_LH].contents == SGML_EMPTY &&
+ (me->sp[0].tag_number == HTML_UL ||
+ me->sp[0].tag_number == HTML_OL ||
+ me->sp[0].tag_number == HTML_MENU ||
+ me->sp[0].tag_number == HTML_DIR) &&
+ (element_number == HTML_H1 ||
+ element_number == HTML_H2 ||
+ element_number == HTML_H3 ||
+ element_number == HTML_H4 ||
+ element_number == HTML_H6 ||
+ element_number == HTML_H6)) {
+ /*
+ * It's an H# for which we substituted
+ * an HTML_LH, which we've declared as
+ * SGML_EMPTY, so just return. - FM
+ */
+ return;
+ } else if (me->sp < (me->stack + MAX_NESTING - 1)) {
+ (me->sp)++;
+ if (TRACE)
+ fprintf(stderr,
+ "HTML:end_element: Popped style off stack - %s\n",
+ me->sp->style->name);
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "Stack underflow error! Tried to pop off more styles than exist in stack\n");
+ }
+ }
+ if (BreakFlag == TRUE)
+ return;
+
+ /*
+ * Check for unclosed TEXTAREA. - FM
+ */
+ if (me->inTEXTAREA && element_number != HTML_TEXTAREA) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Missing TEXTAREA end tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ }
+
+ if (!me->text && !LYMapsOnly) {
+ UPDATE_STYLE;
+ }
+
+ /*
+ * Handle the end tag. - FM
+ */
+ switch(element_number) {
+
+ case HTML_HTML:
+ if (me->inA || me->inSELECT || me->inTEXTAREA)
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: %s%s%s%s%s not closed before HTML end tag *****\n",
+ me->inSELECT ? "SELECT" : "",
+ (me->inSELECT && me->inTEXTAREA) ? ", " : "",
+ me->inTEXTAREA ? "TEXTAREA" : "",
+ ((me->inSELECT || me->inTEXTAREA) && me->inA) ? ", " : "",
+ me->inA ? "A" : "");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ break;
+
+ case HTML_HEAD:
+ if (me->inBASE &&
+ !strcmp(me->node_anchor->address, LYlist_temp_url())) {
+ /* If we are parsing the List Page, and have a BASE after
+ * we are done with the HEAD element, propagate it back
+ * to the node_anchor object. The base should have been
+ * inserted by showlist() to record what document the List
+ * Page is about, and other functions may later look for it
+ * in the anchor. - kw
+ */
+ StrAllocCopy(me->node_anchor->content_base, me->base_href);
+ }
+ if (HText_hasToolbar(me->text))
+ HText_appendParagraph(me->text);
+ break;
+
+ case HTML_TITLE:
+ HTChunkTerminate(&me->title);
+ HTAnchor_setTitle(me->node_anchor, me->title.data);
+ HTChunkClear(&me->title);
+ /*
+ * Check if it's a bookmark file, and if so, and multiple
+ * bookmark support is on, or it's off but this isn't the
+ * default bookmark file (e.g., because it was on before,
+ * and this is another bookmark file that has been retrieved
+ * as a previous document), insert the current description
+ * string and filepath for it. We pass the strings back to
+ * the SGML parser so that any 8 bit or multibyte/CJK
+ * characters will be handled by the parser's state and
+ * charset routines. - FM
+ */
+ if (me->node_anchor->bookmark && *me->node_anchor->bookmark) {
+ if ((LYMultiBookmarks == TRUE) ||
+ ((bookmark_page && *bookmark_page) &&
+ strcmp(me->node_anchor->bookmark, bookmark_page))) {
+ for (i = 0; i <= MBM_V_MAXFILES; i++) {
+ if (MBM_A_subbookmark[i] &&
+ !strcmp(MBM_A_subbookmark[i],
+ me->node_anchor->bookmark)) {
+ StrAllocCat(*include, "<H2><EM>Description:</EM> ");
+ StrAllocCopy(temp,
+ ((MBM_A_subdescript[i] &&
+ *MBM_A_subdescript[i]) ?
+ MBM_A_subdescript[i] : "(none)"));
+ LYEntify((char **)&temp, TRUE);
+ StrAllocCat(*include, temp);
+ StrAllocCat(*include,
+ "<BR><EM>&nbsp;&nbsp;&nbsp;Filepath:</EM> ");
+ StrAllocCopy(temp,
+ ((MBM_A_subbookmark[i] &&
+ *MBM_A_subbookmark[i]) ?
+ MBM_A_subbookmark[i] : "(unknown)"));
+ LYEntify((char **)&temp, TRUE);
+ StrAllocCat(*include, temp);
+ FREE(temp);
+ StrAllocCat(*include, "</H2>");
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case HTML_STYLE:
+ /*
+ * We're getting it as Literal text, which, for now,
+ * we'll just ignore. - FM
+ */
+ HTChunkTerminate(&me->style_block);
+ if (TRACE) {
+ fprintf(stderr, "HTML: STYLE content =\n%s\n",
+ me->style_block.data);
+ }
+ HTChunkClear(&me->style_block);
+ break;
+
+ case HTML_SCRIPT:
+ /*
+ * We're getting it as Literal text, which, for now,
+ * we'll just ignore. - FM
+ */
+ HTChunkTerminate(&me->script);
+ if (TRACE) {
+ fprintf(stderr, "HTML: SCRIPT content =\n%s\n",
+ me->script.data);
+ }
+ HTChunkClear(&me->script);
+ break;
+
+ case HTML_BODY:
+ if (me->inA || me->inSELECT || me->inTEXTAREA)
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: %s%s%s%s%s not closed before BODY end tag *****\n",
+ me->inSELECT ? "SELECT" : "",
+ (me->inSELECT && me->inTEXTAREA) ? ", " : "",
+ me->inTEXTAREA ? "TEXTAREA" : "",
+ ((me->inSELECT || me->inTEXTAREA) && me->inA) ? ", " : "",
+ me->inA ? "A" : "");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ break;
+
+ case HTML_FRAMESET:
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_NOFRAMES:
+ case HTML_IFRAME:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_BANNER:
+ case HTML_MARQUEE:
+ case HTML_BLOCKQUOTE:
+ case HTML_BQ:
+ case HTML_ADDRESS:
+ /*
+ * Set flag to know that style has ended.
+ * Fall through.
+ i_prior_style = -1;
+ */
+ change_paragraph_style(me, me->sp->style);
+ UPDATE_STYLE;
+ if (me->sp->tag_number == element_number)
+ LYEnsureDoubleSpace(me);
+ if (me->List_Nesting_Level >= 0)
+ HText_NegateLineOne(me->text);
+ break;
+
+ case HTML_CENTER:
+ case HTML_DIV:
+ if (me->Division_Level >= 0)
+ me->Division_Level--;
+ if (me->Division_Level >= 0)
+ me->sp->style->alignment =
+ me->DivisionAlignments[me->Division_Level];
+ change_paragraph_style(me, me->sp->style);
+ UPDATE_STYLE;
+ me->current_default_alignment = me->sp->style->alignment;
+ if (me->List_Nesting_Level >= 0)
+ HText_NegateLineOne(me->text);
+ break;
+
+ case HTML_H1: /* header styles */
+ case HTML_H2:
+ case HTML_H3:
+ case HTML_H4:
+ case HTML_H5:
+ case HTML_H6:
+ if (me->Division_Level >= 0) {
+ me->sp->style->alignment =
+ me->DivisionAlignments[me->Division_Level];
+ } else if (!strcmp(me->sp->style->name, "HeadingCenter") ||
+ !strcmp(me->sp->style->name, "Heading1")) {
+ me->sp->style->alignment = HT_CENTER;
+ } else if (!strcmp(me->sp->style->name, "HeadingRight")) {
+ me->sp->style->alignment = HT_RIGHT;
+ } else {
+ me->sp->style->alignment = HT_LEFT;
+ }
+ change_paragraph_style(me, me->sp->style);
+ UPDATE_STYLE;
+ if (styles[element_number]->font & HT_BOLD) {
+ if (me->inBoldA == FALSE && me->inBoldH == TRUE) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ }
+ me->inBoldH = FALSE;
+ }
+ if (me->List_Nesting_Level >= 0)
+ HText_NegateLineOne(me->text);
+ if (me->Underline_Level > 0 && me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ me->inUnderline = TRUE;
+ }
+ break;
+
+ case HTML_P:
+ LYHandleP(me,
+ (CONST BOOL*)0, (CONST char **)0,
+ (char **)&include,
+ FALSE);
+ break;
+
+ case HTML_FONT:
+ me->inFONT = FALSE;
+ break;
+
+ case HTML_B: /* Physical character highlighting */
+ case HTML_BLINK:
+ case HTML_I:
+ case HTML_U:
+
+ case HTML_CITE: /* Logical character highlighting */
+ case HTML_EM:
+ case HTML_STRONG:
+ /*
+ * Ignore any emphasis end tags if the
+ * Underline_Level is not set. - FM
+ */
+ if (me->Underline_Level <= 0)
+ break;
+
+ /*
+ * Adjust the Underline level counter, and
+ * turn off underlining if appropriate. - FM
+ */
+ me->Underline_Level--;
+ if (me->inUnderline && me->Underline_Level < 1) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ me->inUnderline = FALSE;
+ if (TRACE)
+ fprintf(stderr,"Ending underline\n");
+ } else {
+ if (TRACE)
+ fprintf(stderr,"Underline Level is %d\n", me->Underline_Level);
+ }
+ break;
+
+ case HTML_ABBREV: /* Miscellaneous character containers */
+ case HTML_ACRONYM:
+ case HTML_AU:
+ case HTML_AUTHOR:
+ case HTML_BIG:
+ case HTML_CODE:
+ case HTML_DFN:
+ case HTML_KBD:
+ case HTML_SAMP:
+ case HTML_SMALL:
+ case HTML_SUB:
+ case HTML_SUP:
+ case HTML_TT:
+ case HTML_VAR:
+ break;
+
+ case HTML_DEL:
+ case HTML_S:
+ case HTML_STRIKE:
+ HTML_put_character(me, ' ');
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, ":DEL]");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_INS:
+ HTML_put_character(me, ' ');
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, ":INS]");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ break;
+
+ case HTML_Q:
+ if (me->Quote_Level > 0)
+ me->Quote_Level--;
+ /*
+ * Should check LANG and/or DIR attributes, and the
+ * me->node_anchor->charset and/or yet to be added
+ * structure elements, to determine whether we should
+ * use chevrons, but for now we'll always use double-
+ * or single-quotes. - FM
+ */
+ if (!(me->Quote_Level & 1))
+ HTML_put_character(me, '"');
+ else
+ HTML_put_character(me, '\'');
+ break;
+
+ case HTML_PRE: /* Formatted text */
+ /*
+ * Set to know that we are no longer in a PRE block.
+ */
+ me->inPRE = FALSE;
+ case HTML_LISTING: /* Literal text */
+ case HTML_XMP:
+ case HTML_PLAINTEXT:
+ if (me->comment_start)
+ HText_appendText(me->text, me->comment_start);
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ if (me->List_Nesting_Level >= 0) {
+ UPDATE_STYLE;
+ HText_NegateLineOne(me->text);
+ }
+ break;
+
+ case HTML_NOTE:
+ case HTML_FN:
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ UPDATE_STYLE;
+ if (me->sp->tag_number == element_number)
+ LYEnsureDoubleSpace(me);
+ if (me->List_Nesting_Level >= 0)
+ HText_NegateLineOne(me->text);
+ me->inLABEL = FALSE;
+ break;
+
+ case HTML_OL:
+ me->OL_Counter[me->List_Nesting_Level < 11 ?
+ me->List_Nesting_Level : 11] = OL_VOID;
+ case HTML_DL:
+ case HTML_UL:
+ case HTML_MENU:
+ case HTML_DIR:
+ me->List_Nesting_Level--;
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML_end_element: Reducing List Nesting Level to %d\n",
+ me->List_Nesting_Level);
+ }
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ UPDATE_STYLE;
+ if (me->List_Nesting_Level >= 0)
+ LYEnsureSingleSpace(me);
+ break;
+
+ case HTML_SPAN:
+ /*
+ * Should undo anything we did based on LANG and/or DIR
+ * attributes, and the me->node_anchor->charset and/or
+ * yet to be added structure elements. - FM
+ */
+ break;
+
+ case HTML_BDO:
+ /*
+ * Should undo anything we did based on DIR (and/or LANG)
+ * attributes, and the me->node_anchor->charset and/or
+ * yet to be added structure elements. - FM
+ */
+ break;
+
+ case HTML_A:
+ /*
+ * Ignore any spurious A end tags. - FM
+ */
+ if (me->inA == FALSE)
+ break;
+ /*
+ * Set to know that we are no longer in an anchor.
+ */
+ me->inA = FALSE;
+
+ UPDATE_STYLE;
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->CurrentANum = 0;
+ me->inBoldA = FALSE;
+ if (me->Underline_Level > 0 && me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ me->inUnderline = TRUE;
+ }
+ break;
+
+ case HTML_MAP:
+ FREE(me->map_address);
+ break;
+
+ case HTML_BODYTEXT:
+ /*
+ * We may need to look at this someday to deal with
+ * OBJECTs optimally, but just ignore it for now. - FM
+ */
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_TEXTFLOW:
+ /*
+ * We may need to look at this someday to deal with
+ * APPLETs optimally, but just ignore it for now. - FM
+ */
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_FIG:
+ if (me->inFIGwithP) {
+ LYEnsureDoubleSpace(me);
+ } else {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ }
+ LYResetParagraphAlignment(me);
+ me->inFIGwithP = FALSE;
+ me->inFIG = FALSE;
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ if (me->List_Nesting_Level >= 0) {
+ UPDATE_STYLE;
+ HText_NegateLineOne(me->text);
+ }
+ break;
+
+ case HTML_OBJECT:
+ /*
+ * Finish the data off.
+ */
+ {
+ int s = 0, e = 0;
+ char *start = NULL, *first_end = NULL;
+ BOOL have_param = FALSE;
+ char *data = NULL;
+
+ HTChunkTerminate(&me->object);
+ data = me->object.data;
+ while ((cp = strchr(data, '<')) != NULL) {
+ /*
+ * Look for nested OBJECTs. This procedure
+ * could get tripped up if invalid comments
+ * are present in the content, or if an OBJECT
+ * end tag is present in a quoted attribute. - FM
+ */
+ if (!strncmp(cp, "<!--", 4)) {
+ data = LYFindEndOfComment(cp);
+ cp = data;
+ } else if (s == 0 && !strncasecomp(cp, "<PARAM", 6)) {
+ have_param = TRUE;
+ } else if (!strncasecomp(cp, "<OBJECT", 7)) {
+ if (s == 0)
+ start = cp;
+ s++;
+ } else if (!strncasecomp(cp, "</OBJECT", 8)) {
+ if (e == 0)
+ first_end = cp;
+ e++;
+ }
+ data = ++cp;
+ }
+ if (s > e) {
+ /*
+ * We have nested OBJECT tags, and not yet all of the
+ * end tags, so restore an end tag to the content, and
+ * pass a dummy start tag to the SGML parser so that it
+ * will resume the accumulation of OBJECT content. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "HTML: Nested OBJECT tags. Recycling.\n");
+ if (*include == NULL) {
+ StrAllocCopy(*include, "<OBJECT>");
+ } else {
+ if (0 && strstr(*include, me->object.data) == NULL) {
+ StrAllocCat(*include, "<OBJECT>");
+ }
+ }
+ me->object.size--;
+ HTChunkPuts(&me->object, "</OBJECT>");
+ change_paragraph_style(me, me->sp->style);
+ break;
+ }
+ if (s < e) {
+ /*
+ * We had more end tags than start tags, so
+ * we have bad HTML or otherwise misparsed. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: Unmatched OBJECT start and end tags. Discarding content:\n%s\n",
+ me->object.data);
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ goto End_Object;
+ }
+
+ /*
+ * OBJECT start and end tags are fully matched,
+ * assuming we weren't tripped up by comments
+ * or quoted attributes. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "HTML:OBJECT content:\n%s\n", me->object.data);
+
+ /*
+ * OBJECTs with DECLARE should be saved but
+ * not instantiated, and if nested, can have
+ * only other DECLAREd OBJECTs. Until we have
+ * code to handle these, we'll just create an
+ * anchor for the ID, if present, and discard
+ * the content (sigh 8-). - FM
+ */
+ if (me->object_declare == TRUE) {
+ if (me->object_id && *me->object_id)
+ LYHandleID(me, me->object_id);
+ if (TRACE)
+ fprintf(stderr, "HTML: DECLAREd OBJECT. Ignoring!\n");
+ goto End_Object;
+ }
+
+ /*
+ * OBJECTs with NAME are for FORM submissions.
+ * We'll just create an anchor for the ID, if
+ * present, and discard the content until we
+ * have code to handle these. (sigh 8-). - FM
+ */
+ if (me->object_name != NULL) {
+ if (me->object_id && *me->object_id)
+ LYHandleID(me, me->object_id);
+ if (TRACE)
+ fprintf(stderr, "HTML: NAMEd OBJECT. Ignoring!\n");
+ goto End_Object;
+ }
+
+ /*
+ * Deal with any nested OBJECTs by descending
+ * to the inner-most OBJECT. - FM
+ */
+ if (s > 0) {
+ if (start != NULL &&
+ first_end != NULL && first_end > start) {
+ /*
+ * Minumum requirements for the ad hoc parsing
+ * to have succeeded are met. We'll hope that
+ * it did succeed. - FM
+ */
+ *first_end = '\0';
+ data = NULL;
+ StrAllocCopy(data, start);
+ if (e > 1) {
+ for (i = e; i > 1; i--) {
+ StrAllocCat(data, "</OBJECT><OBJECT>");
+ }
+ }
+ StrAllocCat(data, "</OBJECT>");
+ StrAllocCat(*include, data);
+ if (TRACE)
+ fprintf(stderr, "HTML: Recycling nested OBJECT%s.\n",
+ (e > 1) ? "s" : "");
+ FREE(data);
+ goto End_Object;
+ } else {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: Unmatched OBJECT start and end tags. Discarding content.\n");
+ goto End_Object;
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ goto End_Object;
+ }
+ }
+ }
+
+ /*
+ * If it's content has SHAPES, convert it to FIG. - FM
+ */
+ if (me->object_shapes == TRUE) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: OBJECT has SHAPES. Converting to FIG.\n");
+ StrAllocCat(*include, "<FIG ISOBJECT IMAGEMAP");
+ if (me->object_ismap == TRUE)
+ StrAllocCat(*include, " IMAGEMAP");
+ if (me->object_id != NULL) {
+ StrAllocCat(*include, " ID=\"");
+ StrAllocCat(*include, me->object_id);
+ StrAllocCat(*include, "\"");
+ }
+ if (me->object_data != NULL &&
+ me->object_classid == NULL) {
+ StrAllocCat(*include, " SRC=\"");
+ StrAllocCat(*include, me->object_data);
+ StrAllocCat(*include, "\"");
+ }
+ StrAllocCat(*include, ">");
+ me->object.size--;
+ HTChunkPuts(&me->object, "</FIG>");
+ HTChunkTerminate(&me->object);
+ StrAllocCat(*include, me->object.data);
+ goto End_Object;
+ }
+
+ /*
+ * If it has a USEMAP attribute and didn't have SHAPES,
+ * convert it to IMG. - FM
+ */
+ if (me->object_usemap != NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "HTML: OBJECT has USEMAP. Converting to IMG.\n");
+
+ StrAllocCat(*include, "<IMG ISOBJECT");
+ if (me->object_id != NULL) {
+ /*
+ * Pass the ID. - FM
+ */
+ StrAllocCat(*include, " ID=\"");
+ StrAllocCat(*include, me->object_id);
+ StrAllocCat(*include, "\"");
+ }
+ if (me->object_data != NULL &&
+ me->object_classid == NULL) {
+ /*
+ * We have DATA with no CLASSID, so let's
+ * hope it' equivalent to an SRC. - FM
+ */
+ StrAllocCat(*include, " SRC=\"");
+ StrAllocCat(*include, me->object_data);
+ StrAllocCat(*include, "\"");
+ }
+ if (me->object_title != NULL) {
+ /*
+ * Use the TITLE for both the MAP
+ * and the IMGs ALT. - FM
+ */
+ StrAllocCat(*include, " TITLE=\"");
+ StrAllocCat(*include, me->object_title);
+ StrAllocCat(*include, "\" ALT=\"");
+ StrAllocCat(*include, me->object_title);
+ StrAllocCat(*include, "\"");
+ }
+ /*
+ * Add the USEMAP, and an ISMAP if present. - FM
+ */
+ if (me->object_usemap != NULL) {
+ StrAllocCat(*include, " USEMAP=\"");
+ StrAllocCat(*include, me->object_usemap);
+ if (me->object_ismap == TRUE)
+ StrAllocCat(*include, "\" ISMAP>");
+ else
+ StrAllocCat(*include, "\">");
+ } else {
+ StrAllocCat(*include, ">");
+ }
+ goto End_Object;
+ }
+
+ /*
+ * Add an ID link if needed. - FM
+ */
+ if (me->object_id && *me->object_id)
+ LYHandleID(me, me->object_id);
+
+ /*
+ * Add the OBJECTs content if not empty. - FM
+ */
+ if (me->object.size > 1)
+ StrAllocCat(*include, me->object.data);
+
+ /*
+ * Create a link to the DATA, if desired, and
+ * we can rule out that it involves scripting
+ * code. This a risky thing to do, but we can
+ * toggle clickable_images mode off if it really
+ * screws things up, and so we may as well give
+ * it a try. - FM
+ */
+ if (clickable_images) {
+ if (me->object_data != NULL &&
+ !have_param &&
+ me->object_classid == NULL &&
+ me->object_codebase == NULL &&
+ me->object_codetype == NULL) {
+ /*
+ * We have a DATA value and no need for scripting
+ * code, so close the current Anchor, if one is
+ * open, and add an Anchor for this source. If
+ * we also have a TYPE value, check whether it's
+ * an image or not, and set the link name
+ * accordingly. - FM
+ */
+ if (me->inA)
+ StrAllocCat(*include, "</A>");
+ StrAllocCat(*include, " -<A HREF=\"");
+ StrAllocCat(*include, me->object_data);
+ StrAllocCat(*include, "\">");
+ if ((me->object_type != NULL) &&
+ !strncasecomp(me->object_type, "image/", 6)) {
+ StrAllocCat(*include, "(IMAGE)");
+ } else {
+ StrAllocCat(*include, "(OBJECT)");
+ }
+ StrAllocCat(*include, "</A> ");
+ }
+ }
+ }
+
+ /*
+ * Re-intialize all of the OBJECT elements. - FM
+ */
+End_Object:
+ HTChunkClear(&me->object);
+ me->object_started = FALSE;
+ me->object_declare = FALSE;
+ me->object_shapes = FALSE;
+ me->object_ismap = FALSE;
+ FREE(me->object_usemap);
+ FREE(me->object_id);
+ FREE(me->object_title);
+ FREE(me->object_data);
+ FREE(me->object_type);
+ FREE(me->object_classid);
+ FREE(me->object_codebase);
+ FREE(me->object_codetype);
+ FREE(me->object_name);
+
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_APPLET:
+ if (me->inAPPLETwithP) {
+ LYEnsureDoubleSpace(me);
+ } else {
+ HTML_put_character(me, ' '); /* space char may be ignored */
+ }
+ LYResetParagraphAlignment(me);
+ me->inAPPLETwithP = FALSE;
+ me->inAPPLET = FALSE;
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_CAPTION:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ me->inCAPTION = FALSE;
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ me->inLABEL = FALSE;
+ break;
+
+ case HTML_CREDIT:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ me->inCREDIT = FALSE;
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ me->inLABEL = FALSE;
+ break;
+
+ case HTML_FORM:
+ /*
+ * Check if we had a FORM start tag, and issue a
+ * message if not, but fall through to check for
+ * an open SELECT and ensure that the FORM-related
+ * globals in GridText.c are initialized. - FM
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Unmatched FORM end tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * Check if we still have a SELECT element open.
+ * FORM may have been declared SGML_EMPTY in HTMLDTD.c,
+ * and in that case SGML_character() in SGML.c is
+ * not able to ensure correct nesting; or it may have
+ * failed to enforce valid nesting. If a SELECT is open,
+ * issue a message, then
+ * call HTML_end_element() directly (with a
+ * check in that to bypass decrementing of the HTML
+ * parser's stack) to close the SELECT. - kw
+ */
+ if (me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: Open SELECT at FORM end. Faking SELECT end tag. *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ if (me->sp->tag_number != HTML_SELECT) {
+ SET_SKIP_STACK(HTML_SELECT);
+ }
+ HTML_end_element(me, HTML_SELECT, (char **)&include);
+ }
+
+ /*
+ * Set to know that we are no longer in an form.
+ */
+ me->inFORM = FALSE;
+
+ HText_endForm(me->text);
+ /*
+ * If we are in a list and are on the first line
+ * with no text following a bullet or number,
+ * don't force a newline. This could happen if
+ * we were called from HTML_start_element() due
+ * to a missing FORM end tag. - FM
+ */
+ if (!(me->List_Nesting_Level >= 0 && !me->inP))
+ LYEnsureSingleSpace(me);
+ break;
+
+ case HTML_FIELDSET:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_LEGEND:
+ LYEnsureDoubleSpace(me);
+ LYResetParagraphAlignment(me);
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ case HTML_LABEL:
+ break;
+
+ case HTML_BUTTON:
+ break;
+
+ case HTML_TEXTAREA:
+ {
+ InputFieldData I;
+ int chars;
+ char *data;
+
+ /*
+ * Make sure we had a textarea start tag.
+ */
+ if (!me->inTEXTAREA) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Unmatched TEXTAREA end tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * Set to know that we are no longer in a textarea tag.
+ */
+ me->inTEXTAREA = FALSE;
+
+ /*
+ * Initialize.
+ */
+ I.align=NULL; I.accept=NULL; I.checked=NO; I.class=NULL;
+ I.disabled=NO; I.error=NULL; I.height= NULL; I.id=NULL;
+ I.lang=NULL; I.max=NULL; I.maxlength=NULL; I.md=NULL;
+ I.min=NULL; I.name=NULL; I.size=NULL; I.src=NULL;
+ I.type=NULL; I.value=NULL; I.width=NULL;
+ I.value_cs = current_char_set;
+
+ UPDATE_STYLE;
+ /*
+ * Before any input field add a space if necessary.
+ */
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ /*
+ * Add a return.
+ */
+ HText_appendCharacter(me->text, '\r');
+
+ /*
+ * Finish the data off.
+ */
+ HTChunkTerminate(&me->textarea);
+ data = me->textarea.data;
+ FREE(temp);
+
+ I.type = "textarea";
+ I.size = me->textarea_cols;
+ I.name = me->textarea_name;
+ I.name_cs = me->textarea_name_cs;
+ I.accept_cs = me->textarea_accept_cs;
+ me->textarea_accept_cs = NULL;
+ I.disabled = me->textarea_disabled;
+ I.id = me->textarea_id;
+
+ /*
+ * SGML unescape any character references in TEXTAREA
+ * content, then parse it into individual lines
+ * to be handled as a series of INPUT fields (ugh!).
+ * Any raw 8-bit or multibyte characters already have been
+ * handled in relation to the display character set
+ * in SGML_character().
+ */
+ me->UsePlainSpace = TRUE;
+
+ TRANSLATE_AND_UNESCAPE_ENTITIES5(&me->textarea.data,
+ me->UCLYhndl,
+ current_char_set,
+ me->UsePlainSpace, me->HiddenValue);
+
+ /*
+ * Trim any trailing newlines and
+ * skip any lead newlines. - FM
+ */
+ if (*data != '\0') {
+ cp = (data + strlen(data)) - 1;
+ while (cp >= data && *cp == '\n') {
+ *cp-- = '\0';
+ }
+ while (*data == '\n') {
+ data++;
+ }
+ }
+ /*
+ * Load the first text line, or set
+ * up for all blank rows. - FM
+ */
+ if ((cp = strchr(data, '\n')) != NULL) {
+ *cp = '\0';
+ StrAllocCopy(temp, data);
+ *cp = '\n';
+ data = (cp + 1);
+ } else {
+ if (*data != '\0') {
+ StrAllocCopy(temp, data);
+ } else {
+ FREE(temp);
+ }
+ data = "";
+ }
+ /*
+ * Display at least the requested number
+ * of text lines and/or blank rows. - FM
+ */
+ for (i = 0; i < me->textarea_rows; i++) {
+ int j;
+ for (j = 0; temp && temp[j]; j++) {
+ if (temp[j] == '\r')
+ temp[j] = (temp[j+1] ? ' ' : '\0');
+ }
+ I.value = temp;
+ chars = HText_beginInput(me->text, me->inUnderline, &I);
+ for (; chars > 0; chars--)
+ HTML_put_character(me, '_');
+ HText_appendCharacter(me->text, '\r');
+ if (*data != '\0') {
+ if (*data == '\n') {
+ FREE(temp);
+ data++;
+ } else if ((cp = strchr(data, '\n')) != NULL) {
+ *cp = '\0';
+ StrAllocCopy(temp, data);
+ *cp = '\n';
+ data = (cp + 1);
+ } else {
+ StrAllocCopy(temp, data);
+ data = "";
+ }
+ } else {
+ FREE(temp);
+ }
+ }
+ /*
+ * Check for more data lines than the rows attribute.
+ * We add them to the display, because we support only
+ * horizontal and not also vertical scrolling. - FM
+ */
+ while (*data != '\0' || temp != NULL) {
+ int j;
+ for (j = 0; temp && temp[j]; j++) {
+ if (temp[j] == '\r')
+ temp[j] = (temp[j+1] ? ' ' : '\0');
+ }
+ I.value = temp;
+ chars = HText_beginInput(me->text, me->inUnderline, &I);
+ for (chars = atoi(me->textarea_cols); chars > 0; chars--)
+ HTML_put_character(me, '_');
+ HText_appendCharacter(me->text, '\r');
+ if (*data == '\n') {
+ FREE(temp);
+ data++;
+ } else if ((cp = strchr(data, '\n')) != NULL) {
+ *cp = '\0';
+ StrAllocCopy(temp, data);
+ *cp = '\n';
+ data = (cp + 1);
+ } else if (*data != '\0') {
+ StrAllocCopy(temp, data);
+ data = "";
+ } else {
+ FREE(temp);
+ }
+ }
+ FREE(temp);
+ cp = NULL;
+ me->UsePlainSpace = FALSE;
+
+ HTChunkClear(&me->textarea);
+ FREE(me->textarea_name);
+ me->textarea_name_cs = -1;
+ FREE(me->textarea_cols);
+ FREE(me->textarea_id);
+ break;
+ }
+
+ case HTML_SELECT:
+ {
+ char *ptr;
+
+ /*
+ * Make sure we had a select start tag.
+ */
+ if (!me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Unmatched SELECT end tag *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * Set to know that we are no longer in a select tag.
+ */
+ me->inSELECT = FALSE;
+
+ /*
+ * Clear the disable attribute.
+ */
+ me->select_disabled = FALSE;
+
+ /*
+ * Make sure we're in a form.
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: SELECT end tag not within FORM element *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ /*
+ * Hopefully won't crash, so we'll ignore it. - kw
+ */
+ }
+
+ /*
+ * Finish the data off.
+ */
+ HTChunkTerminate(&me->option);
+ /*
+ * Finish the previous option.
+ */
+ ptr = HText_setLastOptionValue(me->text,
+ me->option.data,
+ me->LastOptionValue,
+ LAST_ORDER,
+ me->LastOptionChecked,
+ me->UCLYhndl,
+ ATTR_CS_IN);
+ FREE(me->LastOptionValue);
+
+ me->LastOptionChecked = FALSE;
+
+ if (HTCurSelectGroupType == F_CHECKBOX_TYPE ||
+ LYSelectPopups == FALSE) {
+ /*
+ * Start a newline after the last checkbox/button option.
+ */
+ LYEnsureSingleSpace(me);
+ } else {
+ /*
+ * Output popup box with the default option to screen,
+ * but use non-breaking spaces for output.
+ */
+ if (ptr &&
+ (me->sp[0].tag_number == HTML_PRE || me->inPRE == TRUE ||
+ !me->sp->style->freeFormat) &&
+ strlen(ptr) > 6) {
+ /*
+ * The code inadequately handles OPTION fields in PRE tags.
+ * We'll put up a minimum of 6 characters, and if any
+ * more would exceed the wrap column, we'll ignore them.
+ */
+ for (i = 0; i < 6; i++) {
+ if (*ptr == ' ')
+ HText_appendCharacter(me->text,HT_NON_BREAK_SPACE);
+ else
+ HText_appendCharacter(me->text,*ptr);
+ ptr++;
+ }
+ HText_setIgnoreExcess(me->text, TRUE);
+ }
+ for (; ptr && *ptr != '\0'; ptr++) {
+ if (*ptr == ' ')
+ HText_appendCharacter(me->text,HT_NON_BREAK_SPACE);
+ else
+ HText_appendCharacter(me->text,*ptr);
+ }
+ /*
+ * Add end option character.
+ */
+ if (!me->first_option) {
+ HText_appendCharacter(me->text, ']');
+ HText_setLastChar(me->text, ']');
+ me->in_word = YES;
+ }
+ HText_setIgnoreExcess(me->text, FALSE);
+ }
+ HTChunkClear(&me->option);
+
+ if (me->Underline_Level > 0 && me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ me->inUnderline = TRUE;
+ }
+ if (me->needBoldH == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ me->inBoldH = TRUE;
+ me->needBoldH = FALSE;
+ }
+ }
+ break;
+
+ case HTML_TABLE:
+ me->inTABLE = FALSE;
+ if (!strcmp(me->sp->style->name, "Preformatted")) {
+ break;
+ }
+ if (me->Division_Level >= 0)
+ me->Division_Level--;
+ if (me->Division_Level >= 0)
+ me->sp->style->alignment =
+ me->DivisionAlignments[me->Division_Level];
+ change_paragraph_style(me, me->sp->style);
+ UPDATE_STYLE;
+ me->current_default_alignment = me->sp->style->alignment;
+ if (me->List_Nesting_Level >= 0)
+ HText_NegateLineOne(me->text);
+ break;
+
+/* These TABLE related elements may now not be SGML_EMPTY. - kw */
+ case HTML_TR:
+ break;
+
+ case HTML_THEAD:
+ case HTML_TFOOT:
+ case HTML_TBODY:
+ break;
+
+ case HTML_COLGROUP:
+ break;
+
+ case HTML_TH:
+ break;
+
+ case HTML_TD:
+ break;
+
+/* More stuff that may now not be SGML_EMPTY any more: */
+ case HTML_DT:
+ case HTML_DD:
+ case HTML_LH:
+ case HTML_LI:
+ case HTML_OVERLAY:
+ break;
+
+ case HTML_MATH:
+ /*
+ * We're getting it as Literal text, which, until we can process
+ * it, we'll display as is, within brackets to alert the user. - FM
+ */
+ HTChunkPutc(&me->math, ' ');
+ HTChunkTerminate(&me->math);
+ if (me->math.size > 2) {
+ LYEnsureSingleSpace(me);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "[MATH:");
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ HTML_put_string(me, me->math.data);
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, ":MATH]");
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ LYEnsureSingleSpace(me);
+ }
+ HTChunkClear(&me->math);
+ break;
+
+ default:
+ change_paragraph_style(me, me->sp->style); /* Often won't really change */
+ break;
+
+ } /* switch */
+#ifdef USE_COLOR_STYLE
+ {
+ char *end, *start=NULL, *lookfrom;
+ char tmp[64];
+ sprintf(tmp, ";%s", HTML_dtd.tags[element_number].name);
+ strtolower(tmp);
+
+ lookfrom = Style_className;
+ do
+ {
+ end = start;
+ start = strstr(lookfrom, tmp);
+ if (start)
+ lookfrom = start + 1;
+ }
+ while (start);
+/* trim the last matching element off the end
+** - should match classes here as well (rp)
+*/
+ if (end)
+ *end='\0';
+ hcode=hash_code(lookfrom && *lookfrom ? lookfrom : &tmp[1]);
+ if (TRACE)
+ fprintf(stderr, "CSS:%s (trimmed %s, END_ELEMENT)\n", Style_className, tmp);
+ }
+
+ if (HTML_dtd.tags[element_number].contents != SGML_EMPTY)
+ {
+ if (TRACE)
+ fprintf(stderr, "STYLE:end_element: ending non-EMPTY style\n");
+#if !defined(USE_HASH)
+ HText_characterStyle(me->text, element_number+STARTAT, STACK_OFF);
+#else
+ HText_characterStyle(me->text, hcode, STACK_OFF);
+#endif /* USE_HASH */
+#if defined(PREVAIL)
+ /* reset the prevailing class to the previous one */
+ {
+ char *dot=strrchr(Style_className,'.');
+ LYstrncpy(prevailing_class,
+ dot ? (char*)(dot+1) : "",
+ (TEMPSTRINGSIZE - 1));
+ }
+#endif
+ }
+#endif /* USE_COLOR_STYLE */
+}
+
+/* Expanding entities
+** ------------------
+*/
+/* (In fact, they all shrink!)
+*/
+PUBLIC int HTML_put_entity ARGS2(HTStructured *, me, int, entity_number)
+{
+ int nent = HTML_dtd.number_of_entities;
+
+ if (entity_number < nent) {
+ HTML_put_string(me, p_entity_values[entity_number]);
+ return HT_OK;
+ }
+ return HT_CANNOT_TRANSLATE;
+}
+
+/* Free an HTML object
+** -------------------
+**
+** If the document is empty, the text object will not yet exist.
+** So we could in fact abandon creating the document and return
+** an error code. In fact an empty document is an important type
+** of document, so we don't.
+**
+** If non-interactive, everything is freed off. No: crashes -listrefs
+** Otherwise, the interactive object is left.
+*/
+PRIVATE void HTML_free ARGS1(HTStructured *, me)
+{
+ char *include = NULL;
+
+ if (LYMapsOnly && !me->text) {
+ /*
+ * We only handled MAP, AREA and BASE tags, and didn't
+ * create an HText structure for the document nor want
+ * one now, so just make sure we free anything that might
+ * have been allocated. - FM
+ */
+ FREE(me->base_href);
+ FREE(me->map_address);
+ FREE(me);
+ return;
+ }
+
+ UPDATE_STYLE; /* Creates empty document here! */
+ if (me->comment_end)
+ HTML_put_string(me, me->comment_end);
+ if (me->text) {
+ /*
+ * Emphasis containers, A, FONT, and FORM may be declared
+ * SGML_EMPTY in HTMLDTD.c, and SGML_character() in SGML.c
+ * may check for their end tags to call HTML_end_element()
+ * directly (with a check in that to bypass decrementing
+ * of the HTML parser's stack). So if we still have the
+ * emphasis (Underline) on, or any open A, FONT, or FORM
+ * containers, turn it off or close them now. - FM & kw
+ *
+ * IF those tags are not declared SGML_EMPTY, but we let
+ * the SGML.c parser take care of correctly stacked ordering,
+ * and of correct wind-down on end-of-stream (in SGML_free
+ * SGML_abort),
+ * THEN these and other checks here in HTML.c should not be
+ * necessary. Still it can't hurt to include them. - kw
+ */
+ if (me->inUnderline) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ me->inUnderline = FALSE;
+ me->Underline_Level = 0;
+ if (TRACE)
+ fprintf(stderr,"HTML_free: Ending underline\n");
+ }
+ if (me->inA) {
+ HTML_end_element(me, HTML_A, (char **)&include);
+ me->inA = FALSE;
+ }
+ if (me->inFONT) {
+ HTML_end_element(me, HTML_FONT, (char **)&include);
+ me->inFONT = FALSE;
+ }
+ if (me->inFORM) {
+ HTML_end_element(me, HTML_FORM, (char **)&include);
+ me->inFORM = FALSE;
+ }
+ if (me->option.size > 0) {
+ /*
+ * If we still have data in the me->option chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: SELECT or OPTION not ended properly *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ HTChunkTerminate(&me->option);
+ /*
+ * Output the left-over data as text, maybe it was invalid
+ * markup meant to be shown somewhere. - kw
+ */
+ if (TRACE)
+ fprintf(stderr, "HTML_free: ***** leftover option data: %s\n",
+ me->option.data);
+ HTML_put_string(me, me->option.data);
+ HTChunkClear(&me->option);
+ }
+ if (me->textarea.size > 0) {
+ /*
+ * If we still have data in the me->textarea chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: TEXTAREA not used properly *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ HTChunkTerminate(&me->textarea);
+ /*
+ * Output the left-over data as text, maybe it was invalid
+ * markup meant to be shown somewhere. - kw
+ */
+ if (TRACE)
+ fprintf(stderr, "HTML_free: ***** leftover textarea data: %s\n",
+ me->textarea.data);
+ HTML_put_string(me, me->textarea.data);
+ HTChunkClear(&me->textarea);
+ }
+ /*
+ * If we're interactive and have hidden links but no visible
+ * links, add a message informing the user about this and
+ * suggesting use of the 'l'ist command. - FM
+ */
+ if (!dump_output_immediately &&
+ HText_sourceAnchors(me->text) < 1 &&
+ HText_HiddenLinkCount(me->text) > 0) {
+ HTML_start_element(me, HTML_P, 0, 0, -1, (char **)&include);
+ HTML_put_character(me, '[');
+ HTML_start_element(me, HTML_EM, 0, 0, -1, (char **)&include);
+ HTML_put_string(me,
+ "Document has only hidden links. Use the 'l'ist command.");
+ HTML_end_element(me, HTML_EM, (char **)&include);
+ HTML_put_character(me, ']');
+ HTML_end_element(me, HTML_P, (char **)&include);
+ }
+
+ /*
+ * Now call the cleanup function. - FM
+ */
+ HText_endAppend(me->text);
+ }
+ if (me->option.size > 0) {
+ /*
+ * If we still have data in the me->option chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: SELECT or OPTION not ended properly *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ if (TRACE) {
+ HTChunkTerminate(&me->option);
+ fprintf(stderr, "HTML_free: ***** leftover option data: %s\n",
+ me->option.data);
+ }
+ HTChunkClear(&me->option);
+ }
+ if (me->textarea.size > 0) {
+ /*
+ * If we still have data in the me->textarea chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: TEXTAREA not used properly *****\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ if (TRACE) {
+ HTChunkTerminate(&me->textarea);
+ fprintf(stderr, "HTML_free: ***** leftover textarea data: %s\n",
+ me->textarea.data);
+ }
+ HTChunkClear(&me->textarea);
+ }
+
+ if (me->target) {
+ (*me->targetClass._free)(me->target);
+ }
+ if (me->sp && me->sp->style && me->sp->style->name) {
+ if (!strcmp(me->sp->style->name, "DivCenter") ||
+ !strcmp(me->sp->style->name, "HeadingCenter") ||
+ !strcmp(me->sp->style->name, "Heading1")) {
+ me->sp->style->alignment = HT_CENTER;
+ } else if (!strcmp(me->sp->style->name, "DivRight") ||
+ !strcmp(me->sp->style->name, "HeadingRight")) {
+ me->sp->style->alignment = HT_RIGHT;
+ } else {
+ me->sp->style->alignment = HT_LEFT;
+ }
+ styles[HTML_PRE]->alignment = HT_LEFT;
+ }
+ FREE(me->base_href);
+ FREE(me->map_address);
+ FREE(me->LastOptionValue);
+ FREE(me);
+}
+
+PRIVATE void HTML_abort ARGS2(HTStructured *, me, HTError, e)
+{
+ char *include = NULL;
+
+ if (me->text) {
+ /*
+ * If we have emphasis on, or open A, FONT, or FORM
+ * containers, turn it off or close them now. - FM
+ */
+ if (me->inUnderline) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ me->inUnderline = FALSE;
+ me->Underline_Level = 0;
+ }
+ if (me->inA) {
+ HTML_end_element(me, HTML_A, (char **)&include);
+ me->inA = FALSE;
+ }
+ if (me->inFONT) {
+ HTML_end_element(me, HTML_FONT, (char **)&include);
+ me->inFONT = FALSE;
+ }
+ if (me->inFORM) {
+ HTML_end_element(me, HTML_FORM, (char **)&include);
+ me->inFORM = FALSE;
+ }
+
+ /*
+ * Now call the cleanup function. - FM
+ */
+ HText_endAppend(me->text);
+ }
+
+ if (me->option.size > 0) {
+ /*
+ * If we still have data in the me->option chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML_abort: SELECT or OPTION not ended properly *****\n");
+ HTChunkTerminate(&me->option);
+ fprintf(stderr, "HTML_abort: ***** leftover option data: %s\n",
+ me->option.data);
+ }
+ HTChunkClear(&me->option);
+ }
+ if (me->textarea.size > 0) {
+ /*
+ * If we still have data in the me->textarea chunk after
+ * forcing a close of a still-open form, something must
+ * have gone very wrong. - kw
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "HTML_abort: TEXTAREA not used properly *****\n");
+ HTChunkTerminate(&me->textarea);
+ fprintf(stderr, "HTML_abort: ***** leftover textarea data: %s\n",
+ me->textarea.data);
+ }
+ HTChunkClear(&me->textarea);
+ }
+
+ if (me->target) {
+ (*me->targetClass._abort)(me->target, e);
+ }
+ if (me->sp && me->sp->style && me->sp->style->name) {
+ if (!strcmp(me->sp->style->name, "DivCenter") ||
+ !strcmp(me->sp->style->name, "HeadingCenter") ||
+ !strcmp(me->sp->style->name, "Heading1")) {
+ me->sp->style->alignment = HT_CENTER;
+ } else if (!strcmp(me->sp->style->name, "DivRight") ||
+ !strcmp(me->sp->style->name, "HeadingRight")) {
+ me->sp->style->alignment = HT_RIGHT;
+ } else {
+ me->sp->style->alignment = HT_LEFT;
+ }
+ styles[HTML_PRE]->alignment = HT_LEFT;
+ }
+ FREE(me->base_href);
+ FREE(me->map_address);
+ FREE(me->textarea_name);
+ FREE(me->textarea_accept_cs);
+ FREE(me->textarea_cols);
+ FREE(me->textarea_id);
+ FREE(me->LastOptionValue);
+ FREE(me);
+}
+
+/* Get Styles from style sheet
+** ---------------------------
+*/
+PRIVATE void get_styles NOARGS
+{
+ default_style = HTStyleNamed(styleSheet, "Normal");
+
+ styles[HTML_H1] = HTStyleNamed(styleSheet, "Heading1");
+ styles[HTML_H2] = HTStyleNamed(styleSheet, "Heading2");
+ styles[HTML_H3] = HTStyleNamed(styleSheet, "Heading3");
+ styles[HTML_H4] = HTStyleNamed(styleSheet, "Heading4");
+ styles[HTML_H5] = HTStyleNamed(styleSheet, "Heading5");
+ styles[HTML_H6] = HTStyleNamed(styleSheet, "Heading6");
+ styles[HTML_HCENTER] = HTStyleNamed(styleSheet, "HeadingCenter");
+ styles[HTML_HLEFT] = HTStyleNamed(styleSheet, "HeadingLeft");
+ styles[HTML_HRIGHT] = HTStyleNamed(styleSheet, "HeadingRight");
+
+ styles[HTML_DCENTER] = HTStyleNamed(styleSheet, "DivCenter");
+ styles[HTML_DLEFT] = HTStyleNamed(styleSheet, "DivLeft");
+ styles[HTML_DRIGHT] = HTStyleNamed(styleSheet, "DivRight");
+
+ styles[HTML_DL] = HTStyleNamed(styleSheet, "Glossary");
+ /* nested list styles */
+ styles[HTML_DL1] = HTStyleNamed(styleSheet, "Glossary1");
+ styles[HTML_DL2] = HTStyleNamed(styleSheet, "Glossary2");
+ styles[HTML_DL3] = HTStyleNamed(styleSheet, "Glossary3");
+ styles[HTML_DL4] = HTStyleNamed(styleSheet, "Glossary4");
+ styles[HTML_DL5] = HTStyleNamed(styleSheet, "Glossary5");
+ styles[HTML_DL6] = HTStyleNamed(styleSheet, "Glossary6");
+
+ styles[HTML_UL] =
+ styles[HTML_OL] = HTStyleNamed(styleSheet, "List");
+ /* nested list styles */
+ styles[HTML_OL1] = HTStyleNamed(styleSheet, "List1");
+ styles[HTML_OL2] = HTStyleNamed(styleSheet, "List2");
+ styles[HTML_OL3] = HTStyleNamed(styleSheet, "List3");
+ styles[HTML_OL4] = HTStyleNamed(styleSheet, "List4");
+ styles[HTML_OL5] = HTStyleNamed(styleSheet, "List5");
+ styles[HTML_OL6] = HTStyleNamed(styleSheet, "List6");
+
+ styles[HTML_MENU] =
+ styles[HTML_DIR] = HTStyleNamed(styleSheet, "Menu");
+ /* nested list styles */
+ styles[HTML_MENU1] = HTStyleNamed(styleSheet, "Menu1");
+ styles[HTML_MENU2] = HTStyleNamed(styleSheet, "Menu2");
+ styles[HTML_MENU3] = HTStyleNamed(styleSheet, "Menu3");
+ styles[HTML_MENU4] = HTStyleNamed(styleSheet, "Menu4");
+ styles[HTML_MENU5] = HTStyleNamed(styleSheet, "Menu5");
+ styles[HTML_MENU6] = HTStyleNamed(styleSheet, "Menu6");
+
+ styles[HTML_DLC] = HTStyleNamed(styleSheet, "GlossaryCompact");
+ /* nested list styles */
+ styles[HTML_DLC1] = HTStyleNamed(styleSheet, "GlossaryCompact1");
+ styles[HTML_DLC2] = HTStyleNamed(styleSheet, "GlossaryCompact2");
+ styles[HTML_DLC3] = HTStyleNamed(styleSheet, "GlossaryCompact3");
+ styles[HTML_DLC4] = HTStyleNamed(styleSheet, "GlossaryCompact4");
+ styles[HTML_DLC5] = HTStyleNamed(styleSheet, "GlossaryCompact5");
+ styles[HTML_DLC6] = HTStyleNamed(styleSheet, "GlossaryCompact6");
+
+ styles[HTML_ADDRESS] = HTStyleNamed(styleSheet, "Address");
+ styles[HTML_BANNER] = HTStyleNamed(styleSheet, "Banner");
+ styles[HTML_BLOCKQUOTE] = HTStyleNamed(styleSheet, "Blockquote");
+ styles[HTML_BQ] = HTStyleNamed(styleSheet, "Bq");
+ styles[HTML_FN] = HTStyleNamed(styleSheet, "Footnote");
+ styles[HTML_NOTE] = HTStyleNamed(styleSheet, "Note");
+ styles[HTML_PLAINTEXT] =
+ styles[HTML_XMP] = HTStyleNamed(styleSheet, "Example");
+ styles[HTML_PRE] = HTStyleNamed(styleSheet, "Preformatted");
+ styles[HTML_LISTING] = HTStyleNamed(styleSheet, "Listing");
+}
+
+/* P U B L I C
+*/
+
+/* Structured Object Class
+** -----------------------
+*/
+PUBLIC CONST HTStructuredClass HTMLPresentation = /* As opposed to print etc */
+{
+ "Lynx_HTML_Handler",
+ HTML_free,
+ HTML_abort,
+ HTML_put_character, HTML_put_string, HTML_write,
+ HTML_start_element, HTML_end_element,
+ HTML_put_entity
+};
+
+/* New Structured Text object
+** --------------------------
+**
+** The structured stream can generate either presentation,
+** or plain text, or HTML.
+*/
+PUBLIC HTStructured* HTML_new ARGS3(
+ HTParentAnchor *, anchor,
+ HTFormat, format_out,
+ HTStream*, stream)
+{
+
+ HTStructured * me;
+
+ if (format_out != WWW_PLAINTEXT && format_out != WWW_PRESENT) {
+ HTStream * intermediate = HTStreamStack(WWW_HTML, format_out,
+ stream, anchor);
+ if (intermediate)
+ return HTMLGenerator(intermediate);
+ fprintf(stderr, "\n** Internal error: can't parse HTML to %s\n",
+ HTAtom_name(format_out));
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit (-1);
+ }
+
+ me = (HTStructured*) calloc(sizeof(*me),1);
+ if (me == NULL)
+ outofmem(__FILE__, "HTML_new");
+
+ /*
+ * This used to call 'get_styles()' only on the first time through this
+ * function. However, if the user reloads a page with ^R, the styles[]
+ * array is not necessarily the same as it was from 'get_styles()'. So
+ * we reinitialize the whole thing.
+ */
+ styleSheet = DefaultStyle();
+ get_styles();
+
+ me->isa = &HTMLPresentation;
+ me->node_anchor = anchor;
+
+ me->CurrentA = NULL;
+ me->CurrentANum = 0;
+ me->base_href = NULL;
+ me->map_address = NULL;
+
+ me->title.size = 0;
+ me->title.growby = 128;
+ me->title.allocated = 0;
+ me->title.data = NULL;
+
+ me->object.size = 0;
+ me->object.growby = 128;
+ me->object.allocated = 0;
+ me->object.data = NULL;
+ me->object_started = FALSE;
+ me->object_declare = FALSE;
+ me->object_shapes = FALSE;
+ me->object_ismap = FALSE;
+ me->object_id = NULL;
+ me->object_title = NULL;
+ me->object_data = NULL;
+ me->object_type = NULL;
+ me->object_classid = NULL;
+ me->object_codebase = NULL;
+ me->object_codetype = NULL;
+ me->object_usemap = NULL;
+ me->object_name = NULL;
+
+ me->option.size = 0;
+ me->option.growby = 128;
+ me->option.allocated = 0;
+ me->option.data = NULL;
+ me->first_option = TRUE;
+ me->LastOptionValue = NULL;
+ me->LastOptionChecked = FALSE;
+ me->select_disabled = FALSE;
+
+ me->textarea.size = 0;
+ me->textarea.growby = 128;
+ me->textarea.allocated = 0;
+ me->textarea.data = NULL;
+ me->textarea_name = NULL;
+ me->textarea_name_cs = -1;
+ me->textarea_accept_cs = NULL;
+ me->textarea_cols = NULL;
+ me->textarea_rows = 4;
+ me->textarea_disabled = NO;
+ me->textarea_id = NULL;
+
+ me->math.size = 0;
+ me->math.growby = 128;
+ me->math.allocated = 0;
+ me->math.data = NULL;
+
+ me->style_block.size = 0;
+ me->style_block.growby = 128;
+ me->style_block.allocated = 0;
+ me->style_block.data = NULL;
+
+ me->script.size = 0;
+ me->script.growby = 128;
+ me->script.allocated = 0;
+ me->script.data = NULL;
+
+ me->text = 0;
+ me->style_change = YES; /* Force check leading to text creation */
+ me->new_style = default_style;
+ me->old_style = 0;
+ me->current_default_alignment = HT_LEFT;
+ me->sp = (me->stack + MAX_NESTING - 1);
+ me->skip_stack = 0;
+ me->sp->tag_number = -1; /* INVALID */
+ me->sp->style = default_style; /* INVALID */
+ me->sp->style->alignment = HT_LEFT;
+ me->stack_overrun = FALSE;
+
+ me->Division_Level = -1;
+ me->Underline_Level = 0;
+ me->Quote_Level = 0;
+
+ me->UsePlainSpace = FALSE;
+ me->HiddenValue = FALSE;
+ me->lastraw = -1;
+
+ /*
+ * Used for nested lists. - FM
+ */
+ me->List_Nesting_Level = -1; /* counter for list nesting level */
+ LYZero_OL_Counter(me); /* Initializes OL_Counter[] and OL_Type[] */
+ me->Last_OL_Count = 0; /* last count in ordered lists */
+ me->Last_OL_Type = '1'; /* last type in ordered lists */
+
+ me->inA = FALSE;
+ me->inAPPLET = FALSE;
+ me->inAPPLETwithP = FALSE;
+ me->inBadBASE = FALSE;
+ me->inBadHREF = FALSE;
+ me->inBadHTML = FALSE;
+ me->inBASE = FALSE;
+ me->inBoldA = FALSE;
+ me->inBoldH = FALSE;
+ me->inCAPTION = FALSE;
+ me->inCREDIT = FALSE;
+ me->inFIG = FALSE;
+ me->inFIGwithP = FALSE;
+ me->inFONT = FALSE;
+ me->inFORM = FALSE;
+ me->inLABEL = FALSE;
+ me->inP = FALSE;
+ me->inPRE = FALSE;
+ me->inSELECT = FALSE;
+ me->inTABLE = FALSE;
+ me->inUnderline = FALSE;
+
+ me->needBoldH = FALSE;
+
+ me->comment_start = NULL;
+ me->comment_end = NULL;
+
+#ifdef USE_COLOR_STYLE
+ Style_className[0] = '\0';
+ class_string[0] = '\0';
+ prevailing_class[0] = '\0';
+#endif
+
+#ifdef NOTUSED_FOTEMODS
+ /*
+ ** If the anchor already has stage info, make sure that it is
+ ** appropriate for the current display charset. HTMIMEConvert()
+ ** does this for the http and https schemes, and HTCharsetFormat()
+ ** does it for the file and and ftp schemes, be we need to do it,
+ ** if necessary, for the gateway schemes. - FM
+ */
+ if (me->node_anchor->UCStages) {
+ if (HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_STRUCTURED) != current_char_set) {
+ /*
+ ** We are reloading due to a change in the display character
+ ** set. Free the stage info and let the stage info creation
+ ** mechanisms create a new UCStages structure appropriate for
+ ** the current display character set. - FM
+ */
+ FREE(anchor->UCStages);
+ } else if (HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_MIME) == current_char_set) {
+ /*
+ ** The MIME stage is set to the current display character
+ ** set. If it is CJK, and HTCJK does not point to a CJK
+ ** character set, assume we are reloading due to a raw
+ ** mode toggle and reset the MIME and PARSER stages to
+ ** an ISO Latin 1 default. - FM
+ */
+ LYUCcharset *p_in = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_MIME);
+ if (p_in->enc == UCT_ENC_CJK && HTCJK == NOCJK) {
+ HTAnchor_resetUCInfoStage(me->node_anchor, 0,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_setUCInfoStage(me->node_anchor, 0,
+ UCT_STAGE_MIME,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_resetUCInfoStage(me->node_anchor, 0,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT);
+ HTAnchor_setUCInfoStage(me->node_anchor, 0,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT);
+ }
+ }
+ }
+#endif /* NOTUSED_FOTEMODS */
+
+ /*
+ ** Create a chartrans stage info structure for the anchor,
+ ** if it does not exist already (in which case the default
+ ** MIME stage info will be loaded as well), and load the
+ ** HTML stage info into me->UCI and me->UCLYhndl. - FM
+ */
+ LYGetChartransInfo(me);
+ UCTransParams_clear(&me->T);
+
+ /*
+ ** Load the existing or default input charset info
+ ** into the holding elements. We'll believe what
+ ** is indicated for UCT_STAGE_PARSER. - FM
+ */
+ me->inUCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_PARSER);
+ if (me->inUCLYhndl < 0) {
+ me->inUCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_MIME);
+ me->inUCI = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_MIME);
+ } else {
+ me->inUCI = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_PARSER);
+ }
+
+ /*
+ ** Load the existing or default output charset info
+ ** into the holding elements, UCT_STAGE_STRUCTURED
+ ** should be the same as UCT_STAGE_TEXT at this point,
+ ** but we could check, perhaps. - FM
+ */
+ me->outUCI = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_STRUCTURED);
+ me->outUCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_STRUCTURED);
+#ifdef NOTUSED_FOTEMODS
+ UCSetTransParams(&me->T,
+ me->inUCLYhndl, me->inUCI,
+ me->outUCLYhndl, me->outUCI);
+#endif
+
+ me->target = stream;
+ if (stream)
+ me->targetClass = *stream->isa; /* Copy pointers */
+
+ return (HTStructured*) me;
+}
+
+/* HTConverter for HTML to plain text
+** ----------------------------------
+**
+** This will convert from HTML to presentation or plain text.
+*/
+PUBLIC HTStream* HTMLToPlain ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ return SGML_new(&HTML_dtd, anchor, HTML_new(anchor, pres->rep_out, sink));
+}
+
+/* HTConverter for HTML source to plain text
+** -----------------------------------------
+**
+** This will preparse HTML and convert back to presentation or plain text.
+*/
+PUBLIC HTStream* HTMLParsedPresent ARGS3(
+ HTPresentation *, pres,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStream * intermediate = sink;
+ if (!intermediate) {
+ /*
+ * Trick to prevent HTPlainPresent from translating again.
+ * Temporarily change UCT_STAGE_PARSER setting in anchor
+ * while the HTPlain stream is initialized, so that HTPlain
+ * sees its input and output charsets as the same. - kw
+ */
+ int old_parser_cset = HTAnchor_getUCLYhndl(anchor,UCT_STAGE_PARSER);
+ int structured_cset = HTAnchor_getUCLYhndl(anchor,UCT_STAGE_STRUCTURED);
+ if (structured_cset < 0)
+ structured_cset = HTAnchor_getUCLYhndl(anchor,UCT_STAGE_HTEXT);
+ if (structured_cset < 0)
+ structured_cset = current_char_set;
+ HTAnchor_setUCInfoStage(anchor, structured_cset,
+ UCT_STAGE_PARSER, UCT_SETBY_MIME);
+ if (pres->rep_out == WWW_SOURCE) {
+/* intermediate = HTPlainPresent(pres, anchor, NULL); */
+ intermediate = HTStreamStack(WWW_PLAINTEXT, WWW_PRESENT,
+ NULL, anchor);
+ } else {
+ intermediate = HTStreamStack(WWW_PLAINTEXT, pres->rep_out,
+ NULL, anchor);
+ }
+ if (old_parser_cset != structured_cset) {
+ HTAnchor_resetUCInfoStage(anchor, old_parser_cset,
+ UCT_STAGE_PARSER, UCT_SETBY_NONE);
+ if (old_parser_cset >= 0) {
+ HTAnchor_setUCInfoStage(anchor, old_parser_cset,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT+1);
+ }
+ }
+ }
+ if (!intermediate)
+ return NULL;
+ return SGML_new(&HTML_dtd, anchor, HTMLGenerator(intermediate));
+}
+
+/* HTConverter for HTML to C code
+** ------------------------------
+**
+** C code is like plain text but all non-preformatted code
+** is commented out.
+** This will convert from HTML to presentation or plain text.
+*/
+PUBLIC HTStream* HTMLToC ARGS3(
+ HTPresentation *, pres GCC_UNUSED,
+ HTParentAnchor *, anchor,
+ HTStream *, sink)
+{
+ HTStructured * html;
+
+ (*sink->isa->put_string)(sink, "/* "); /* Before even title */
+ html = HTML_new(anchor, WWW_PLAINTEXT, sink);
+ html->comment_start = "/* ";
+ html->comment_end = " */\n"; /* Must start in col 1 for cpp */
+/* HTML_put_string(html,html->comment_start); */
+ return SGML_new(&HTML_dtd, anchor, html);
+}
+
+/* Presenter for HTML
+** ------------------
+**
+** This will convert from HTML to presentation or plain text.
+**
+** Override this if you have a windows version
+*/
+#ifndef GUI
+PUBLIC HTStream* HTMLPresent ARGS3(
+ HTPresentation *, pres GCC_UNUSED,
+ HTParentAnchor *, anchor,
+ HTStream *, sink GCC_UNUSED)
+{
+ return SGML_new(&HTML_dtd, anchor, HTML_new(anchor, WWW_PRESENT, NULL));
+}
+#endif /* !GUI */
+
+/* Record error message as a hypertext object
+** ------------------------------------------
+**
+** The error message should be marked as an error so that
+** it can be reloaded later.
+** This implementation just throws up an error message
+** and leaves the document unloaded.
+** A smarter implementation would load an error document,
+** marking at such so that it is retried on reload.
+**
+** On entry,
+** sink is a stream to the output device if any
+** number is the HTTP error number
+** message is the human readable message.
+**
+** On exit,
+** returns a negative number to indicate lack of success in the load.
+*/
+PUBLIC int HTLoadError ARGS3(
+ HTStream *, sink GCC_UNUSED,
+ int, number,
+ CONST char *, message)
+{
+ HTAlert(message); /* @@@@@@@@@@@@@@@@@@@ */
+ return -number;
+}
diff --git a/gnu/usr.bin/lynx/src/HTML.h b/gnu/usr.bin/lynx/src/HTML.h
new file mode 100644
index 00000000000..d75a10bd0bc
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTML.h
@@ -0,0 +1,281 @@
+/* HTML to rich text converter for libwww
+**
+** THE HTML TO RTF OBJECT CONVERTER
+**
+** This interprets the HTML semantics.
+*/
+#ifndef HTML_H
+#define HTML_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+#include "UCDefs.h"
+#include "UCAux.h"
+#include "HTAnchor.h"
+#include "HTMLDTD.h"
+
+#ifdef SHORT_NAMES
+#define HTMLPresentation HTMLPren
+#define HTMLPresent HTMLPres
+#endif /* SHORT_NAMES */
+
+/* #define ATTR_CS_IN (me->T.output_utf8 ? me->UCLYhndl : 0) */
+#define ATTR_CS_IN me->tag_charset
+
+#define TRANSLATE_AND_UNESCAPE_ENTITIES(s, p, h) \
+ LYUCFullyTranslateString(s, ATTR_CS_IN, current_char_set, YES, p, h, st_HTML)
+
+#define TRANSLATE_AND_UNESCAPE_ENTITIES5(s,cs_from,cs_to,p,h) \
+ LYUCFullyTranslateString(s, cs_from, cs_to, YES, p, h, st_HTML)
+
+#define TRANSLATE_AND_UNESCAPE_ENTITIES6(s,cs_from,cs_to,spcls,p,h) \
+ LYUCFullyTranslateString(s, cs_from, cs_to, spcls, p, h, st_HTML)
+
+/*
+ * Strings from attributes which should be converted to some kind
+ * of "standard" representation (character encoding), was Latin-1,
+ * esp. URLs (incl. #fragments) and HTML NAME and ID stuff.
+ */
+#define TRANSLATE_AND_UNESCAPE_TO_STD(s) \
+ LYUCFullyTranslateString(s, ATTR_CS_IN, ATTR_CS_IN, NO, NO, YES, st_URL)
+#define UNESCAPE_FIELDNAME_TO_STD(s) \
+ LYUCFullyTranslateString(s, ATTR_CS_IN, ATTR_CS_IN, NO, NO, YES, st_HTML)
+
+extern CONST HTStructuredClass HTMLPresentation;
+
+#ifdef Lynx_HTML_Handler
+/*
+** This section is semi-private to HTML.c and it's helper modules. - FM
+** --------------------------------------------------------------------
+*/
+
+typedef struct _stack_element {
+ HTStyle * style;
+ int tag_number;
+} stack_element;
+
+/* HTML Object
+** -----------
+*/
+#define MAX_NESTING 800 /* Should be checked by parser */
+
+struct _HTStructured {
+ CONST HTStructuredClass * isa;
+ HTParentAnchor * node_anchor;
+ HText * text;
+
+ HTStream* target; /* Output stream */
+ HTStreamClass targetClass; /* Output routines */
+
+ HTChildAnchor * CurrentA; /* current HTML_A anchor */
+ int CurrentANum; /* current HTML_A number */
+ char * base_href; /* current HTML_BASE href */
+ char * map_address; /* current HTML_MAP address */
+
+ HTChunk title; /* Grow by 128 */
+ HTChunk object; /* Grow by 128 */
+ BOOL object_started;
+ BOOL object_declare;
+ BOOL object_shapes;
+ BOOL object_ismap;
+ char * object_usemap;
+ char * object_id;
+ char * object_title;
+ char * object_data;
+ char * object_type;
+ char * object_classid;
+ char * object_codebase;
+ char * object_codetype;
+ char * object_name;
+ HTChunk option; /* Grow by 128 */
+ BOOL first_option; /* First OPTION in SELECT? */
+ char * LastOptionValue;
+ BOOL LastOptionChecked;
+ BOOL select_disabled;
+ HTChunk textarea; /* Grow by 128 */
+ char * textarea_name;
+ int textarea_name_cs;
+ char * textarea_accept_cs;
+ char * textarea_cols;
+ int textarea_rows;
+ int textarea_disabled;
+ char * textarea_id;
+ HTChunk math; /* Grow by 128 */
+ HTChunk style_block; /* Grow by 128 */
+ HTChunk script; /* Grow by 128 */
+
+ /*
+ * Used for nested lists. - FM
+ */
+ int List_Nesting_Level; /* counter for list nesting level */
+ int OL_Counter[12]; /* counter for ordered lists */
+ char OL_Type[12]; /* types for ordered lists */
+ int Last_OL_Count; /* last count in ordered lists */
+ char Last_OL_Type; /* last type in ordered lists */
+
+ int Division_Level;
+ short DivisionAlignments[MAX_NESTING];
+ int Underline_Level;
+ int Quote_Level;
+
+ BOOL UsePlainSpace;
+ BOOL HiddenValue;
+ int lastraw;
+
+ char * comment_start; /* for literate programming */
+ char * comment_end;
+
+ HTTag * current_tag;
+ BOOL style_change;
+ HTStyle * new_style;
+ HTStyle * old_style;
+ int current_default_alignment;
+ BOOL in_word; /* Have just had a non-white char */
+ stack_element stack[MAX_NESTING];
+ stack_element *sp; /* Style stack pointer */
+ BOOL stack_overrun; /* Was MAX_NESTING exceeded? */
+ int skip_stack; /* flag to skip next style stack operation */
+
+ /*
+ ** Track if we are in an anchor, paragraph, address, base, etc.
+ */
+ BOOL inA;
+ BOOL inAPPLET;
+ BOOL inAPPLETwithP;
+ BOOL inBadBASE;
+ BOOL inBadHREF;
+ BOOL inBadHTML;
+ BOOL inBASE;
+ BOOL inBoldA;
+ BOOL inBoldH;
+ BOOL inCAPTION;
+ BOOL inCREDIT;
+ BOOL inFIG;
+ BOOL inFIGwithP;
+ BOOL inFONT;
+ BOOL inFORM;
+ BOOL inLABEL;
+ BOOL inP;
+ BOOL inPRE;
+ BOOL inSELECT;
+ BOOL inTABLE;
+ BOOL inTEXTAREA;
+ BOOL inUnderline;
+
+ BOOL needBoldH;
+
+ /*
+ ** UCI and UCLYhndl give the UCInfo and charset registered for
+ ** the HTML parser in the node_anchor's UCStages structure. It
+ ** indicates what is fed to the HTML parser as the stream of character
+ ** data (not necessarily tags and attributes). It should currently
+ ** always be set to be the same as UCI and UCLhndl for the HTEXT stage
+ ** in the node_anchor's UCStages structure, since the HTML parser sends
+ ** its input character data to the output without further charset
+ ** translation.
+ */
+ LYUCcharset * UCI;
+ int UCLYhndl;
+ /*
+ ** inUCI and inUCLYhndl indicate the UCInfo and charset which the
+ ** HTML parser treats at the input charset. It is normally set
+ ** to the UCI and UCLhndl for the SGML parser in the node_anchor's
+ ** UCStages structure (which may be a dummy, based on the MIME
+ ** parser's UCI and UCLhndl in that structure, when we are handling
+ ** a local file or non-http(s) gateway). It could be changed
+ ** temporarily by the HTML parser, for conversions of attribute
+ ** strings, but should be reset once done. - FM
+ */
+ LYUCcharset * inUCI;
+ int inUCLYhndl;
+ /*
+ ** outUCI and outUCLYhndl indicate the UCInfo and charset which
+ ** the HTML parser treats as the output charset. It is normally
+ ** set to its own UCI and UCLhndl. It could be changed for
+ ** conversions of attribute strings, but should be reset once
+ ** done. - FM
+ */
+ LYUCcharset * outUCI;
+ int outUCLYhndl;
+ /*
+ ** T holds the transformation rules for conversions of strings
+ ** between the input and output charsets by the HTML parser. - FM
+ */
+ UCTransParams T;
+
+ int tag_charset; /* charset for attribute values etc. */
+};
+
+extern HTStyle *styles[HTML_ELEMENTS+31]; /* adding 24 nested list styles */
+ /* and 3 header alignment styles */
+ /* and 3 div alignment styles */
+
+/*
+ * Semi-Private functions. - FM
+ */
+extern void HTML_put_character PARAMS((HTStructured *me, char c));
+extern void HTML_put_string PARAMS((HTStructured *me, CONST char *s));
+extern void HTML_write PARAMS((HTStructured *me, CONST char *s, int l));
+extern int HTML_put_entity PARAMS((HTStructured *me, int entity_number));
+extern void actually_set_style PARAMS((HTStructured * me));
+
+/* Style buffering avoids dummy paragraph begin/ends.
+*/
+#define UPDATE_STYLE if (me->style_change) { actually_set_style(me); }
+#endif /* Lynx_HTML_Handler */
+
+extern void strtolower PARAMS((char* i));
+
+/* P U B L I C
+*/
+
+/*
+** HTConverter to present HTML
+*/
+extern HTStream* HTMLToPlain PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStream* HTMLParsedPresent PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStream* HTMLToC PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStream* HTMLPresent PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStructured* HTML_new PARAMS((
+ HTParentAnchor * anchor,
+ HTFormat format_out,
+ HTStream * target));
+
+/*
+** Record error message as a hypertext object.
+**
+** The error message should be marked as an error so that it can be
+** reloaded later. This implementation just throws up an error message
+** and leaves the document unloaded.
+**
+** On entry,
+** sink is a stream to the output device if any
+** number is the HTTP error number
+** message is the human readable message.
+** On exit,
+** a retrun code like HT_LOADED if object exists else 60; 0
+*/
+extern int HTLoadError PARAMS((
+ HTStream * sink,
+ int number,
+ CONST char * message));
+
+#endif /* HTML_H */
+
diff --git a/gnu/usr.bin/lynx/src/HTNestedList.h b/gnu/usr.bin/lynx/src/HTNestedList.h
new file mode 100644
index 00000000000..32a3049bc9c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTNestedList.h
@@ -0,0 +1,40 @@
+#ifndef HTNESTEDLIST_H
+#define HTNESTEDLIST_H
+
+#define HTML_OL1 HTML_ELEMENTS+1
+#define HTML_OL2 HTML_ELEMENTS+2
+#define HTML_OL3 HTML_ELEMENTS+3
+#define HTML_OL4 HTML_ELEMENTS+4
+#define HTML_OL5 HTML_ELEMENTS+5
+#define HTML_OL6 HTML_ELEMENTS+6
+
+#define HTML_MENU1 HTML_ELEMENTS+7
+#define HTML_MENU2 HTML_ELEMENTS+8
+#define HTML_MENU3 HTML_ELEMENTS+9
+#define HTML_MENU4 HTML_ELEMENTS+10
+#define HTML_MENU5 HTML_ELEMENTS+11
+#define HTML_MENU6 HTML_ELEMENTS+12
+
+#define HTML_DL1 HTML_ELEMENTS+13
+#define HTML_DL2 HTML_ELEMENTS+14
+#define HTML_DL3 HTML_ELEMENTS+15
+#define HTML_DL4 HTML_ELEMENTS+16
+#define HTML_DL5 HTML_ELEMENTS+17
+#define HTML_DL6 HTML_ELEMENTS+18
+
+#define HTML_DLC1 HTML_ELEMENTS+19
+#define HTML_DLC2 HTML_ELEMENTS+20
+#define HTML_DLC3 HTML_ELEMENTS+21
+#define HTML_DLC4 HTML_ELEMENTS+22
+#define HTML_DLC5 HTML_ELEMENTS+23
+#define HTML_DLC6 HTML_ELEMENTS+24
+
+#define HTML_HCENTER HTML_ELEMENTS+25
+#define HTML_HLEFT HTML_ELEMENTS+26
+#define HTML_HRIGHT HTML_ELEMENTS+27
+
+#define HTML_DCENTER HTML_ELEMENTS+28
+#define HTML_DLEFT HTML_ELEMENTS+29
+#define HTML_DRIGHT HTML_ELEMENTS+30
+
+#endif /* HTNESTEDLIST_H */
diff --git a/gnu/usr.bin/lynx/src/HTSaveToFile.h b/gnu/usr.bin/lynx/src/HTSaveToFile.h
new file mode 100644
index 00000000000..a13ad78a32c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/HTSaveToFile.h
@@ -0,0 +1,19 @@
+#ifndef HTSAVETOFILE_H
+#define HTSAVETOFILE_H
+
+extern HTStream * HTSaveToFile PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStream * HTDumpToStdout PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+extern HTStream * HTCompressed PARAMS((
+ HTPresentation * pres,
+ HTParentAnchor * anchor,
+ HTStream * sink));
+
+#endif /* HTSAVETOFILE_H */
diff --git a/gnu/usr.bin/lynx/src/LYBookmark.c b/gnu/usr.bin/lynx/src/LYBookmark.c
new file mode 100644
index 00000000000..e43f337b893
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYBookmark.c
@@ -0,0 +1,918 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYBookmark.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYSystem.h"
+#include "LYKeymap.h"
+#include "LYCharUtils.h"
+#include "LYCurses.h"
+#include "GridText.h"
+
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+#ifdef VMS
+#include "HTVMSUtils.h"
+#include <nam.h>
+extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC char *MBM_A_subbookmark[MBM_V_MAXFILES+1];
+PUBLIC char *MBM_A_subdescript[MBM_V_MAXFILES+1];
+
+PRIVATE BOOLEAN is_mosaic_hotlist = FALSE;
+PRIVATE char * convert_mosaic_bookmark_file PARAMS((char *filename_buffer));
+
+/*
+ * Tries to open a bookmark file for reading, which may be
+ * the default, or based on offering the user a choice from
+ * the MBM_A_subbookmark[] array. If successful the file is
+ * closed, and the filename in system path specs is returned,
+ * the URL is allocated into *URL, and the MBM_A_subbookmark[]
+ * filepath is allocated into the BookmarkPage global. Returns
+ * a zero-length pointer to flag a cancel, or a space to flag
+ * an undefined selection, without allocating into *URL or
+ * BookmarkPage. Returns NULL with allocating into BookmarkPage
+ * but not *URL is the selection is valid but the file doesn't
+ * yet exist. - FM
+ */
+PUBLIC char * get_bookmark_filename ARGS1(
+ char **, URL)
+{
+ char URL_buffer[256];
+ static char filename_buffer[256];
+ char string_buffer[256];
+ FILE *fp;
+ int MBM_tmp;
+
+ /*
+ * Multi_Bookmarks support. - FMG & FM
+ * Let user select a bookmark file.
+ */
+ MBM_tmp = select_multi_bookmarks();
+ if (MBM_tmp == -2)
+ /*
+ * Zero-length pointer flags a cancel. - FM
+ */
+ return("");
+ if (MBM_tmp == -1) {
+ sprintf(string_buffer,
+ BOOKMARK_FILE_NOT_DEFINED,
+ key_for_func(LYK_OPTIONS));
+ _statusline(string_buffer);
+ sleep(AlertSecs);
+ /*
+ * Space flags an undefined selection. - FMG
+ */
+ return(" ");
+ } else {
+ /*
+ * Save the filepath as a global. The system path will be
+ * loaded into to the (static) filename_buffer as the return
+ * value, the URL will be allocated into *URL, and we also
+ * need the filepath available to calling functions. This
+ * is all pitifully non-reentrant, a la the original Lynx,
+ * and should be redesigned someday. - FM
+ */
+ StrAllocCopy(BookmarkPage, MBM_A_subbookmark[MBM_tmp]);
+ }
+
+ /*
+ * Seek it in the home path. - FM
+ */
+ filename_buffer[255] = '\0';
+ LYAddPathToHome(filename_buffer,
+ sizeof(filename_buffer),
+ BookmarkPage);
+ if (TRACE)
+ fprintf(stderr, "\nget_bookmark_filename: SEEKING %s\n AS %s\n\n",
+ BookmarkPage, filename_buffer);
+ if ((fp = fopen(filename_buffer,"r")) != NULL) {
+ goto success;
+ }
+
+ /*
+ * Failure.
+ */
+ return(NULL);
+
+success:
+ /*
+ * We now have the file open.
+ * Check if it is a mosaic hotlist.
+ */
+ if (fgets(string_buffer, 255, fp) &&
+ !strncmp(string_buffer, "ncsa-xmosaic-hotlist-format-1", 29)) {
+ char *newname;
+ /*
+ * It is a mosaic hotlist file.
+ */
+ is_mosaic_hotlist = TRUE;
+ fclose(fp);
+ newname = convert_mosaic_bookmark_file(filename_buffer);
+#ifdef DOSPATH
+ sprintf(URL_buffer, "file://localhost/%s",
+ HTDOS_wwwName((char *)newname));
+#else
+#ifdef VMS
+ sprintf(URL_buffer,"file://localhost%s",
+ HTVMS_wwwName((char *)newname));
+#else
+ sprintf(URL_buffer,"file://localhost%s", newname);
+#endif /* VMS */
+#endif /* DOSPATH */
+ } else {
+ fclose(fp);
+ is_mosaic_hotlist = FALSE;
+#ifdef DOSPATH
+ sprintf(URL_buffer,"file://localhost/%s",
+ HTDOS_wwwName((char *)filename_buffer));
+#else
+#ifdef VMS
+ sprintf(URL_buffer,"file://localhost%s",
+ HTVMS_wwwName((char *)filename_buffer));
+#else
+ sprintf(URL_buffer,"file://localhost%s", filename_buffer);
+#endif /* VMS */
+#endif /* DOSPATH */
+ }
+
+ StrAllocCopy(*URL, URL_buffer);
+ return(filename_buffer); /* bookmark file exists */
+
+} /* big end */
+
+/*
+ * Converts a Mosaic hotlist file into an HTML
+ * file for handling as a Lynx bookmark file. - FM
+ */
+PRIVATE char * convert_mosaic_bookmark_file ARGS1(
+ char *, filename_buffer)
+{
+ static char newfile[256];
+ static BOOLEAN first = TRUE;
+ FILE *fp, *nfp;
+ char buf[BUFSIZ];
+ int line = -2;
+ char *endline;
+
+ if (first) {
+ tempname(newfile, NEW_FILE);
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(newfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ if ((nfp = fopen(newfile, "w")) == NULL) {
+ LYMBM_statusline(NO_TEMP_FOR_HOTLIST);
+ sleep(AlertSecs);
+ return ("");
+ }
+
+ if ((fp = fopen(filename_buffer, "r")) == NULL)
+ return (""); /* should always open */
+
+ fprintf(nfp,"<head>\n<title>%s</title>\n</head>\n",MOSAIC_BOOKMARK_TITLE);
+ fprintf(nfp,"\
+ This file is an HTML representation of the X Mosaic hotlist file.\n\
+ Outdated or invalid links may be removed by using the\n\
+ remove bookmark command, it is usually the 'R' key but may have\n\
+ been remapped by you or your system administrator.\n\n<p>\n<ol>\n");
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if(line >= 0) {
+ endline = &buf[strlen(buf)-1];
+ if(*endline == '\n')
+ *endline = '\0';
+ if((line % 2) == 0) { /* even lines */
+ if(*buf != '\0') {
+ strtok(buf," "); /* kill everything after the space */
+ fprintf(nfp,"<LI><a href=\"%s\">",buf); /* the URL */
+ }
+ } else { /* odd lines */
+ fprintf(nfp,"%s</a>\n",buf); /* the title */
+ }
+ }
+ /* else - ignore the line (this gets rid of first two lines) */
+ line++;
+ }
+ fclose(nfp);
+ fclose(fp);
+ return(newfile);
+}
+
+/*
+ * Adds a link to a bookmark file, creating the file
+ * if it doesn't already exist, and making sure that
+ * no_cache is set for a pre-existing, cached file,
+ * so that the change will be evident on return to
+ * to that file. - FM
+ */
+PUBLIC void save_bookmark_link ARGS2(
+ char *, address,
+ char *, title)
+{
+ FILE *fp;
+ BOOLEAN first_time = FALSE;
+ char *filename;
+ char *bookmark_URL = NULL;
+ char filename_buffer[256];
+ char string_buffer[256];
+ char *Address = NULL;
+ char *Title = NULL;
+ int i, c;
+ DocAddress WWWDoc;
+ HTParentAnchor *tmpanchor;
+ HText *text;
+
+ /*
+ * Make sure we were passed something to save. - FM
+ */
+ if (!(address && *address)) {
+ HTAlert(MALFORMED_ADDRESS);
+ return;
+ }
+
+ /*
+ * Offer a choice of bookmark files,
+ * or get the default. - FMG
+ */
+ filename = get_bookmark_filename(&bookmark_URL);
+
+ /*
+ * If filename is NULL, must create a new file. If
+ * filename is a space, an invalid bookmark file was
+ * selected, or if zero-length, the user cancelled.
+ * Ignore request in both cases. Otherwise, make
+ * a copy before anything might change the static
+ * get_bookmark_filename() buffer. - FM
+ */
+ if (filename == NULL) {
+ first_time = TRUE;
+ filename_buffer[0] = '\0';
+ } else {
+ if (*filename == '\0' || !strcmp(filename," ")) {
+ FREE(bookmark_URL);
+ return;
+ }
+ strcpy(filename_buffer, filename);
+ }
+
+ /*
+ * If BookmarkPage is NULL, something went
+ * wrong, so ignore the request. - FM
+ */
+ if (BookmarkPage == NULL) {
+ FREE(bookmark_URL);
+ return;
+ }
+
+ /*
+ * If the link will be added to the same
+ * bookmark file, get confirmation. - FM
+ */
+ if (LYMultiBookmarks == TRUE &&
+ strstr(HTLoadedDocumentURL(),
+ (*BookmarkPage == '.' ?
+ (BookmarkPage+1) : BookmarkPage)) != NULL) {
+ LYMBM_statusline(MULTIBOOKMARKS_SELF);
+ c = LYgetch();
+ if (TOUPPER(c) != 'L') {
+ FREE(bookmark_URL);
+ return;
+ }
+ }
+
+ /*
+ * Allow user to change the title. - FM
+ */
+ string_buffer[255] = '\0';
+ LYstrncpy(string_buffer, title, 255);
+ convert_to_spaces(string_buffer, FALSE);
+ LYMBM_statusline(TITLE_PROMPT);
+ LYgetstr(string_buffer, VISIBLE, sizeof(string_buffer), NORECALL);
+ if (*string_buffer == '\0') {
+ LYMBM_statusline(CANCELLED);
+ sleep(MessageSecs);
+ FREE(bookmark_URL);
+ return;
+ }
+
+ /*
+ * Create the Title with any left-angle-brackets
+ * converted to &lt; entities and any ampersands
+ * converted to &amp; entities. - FM
+ */
+ StrAllocCopy(Title, string_buffer);
+ LYEntify(&Title, TRUE);
+
+ /*
+ * Create the bookmark file, if it doesn't exist already,
+ * Otherwise, open the pre-existing bookmark file. - FM
+ */
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_TEXT;
+#endif /* __DJGPP__ or _WINDOWS */
+ if (first_time) {
+ /*
+ * Seek it in the home path. - FM
+ */
+ LYAddPathToHome(filename_buffer,
+ sizeof(filename_buffer),
+ BookmarkPage);
+ }
+ if (TRACE)
+ fprintf(stderr, "\nsave_bookmark_link: SEEKING %s\n AS %s\n\n",
+ BookmarkPage, filename_buffer);
+ if ((fp = fopen(filename_buffer, (first_time ? "w" : "a+"))) == NULL) {
+ LYMBM_statusline(BOOKMARK_OPEN_FAILED);
+ sleep(AlertSecs);
+ FREE(bookmark_URL);
+ return;
+ }
+
+ /*
+ * Convert all ampersands in the address to &amp; entities. - FM
+ */
+ StrAllocCopy(Address, address);
+ LYEntify(&Address, FALSE);
+
+ /*
+ * If we created a new bookmark file, write the headers. - FM
+ */
+ if (first_time) {
+ fprintf(fp,"<head>\n");
+ LYAddMETAcharsetToFD(fp, -1);
+ fprintf(fp,"<title>%s</title>\n</head>\n",BOOKMARK_TITLE);
+ fprintf(fp,"\
+ You can delete links using the remove bookmark command. It is usually\n\
+ the 'R' key but may have been remapped by you or your system\n\
+ administrator.<br>\n\
+ This file also may be edited with a standard text editor to delete\n\
+ outdated or invalid links, or to change their order, but you should\n\
+ not change the format within the lines or add other HTML markup.\n\n\
+ <p>\n<ol>\n");
+ }
+
+ /*
+ * Add the bookmark link, in Mosaic hotlist or Lynx format. - FM
+ */
+ if (is_mosaic_hotlist) {
+ time_t NowTime = time(NULL);
+ char *TimeString = (char *)ctime (&NowTime);
+ /*
+ * TimeString has a \n at the end.
+ */
+ fprintf(fp,"%s %s%s\n", Address, TimeString, Title);
+ } else {
+ fprintf(fp,"<LI><a href=\"%s\">%s</a>\n", Address, Title);
+ }
+ fclose(fp);
+
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_BINARY;
+#endif /* __DJGPP__ or _WINDOWS */
+ /*
+ * If this is a cached bookmark file, set nocache for
+ * it so we'll see the new bookmark link when that
+ * cache is retrieved. - FM
+ */
+ if (!first_time && nhist > 0 && bookmark_URL) {
+ for (i = 0; i < nhist; i++) {
+ if (history[i].bookmark &&
+ !strcmp(history[i].address, bookmark_URL)) {
+ WWWDoc.address = history[i].address;
+ WWWDoc.post_data = NULL;
+ WWWDoc.post_content_type = NULL;
+ WWWDoc.bookmark = history[i].bookmark;
+ WWWDoc.isHEAD = FALSE;
+ WWWDoc.safe = FALSE;
+ if (((tmpanchor = HTAnchor_parent(
+ HTAnchor_findAddress(&WWWDoc)
+ )) != NULL) &&
+ (text = (HText *)HTAnchor_document(tmpanchor)) != NULL) {
+ HText_setNoCache(text);
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Clean up and report success.
+ */
+ FREE(Title);
+ FREE(Address);
+ FREE(bookmark_URL);
+ LYMBM_statusline(OPERATION_DONE);
+ sleep(MessageSecs);
+}
+
+/*
+ * Remove a link from a bookmark file. The calling
+ * function is expected to have used get_filename_link(),
+ * pass us the link number as cur, the MBM_A_subbookmark[]
+ * string as cur_bookmark_page, and to have set up no_cache
+ * itself. - FM
+ */
+PUBLIC void remove_bookmark_link ARGS2(
+ int, cur,
+ char *, cur_bookmark_page)
+{
+ FILE *fp, *nfp;
+ char buf[BUFSIZ];
+ int n;
+#ifdef VMS
+ char filename_buffer[NAM$C_MAXRSS+12];
+ char newfile[NAM$C_MAXRSS+12];
+#else
+ char filename_buffer[256];
+ char newfile[256];
+ struct stat stat_buf;
+ mode_t mode;
+#endif /* VMS */
+
+ if (TRACE)
+ fprintf(stderr, "remove_bookmark_link: deleting link number: %d\n",
+ cur);
+
+ if (!cur_bookmark_page)
+ return;
+ LYAddPathToHome(filename_buffer,
+ sizeof(filename_buffer),
+ cur_bookmark_page);
+ if (TRACE)
+ fprintf(stderr, "\nremove_bookmark_link: SEEKING %s\n AS %s\n\n",
+ cur_bookmark_page, filename_buffer);
+ if ((fp = fopen(filename_buffer, "r")) == NULL) {
+ _statusline(BOOKMARK_OPEN_FAILED_FOR_DEL);
+ sleep(AlertSecs);
+ return;
+ }
+
+#ifdef VMS
+ sprintf(newfile, "%s-%d", filename_buffer, getpid());
+#else
+ tempname(newfile, NEW_FILE);
+#endif /* VMS */
+ if ((nfp = LYNewTxtFile(newfile)) == NULL) {
+ fclose(fp);
+#ifdef VMS
+ _statusline(BOOKSCRA_OPEN_FAILED_FOR_DEL);
+#else
+ _statusline(BOOKTEMP_OPEN_FAILED_FOR_DEL);
+#endif /* VMS */
+ sleep(AlertSecs);
+ return;
+ }
+
+#ifdef UNIX
+ /*
+ * Explicitly preserve bookmark file mode on Unix. - DSL
+ */
+ if (stat(filename_buffer, &stat_buf) == 0) {
+ mode = ((stat_buf.st_mode & 0777) | HIDE_CHMOD);
+ (void) fclose(nfp);
+ nfp = NULL;
+ (void) chmod(newfile, mode);
+ if ((nfp = fopen(newfile, "a")) == NULL) {
+ (void) fclose(fp);
+ _statusline(BOOKTEMP_REOPEN_FAIL_FOR_DEL);
+ sleep(AlertSecs);
+ return;
+ }
+ }
+#endif /* UNIX */
+
+ if (is_mosaic_hotlist) {
+ int del_line = cur*2; /* two lines per entry */
+ n = -3; /* skip past cookie and name lines */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ n++;
+ if (n == del_line || n == del_line+1)
+ continue; /* remove two lines */
+ if (fputs(buf, nfp) == EOF)
+ goto failure;
+ }
+
+ } else {
+ char *cp;
+ BOOLEAN retain;
+ int seen;
+
+ n = -1;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ retain = TRUE;
+ seen = 0;
+ cp = buf;
+ while (n < cur && (cp = LYstrstr(cp, "<a href="))) {
+ seen++;
+ if (++n == cur) {
+ if (seen != 1 || !LYstrstr(buf, "</a>") ||
+ LYstrstr((cp + 1), "<a href=")) {
+ _statusline(BOOKMARK_LINK_NOT_ONE_LINE);
+ sleep(AlertSecs);
+ goto failure;
+ }
+ if (TRACE)
+ fprintf(stderr,
+ "remove_bookmark_link: skipping link %d\n", n);
+ retain = FALSE;
+ }
+ cp += 8;
+ }
+ if (retain && fputs(buf, nfp) == EOF)
+ goto failure;
+ }
+ }
+
+ if (TRACE)
+ fprintf(stderr, "remove_bookmark_link: files: %s %s\n",
+ newfile, filename_buffer);
+
+ fclose(fp);
+ fp = NULL;
+ fclose(nfp);
+ nfp = NULL;
+#ifdef DOSPATH
+ remove(filename_buffer);
+#endif /* DOSPATH */
+ if (rename(newfile, filename_buffer) != -1) {
+#ifdef VMS
+ char VMSfilename[256];
+ /*
+ * Purge lower version of file.
+ */
+ sprintf(VMSfilename, "%s;-1", filename_buffer);
+ while (remove(VMSfilename) == 0)
+ ;
+ /*
+ * Reset version number.
+ */
+ sprintf(VMSfilename, "%s;1", filename_buffer);
+ rename(filename_buffer, VMSfilename);
+#endif /* VMS */
+ return;
+ } else {
+#ifndef VMS
+ /*
+ * Rename won't work across file systems.
+ * Check if this is the case and do something appropriate.
+ * Used to be ODD_RENAME
+ */
+#ifdef _WINDOWS
+ if (errno == ENOTSAM) {
+#else
+ if (errno == EXDEV) {
+#endif /* WINDOWS */
+ char buffer[2048];
+ sprintf(buffer, "%s %s %s", MV_PATH, newfile, filename_buffer);
+ system(buffer);
+ return;
+ }
+#endif /* !VMS */
+
+#ifdef VMS
+ _statusline(ERROR_RENAMING_SCRA);
+#else
+ _statusline(ERROR_RENAMING_TEMP);
+#endif /* VMS */
+ if (TRACE)
+ perror("renaming the file");
+ sleep(AlertSecs);
+ }
+
+failure:
+ _statusline(BOOKMARK_DEL_FAILED);
+ sleep(AlertSecs);
+ if (nfp != NULL)
+ fclose(nfp);
+ if (fp != NULL)
+ fclose(fp);
+ remove(newfile);
+}
+
+/*
+ * Allows user to select sub-bookmarks files. - FMG & FM
+ */
+PUBLIC int select_multi_bookmarks NOARGS
+{
+ int c;
+
+ /*
+ * If not enabled, pick the "default" (0).
+ */
+ if (LYMultiBookmarks == FALSE || LYHaveSubBookmarks() == FALSE) {
+ if (MBM_A_subbookmark[0]) /* If it exists! */
+ return(0);
+ else
+ return(-1);
+ }
+
+ /*
+ * For ADVANCED users, we can just mess with the status line to save
+ * the 2 redraws of the screen, if LYMBMAdvnced is TRUE. '=' will
+ * still show the screen and let them do it the "long" way.
+ */
+ if (LYMBMAdvanced && user_mode == ADVANCED_MODE) {
+ LYMBM_statusline(MULTIBOOKMARKS_SELECT);
+get_advanced_choice:
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ c = 7;
+ }
+#endif /* VMS */
+ if (LYisNonAlnumKeyname(c, LYK_PREV_DOC) ||
+ c == 7 || c == 3) {
+ /*
+ * Treat left-arrow, ^G, or ^C as cancel.
+ */
+ return(-2);
+ }
+ if (LYisNonAlnumKeyname(c, LYK_REFRESH)) {
+ /*
+ * Refresh the screen.
+ */
+ lynx_force_repaint();
+ refresh();
+ goto get_advanced_choice;
+ }
+ if (LYisNonAlnumKeyname(c, LYK_ACTIVATE)) {
+ /*
+ * Assume default bookmark file on ENTER or right-arrow.
+ */
+ return (MBM_A_subbookmark[0] ? 0 : -1);
+ }
+ switch (c) {
+ case '=':
+ /*
+ * Get the choice via the menu.
+ */
+ return(select_menu_multi_bookmarks());
+
+ default:
+ /*
+ * Convert to an array index, act on it if valid.
+ * Otherwise, get another keystroke.
+ */
+ c = TOUPPER(c) - 'A';
+ if (c < 0 || c > MBM_V_MAXFILES) {
+ goto get_advanced_choice;
+ }
+ }
+ /*
+ * See if we have a bookmark like that.
+ */
+ return (MBM_A_subbookmark[c] ? c : -1);
+ } else {
+ /*
+ * Get the choice via the menu.
+ */
+ return(select_menu_multi_bookmarks());
+ }
+}
+
+/*
+ * Allows user to select sub-bookmarks files. - FMG & FM
+ */
+PUBLIC int select_menu_multi_bookmarks NOARGS
+{
+ int c, MBM_tmp_count, MBM_allow;
+ int MBM_screens, MBM_from, MBM_to, MBM_current;
+ char string_buffer[256];
+ char shead_buffer[256];
+
+ /*
+ * If not enabled, pick the "default" (0).
+ */
+ if (LYMultiBookmarks == FALSE)
+ return(0);
+
+ /*
+ * Filip M. Gieszczykiewicz (filipg@paranoia.com) & FM
+ * ---------------------------------------------------
+ * LYMultiBookmarks - TRUE when multi_support enabled.
+ *
+ * MBM_A_subbookmark[n] - Hold values of the respective
+ * "multi_bookmarkn" in the lynxrc file.
+ *
+ * MBM_A_subdescript[n] - Hold description entries in the
+ * lynxrc file.
+ *
+ * Note: MBM_A_subbookmark[0] is defined to be same value as
+ * "bookmark_file" in the lynxrc file and/or the startup
+ * "bookmark_page".
+ *
+ * We make the display of bookmarks depend on rows we have
+ * available.
+ *
+ * We load BookmarkPage with the valid MBM_A_subbookmark[n]
+ * via get_bookmark_filename(). Otherwise, that function
+ * returns a zero-length string to indicate a cancel, a
+ * single space to indicate an invalid choice, or NULL to
+ * indicate an inaccessible file.
+ */
+ MBM_allow=(LYlines-7); /* We need 7 for header and footer */
+ /*
+ * Screen big enough?
+ */
+ if (MBM_allow <= 0) {
+ /*
+ * Too small.
+ */
+ _statusline(MULTIBOOKMARKS_SMALL);
+ sleep(AlertSecs);
+ return (-2);
+ }
+ /*
+ * Load the bad choice message buffer.
+ */
+ sprintf(string_buffer,
+ BOOKMARK_FILE_NOT_DEFINED,
+ key_for_func(LYK_OPTIONS));
+
+ MBM_screens = (MBM_V_MAXFILES/MBM_allow)+1; /* int rounds off low. */
+
+ MBM_current = 1; /* Gotta start somewhere :-) */
+
+draw_bookmark_choices:
+ MBM_from = MBM_allow * MBM_current - MBM_allow;
+ if (MBM_from < 0)
+ MBM_from = 0; /* 0 is default bookmark... */
+ if (MBM_current != 1)
+ MBM_from++;
+
+ MBM_to = (MBM_allow * MBM_current);
+ if (MBM_to > MBM_V_MAXFILES)
+ MBM_to = MBM_V_MAXFILES;
+
+ /*
+ * Display menu of bookmarks. NOTE that we avoid printw()'s
+ * to increase the chances that any non-ASCII or multibyte/CJK
+ * characters will be handled properly. - FM
+ */
+ clear();
+ move(1, 5);
+ lynx_start_h1_color ();
+ if (MBM_screens > 1) {
+ sprintf(shead_buffer,
+ MULTIBOOKMARKS_SHEAD_MASK, MBM_current, MBM_screens);
+ addstr(shead_buffer);
+ } else {
+ addstr(MULTIBOOKMARKS_SHEAD);
+ }
+
+ lynx_stop_h1_color ();
+
+ MBM_tmp_count = 0;
+ for (c = MBM_from; c <= MBM_to; c++) {
+ move(3+MBM_tmp_count, 5);
+ addch((unsigned char)(c + 'A'));
+ addstr(" : ");
+ if (MBM_A_subdescript[c])
+ addstr(MBM_A_subdescript[c]);
+ move(3+MBM_tmp_count,36);
+ addch('(');
+ if (MBM_A_subbookmark[c])
+ addstr(MBM_A_subbookmark[c]);
+ addch(')');
+ MBM_tmp_count++;
+ }
+
+ /*
+ * Don't need to show it if it all fits on one screen!
+ */
+ if (MBM_screens > 1) {
+ move(LYlines-2, 0);
+ addstr("'");
+ standout();
+ addstr("[");
+ standend();
+ addstr("' ");
+ addstr(PREVIOUS);
+ addstr(", '");
+ standout();
+ addstr("]");
+ standend();
+ addstr("' ");
+ addstr(NEXT_SCREEN);
+ }
+
+ LYMBM_statusline(MULTIBOOKMARKS_SAVE);
+get_bookmark_choice:
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ c = 7;
+ }
+#endif /* VMS */
+
+ if (LYisNonAlnumKeyname(c, LYK_PREV_DOC) ||
+ c == 7 || c == 3) {
+ /*
+ * Treat left-arrow, ^G, or ^C as cancel.
+ */
+ return(-2);
+ }
+
+ if (LYisNonAlnumKeyname(c, LYK_REFRESH)) {
+ /*
+ * Refresh the screen.
+ */
+ lynx_force_repaint();
+ refresh();
+ goto get_bookmark_choice;
+ }
+
+ if (LYisNonAlnumKeyname(c, LYK_ACTIVATE)) {
+ /*
+ * Assume default bookmark file on ENTER or right-arrow.
+ */
+ return(MBM_A_subbookmark[0] ? 0 : -1);
+ }
+
+ /*
+ * Next range, if available.
+ */
+ if ((c == ']' || LYisNonAlnumKeyname(c, LYK_NEXT_PAGE)) &&
+ MBM_screens > 1) {
+ if (++MBM_current > MBM_screens)
+ MBM_current = 1;
+ goto draw_bookmark_choices;
+ }
+
+ /*
+ * Previous range, if available.
+ */
+ if ((c == '[' || LYisNonAlnumKeyname(c, LYK_PREV_PAGE)) &&
+ MBM_screens > 1) {
+ if (--MBM_current <= 0)
+ MBM_current = MBM_screens;
+ goto draw_bookmark_choices;
+ }
+
+ c = TOUPPER(c) - 'A';
+ /*
+ * See if we have a bookmark like that.
+ */
+ if (c < 0 || c > MBM_V_MAXFILES) {
+ goto get_bookmark_choice;
+ } else if (!MBM_A_subbookmark[c]) {
+ LYMBM_statusline(string_buffer);
+ sleep(AlertSecs);
+ LYMBM_statusline(MULTIBOOKMARKS_SAVE);
+ goto get_bookmark_choice;
+ } else {
+ return(c);
+ }
+}
+
+/*
+ * This function returns TRUE if we have sub-bookmarks defined.
+ * Otherwise (i.e., only the default bookmark file is defined),
+ * it returns FALSE. - FM
+ */
+PUBLIC BOOLEAN LYHaveSubBookmarks NOARGS
+{
+ int i;
+
+ for (i = 1; i < MBM_V_MAXFILES; i++) {
+ if (MBM_A_subbookmark[i] != NULL && *MBM_A_subbookmark[i] != '\0')
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+/*
+ * This function passes a string to _statusline(), making
+ * sure it is at the bottom of the screen if LYMultiBookmarks
+ * is TRUE, otherwise, letting it go to the normal statusline
+ * position based on the current user mode. We want to use
+ * _statusline() so that any multibyte/CJK characters in the
+ * string will be handled properly. - FM
+ */
+ PUBLIC void LYMBM_statusline ARGS1(
+ char *, text)
+{
+ if (LYMultiBookmarks == TRUE && user_mode == NOVICE_MODE) {
+ LYStatusLine = (LYlines - 1);
+ _statusline(text);
+ LYStatusLine = -1;
+ } else {
+ _statusline(text);
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/LYBookmark.h b/gnu/usr.bin/lynx/src/LYBookmark.h
new file mode 100644
index 00000000000..ee642be2f87
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYBookmark.h
@@ -0,0 +1,18 @@
+
+#ifndef LYBOOKMARK_H
+#define LYBOOKMARK_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern char * get_bookmark_filename PARAMS((char **name));
+extern void save_bookmark_link PARAMS((char *address, char *title));
+extern void remove_bookmark_link PARAMS((int cur, char *cur_bookmark_page));
+extern int select_multi_bookmarks NOPARAMS;
+extern int select_menu_multi_bookmarks NOPARAMS;
+extern BOOLEAN LYHaveSubBookmarks NOPARAMS;
+extern void LYMBM_statusline PARAMS((char *text));
+
+#endif /* LYBOOKMARK_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYCgi.c b/gnu/usr.bin/lynx/src/LYCgi.c
new file mode 100644
index 00000000000..c1840e7481e
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCgi.c
@@ -0,0 +1,660 @@
+/* Lynx CGI support LYCgi.c
+** ================
+**
+** Authors
+** GL George Lindholm <George.Lindholm@ubc.ca>
+**
+** History
+** 15 Jun 95 Created as way to provide a lynx based service with
+** dynamic pages without the need for a http daemon. GL
+** 27 Jun 95 Added <index> (command line) support. Various cleanup
+** and bug fixes. GL
+** 04 Sep 97 Added support for PATH_INFO scripts. JKT
+**
+** Bugs
+** If the called scripts aborts before sending the mime headers then
+** lynx hangs.
+**
+** Should do something about SIGPIPE, (but then it should never happen)
+**
+** No support for redirection. Or mime-types.
+**
+** Should try and parse for a HTTP 1.1 header in case we are "calling" a
+** nph- script.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTP.h"
+#include "HTParse.h"
+#include "HTTCP.h"
+#include "HTFormat.h"
+#include "HTFile.h"
+#include "HTAlert.h"
+#include "HTMIME.h"
+#include "HTAABrow.h"
+
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "HTML.h"
+#include "HTInit.h"
+#include "LYGetFile.h"
+#include "LYBookmark.h"
+#include "GridText.h"
+#include <ctype.h>
+#include "LYCgi.h"
+#include "LYSignal.h"
+#include "LYLocal.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+PRIVATE char **env = NULL; /* Environment variables */
+PRIVATE int envc_size = 0; /* Slots in environment array */
+PRIVATE int envc = 0; /* Slots used so far */
+#ifdef LYNXCGI_LINKS
+PRIVATE char user_agent[64];
+PRIVATE char server_software[64];
+#endif /* LYNXCGI_LINKS */
+
+PRIVATE void add_environment_value PARAMS((char *env_value));
+
+
+/*
+ * Simple routine for expanding the environment array and adding a value to
+ * it
+ */
+PRIVATE void add_environment_value ARGS1(
+ char *, env_value)
+{
+ if (envc == envc_size) { /* Need some more slots */
+ envc_size += 10;
+ if (env)
+ env = (char **)realloc(env,
+ sizeof(env[0]) * (envc_size + 2));
+ /* + terminator and base 0 */
+ else
+ env = (char **)malloc(sizeof(env[0]) * (envc_size + 2));
+ /* + terminator and base 0 */
+ if (env == NULL) {
+ outofmem(__FILE__, "LYCgi");
+ }
+ }
+
+ env[envc++] = env_value;
+ env[envc] = NULL; /* Make sure it is always properly terminated */
+}
+
+/*
+ * Add the value of an existing environment variable to those passed on to the
+ * lynxcgi script.
+ */
+PUBLIC void add_lynxcgi_environment ARGS1(
+ CONST char *, variable_name)
+{
+ char *env_value;
+
+ env_value = getenv(variable_name);
+ if (env_value != NULL) {
+ char *add_value = NULL;
+
+ add_value = (char *)malloc(strlen(variable_name) +
+ strlen(env_value) + 2);
+ if (add_value == NULL) {
+ outofmem(__FILE__, "LYCgi");
+ }
+ strcpy(add_value, variable_name);
+ strcat(add_value, "=");
+ strcat(add_value, env_value);
+ add_environment_value(add_value);
+ }
+}
+
+PRIVATE int LYLoadCGI ARGS4(
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ int status;
+#ifdef LYNXCGI_LINKS
+#ifndef VMS
+ char *cp;
+ struct stat stat_buf;
+ char *pgm = NULL; /* executable */
+ char *pgm_args = NULL; /* and its argument(s) */
+ int statrv;
+ char *orig_pgm = NULL; /* Path up to ? as given, URL-escaped*/
+ char *document_root = NULL; /* Corrected value of DOCUMENT_ROOT */
+ char *path_info = NULL; /* PATH_INFO extracted from pgm */
+ char *pgm_buff = NULL; /* PATH_INFO extraction buffer */
+ char *path_translated; /* From document_root/path_info */
+
+ if (!arg || !*arg || strlen(arg) <= 8) {
+ HTAlert(BAD_REQUEST);
+ status = -2;
+ return(status);
+
+ } else {
+ if (strncmp(arg, "lynxcgi://localhost", 19) == 0) {
+ StrAllocCopy(pgm, arg+19);
+ } else {
+ StrAllocCopy(pgm, arg+8);
+ }
+ if ((cp=strchr(pgm, '?')) != NULL) { /* Need to terminate executable */
+ *cp++ = '\0';
+ pgm_args = cp;
+ }
+ }
+
+ StrAllocCopy(orig_pgm, pgm);
+ if ((cp=strchr(pgm, '#')) != NULL) {
+ /*
+ * Strip a #fragment from path. In this case any pgm_args
+ * found above will also be bogus, since the '?' came after
+ * the '#' and is part of the fragment. Note that we don't
+ * handle the case where a '#' appears after a '?' properly
+ * according to URL rules. - kw
+ */
+ *cp = '\0';
+ pgm_args = NULL;
+ }
+ HTUnEscape(pgm);
+
+ /* BEGIN WebSter Mods */
+ /* If pgm is not stat-able, see if PATH_INFO data is at the end of pgm */
+ if ((statrv = stat(pgm, &stat_buf)) < 0) {
+ StrAllocCopy(pgm_buff, pgm);
+ while (statrv < 0 || (statrv = stat(pgm_buff, &stat_buf)) < 0) {
+ if ((cp=strrchr(pgm_buff, '/')) != NULL) {
+ *cp = '\0';
+ statrv = 999; /* force new stat() - kw */
+ } else {
+ if (TRACE)
+ perror("LYNXCGI: strrchr(pgm_buff, '/') returned NULL");
+ break;
+ }
+ }
+
+ if (statrv < 0) {
+ /* Did not find PATH_INFO data */
+ if (TRACE)
+ perror("LYNXCGI: stat() of pgm_buff failed");
+ } else {
+ /* Found PATH_INFO data. Strip it off of pgm and into path_info. */
+ StrAllocCopy(path_info, pgm+strlen(pgm_buff));
+ strcpy(pgm, pgm_buff);
+ if (TRACE)
+ fprintf(stderr,
+ "LYNXCGI: stat() of %s succeeded, path_info=\"%s\".\n",
+ pgm_buff, path_info);
+ }
+ FREE(pgm_buff);
+ }
+ /* END WebSter Mods */
+
+ if (statrv != 0) {
+ /*
+ * Neither the path as given nor any components examined by
+ * backing up were stat()able. - kw
+ */
+ HTAlert("Unable to access cgi script");
+ if (TRACE) {
+ perror("LYNXCGI: stat() failed");
+ }
+ status = -4;
+
+ } else if (!(S_ISREG(stat_buf.st_mode) &&
+ stat_buf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+ /*
+ * Not a runnable file, See if we can load it using "file:" code.
+ */
+ char *new_arg = NULL;
+
+ /*
+ * But try "file:" only if the file we are looking at is the path
+ * as given (no path_info was extracted), otherwise it will be
+ * to confusing to know just what file is loaded. - kw
+ */
+ if (path_info) {
+ if (TRACE) {
+ fprintf(stderr,
+ "%s is not a file and %s not an executable, giving up.\n",
+ orig_pgm, pgm);
+ }
+ FREE(path_info);
+ FREE(pgm);
+ FREE(orig_pgm);
+ status = -4;
+ return(status);
+ }
+
+ StrAllocCopy(new_arg, "file://localhost");
+ StrAllocCat(new_arg, orig_pgm);
+
+ if (TRACE) {
+ fprintf(stderr,
+ "%s is not an executable file, passing the buck.\n", arg);
+ }
+ status = HTLoadFile(new_arg, anAnchor, format_out, sink);
+ FREE(new_arg);
+
+ } else if (path_info &&
+ anAnchor != HTMainAnchor &&
+ !(reloading && anAnchor->document) &&
+ strcmp(arg, HTLoadedDocumentURL()) &&
+ HText_AreDifferent(anAnchor, arg) &&
+ HTUnEscape(orig_pgm) &&
+ !exec_ok(HTLoadedDocumentURL(), orig_pgm,
+ CGI_PATH)) { /* exec_ok gives out msg. */
+ /*
+ * If we have extra path info and are not just reloading
+ * the current, check the full file path (after unescaping)
+ * now to catch forbidden segments. - kw
+ */
+ status = HT_NOT_LOADED;
+
+ } else if (no_lynxcgi) {
+ _statusline(CGI_DISABLED);
+ sleep(MessageSecs);
+ status = HT_NOT_LOADED;
+
+ } else if (no_bookmark_exec &&
+ anAnchor != HTMainAnchor &&
+ !(reloading && anAnchor->document) &&
+ strcmp(arg, HTLoadedDocumentURL()) &&
+ HText_AreDifferent(anAnchor, arg) &&
+ HTLoadedDocumentBookmark()) {
+ /*
+ * If we are reloading a lynxcgi document that had already been
+ * loaded, the various checks above should allow it even if
+ * no_bookmark_exec is TRUE an we are not now coming from a
+ * bookmark page. - kw
+ */
+ _statusline(BOOKMARK_EXEC_DISABLED);
+ sleep(MessageSecs);
+ status = HT_NOT_LOADED;
+
+ } else if (anAnchor != HTMainAnchor &&
+ !(reloading && anAnchor->document) &&
+ strcmp(arg, HTLoadedDocumentURL()) &&
+ HText_AreDifferent(anAnchor, arg) &&
+ !exec_ok(HTLoadedDocumentURL(), pgm,
+ CGI_PATH)) { /* exec_ok gives out msg. */
+ /*
+ * If we are reloading a lynxcgi document that had already been
+ * loaded, the various checks above should allow it even if
+ * exec_ok() would reject it because we are not now coming from
+ * a document with a URL allowed by TRUSTED_LYNXCGI rules. - kw
+ */
+ status = HT_NOT_LOADED;
+
+ } else {
+ HTFormat format_in;
+ HTStream *target = NULL; /* Unconverted data */
+ int fd1[2], fd2[2];
+ char buf[1024];
+ pid_t pid;
+#if HAVE_TYPE_UNIONWAIT
+ union wait wstatus;
+#else
+ int wstatus;
+#endif
+
+ if (anAnchor->isHEAD || keep_mime_headers) {
+
+ /* Show output as plain text */
+ format_in = WWW_PLAINTEXT;
+ } else {
+
+ /* Decode full HTTP response */
+ format_in = HTAtom_for("www/mime");
+ }
+
+ target = HTStreamStack(format_in,
+ format_out,
+ sink, anAnchor);
+
+ if (!target || target == NULL) {
+ sprintf(buf, CANNOT_CONVERT_I_TO_O,
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ _statusline(buf);
+ sleep(AlertSecs);
+ status = HT_NOT_LOADED;
+
+ } else if (anAnchor->post_data && pipe(fd1) < 0) {
+ HTAlert(CONNECT_SET_FAILED);
+ if (TRACE) {
+ perror("LYNXCGI: pipe() failed");
+ }
+ status = -3;
+
+ } else if (pipe(fd2) < 0) {
+ HTAlert(CONNECT_SET_FAILED);
+ if (TRACE) {
+ perror("LYNXCGI: pipe() failed");
+ }
+ close(fd1[0]);
+ close(fd1[1]);
+ status = -3;
+
+ } else {
+ static BOOL first_time = TRUE; /* One time setup flag */
+
+ if (first_time) { /* Set up static environment variables */
+ first_time = FALSE; /* Only once */
+
+ add_environment_value("REMOTE_HOST=localhost");
+ add_environment_value("REMOTE_ADDR=127.0.0.1");
+
+ sprintf(user_agent, "HTTP_USER_AGENT=%s/%s libwww/%s",
+ LYNX_NAME, LYNX_VERSION, HTLibraryVersion);
+ add_environment_value(user_agent);
+
+ sprintf(server_software, "SERVER_SOFTWARE=%s/%s",
+ LYNX_NAME, LYNX_VERSION);
+ add_environment_value(server_software);
+ }
+
+ if ((pid = fork()) > 0) { /* The good, */
+ int chars, total_chars;
+
+ close(fd2[1]);
+
+ if (anAnchor->post_data) {
+ int written, remaining, total_written = 0;
+ close(fd1[0]);
+
+ /* We have form data to push across the pipe */
+ if (TRACE) {
+ fprintf(stderr, "LYNXCGI: Doing post, content-type '%s'\n",
+ anAnchor->post_content_type);
+ fprintf(stderr,
+ "LYNXCGI: Writing:\n%s----------------------------------\n",
+ anAnchor->post_data);
+ }
+ remaining = strlen(anAnchor->post_data);
+ while ((written = write(fd1[1],
+ anAnchor->post_data + total_written,
+ remaining)) != 0) {
+ if (written < 0) {
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif /* EINTR */
+#ifdef ERESTARTSYS
+ if (errno == ERESTARTSYS)
+ continue;
+#endif /* ERESTARTSYS */
+ if (TRACE) {
+ perror("LYNXCGI: write() of POST data failed");
+ }
+ break;
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "LYNXCGI: Wrote %d bytes of POST data.\n",
+ written);
+ }
+ total_written += written;
+ remaining -= written;
+ if (remaining == 0)
+ break;
+ }
+ if (remaining != 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "LYNXCGI: %d bytes remain unwritten!\n",
+ remaining);
+ }
+ close(fd1[1]);
+ }
+
+ total_chars = 0;
+ while((chars = read(fd2[0], buf, sizeof(buf))) > 0) {
+ char line[40];
+
+ total_chars += chars;
+ sprintf (line, "Read %d bytes of data.", total_chars);
+ HTProgress(line);
+ if (TRACE) {
+ fprintf(stderr, "LYNXCGI: Rx: %.*s\n", chars, buf);
+ }
+
+ (*target->isa->put_block)(target, buf, chars);
+ }
+#if !HAVE_WAITPID
+ while (wait(&wstatus) != pid)
+ ; /* do nothing */
+#else
+ while (-1 == waitpid(pid, &wstatus, 0)) { /* wait for child */
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif /* EINTR */
+#ifdef ERESTARTSYS
+ if (errno == ERESTARTSYS)
+ continue;
+#endif /* ERESTARTSYS */
+ break;
+ }
+#endif /* !HAVE_WAITPID */
+ close(fd2[0]);
+ status = HT_LOADED;
+
+ } else if (pid == 0) { /* The Bad, */
+ char **argv = NULL;
+ char post_len[32];
+ int argv_cnt = 3; /* name, one arg and terminator */
+ char **cur_argv = NULL;
+ char buf[BUFSIZ];
+
+ /* Set up output pipe */
+ close(fd2[0]);
+ dup2(fd2[1], fileno(stdout)); /* Should check success code */
+ dup2(fd2[1], fileno(stderr));
+ close(fd2[1]);
+
+ sprintf(buf, "HTTP_ACCEPT_LANGUAGE=%.*s",
+ (int)(sizeof(buf) - 22), language);
+ buf[(sizeof(buf) - 1)] = '\0';
+ add_environment_value(buf);
+
+ if (pref_charset) {
+ cp = NULL;
+ StrAllocCopy(cp, "HTTP_ACCEPT_CHARSET=");
+ StrAllocCat(cp, pref_charset);
+ add_environment_value(cp);
+ }
+
+ if (anAnchor->post_data &&
+ anAnchor->post_content_type) {
+ cp = NULL;
+ StrAllocCopy(cp, "CONTENT_TYPE=");
+ StrAllocCat(cp, anAnchor->post_content_type);
+ add_environment_value(cp);
+ }
+
+ if (anAnchor->post_data) { /* post script, read stdin */
+ close(fd1[1]);
+ dup2(fd1[0], fileno(stdin));
+ close(fd1[0]);
+
+ /* Build environment variables */
+
+ add_environment_value("REQUEST_METHOD=POST");
+
+ sprintf(post_len, "CONTENT_LENGTH=%d",
+ strlen(anAnchor->post_data));
+ add_environment_value(post_len);
+ } else {
+ close(fileno(stdin));
+
+ if (anAnchor->isHEAD) {
+ add_environment_value("REQUEST_METHOD=HEAD");
+ }
+ }
+
+ /*
+ * Set up argument line, mainly for <index> scripts
+ */
+ if (pgm_args != NULL) {
+ for (cp = pgm_args; *cp != '\0'; cp++) {
+ if (*cp == '+') {
+ argv_cnt++;
+ }
+ }
+ }
+
+ argv = (char**)malloc(argv_cnt * sizeof(char*));
+ if (argv == NULL) {
+ outofmem(__FILE__, "LYCgi");
+ }
+ cur_argv = argv + 1; /* For argv[0] */
+ if (pgm_args != NULL) {
+ char *cr;
+
+ /* Data for a get/search form */
+ if (is_www_index) {
+ add_environment_value("REQUEST_METHOD=SEARCH");
+ } else if (!anAnchor->isHEAD) {
+ add_environment_value("REQUEST_METHOD=GET");
+ }
+
+ cp = NULL;
+ StrAllocCopy(cp, "QUERY_STRING=");
+ StrAllocCat(cp, pgm_args);
+ add_environment_value(cp);
+
+ /*
+ * Split up arguments into argv array
+ */
+ cp = pgm_args;
+ cr = cp;
+ while(1) {
+ if (*cp == '\0') {
+ *(cur_argv++) = HTUnEscape(cr);
+ break;
+
+ } else if (*cp == '+') {
+ *cp++ = '\0';
+ *(cur_argv++) = HTUnEscape(cr);
+ cr = cp;
+ }
+ cp++;
+ }
+ }
+ *cur_argv = NULL; /* Terminate argv */
+ argv[0] = pgm;
+
+ /* Begin WebSter Mods -jkt */
+ if (LYCgiDocumentRoot != NULL) {
+ /* Add DOCUMENT_ROOT to env */
+ cp = NULL;
+ StrAllocCopy(cp, "DOCUMENT_ROOT=");
+ StrAllocCat(cp, LYCgiDocumentRoot);
+ add_environment_value(cp);
+ }
+ if (path_info != NULL ) {
+ /* Add PATH_INFO to env */
+ cp = NULL;
+ StrAllocCopy(cp, "PATH_INFO=");
+ StrAllocCat(cp, path_info);
+ add_environment_value(cp);
+ }
+ if (LYCgiDocumentRoot != NULL && path_info != NULL ) {
+ /* Construct and add PATH_TRANSLATED to env */
+ StrAllocCopy(document_root, LYCgiDocumentRoot);
+ if (document_root[strlen(document_root) - 1] == '/') {
+ document_root[strlen(document_root) - 1] = '\0';
+ }
+ path_translated = document_root;
+ StrAllocCat(path_translated, path_info);
+ cp = NULL;
+ StrAllocCopy(cp, "PATH_TRANSLATED=");
+ StrAllocCat(cp, path_translated);
+ add_environment_value(cp);
+ FREE(path_translated);
+ }
+ /* End WebSter Mods -jkt */
+
+ execve(argv[0], argv, env);
+ if (TRACE) {
+ perror("LYNXCGI: execve failed");
+ }
+
+ } else { /* and the Ugly */
+ HTAlert(CONNECT_FAILED);
+ if (TRACE) {
+ perror("LYNXCGI: fork() failed");
+ }
+ status = HT_NO_DATA;
+ close(fd1[0]);
+ close(fd1[1]);
+ close(fd2[0]);
+ close(fd2[1]);
+ status = -1;
+ }
+
+ }
+ if (target != NULL) {
+ (*target->isa->_free)(target);
+ }
+ }
+ FREE(path_info);
+ FREE(pgm);
+ FREE(orig_pgm);
+#else /* VMS */
+ HTStream *target;
+ char buf[256];
+
+ target = HTStreamStack(WWW_HTML,
+ format_out,
+ sink, anAnchor);
+
+ sprintf(buf,"<head>\n<title>Good Advice</title>\n</head>\n<body>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf,"<h1>Good Advice</h1>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "An excellent http server for VMS is available via <a\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf,
+ "href=\"http://kcgl1.eng.ohio-state.edu/www/doc/serverinfo.html\"\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, ">this link</a>.\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf,
+ "<p>It provides <b>state of the art</b> CGI script support.\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf,"</body>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ (*target->isa->_free)(target);
+ status = HT_LOADED;
+#endif /* VMS */
+#else /* LYNXCGI_LINKS */
+ _statusline(CGI_NOT_COMPILED);
+ sleep(MessageSecs);
+ status = HT_NOT_LOADED;
+#endif /* LYNXCGI_LINKS */
+ return(status);
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _LYCGI_C_GLOBALDEF_1_INIT { "lynxcgi", LYLoadCGI, 0 }
+GLOBALDEF (HTProtocol,LYLynxCGI,_LYCGI_C_GLOBALDEF_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol LYLynxCGI = { "lynxcgi", LYLoadCGI, 0 };
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/src/LYCgi.h b/gnu/usr.bin/lynx/src/LYCgi.h
new file mode 100644
index 00000000000..56a8d15d21d
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCgi.h
@@ -0,0 +1,7 @@
+
+#ifndef LYCGI_H
+#define LYCGI_H
+
+extern void add_lynxcgi_environment PARAMS((CONST char *variable_name));
+
+#endif /* LYGETFILE_H */
diff --git a/gnu/usr.bin/lynx/src/LYCharSets.c b/gnu/usr.bin/lynx/src/LYCharSets.c
new file mode 100644
index 00000000000..2f9e4362ad6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCharSets.c
@@ -0,0 +1,937 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTCJK.h"
+#include "HTMLDTD.h"
+
+#include "LYGlobalDefs.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h"
+#include "HTFont.h"
+#include "GridText.h"
+#include "LYCurses.h"
+#include "LYStrings.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+extern BOOL HTPassEightBitRaw;
+extern BOOL HTPassEightBitNum;
+extern BOOL HTPassHighCtrlRaw;
+extern BOOL HTPassHighCtrlNum;
+extern HTCJKlang HTCJK;
+PUBLIC HTkcode kanji_code = NOKANJI;
+PUBLIC BOOLEAN LYHaveCJKCharacterSet = FALSE;
+extern void UCInit NOARGS;
+extern int UCInitialized;
+PUBLIC int LYNumCharsets = 0; /* Will be initialized later by UC_Register. */
+
+/*
+ * INSTRUCTIONS for adding new character sets which do not have
+ * Unicode tables.
+ *
+ * Currently we only declare some charset's properties here
+ * (such as MIME names, etc.), it does not include real mapping.
+ *
+ * [We hope you need not correct/add old-style mapping
+ * as in ISO_LATIN1[] or SevenBitApproximations[] any more -
+ * it works now via new chartrans mechanism, but kept for compatibility only:
+ * we should cleanup the stuff, but this is not so easy...]
+ *
+ * There is a place marked "Add your new character sets HERE" in this file.
+ * Make up a character set and add it in the same
+ * style as the ISO_LATIN1 set below, giving it a unique name.
+ *
+ * Add the name of the set to LYCharSets.
+ * Similarly add the appropriate information to the tables below:
+ * LYchar_set_names, LYCharSet_UC, LYlowest_eightbit.
+ * These 4 tables all MUST have the same order.
+ * (And this is the order you will see in Lynx Options Menu,
+ * which is why few unicode-based charsets are listed here).
+ *
+ */
+
+/* Entity values -- for ISO Latin 1 local representation
+**
+** This MUST match exactly the table referred to in the DTD!
+*/
+PRIVATE char * ISO_Latin1[] = {
+ "\306", /* capital AE diphthong (ligature) (&#198;) - AElig */
+ "\301", /* capital A, acute accent (&#193;) - Aacute */
+ "\302", /* capital A, circumflex accent (&#194;) - Acirc */
+ "\300", /* capital A, grave accent (&#192;) - Agrave */
+ "\305", /* capital A, ring - Aring (&#197;) */
+ "\303", /* capital A, tilde - Atilde (&#195;) */
+ "\304", /* capital A, dieresis or umlaut mark (&#196;) - Auml */
+ "\307", /* capital C, cedilla - Ccedil (&#199;) */
+ "\320", /* capital Eth or D with stroke (&#208;) - Dstrok */
+ "\320", /* capital Eth, Icelandic (&#208;) - ETH */
+ "\311", /* capital E, acute accent (&#201;) - Eacute */
+ "\312", /* capital E, circumflex accent (&#202;) - Ecirc */
+ "\310", /* capital E, grave accent (&#200;) - Egrave */
+ "\313", /* capital E, dieresis or umlaut mark (&#203;) - Euml */
+ "\315", /* capital I, acute accent (&#205;) - Iacute */
+ "\316", /* capital I, circumflex accent (&#206;) - Icirc */
+ "\314", /* capital I, grave accent (&#200;) - Igrave */
+ "\317", /* capital I, dieresis or umlaut mark (&#207;) - Iuml */
+ "\321", /* capital N, tilde (&#209;) - Ntilde */
+ "\323", /* capital O, acute accent (&#211;) - Oacute */
+ "\324", /* capital O, circumflex accent (&#212;) - Ocirc */
+ "\322", /* capital O, grave accent (&#210;) - Ograve */
+ "\330", /* capital O, slash (&#216;) - Oslash */
+ "\325", /* capital O, tilde (&#213;) - Otilde */
+ "\326", /* capital O, dieresis or umlaut mark (&#214;) - Ouml */
+ "\336", /* capital THORN, Icelandic (&#222;) - THORN */
+ "\332", /* capital U, acute accent (&#218;) - Uacute */
+ "\333", /* capital U, circumflex accent (&#219;) - Ucirc */
+ "\331", /* capital U, grave accent (&#217;) - Ugrave */
+ "\334", /* capital U, dieresis or umlaut mark (&#220;) - Uuml */
+ "\335", /* capital Y, acute accent (&#221;) - Yacute */
+ "\341", /* small a, acute accent (&#225;) - aacute */
+ "\342", /* small a, circumflex accent (&#226;) - acirc */
+ "\264", /* spacing acute (&#180;) - acute */
+ "\346", /* small ae diphthong (ligature) (&#230;) - aelig */
+ "\340", /* small a, grave accent (&#224;) - agrave */
+ "\046", /* ampersand (&#38;) - amp */
+ "\345", /* small a, ring (&#229;) - aring */
+ "\343", /* small a, tilde (&#227;) - atilde */
+ "\344", /* small a, dieresis or umlaut mark (&#228;) - auml */
+ "\246", /* broken vertical bar (&#166;) - brkbar */
+ "\246", /* broken vertical bar (&#166;) - brvbar */
+ "\347", /* small c, cedilla (&#231;) - ccedil */
+ "\270", /* spacing cedilla (&#184;) - cedil */
+ "\242", /* cent sign (&#162;) - cent */
+ "\251", /* copyright sign (&#169;) - copy */
+ "\244", /* currency sign (&#164;) - curren */
+ "\260", /* degree sign (&#176;) - deg */
+ "\250", /* spacing dieresis (&#168;) - die */
+ "\367", /* division sign (&#247;) - divide */
+ "\351", /* small e, acute accent (&#233;) - eacute */
+ "\352", /* small e, circumflex accent (&#234;) - ecirc */
+ "\350", /* small e, grave accent (&#232;) - egrave */
+ "-", /* dash the width of emsp - emdash */
+ "\002", /* emsp, em space - not collapsed NEVER CHANGE THIS - emsp */
+ "-", /* dash the width of ensp - endash */
+ "\002", /* ensp, en space - not collapsed NEVER CHANGE THIS - ensp */
+ "\360", /* small eth, Icelandic (&#240;) - eth */
+ "\353", /* small e, dieresis or umlaut mark (&#235;) - euml */
+ "\275", /* fraction 1/2 (&#189;) - frac12 */
+ "\274", /* fraction 1/4 (&#188;) - frac14 */
+ "\276", /* fraction 3/4 (&#190;) - frac34 */
+ "\076", /* greater than (&#62;) - gt */
+ "\257", /* spacing macron (&#175;) - hibar */
+ "\355", /* small i, acute accent (&#237;) - iacute */
+ "\356", /* small i, circumflex accent (&#238;) - icirc */
+ "\241", /* inverted exclamation mark (&#161;) - iexcl */
+ "\354", /* small i, grave accent (&#236;) - igrave */
+ "\277", /* inverted question mark (&#191;) - iquest */
+ "\357", /* small i, dieresis or umlaut mark (&#239;) - iuml */
+ "\253", /* angle quotation mark, left (&#171;) - laquo */
+ "\074", /* less than (&#60;) - lt */
+ "\257", /* spacing macron (&#175;) - macr */
+ "-", /* dash the width of emsp - mdash */
+ "\265", /* micro sign (&#181;) - micro */
+ "\267", /* middle dot (&#183;) - middot */
+ "\001", /* nbsp non-breaking space NEVER CHANGE THIS - nbsp */
+ "-", /* dash the width of ensp - ndash */
+ "\254", /* negation sign (&#172;) - not */
+ "\361", /* small n, tilde (&#241;) - ntilde */
+ "\363", /* small o, acute accent (&#243;) - oacute */
+ "\364", /* small o, circumflex accent (&#244;) - ocirc */
+ "\362", /* small o, grave accent (&#242;) - ograve */
+ "\252", /* feminine ordinal indicator (&#170;) - ordf */
+ "\272", /* masculine ordinal indicator (&#186;) - ordm */
+ "\370", /* small o, slash (&#248;) - oslash */
+ "\365", /* small o, tilde (&#245;) - otilde */
+ "\366", /* small o, dieresis or umlaut mark (&#246;) - ouml */
+ "\266", /* paragraph sign (&#182;) - para */
+ "\261", /* plus-or-minus sign (&#177;) - plusmn */
+ "\243", /* pound sign (&#163;) - pound */
+ "\042", /* quote '"' (&#34;) - quot */
+ "\273", /* angle quotation mark, right (&#187;) - raquo */
+ "\256", /* circled R registered sign (&#174;) - reg */
+ "\247", /* section sign (&#167;) - sect */
+ "\007", /* soft hyphen (&#173;) NEVER CHANGE THIS - shy */
+ "\271", /* superscript 1 (&#185;) - sup1 */
+ "\262", /* superscript 2 (&#178;) - sup2 */
+ "\263", /* superscript 3 (&#179;) - sup3 */
+ "\337", /* small sharp s, German (sz ligature) (&#223;) - szlig */
+ "\002", /* thin space - not collapsed NEVER CHANGE THIS - thinsp */
+ "\376", /* small thorn, Icelandic (&#254;) - thorn */
+ "\327", /* multiplication sign (&#215;) - times */
+ "(TM)", /* circled TM trade mark sign (&#8482;) - trade */
+ "\372", /* small u, acute accent (&#250;) - uacute */
+ "\373", /* small u, circumflex accent (&#251;) - ucirc */
+ "\371", /* small u, grave accent (&#249;) - ugrave */
+ "\250", /* spacing dieresis (&#168;) - uml */
+ "\374", /* small u, dieresis or umlaut mark (&#252;) - uuml */
+ "\375", /* small y, acute accent (&#253;) - yacute */
+ "\245", /* yen sign (&#165;) - yen */
+ "\377", /* small y, dieresis or umlaut mark (&#255;) - yuml */
+};
+
+/* Entity values -- 7 bit character approximations
+**
+** This MUST match exactly the table referred to in the DTD!
+*/
+PUBLIC char * SevenBitApproximations[] = {
+ "AE", /* capital AE diphthong (ligature) (&#198;) - AElig */
+ "A", /* capital A, acute accent (&#193;) - Aacute */
+ "A", /* capital A, circumflex accent (&#194;) - Acirc */
+ "A", /* capital A, grave accent (&#192;) - Agrave */
+ "A", /* capital A, ring - Aring (&#197;) */
+ "A", /* capital A, tilde - Atilde (&#195;) */
+#ifdef LY_UMLAUT
+ "Ae", /* capital A, dieresis or umlaut mark (&#196;) - Auml*/
+#else
+ "A", /* capital A, dieresis or umlaut mark (&#196;) - Auml*/
+#endif /* LY_UMLAUT */
+ "C", /* capital C, cedilla (&#199;) - Ccedil */
+ "Dj", /* capital D with stroke (&#208;) - Dstrok */
+ "DH", /* capital Eth, Icelandic (&#208;) - ETH */
+ "E", /* capital E, acute accent (&#201;) - Eacute */
+ "E", /* capital E, circumflex accent (&#202;) - Ecirc */
+ "E", /* capital E, grave accent (&#200;) - Egrave */
+ "E", /* capital E, dieresis or umlaut mark (&#203;) - Euml */
+ "I", /* capital I, acute accent (&#205;) - Iacute */
+ "I", /* capital I, circumflex accent (&#206;) - Icirc */
+ "I", /* capital I, grave accent (&#204;) - Igrave */
+ "I", /* capital I, dieresis or umlaut mark (&#207;) - Iuml */
+ "N", /* capital N, tilde - Ntilde (&#209;) */
+ "O", /* capital O, acute accent (&#211;) - Oacute */
+ "O", /* capital O, circumflex accent (&#212;) - Ocirc */
+ "O", /* capital O, grave accent (&#210;) - Ograve */
+ "O", /* capital O, slash (&#216;) - Oslash */
+ "O", /* capital O, tilde (&#213;) - Otilde */
+#ifdef LY_UMLAUT
+ "Oe", /* capital O, dieresis or umlaut mark (&#214;) - Ouml */
+#else
+ "O", /* capital O, dieresis or umlaut mark (&#214;) - Ouml */
+#endif /* LY_UMLAUT */
+ "P", /* capital THORN, Icelandic (&#222;) - THORN */
+ "U", /* capital U, acute accent (&#218;) - Uacute */
+ "U", /* capital U, circumflex accent (&#219;) - Ucirc */
+ "U", /* capital U, grave accent (&#217;) - Ugrave */
+#ifdef LY_UMLAUT
+ "Ue", /* capital U, dieresis or umlaut mark (&#220;) - Uuml */
+#else
+ "U", /* capital U, dieresis or umlaut mark (&#220;) - Uuml */
+#endif /* LY_UMLAUT */
+ "Y", /* capital Y, acute accent (&#221;) - Yacute */
+ "a", /* small a, acute accent (&#225;) - aacute */
+ "a", /* small a, circumflex accent (&#226;) - acirc */
+ "'", /* spacing acute (&#180;) - acute */
+ "ae", /* small ae diphthong (ligature) (&#230;) - aelig */
+ "`a", /* small a, grave accent (&#232;) - agrave */
+ "&", /* ampersand (&#38;) - amp */
+ "a", /* small a, ring (&#229;) - aring */
+ "a", /* small a, tilde (&#227;) - atilde */
+#ifdef LY_UMLAUT
+ "ae", /* small a, dieresis or umlaut mark (&#228;) - auml */
+#else
+ "a", /* small a, dieresis or umlaut mark (&#228;) - auml */
+#endif /* LY_UMLAUT */
+ "|", /* broken vertical bar (&#166;) - brkbar */
+ "|", /* broken vertical bar (&#166;) - brvbar */
+ "c", /* small c, cedilla (&#231;) - ccedil */
+ ",", /* spacing cedilla (&#184;) - cedil */
+ "-c-", /* cent sign (&#162;) - cent */
+ "(c)", /* copyright sign (&#169;) - copy */
+ "CUR", /* currency sign (&#164;) - curren */
+ "DEG", /* degree sign (&#176;) - deg */
+ "\042", /* spacing dieresis (&#168;) - die */
+ "/", /* division sign (&#247;) - divide */
+ "e", /* small e, acute accent (&#233;) - eacute */
+ "e", /* small e, circumflex accent (&#234;) - ecirc */
+ "e", /* small e, grave accent (&#232;) - egrave */
+ "-", /* dash the width of emsp - emdash */
+ "\002", /* emsp NEVER CHANGE THIS - emsp */
+ "-", /* dash the width of ensp - endash */
+ "\002", /* ensp NEVER CHANGE THIS - ensp */
+ "dh", /* small eth, Icelandic eth (&#240;) */
+ "e", /* small e, dieresis or umlaut mark (&#235;) - euml */
+ " 1/2", /* fraction 1/2 (&#189;) - frac12 */
+ " 1/4", /* fraction 1/4 (&#188;) - frac14 */
+ " 3/4", /* fraction 3/4 (&#190;) - frac34 */
+ ">", /* greater than (&#62;) - gt */
+ "-", /* spacing macron (&#175;) - hibar */
+ "i", /* small i, acute accent (&#237;) - iacute */
+ "i", /* small i, circumflex accent (&#238;) - icirc*/
+ "!", /* inverted exclamation mark (&#161;) - iexcl */
+ "`i", /* small i, grave accent (&#236;) - igrave */
+ "?", /* inverted question mark (&#191;) - iquest */
+ "i", /* small i, dieresis or umlaut mark (&#239;) - iuml */
+ "<<", /* angle quotation mark, left (&#171;) - laquo */
+ "<", /* less than - lt (&#60;) */
+ "-", /* spacing macron (&#175;) - macr */
+ "-", /* dash the width of emsp - mdash */
+ "u", /* micro sign (&#181;) - micro */
+ ".", /* middle dot (&#183;) - middot */
+ "\001", /* nbsp non-breaking space NEVER CHANGE THIS - nbsp */
+ "-", /* dash the width of ensp - ndash */
+ "NOT", /* negation sign (&#172;) - not */
+ "n", /* small n, tilde (&#241;) - ntilde */
+ "o", /* small o, acute accent (&#243;) - oacute */
+ "o", /* small o, circumflex accent (&#244;) - ocirc */
+ "o", /* small o, grave accent (&#242;) - ograve */
+ "-a", /* feminine ordinal indicator (&#170;) - ordf */
+ "-o", /* masculine ordinal indicator (&#186;) - ordm */
+ "o", /* small o, slash (&#248;) - oslash */
+ "o", /* small o, tilde (&#245;) - otilde */
+#ifdef LY_UMLAUT
+ "oe", /* small o, dieresis or umlaut mark (&#246;) - ouml */
+#else
+ "o", /* small o, dieresis or umlaut mark (&#246;) - ouml */
+#endif /* LY_UMLAUT */
+ "P:", /* paragraph sign (&#182;) - para */
+ "+-", /* plus-or-minus sign (&#177;) - plusmn */
+ "-L-", /* pound sign (&#163;) - pound */
+ "\"", /* quote '"' (&#34;) - quot */
+ ">>", /* angle quotation mark, right (&#187;) - raquo */
+ "(R)", /* circled R registered sign (&#174;) - reg */
+ "S:", /* section sign (&#167;) - sect */
+ "\007", /* soft hyphen (&#173;) NEVER CHANGE THIS - shy */
+ "^1", /* superscript 1 (&#185;) - sup1 */
+ "^2", /* superscript 2 (&#178;) - sup2 */
+ "^3", /* superscript 3 (&#179;) - sup3 */
+ "ss", /* small sharp s, German (sz ligature) (&#223;) - szlig */
+ "\002", /* thin space - not collapsed NEVER CHANGE THIS - thinsp */
+ "p", /* small thorn, Icelandic (&#254;) - thorn */
+ "*", /* multiplication sign (&#215;) - times */
+ "(TM)", /* circled TM trade mark sign (&#8482;) - trade */
+ "u", /* small u, acute accent (&#250;) - uacute */
+ "u", /* small u, circumflex accent (&#251;) - ucirc */
+ "u", /* small u, grave accent (&#249;) - ugrave */
+ "\042", /* spacing dieresis (&#168;) - uml */
+#ifdef LY_UMLAUT
+ "ue", /* small u, dieresis or umlaut mark (&#252;) - uuml */
+#else
+ "u", /* small u, dieresis or umlaut mark (&#252;) - uuml */
+#endif /* LY_UMLAUT */
+ "y", /* small y, acute accent (&#253;) - yacute */
+ "YEN", /* yen sign (&#165;) - yen */
+ "y", /* small y, dieresis or umlaut mark (&#255;) - yuml */
+};
+
+/*
+ * Add your new character sets HERE (but only if you
+ * can't construct Unicode tables for them). - FM
+ */
+
+/*
+ * Add the array name to LYCharSets
+ */
+PUBLIC char ** LYCharSets[MAXCHARSETS]={
+ ISO_Latin1, /* ISO Latin 1 */
+ SevenBitApproximations, /* DosLatin1 (cp850) */
+ SevenBitApproximations, /* WinLatin1 (cp1252) */
+ SevenBitApproximations, /* DosLatinUS (cp437) */
+ SevenBitApproximations, /* DEC Multinational */
+ SevenBitApproximations, /* Macintosh (8 bit) */
+ SevenBitApproximations, /* NeXT character set */
+ SevenBitApproximations, /* Chinese */
+ SevenBitApproximations, /* Japanese (EUC) */
+ SevenBitApproximations, /* Japanese (SJIS) */
+ SevenBitApproximations, /* Korean */
+ SevenBitApproximations, /* Taipei (Big5) */
+ SevenBitApproximations, /* Vietnamese (VISCII) */
+ SevenBitApproximations, /* 7 Bit Approximations */
+ SevenBitApproximations, /* Transparent */
+};
+
+/*
+ * Add the name that the user will see below.
+ * The order of LYCharSets and LYchar_set_names MUST be the same
+ */
+PUBLIC CONST char * LYchar_set_names[MAXCHARSETSP]={
+ "ISO Latin 1 ",
+ "DosLatin1 (cp850) ",
+ "WinLatin1 (cp1252) ",
+ "DosLatinUS (cp437) ",
+ "DEC Multinational ",
+ "Macintosh (8 bit) ",
+ "NeXT character set ",
+ "Chinese ",
+ "Japanese (EUC) ",
+ "Japanese (SJIS) ",
+ "Korean ",
+ "Taipei (Big5) ",
+ "Vietnamese (VISCII) ",
+ "7 bit approximations",
+ "Transparent ",
+ (char *) 0
+};
+
+/*
+ * Associate additional pieces of info with each of the charsets listed
+ * above.
+ * Will be automatically modified (and extended) by charset translations
+ * which are loaded using the chartrans mechanism.
+ * Most important piece of info to put here is a MIME charset name.
+ * Used for chartrans.
+ * The order of LYCharSets and LYCharSet_UC MUST be the same.
+ *
+ * Note that most of the charsets added by the new mechanism in src/chrtrans
+ * don't show up here at all. They don't have to.
+ */
+PUBLIC LYUCcharset LYCharSet_UC[MAXCHARSETS]=
+{
+ /*
+ * Zero position placeholder and HTMLGetEntityUCValue() reference. - FM
+ */
+ {-1,"iso-8859-1", UCT_ENC_8BIT,
+ UCT_REP_IS_LAT1,
+ UCT_CP_IS_LAT1, UCT_R_LAT1,UCT_R_LAT1},
+
+ /*
+ * Placeholders for Unicode tables. - FM
+ */
+ {-1,"cp850", UCT_ENC_8BIT,
+ UCT_REP_SUPERSETOF_LAT1,
+ 0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"cp1252", UCT_ENC_8BIT,
+ UCT_REP_SUPERSETOF_LAT1,
+ 0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"cp437", UCT_ENC_8BIT,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"dec-mcs", UCT_ENC_8BIT,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"macintosh", UCT_ENC_8BIT,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"next", UCT_ENC_8BIT,0,0, UCT_R_8BIT,UCT_R_ASCII},
+
+ /*
+ * There is no strict correlation for the next five, since the transfer
+ * charset gets decoded into Display Char Set by the CJK code (separate
+ * from Unicode mechanism). For now we use the MIME name that describes
+ * what is output to the terminal. - KW
+ */
+ {-1,"euc-cn", UCT_ENC_CJK,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"euc-jp", UCT_ENC_CJK,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"shift_jis", UCT_ENC_CJK,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"euc-kr", UCT_ENC_CJK,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"big5", UCT_ENC_CJK,0,0, UCT_R_8BIT,UCT_R_ASCII},
+
+ /*
+ * Placeholders for Unicode tables. - FM
+ */
+ {-1,"viscii", UCT_ENC_8BIT_C0,0,0, UCT_R_8BIT,UCT_R_ASCII},
+ {-1,"us-ascii", UCT_ENC_7BIT,
+ UCT_REP_SUBSETOF_LAT1,
+ UCT_CP_SUBSETOF_LAT1, UCT_R_ASCII,UCT_R_ASCII},
+
+ /*
+ * Placeholder for non-translation mode. - FM
+ */
+ {-1,"x-transparent", UCT_ENC_8BIT,0,0, UCT_R_8BIT,UCT_R_ASCII}
+
+};
+
+/*
+ * Add the code of the the lowest character with the high bit set
+ * that can be directly displayed.
+ * The order of LYCharSets and LYlowest_eightbit MUST be the same.
+ *
+ * (If charset have chartrans unicode table,
+ * LYlowest_eightbit will be verified/modified anyway.)
+ */
+PUBLIC int LYlowest_eightbit[MAXCHARSETS]={
+ 160, /* ISO Latin 1 */
+ 128, /* DosLatin1 (cp850) */
+ 130, /* WinLatin1 (cp1252) */
+ 128, /* DosLatinUS (cp437) */
+ 160, /* DEC Multinational */
+ 128, /* Macintosh (8 bit) */
+ 128, /* NeXT character set */
+ 128, /* Chinese */
+ 128, /* Japanese (EUC) */
+ 128, /* Japanese (SJIS) */
+ 128, /* Korean */
+ 128, /* Taipei (Big5) */
+ 128, /* Vietnamese (VISCII) */
+ 999, /* 7 bit approximations */
+ 128 /* Transparent (???) */
+};
+
+/*
+ * The default character set.
+ * --------------------------
+ * Use lynx.cfg and/or user
+ * 'o'ptions (.lynxrc) to
+ * set a different default.
+ */
+PUBLIC char** p_entity_values = ISO_Latin1; /* Pointer to translation */
+PUBLIC int current_char_set = 0; /* Index for translation */
+
+/*
+ * Function to set the handling of selected character sets
+ * based on the current LYUseDefaultRawMode value. - FM
+ */
+PUBLIC void HTMLSetCharacterHandling ARGS1(int,i)
+{
+ int chndl = -2;
+ if (LYCharSet_UC[i].enc != UCT_ENC_CJK) {
+ chndl = 0;
+
+ if (UCAssume_MIMEcharset)
+ chndl = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ HTCJK = NOCJK;
+ kanji_code = NOKANJI;
+
+ HTPassEightBitNum =
+ ((LYCharSet_UC[i].codepoints & UCT_CP_SUPERSETOF_LAT1) ||
+ (LYCharSet_UC[i].like8859 & UCT_R_HIGH8BIT));
+
+ if (i == (chndl < 0 ? 0 : chndl)) {
+ LYRawMode = LYUseDefaultRawMode ? TRUE : FALSE;
+ } else {
+ LYRawMode = LYUseDefaultRawMode ? FALSE : TRUE;
+ }
+ if (LYRawMode) {
+ HTPassEightBitRaw = (LYlowest_eightbit[i] <= 160);
+ } else {
+ HTPassEightBitRaw = FALSE;
+ }
+ if (LYRawMode || i == chndl) {
+ HTPassHighCtrlRaw = (LYlowest_eightbit[i] <= 130);
+ } else {
+ HTPassHighCtrlRaw = FALSE;
+ }
+
+ HTPassHighCtrlNum = FALSE;
+
+ } else if (!strncmp(LYchar_set_names[i], "Chinese", 7)) {
+ HTCJK = LYUseDefaultRawMode ? CHINESE : NOCJK;
+ LYRawMode = (HTCJK != NOCJK) ? TRUE : FALSE;
+ kanji_code = EUC;
+ HTPassEightBitRaw = FALSE;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = (HTCJK != NOCJK) ? TRUE : FALSE;
+ HTPassHighCtrlNum = FALSE;
+
+ } else if (!strncmp(LYchar_set_names[i], "Japanese (EUC)", 14)) {
+ HTCJK = LYUseDefaultRawMode ? JAPANESE : NOCJK;
+ LYRawMode = (HTCJK != NOCJK) ? TRUE : FALSE;
+ kanji_code = EUC;
+ HTPassEightBitRaw = FALSE;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = (HTCJK != NOCJK) ? TRUE : FALSE;
+ HTPassHighCtrlNum = FALSE;
+
+ } else if (!strncmp(LYchar_set_names[i], "Japanese (SJIS)", 15)) {
+ HTCJK = LYUseDefaultRawMode ? JAPANESE : NOCJK;
+ LYRawMode = (HTCJK != NOCJK) ? TRUE : FALSE;
+ kanji_code = SJIS;
+ HTPassEightBitRaw = FALSE;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = (HTCJK != NOCJK) ? TRUE : FALSE;
+ HTPassHighCtrlNum = FALSE;
+
+ } else if (!strncmp(LYchar_set_names[i], "Korean", 6)) {
+ HTCJK = LYUseDefaultRawMode ? KOREAN : NOCJK;
+ LYRawMode = (HTCJK != NOCJK) ? TRUE : FALSE;
+ kanji_code = EUC;
+ HTPassEightBitRaw = FALSE;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = (HTCJK != NOCJK) ? TRUE : FALSE;
+ HTPassHighCtrlNum = FALSE;
+
+ } else if (!strncmp(LYchar_set_names[i], "Taipei (Big5)", 13)) {
+ HTCJK = LYUseDefaultRawMode ? TAIPEI : NOCJK;
+ LYRawMode = (HTCJK != NOCJK) ? TRUE : FALSE;
+ kanji_code = EUC;
+ HTPassEightBitRaw = FALSE;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = (HTCJK != NOCJK) ? TRUE : FALSE;
+ HTPassHighCtrlNum = FALSE;
+
+ } else {
+ HTCJK = NOCJK;
+ kanji_code = NOKANJI;
+ HTPassEightBitRaw = LYUseDefaultRawMode ? FALSE : TRUE;
+ LYRawMode = HTPassEightBitRaw;
+ HTPassEightBitNum = FALSE;
+ HTPassHighCtrlRaw = FALSE;
+ HTPassHighCtrlNum = FALSE;
+ }
+
+ if (LYRawMode) {
+ UCLYhndl_for_unspec = i;
+ } else {
+ if (chndl == -2) {
+ chndl = 0;
+
+ if (UCAssume_MIMEcharset)
+ chndl = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ }
+ if (chndl != i && chndl >= 0 &&
+ (LYCharSet_UC[i].enc != UCT_ENC_CJK ||
+ LYCharSet_UC[chndl].enc != UCT_ENC_CJK)) {
+ UCLYhndl_for_unspec = chndl;
+ } else {
+ UCLYhndl_for_unspec = 0;
+ }
+ }
+
+#ifdef USE_SLANG
+ if (LYlowest_eightbit[i] > 191) {
+ /*
+ * Higher than this may output cntrl chars to screen. - KW
+ */
+ SLsmg_Display_Eight_Bit = 191;
+ } else {
+ SLsmg_Display_Eight_Bit = LYlowest_eightbit[i];
+ }
+#endif /* USE_SLANG */
+
+ ena_csi((LYlowest_eightbit[current_char_set] > 155));
+
+ return;
+}
+
+/*
+ * Function to set the LYDefaultRawMode value
+ * based on the selected character set. - FM
+ */
+PUBLIC void HTMLSetRawModeDefault ARGS1(int,i)
+{
+ if (!strncmp(LYchar_set_names[i], "ISO Latin 1", 11) ||
+ !strncmp(LYchar_set_names[i], "Chinese", 7) ||
+ !strncmp(LYchar_set_names[i], "Japanese (EUC)", 14) ||
+ !strncmp(LYchar_set_names[i], "Japanese (SJIS)", 15) ||
+ !strncmp(LYchar_set_names[i], "Korean", 6) ||
+ !strncmp(LYchar_set_names[i], "Taipei (Big5)", 13)) {
+ LYDefaultRawMode = TRUE;
+ } else {
+ LYDefaultRawMode = FALSE;
+ }
+ return;
+}
+
+/*
+ * Function to set the LYUseDefaultRawMode value
+ * based on the selected character set and the
+ * current LYRawMode value. - FM
+ */
+PUBLIC void HTMLSetUseDefaultRawMode ARGS2(
+ int, i,
+ BOOLEAN, modeflag)
+{
+ if (LYCharSet_UC[i].enc != UCT_ENC_CJK) {
+ int chndl = 0;
+
+ if (UCAssume_MIMEcharset)
+ chndl = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ if (i == chndl)
+ LYUseDefaultRawMode = modeflag;
+ else
+ LYUseDefaultRawMode = (!modeflag);
+ } else if (!strncmp(LYchar_set_names[i], "ISO Latin 1", 11) ||
+ !strncmp(LYchar_set_names[i], "Chinese", 7) ||
+ !strncmp(LYchar_set_names[i], "Japanese (EUC)", 14) ||
+ !strncmp(LYchar_set_names[i], "Japanese (SJIS)", 15) ||
+ !strncmp(LYchar_set_names[i], "Korean", 6) ||
+ !strncmp(LYchar_set_names[i], "Taipei (Big5)", 13)) {
+ if (modeflag == TRUE) {
+ LYUseDefaultRawMode = TRUE;
+ } else {
+ LYUseDefaultRawMode = FALSE;
+ }
+ } else {
+ if (modeflag == FALSE) {
+ LYUseDefaultRawMode = TRUE;
+ } else {
+ LYUseDefaultRawMode = FALSE;
+ }
+ }
+ return;
+}
+
+/*
+ * Function to set the LYHaveCJKCharacterSet value
+ * based on the selected character set. - FM
+ */
+PUBLIC void HTMLSetHaveCJKCharacterSet ARGS1(int,i)
+{
+ if (!strncmp(LYchar_set_names[i], "Chinese", 7) ||
+ !strncmp(LYchar_set_names[i], "Japanese (EUC)", 14) ||
+ !strncmp(LYchar_set_names[i], "Japanese (SJIS)", 15) ||
+ !strncmp(LYchar_set_names[i], "Korean", 6) ||
+ !strncmp(LYchar_set_names[i], "Taipei (Big5)", 13)) {
+ LYHaveCJKCharacterSet = TRUE;
+ } else {
+ LYHaveCJKCharacterSet = FALSE;
+ }
+ return;
+}
+
+/*
+ * Entity names -- Ordered by ISO Latin 1 value.
+ * ---------------------------------------------
+ * For conversions of DECIMAL escaped entities.
+ * Must be in order of ascending value.
+ */
+PUBLIC CONST char * LYEntityNames[] = {
+/* NAME DECIMAL VALUE */
+ "nbsp", /* 160, non breaking space */
+ "iexcl", /* 161, inverted exclamation mark */
+ "cent", /* 162, cent sign */
+ "pound", /* 163, pound sign */
+ "curren", /* 164, currency sign */
+ "yen", /* 165, yen sign */
+ "brvbar", /* 166, broken vertical bar, (brkbar) */
+ "sect", /* 167, section sign */
+ "uml", /* 168, spacing dieresis */
+ "copy", /* 169, copyright sign */
+ "ordf", /* 170, feminine ordinal indicator */
+ "laquo", /* 171, angle quotation mark, left */
+ "not", /* 172, negation sign */
+ "shy", /* 173, soft hyphen */
+ "reg", /* 174, circled R registered sign */
+ "hibar", /* 175, spacing macron */
+ "deg", /* 176, degree sign */
+ "plusmn", /* 177, plus-or-minus sign */
+ "sup2", /* 178, superscript 2 */
+ "sup3", /* 179, superscript 3 */
+ "acute", /* 180, spacing acute (96) */
+ "micro", /* 181, micro sign */
+ "para", /* 182, paragraph sign */
+ "middot", /* 183, middle dot */
+ "cedil", /* 184, spacing cedilla */
+ "sup1", /* 185, superscript 1 */
+ "ordm", /* 186, masculine ordinal indicator */
+ "raquo", /* 187, angle quotation mark, right */
+ "frac14", /* 188, fraction 1/4 */
+ "frac12", /* 189, fraction 1/2 */
+ "frac34", /* 190, fraction 3/4 */
+ "iquest", /* 191, inverted question mark */
+ "Agrave", /* 192, capital A, grave accent */
+ "Aacute", /* 193, capital A, acute accent */
+ "Acirc", /* 194, capital A, circumflex accent */
+ "Atilde", /* 195, capital A, tilde */
+ "Auml", /* 196, capital A, dieresis or umlaut mark */
+ "Aring", /* 197, capital A, ring */
+ "AElig", /* 198, capital AE diphthong (ligature) */
+ "Ccedil", /* 199, capital C, cedilla */
+ "Egrave", /* 200, capital E, grave accent */
+ "Eacute", /* 201, capital E, acute accent */
+ "Ecirc", /* 202, capital E, circumflex accent */
+ "Euml", /* 203, capital E, dieresis or umlaut mark */
+ "Igrave", /* 204, capital I, grave accent */
+ "Iacute", /* 205, capital I, acute accent */
+ "Icirc", /* 206, capital I, circumflex accent */
+ "Iuml", /* 207, capital I, dieresis or umlaut mark */
+ "ETH", /* 208, capital Eth, Icelandic (or Latin2 Dstrok) */
+ "Ntilde", /* 209, capital N, tilde */
+ "Ograve", /* 210, capital O, grave accent */
+ "Oacute", /* 211, capital O, acute accent */
+ "Ocirc", /* 212, capital O, circumflex accent */
+ "Otilde", /* 213, capital O, tilde */
+ "Ouml", /* 214, capital O, dieresis or umlaut mark */
+ "times", /* 215, multiplication sign */
+ "Oslash", /* 216, capital O, slash */
+ "Ugrave", /* 217, capital U, grave accent */
+ "Uacute", /* 218, capital U, acute accent */
+ "Ucirc", /* 219, capital U, circumflex accent */
+ "Uuml", /* 220, capital U, dieresis or umlaut mark */
+ "Yacute", /* 221, capital Y, acute accent */
+ "THORN", /* 222, capital THORN, Icelandic */
+ "szlig", /* 223, small sharp s, German (sz ligature) */
+ "agrave", /* 224, small a, grave accent */
+ "aacute", /* 225, small a, acute accent */
+ "acirc", /* 226, small a, circumflex accent */
+ "atilde", /* 227, small a, tilde */
+ "auml", /* 228, small a, dieresis or umlaut mark */
+ "aring", /* 229, small a, ring */
+ "aelig", /* 230, small ae diphthong (ligature) */
+ "ccedil", /* 231, small c, cedilla */
+ "egrave", /* 232, small e, grave accent */
+ "eacute", /* 233, small e, acute accent */
+ "ecirc", /* 234, small e, circumflex accent */
+ "euml", /* 235, small e, dieresis or umlaut mark */
+ "igrave", /* 236, small i, grave accent */
+ "iacute", /* 237, small i, acute accent */
+ "icirc", /* 238, small i, circumflex accent */
+ "iuml", /* 239, small i, dieresis or umlaut mark */
+ "eth", /* 240, small eth, Icelandic */
+ "ntilde", /* 241, small n, tilde */
+ "ograve", /* 242, small o, grave accent */
+ "oacute", /* 243, small o, acute accent */
+ "ocirc", /* 244, small o, circumflex accent */
+ "otilde", /* 245, small o, tilde */
+ "ouml", /* 246, small o, dieresis or umlaut mark */
+ "divide", /* 247, division sign */
+ "oslash", /* 248, small o, slash */
+ "ugrave", /* 249, small u, grave accent */
+ "uacute", /* 250, small u, acute accent */
+ "ucirc", /* 251, small u, circumflex accent */
+ "uuml", /* 252, small u, dieresis or umlaut mark */
+ "yacute", /* 253, small y, acute accent */
+ "thorn", /* 254, small thorn, Icelandic */
+ "yuml", /* 255, small y, dieresis or umlaut mark */
+};
+
+/*
+ * Function to return the entity names of
+ * ISO-8859-1 8-bit characters. - FM
+ */
+PUBLIC CONST char * HTMLGetEntityName ARGS1(
+ UCode_t, code)
+{
+#define IntValue code
+ int MaxValue = ((sizeof(LYEntityNames)/sizeof(char **)) - 1);
+
+ if (IntValue < 0 || IntValue > MaxValue) {
+ return "";
+ }
+
+ return LYEntityNames[IntValue];
+}
+
+/*
+ * Function to return the UCode_t (long int) value for entity names
+ * in the ISO_Latin1 and UC_entity_info unicode_entities arrays.
+ * It returns 0 if not found. - FM
+ *
+ * unicode_entities[] now handles all the names from old style entities[] too.
+ * Lynx now calls unicode_entities[] only through this function:
+ * HTMLGetEntityUCValue(). Note, we need not check for special characters
+ * here in function or even before it, we should check them *after*
+ * invoking this function, see put_special_unicodes() in SGML.c.
+ *
+ * In the future we will try to isolate all calls to entities[]
+ * in favor of new unicode-based chartrans scheme. - LP
+ */
+PUBLIC UCode_t HTMLGetEntityUCValue ARGS1(
+ CONST char *, name)
+{
+ UCode_t value = 0;
+ size_t i, high, low;
+ int diff = 0;
+/* CONST char ** entities = HTML_dtd.entity_names; */
+ CONST UC_entity_info * unicode_entities = HTML_dtd.unicode_entity_info;
+
+ /*
+ * Make sure we have a non-zero length name. - FM
+ */
+ if (!(name && *name))
+ return(value);
+
+
+#ifdef NOTDEFINED
+/*
+** unicode_entities[] now handles all names from entities[], so disable latter.
+** Let us keep this some sort of comment until we remove
+** all calls to old-style entities[] from the code. - LP
+*/
+
+ /*
+ * Handle names that have control characters
+ * or strings in ISO_Latin1[]. - FM
+ */
+ if (!strcmp(name, "nbsp")) {
+ return(160);
+ }
+ if (!strcmp(name, "shy")) {
+ return(173);
+ }
+ if (!strcmp(name, "ensp")) {
+ return(8194);
+ }
+ if (!strcmp(name, "emsp")) {
+ return(8195);
+ }
+ if (!strcmp(name, "thinsp")) {
+ return(8201);
+ }
+ if (!strcmp(name, "ndash") ||
+ !strcmp(name, "endash")) {
+ return(8211);
+ }
+ if (!strcmp(name, "mdash") ||
+ !strcmp(name, "emdash")) {
+ return(8212);
+ }
+ if (!strcmp(name, "trade")) {
+ return(8482);
+ }
+
+ /*
+ * Now try ISO_Latin1[]. - FM
+ */
+ for (low = 0, high = HTML_dtd.number_of_entities;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) {
+ /*
+ ** Binary search.
+ */
+ i = (low + (high-low)/2);
+ diff = strcmp(entities[i], name);
+ if (diff == 0) {
+ if (strlen(ISO_Latin1[i]) == 1) {
+ value = (unsigned char)(ISO_Latin1[i][0]);
+ }
+ break;
+ }
+ }
+ if (value > 0) {
+ return(value);
+ }
+
+ /*
+ * Not yet found... - FM
+ */
+#endif /* NOTDEFINED */
+
+ /*
+ * Try UC_entity_info unicode_entities[].
+ */
+ for (low = 0, high = HTML_dtd.number_of_unicode_entities;
+ high > low;
+ diff < 0 ? (low = i+1) : (high = i)) {
+ /*
+ ** Binary search.
+ */
+ i = (low + (high-low)/2);
+ diff = strcmp(unicode_entities[i].name, name); /* Case sensitive! */
+ if (diff == 0) {
+ value = unicode_entities[i].code;
+ break;
+ }
+ }
+
+ return(value);
+}
+
+/*
+ * Function to select a character set and then set the
+ * character handling and LYHaveCJKCharacterSet flag. - FM
+ */
+PUBLIC void HTMLUseCharacterSet ARGS1(int,i)
+{
+ p_entity_values = LYCharSets[i];
+ HTMLSetCharacterHandling(i);
+ HTMLSetHaveCJKCharacterSet(i);
+ return;
+}
+
+/*
+ * Initializer, calls initialization function for the
+ * CHARTRANS handling. - KW
+ */
+PUBLIC int LYCharSetsDeclared NOPARAMS
+{
+ UCInit();
+
+ if (UCAssume_MIMEcharset && *UCAssume_MIMEcharset) {
+ UCLYhndl_for_unspec = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ } else {
+ UCLYhndl_for_unspec = 0;
+ }
+ if (UCAssume_localMIMEcharset && *UCAssume_localMIMEcharset)
+ UCLYhndl_HTFile_for_unspec =
+ UCGetLYhndl_byMIME(UCAssume_localMIMEcharset);
+ if (UCAssume_unrecMIMEcharset && *UCAssume_unrecMIMEcharset)
+ UCLYhndl_for_unrec =
+ UCGetLYhndl_byMIME(UCAssume_unrecMIMEcharset);
+
+ return UCInitialized;
+}
diff --git a/gnu/usr.bin/lynx/src/LYCharSets.h b/gnu/usr.bin/lynx/src/LYCharSets.h
new file mode 100644
index 00000000000..17ee98e2774
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCharSets.h
@@ -0,0 +1,47 @@
+
+#ifndef LYCHARSETS_H
+#define LYCHARSETS_H
+
+#ifndef UCMAP_H
+#include "UCMap.h"
+#endif /* !UCMAP_H */
+
+extern BOOLEAN LYHaveCJKCharacterSet;
+
+/*
+ * LYchar_set_name[current_char_set] points to the currently active set.
+ */
+extern int current_char_set;
+extern CONST char * LYchar_set_names[];
+
+/*
+ * Initializer, calls initialization function for the
+ * CHARTRANS handling. - KW
+ */
+extern int LYCharSetsDeclared NOPARAMS;
+
+
+extern char ** LYCharSets[];
+extern char * SevenBitApproximations[];
+extern char ** p_entity_values;
+extern int LYlowest_eightbit[];
+extern int LYNumCharsets;
+extern LYUCcharset LYCharSet_UC[];
+extern void HTMLSetCharacterHandling PARAMS((int i));
+extern void HTMLSetRawModeDefault PARAMS((int i));
+extern void HTMLSetUseDefaultRawMode PARAMS((int i, BOOLEAN modeflag));
+extern void HTMLSetHaveCJKCharacterSet PARAMS((int i));
+extern void HTMLUseCharacterSet PARAMS((int i));
+extern UCode_t HTMLGetEntityUCValue PARAMS((CONST char *name));
+
+extern CONST char * LYEntityNames[];
+extern CONST char * HTMLGetEntityName PARAMS((UCode_t code));
+ /*
+ ** HTMLGetEntityName calls LYEntityNames for iso-8859-1 entity
+ ** names only. This is an obsolete technique but widely used in
+ ** the code. Note that unicode number in general may have
+ ** several equivalent entity names because of synonyms.
+ */
+
+
+#endif /* LYCHARSETS_H */
diff --git a/gnu/usr.bin/lynx/src/LYCharUtils.c b/gnu/usr.bin/lynx/src/LYCharUtils.c
new file mode 100644
index 00000000000..1f0d325dcd0
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCharUtils.c
@@ -0,0 +1,3710 @@
+/*
+** Functions associated with LYCharSets.c and the Lynx version of HTML.c - FM
+** ==========================================================================
+*/
+#include "HTUtils.h"
+#include "tcp.h"
+#include "SGML.h"
+
+#define Lynx_HTML_Handler
+#include "HTChunk.h"
+#include "HText.h"
+#include "HTStyle.h"
+#include "HTMIME.h"
+#include "HTML.h"
+
+#include "HTCJK.h"
+#include "HTAtom.h"
+#include "HTMLGen.h"
+#include "HTParse.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAux.h"
+
+#include "LYGlobalDefs.h"
+#include "LYCharUtils.h"
+#include "LYCharSets.h"
+
+#include "HTAlert.h"
+#include "HTFont.h"
+#include "HTForms.h"
+#include "HTNestedList.h"
+#include "GridText.h"
+#include "LYSignal.h"
+#include "LYUtils.h"
+#include "LYMap.h"
+#include "LYBookmark.h"
+#include "LYCurses.h"
+#include "LYCookie.h"
+
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern BOOL HTPassEightBitRaw;
+extern BOOL HTPassEightBitNum;
+extern BOOL HTPassHighCtrlRaw;
+extern BOOL HTPassHighCtrlNum;
+extern HTkcode kanji_code;
+extern HTCJKlang HTCJK;
+
+/*
+ * Used for nested lists. - FM
+ */
+PUBLIC int OL_CONTINUE = -29999; /* flag for whether CONTINUE is set */
+PUBLIC int OL_VOID = -29998; /* flag for whether a count is set */
+
+
+/*
+** This function converts any ampersands in allocated
+** strings to "&amp;". If isTITLE is TRUE, it also
+** converts any angle-brackets to "&lt;" or "&gt;". - FM
+*/
+PUBLIC void LYEntify ARGS2(
+ char **, str,
+ BOOLEAN, isTITLE)
+{
+ char *p = *str;
+ char *q = NULL, *cp = NULL;
+ int amps = 0, lts = 0, gts = 0;
+
+ if (p == NULL || *p == '\0')
+ return;
+
+ /*
+ * Count the ampersands. - FM
+ */
+ while ((*p != '\0') && (q = strchr(p, '&')) != NULL) {
+ amps++;
+ p = (q + 1);
+ }
+
+ /*
+ * Count the left-angle-brackets, if needed. - FM
+ */
+ if (isTITLE == TRUE) {
+ p = *str;
+ while ((*p != '\0') && (q = strchr(p, '<')) != NULL) {
+ lts++;
+ p = (q + 1);
+ }
+ }
+
+ /*
+ * Count the right-angle-brackets, if needed. - FM
+ */
+ if (isTITLE == TRUE) {
+ p = *str;
+ while ((*p != '\0') && (q = strchr(p, '>')) != NULL) {
+ gts++;
+ p = (q + 1);
+ }
+ }
+
+ /*
+ * Check whether we need to convert anything. - FM
+ */
+ if (amps == 0 && lts == 0 && gts == 0)
+ return;
+
+ /*
+ * Allocate space and convert. - FM
+ */
+ q = (char *)calloc(1,
+ (strlen(*str) + (4 * amps) + (3 * lts) + (3 * gts) + 1));
+ if ((cp = q) == NULL)
+ outofmem(__FILE__, "LYEntify");
+ for (p = *str; *p; p++) {
+ if (*p == '&') {
+ *q++ = '&';
+ *q++ = 'a';
+ *q++ = 'm';
+ *q++ = 'p';
+ *q++ = ';';
+ } else if (isTITLE && *p == '<') {
+ *q++ = '&';
+ *q++ = 'l';
+ *q++ = 't';
+ *q++ = ';';
+ } else if (isTITLE && *p == '>') {
+ *q++ = '&';
+ *q++ = 'g';
+ *q++ = 't';
+ *q++ = ';';
+ } else {
+ *q++ = *p;
+ }
+ }
+ StrAllocCopy(*str, cp);
+ FREE(cp);
+}
+
+/*
+** This function trims characters <= that of a space (32),
+** including HT_NON_BREAK_SPACE (1) and HT_EM_SPACE (2),
+** but not ESC, from the heads of strings. - FM
+*/
+PUBLIC void LYTrimHead ARGS1(
+ char *, str)
+{
+ int i = 0, j;
+
+ if (!str || *str == '\0')
+ return;
+
+ while (str[i] != '\0' && WHITE(str[i]) && (unsigned char)str[i] != 27)
+ i++;
+ if (i > 0) {
+ for (j = 0; str[i] != '\0'; i++) {
+ str[j++] = str[i];
+ }
+ str[j] = '\0';
+ }
+}
+
+/*
+** This function trims characters <= that of a space (32),
+** including HT_NON_BREAK_SPACE (1), HT_EM_SPACE (2), and
+** ESC from the tails of strings. - FM
+*/
+PUBLIC void LYTrimTail ARGS1(
+ char *, str)
+{
+ int i;
+
+ if (!str || *str == '\0')
+ return;
+
+ i = (strlen(str) - 1);
+ while (i >= 0) {
+ if (WHITE(str[i]))
+ str[i] = '\0';
+ else
+ break;
+ i--;
+ }
+}
+
+/*
+** This function should receive a pointer to the start
+** of a comment. It returns a pointer to the end ('>')
+** character of comment, or it's best guess if the comment
+** is invalid. - FM
+*/
+PUBLIC char *LYFindEndOfComment ARGS1(
+ char *, str)
+{
+ char *cp, *cp1;
+ enum comment_state { start1, start2, end1, end2 } state;
+
+ if (str == NULL)
+ /*
+ * We got NULL, so return NULL. - FM
+ */
+ return NULL;
+
+ if (strncmp(str, "<!--", 4))
+ /*
+ * We don't have the start of a comment, so
+ * return the beginning of the string. - FM
+ */
+ return str;
+
+ cp = (str + 4);
+ if (*cp =='>')
+ /*
+ * It's an invalid comment, so
+ * return this end character. - FM
+ */
+ return cp;
+
+ if ((cp1 = strchr(cp, '>')) == NULL)
+ /*
+ * We don't have an end character, so
+ * return the beginning of the string. - FM
+ */
+ return str;
+
+ if (*cp == '-')
+ /*
+ * Ugh, it's a "decorative" series of dashes,
+ * so return the next end character. - FM
+ */
+ return cp1;
+
+ /*
+ * OK, we're ready to start parsing. - FM
+ */
+ state = start2;
+ while (*cp != '\0') {
+ switch (state) {
+ case start1:
+ if (*cp == '-')
+ state = start2;
+ else
+ /*
+ * Invalid comment, so return the first
+ * '>' from the start of the string. - FM
+ */
+ return cp1;
+ break;
+
+ case start2:
+ if (*cp == '-')
+ state = end1;
+ break;
+
+ case end1:
+ if (*cp == '-')
+ state = end2;
+ else
+ /*
+ * Invalid comment, so return the first
+ * '>' from the start of the string. - FM
+ */
+ return cp1;
+ break;
+
+ case end2:
+ if (*cp == '>')
+ /*
+ * Valid comment, so return the end character. - FM
+ */
+ return cp;
+ if (*cp == '-') {
+ state = start1;
+ } else if (!(WHITE(*cp) && (unsigned char)*cp != 27)) {
+ /*
+ * Invalid comment, so return the first
+ * '>' from the start of the string. - FM
+ */
+ return cp1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ cp++;
+ }
+
+ /*
+ * Invalid comment, so return the first
+ * '>' from the start of the string. - FM
+ */
+ return cp1;
+}
+
+/*
+** If an HREF, itself or if resolved against a base,
+** represents a file URL, and the host is defaulted,
+** force in "//localhost". We need this until
+** all the other Lynx code which performs security
+** checks based on the "localhost" string is changed
+** to assume "//localhost" when a host field is not
+** present in file URLs - FM
+*/
+PUBLIC void LYFillLocalFileURL ARGS2(
+ char **, href,
+ char *, base)
+{
+ char * temp = NULL;
+
+ if (*href == NULL || *(*href) == '\0')
+ return;
+
+ if (!strcmp(*href, "//") || !strncmp(*href, "///", 3)) {
+ if (base != NULL && !strncmp(base, "file:", 5)) {
+ StrAllocCopy(temp, "file:");
+ StrAllocCat(temp, *href);
+ StrAllocCopy(*href, temp);
+ }
+ }
+ if (!strncmp(*href, "file:", 5)) {
+ if (*(*href+5) == '\0') {
+ StrAllocCat(*href, "//localhost");
+ } else if (!strcmp(*href, "file://")) {
+ StrAllocCat(*href, "localhost");
+ } else if (!strncmp(*href, "file:///", 8)) {
+ StrAllocCopy(temp, (*href+7));
+ StrAllocCopy(*href, "file://localhost");
+ StrAllocCat(*href, temp);
+ } else if (!strncmp(*href, "file:/", 6) && *(*href+6) != '/') {
+ StrAllocCopy(temp, (*href+5));
+ StrAllocCopy(*href, "file://localhost");
+ StrAllocCat(*href, temp);
+ }
+ }
+
+ /*
+ * No path in a file://localhost URL means a
+ * directory listing for the current default. - FM
+ */
+ if (!strcmp(*href, "file://localhost")) {
+ char *temp2;
+#ifdef VMS
+ temp2 = HTVMS_wwwName(getenv("PATH"));
+#else
+ char curdir[DIRNAMESIZE];
+#if HAVE_GETCWD
+ getcwd (curdir, DIRNAMESIZE);
+#else
+ getwd (curdir);
+#endif /* NO_GETCWD */
+#ifdef DOSPATH
+ temp2 = HTDOS_wwwName(curdir);
+#else
+ temp2 = curdir;
+#endif /* DOSPATH */
+#endif /* VMS */
+ if (temp2[0] != '/')
+ StrAllocCat(*href, "/");
+ /*
+ * Check for pathological cases - current dir has chars which
+ * MUST BE URL-escaped - kw
+ */
+ if (strchr(temp2, '%') != NULL || strchr(temp2, '#') != NULL) {
+ FREE(temp);
+ temp = HTEscape(temp2, URL_PATH);
+ StrAllocCat(*href, temp);
+ } else {
+ StrAllocCat(*href, temp2);
+ }
+ }
+
+#ifdef VMS
+ /*
+ * On VMS, a file://localhost/ URL means
+ * a listing for the login directory. - FM
+ */
+ if (!strcmp(*href, "file://localhost/"))
+ StrAllocCat(*href, (HTVMS_wwwName((char *)Home_Dir())+1));
+#endif /* VMS */
+
+ FREE(temp);
+ return;
+}
+
+/*
+** This function writes a line with a META tag to an open file,
+** which will specify a charset parameter to use when the file is
+** read back in. It is meant for temporary HTML files used by the
+** various special pages which may show titles of documents. When those
+** files are created, the title strings normally have been translated and
+** expanded to the display character set, so we have to make sure they
+** don't get translated again.
+** If the user has changed the display character set during the lifetime
+** of the Lynx session (or, more exactly, during the time the title
+** strings to be written were generated), they may now have different
+** character encodings and there is currently no way to get it all right.
+** To change this, we would have to add a variable for each string which
+** keeps track of its character encoding.
+** But at least we can try to ensure that reading the file after future
+** display character set changes will give reasonable output.
+**
+** The META tag is not written if the display character set (passed as
+** disp_chndl) already corresponds to the charset assumption that
+** would be made when the file is read. - KW
+**
+** Currently this function is used for temporary files like "Lynx Info Page"
+** and for one permanent - bookmarks (so it may be a problem if you change
+** the display charset later: new bookmark entries may be mistranslated).
+** - LP
+*/
+PUBLIC void LYAddMETAcharsetToFD ARGS2(
+ FILE *, fd,
+ int, disp_chndl)
+{
+ if (disp_chndl == -1)
+ /*
+ * -1 means use current_char_set.
+ */
+ disp_chndl = current_char_set;
+
+ if (fd == NULL || disp_chndl < 0)
+ /*
+ * Should not happen.
+ */
+ return;
+
+ if (UCLYhndl_HTFile_for_unspec == disp_chndl)
+ /*
+ * Not need to do, so we don't.
+ */
+ return;
+
+ if (LYCharSet_UC[disp_chndl].enc == UCT_ENC_7BIT)
+ /*
+ * There shouldn't be any 8-bit characters in this case.
+ */
+ return;
+
+ /*
+ * In other cases we don't know because UCLYhndl_for_unspec may
+ * change during the lifetime of the file (by toggling raw mode
+ * or changing the display character set), so proceed.
+ */
+ fprintf(fd, "<META %s content=\"text/html;charset=%s\">\n",
+ "http-equiv=\"content-type\"",
+ LYCharSet_UC[disp_chndl].MIMEname);
+}
+
+/*
+** This function returns OL TYPE="A" strings in
+** the range of " A." (1) to "ZZZ." (18278). - FM
+*/
+PUBLIC char *LYUppercaseA_OL_String ARGS1(
+ int, seqnum)
+{
+ static char OLstring[8];
+
+ if (seqnum <= 1 ) {
+ strcpy(OLstring, " A.");
+ return OLstring;
+ }
+ if (seqnum < 27) {
+ sprintf(OLstring, " %c.", (seqnum + 64));
+ return OLstring;
+ }
+ if (seqnum < 703) {
+ sprintf(OLstring, "%c%c.", ((seqnum-1)/26 + 64),
+ (seqnum - ((seqnum-1)/26)*26 + 64));
+ return OLstring;
+ }
+ if (seqnum < 18279) {
+ sprintf(OLstring, "%c%c%c.", ((seqnum-27)/676 + 64),
+ (((seqnum - ((seqnum-27)/676)*676)-1)/26 + 64),
+ (seqnum - ((seqnum-1)/26)*26 + 64));
+ return OLstring;
+ }
+ strcpy(OLstring, "ZZZ.");
+ return OLstring;
+}
+
+/*
+** This function returns OL TYPE="a" strings in
+** the range of " a." (1) to "zzz." (18278). - FM
+*/
+PUBLIC char *LYLowercaseA_OL_String ARGS1(
+ int, seqnum)
+{
+ static char OLstring[8];
+
+ if (seqnum <= 1 ) {
+ strcpy(OLstring, " a.");
+ return OLstring;
+ }
+ if (seqnum < 27) {
+ sprintf(OLstring, " %c.", (seqnum + 96));
+ return OLstring;
+ }
+ if (seqnum < 703) {
+ sprintf(OLstring, "%c%c.", ((seqnum-1)/26 + 96),
+ (seqnum - ((seqnum-1)/26)*26 + 96));
+ return OLstring;
+ }
+ if (seqnum < 18279) {
+ sprintf(OLstring, "%c%c%c.", ((seqnum-27)/676 + 96),
+ (((seqnum - ((seqnum-27)/676)*676)-1)/26 + 96),
+ (seqnum - ((seqnum-1)/26)*26 + 96));
+ return OLstring;
+ }
+ strcpy(OLstring, "zzz.");
+ return OLstring;
+}
+
+/*
+** This function returns OL TYPE="I" strings in the
+** range of " I." (1) to "MMM." (3000).- FM
+*/
+PUBLIC char *LYUppercaseI_OL_String ARGS1(
+ int, seqnum)
+{
+ static char OLstring[8];
+ int Arabic = seqnum;
+
+ if (Arabic >= 3000) {
+ strcpy(OLstring, "MMM.");
+ return OLstring;
+ }
+
+ switch(Arabic) {
+ case 1:
+ strcpy(OLstring, " I.");
+ return OLstring;
+ case 5:
+ strcpy(OLstring, " V.");
+ return OLstring;
+ case 10:
+ strcpy(OLstring, " X.");
+ return OLstring;
+ case 50:
+ strcpy(OLstring, " L.");
+ return OLstring;
+ case 100:
+ strcpy(OLstring, " C.");
+ return OLstring;
+ case 500:
+ strcpy(OLstring, " D.");
+ return OLstring;
+ case 1000:
+ strcpy(OLstring, " M.");
+ return OLstring;
+ default:
+ OLstring[0] = '\0';
+ break;
+ }
+
+ while (Arabic >= 1000) {
+ strcat(OLstring, "M");
+ Arabic -= 1000;
+ }
+
+ if (Arabic >= 900) {
+ strcat(OLstring, "CM");
+ Arabic -= 900;
+ }
+
+ if (Arabic >= 500) {
+ strcat(OLstring, "D");
+ Arabic -= 500;
+ while (Arabic >= 500) {
+ strcat(OLstring, "C");
+ Arabic -= 10;
+ }
+ }
+
+ if (Arabic >= 400) {
+ strcat(OLstring, "CD");
+ Arabic -= 400;
+ }
+
+ while (Arabic >= 100) {
+ strcat(OLstring, "C");
+ Arabic -= 100;
+ }
+
+ if (Arabic >= 90) {
+ strcat(OLstring, "XC");
+ Arabic -= 90;
+ }
+
+ if (Arabic >= 50) {
+ strcat(OLstring, "L");
+ Arabic -= 50;
+ while (Arabic >= 50) {
+ strcat(OLstring, "X");
+ Arabic -= 10;
+ }
+ }
+
+ if (Arabic >= 40) {
+ strcat(OLstring, "XL");
+ Arabic -= 40;
+ }
+
+ while (Arabic > 10) {
+ strcat(OLstring, "X");
+ Arabic -= 10;
+ }
+
+ switch (Arabic) {
+ case 1:
+ strcat(OLstring, "I.");
+ break;
+ case 2:
+ strcat(OLstring, "II.");
+ break;
+ case 3:
+ strcat(OLstring, "III.");
+ break;
+ case 4:
+ strcat(OLstring, "IV.");
+ break;
+ case 5:
+ strcat(OLstring, "V.");
+ break;
+ case 6:
+ strcat(OLstring, "VI.");
+ break;
+ case 7:
+ strcat(OLstring, "VII.");
+ break;
+ case 8:
+ strcat(OLstring, "VIII.");
+ break;
+ case 9:
+ strcat(OLstring, "IX.");
+ break;
+ case 10:
+ strcat(OLstring, "X.");
+ break;
+ default:
+ strcat(OLstring, ".");
+ break;
+ }
+
+ return OLstring;
+}
+
+/*
+** This function returns OL TYPE="i" strings in
+** range of " i." (1) to "mmm." (3000).- FM
+*/
+PUBLIC char *LYLowercaseI_OL_String ARGS1(
+ int, seqnum)
+{
+ static char OLstring[8];
+ int Arabic = seqnum;
+
+ if (Arabic >= 3000) {
+ strcpy(OLstring, "mmm.");
+ return OLstring;
+ }
+
+ switch(Arabic) {
+ case 1:
+ strcpy(OLstring, " i.");
+ return OLstring;
+ case 5:
+ strcpy(OLstring, " v.");
+ return OLstring;
+ case 10:
+ strcpy(OLstring, " x.");
+ return OLstring;
+ case 50:
+ strcpy(OLstring, " l.");
+ return OLstring;
+ case 100:
+ strcpy(OLstring, " c.");
+ return OLstring;
+ case 500:
+ strcpy(OLstring, " d.");
+ return OLstring;
+ case 1000:
+ strcpy(OLstring, " m.");
+ return OLstring;
+ default:
+ OLstring[0] = '\0';
+ break;
+ }
+
+ while (Arabic >= 1000) {
+ strcat(OLstring, "m");
+ Arabic -= 1000;
+ }
+
+ if (Arabic >= 900) {
+ strcat(OLstring, "cm");
+ Arabic -= 900;
+ }
+
+ if (Arabic >= 500) {
+ strcat(OLstring, "d");
+ Arabic -= 500;
+ while (Arabic >= 500) {
+ strcat(OLstring, "c");
+ Arabic -= 10;
+ }
+ }
+
+ if (Arabic >= 400) {
+ strcat(OLstring, "cd");
+ Arabic -= 400;
+ }
+
+ while (Arabic >= 100) {
+ strcat(OLstring, "c");
+ Arabic -= 100;
+ }
+
+ if (Arabic >= 90) {
+ strcat(OLstring, "xc");
+ Arabic -= 90;
+ }
+
+ if (Arabic >= 50) {
+ strcat(OLstring, "l");
+ Arabic -= 50;
+ while (Arabic >= 50) {
+ strcat(OLstring, "x");
+ Arabic -= 10;
+ }
+ }
+
+ if (Arabic >= 40) {
+ strcat(OLstring, "xl");
+ Arabic -= 40;
+ }
+
+ while (Arabic > 10) {
+ strcat(OLstring, "x");
+ Arabic -= 10;
+ }
+
+ switch (Arabic) {
+ case 1:
+ strcat(OLstring, "i.");
+ break;
+ case 2:
+ strcat(OLstring, "ii.");
+ break;
+ case 3:
+ strcat(OLstring, "iii.");
+ break;
+ case 4:
+ strcat(OLstring, "iv.");
+ break;
+ case 5:
+ strcat(OLstring, "v.");
+ break;
+ case 6:
+ strcat(OLstring, "vi.");
+ break;
+ case 7:
+ strcat(OLstring, "vii.");
+ break;
+ case 8:
+ strcat(OLstring, "viii.");
+ break;
+ case 9:
+ strcat(OLstring, "ix.");
+ break;
+ case 10:
+ strcat(OLstring, "x.");
+ break;
+ default:
+ strcat(OLstring, ".");
+ break;
+ }
+
+ return OLstring;
+}
+
+/*
+** This function initializes the Ordered List counter. - FM
+*/
+PUBLIC void LYZero_OL_Counter ARGS1(
+ HTStructured *, me)
+{
+ int i;
+
+ if (!me)
+ return;
+
+ for (i = 0; i < 12; i++) {
+ me->OL_Counter[i] = OL_VOID;
+ me->OL_Type[i] = '1';
+ }
+
+ me->Last_OL_Count = 0;
+ me->Last_OL_Type = '1';
+
+ return;
+}
+
+/*
+** This function is used by the HTML Structured object. - KW
+*/
+PUBLIC void LYGetChartransInfo ARGS1(
+ HTStructured *, me)
+{
+ me->UCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_STRUCTURED);
+ if (me->UCLYhndl < 0) {
+ int chndl = HTAnchor_getUCLYhndl(me->node_anchor, UCT_STAGE_HTEXT);
+
+ if (chndl < 0) {
+ chndl = current_char_set;
+ HTAnchor_setUCInfoStage(me->node_anchor, chndl,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_STRUCTURED);
+ }
+ HTAnchor_setUCInfoStage(me->node_anchor, chndl,
+ UCT_STAGE_STRUCTURED,
+ UCT_SETBY_STRUCTURED);
+ me->UCLYhndl = HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_STRUCTURED);
+ }
+ me->UCI = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_STRUCTURED);
+}
+
+#if NOTUSED_FOTEMODS
+/*
+** This function reallocates an allocated string and converts
+** characters for the current display character set. It assumes
+** that invalid control characters have been dealt with by the
+** SGML (or other initial) parser of the document input stream
+** (i.e. are present only if elements or global flags have been
+** set to allow them), and that otherwise this is a copy of the
+** string with the charset of the input stream. It handles Lynx
+** special characters based on the 'me' structure's element values
+** (the me->UsePlainSpace and me->HiddenValue elements, and its
+** chartrans related elements), and calls to other functions which
+** return structure element values. HTChunk functions are used to
+** keep memory allocations at a minimum. - FM
+*/
+PUBLIC void LYExpandString ARGS2(
+ HTStructured *, me,
+ char **, str)
+{
+ char *p = *str;
+ HTChunk *s;
+ BOOLEAN plain_space, hidden;
+ char c;
+ unsigned char c_unsign;
+ char saved_char_in = '\0';
+ BOOLEAN chk;
+ UCode_t code, uck;
+ char replace_buf [64];
+ char utf_buf[8], utf_count = 0;
+ char *utf_buf_p = utf_buf;
+ UCode_t utf_char = 0, value;
+ CONST char *name;
+ int i, j, high, low, diff = 0;
+
+ /*
+ ** Don't do anything if we have no structure
+ ** or string, or are in CJK mode. - FM
+ */
+ if (!me || !p || *p == '\0' ||
+ HTCJK != NOCJK)
+ return;
+
+ /*
+ ** Set "convenience copies" of me structure
+ ** elements. - FM
+ */
+ plain_space = me->UsePlainSpace;
+ hidden = me->HiddenValue;
+
+ /*
+ ** Check for special input charsets - FM
+ */
+ if (!strcmp(me->inUCI->MIMEname, "x-transparent")) {
+ /*
+ ** Conversions not intended. - FM
+ */
+ return;
+ }
+ if (!strcmp(me->inUCI->MIMEname, "mnemonic") ||
+ !strcmp(me->inUCI->MIMEname, "mnemonic+ascii+0")) {
+ /*
+ ** All ASCII representations of Unicode characters,
+ ** and we have no reverse translation code for the
+ ** multibyte characters, so punt. - FM
+ */
+ return;
+ }
+ if (me->inUCLYhndl < 0 || me->outUCLYhndl < 0) {
+ /*
+ ** The chartrans procedure failed, so we don't
+ ** do anything, and hope for the best. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandString: Bad in (%d) or out (%d) handle(s).\n",
+ me->inUCLYhndl, me->outUCLYhndl);
+ }
+ return;
+ }
+
+ /*
+ ** Zero the UTF-8 multibytes buffer. - FM
+ */
+ utf_buf[0] = utf_buf[6] = utf_buf[7] = '\0';
+
+ /*
+ ** Set up an HTChunk for accumulating the expanded copy
+ ** of the string, so that allocations are done in 128
+ ** byte increments, only as required. - FM
+ */
+ s = HTChunkCreate(128);
+
+ /*
+ ** Check each character in the original string,
+ ** and add the characters or substitutions to
+ ** our clean copy. - FM
+ */
+ for (i = 0; p[i]; i++) {
+ /*
+ ** Make sure the character is handled as Unicode
+ ** whenever that's appropriate. - FM
+ */
+ c = p[i];
+ c_unsign = (unsigned char)c;
+ code = (UCode_t)c_unsign;
+ saved_char_in = '\0';
+ /*
+ ** Combine any UTF-8 multibytes into Unicode
+ ** to check for special characters. - FM
+ */
+ if (me->T.decode_utf8) {
+ /*
+ ** Our input charset is UTF-8, so check
+ ** for non-ASCII characters. - FM
+ */
+ if (c_unsign > 127) {
+ /*
+ ** We have an octet from a multibyte character. - FM
+ */
+ if (utf_count > 0 && (c & 0xc0) == 0x80) {
+ /*
+ ** Adjust the UCode_t value, add the octet
+ ** to the buffer, and decrement the byte
+ ** count. - FM
+ */
+ utf_char = (utf_char << 6) | (c & 0x3f);
+ utf_count--;
+ *utf_buf_p = c;
+ utf_buf_p++;
+ if (utf_count == 0) {
+ /*
+ ** We have all of the bytes, so terminate
+ ** the buffer and set 'code' to the UCode_t
+ ** value. - FM
+ */
+ *utf_buf_p = '\0';
+ code = utf_char;
+ /*
+ ** Set up the monobyte character
+ ** values or non-character flags
+ ** and fall through. - FM
+ */
+ if (code > 0 && code < 256) {
+ c = ((char)(code & 0xff));
+ c_unsign = (unsigned char)c;
+ }
+ } else {
+ /*
+ ** Get the next byte. - FM
+ */
+ continue;
+ }
+ } else {
+ /*
+ ** Start handling a new multibyte character. - FM
+ */
+ utf_buf[0] = c;
+ utf_buf_p = &utf_buf[1];
+ if ((c & 0xe0) == 0xc0) {
+ utf_count = 1;
+ utf_char = (c & 0x1f);
+ } else if ((c & 0xf0) == 0xe0) {
+ utf_count = 2;
+ utf_char = (c & 0x0f);
+ } else if ((c & 0xf8) == 0xf0) {
+ utf_count = 3;
+ utf_char = (c & 0x07);
+ } else if ((c & 0xfc) == 0xf8) {
+ utf_count = 4;
+ utf_char = (c & 0x03);
+ } else if ((c & 0xfe) == 0xfc) {
+ utf_count = 5;
+ utf_char = (c & 0x01);
+ } else {
+ /*
+ ** We got garbage, even though it should
+ ** have been filtered out by the SGML or
+ ** input stream parser, so we'll ignore
+ ** it. - FM
+ */
+ utf_count = 0;
+ utf_buf[0] = '\0';
+ utf_buf_p = utf_buf;
+ }
+ /*
+ ** Get the next byte. - FM
+ */
+ continue;
+ }
+ } else if (utf_count > 0) {
+ /*
+ ** Got an ASCII character when expecting
+ ** UTF-8 multibytes, so ignore the buffered
+ ** multibyte characters and fall through with
+ ** the current ASCII character. - FM
+ */
+ utf_count = 0;
+ utf_buf[0] = '\0';
+ utf_buf_p = utf_buf;
+ code = (UCode_t)c_unsign;
+ } else {
+ /*
+ ** Got a valid ASCII character, so fall
+ ** through with it. - FM
+ */
+ code = (UCode_t)c_unsign;
+ }
+ }
+ /*
+ ** Convert characters from non-UTF-8 charsets
+ ** to Unicode (if appropriate). - FM
+ */
+ if (!(me->T.decode_utf8 &&
+ (unsigned char)p[i] > 127)) {
+#ifdef NOTDEFINED
+ if (me->T.strip_raw_char_in)
+ saved_char_in = c;
+#endif /* NOTDEFINED */
+ if (me->T.trans_to_uni &&
+ (code >= 127 ||
+ (code < 32 && code != 0 &&
+ me->T.trans_C0_to_uni))) {
+ /*
+ ** Convert the octet to Unicode. - FM
+ */
+ code = (UCode_t)UCTransToUni(c, me->inUCLYhndl);
+ if (code > 0) {
+ saved_char_in = c;
+ if (code < 256) {
+ c = ((char)(code & 0xff));
+ c_unsign = (unsigned char)c;
+ }
+ }
+ } else if (code < 32 && code != 0 &&
+ me->T.trans_C0_to_uni) {
+ /*
+ ** Quote from SGML.c:
+ ** "This else if may be too ugly to keep. - KW"
+ */
+ if (me->T.trans_from_uni &&
+ (((code = UCTransToUni(c, me->inUCLYhndl)) >= 32) ||
+ (me->T.transp &&
+ (code = UCTransToUni(c, me->inUCLYhndl)) > 0))) {
+ saved_char_in = c;
+ if (code < 256) {
+ c = ((char)(code & 0xff));
+ c_unsign = (unsigned char)c;
+ }
+ } else {
+ uck = -1;
+ if (me->T.transp) {
+ uck = UCTransCharStr(replace_buf, 60, c,
+ me->inUCLYhndl,
+ me->inUCLYhndl, NO);
+ }
+ if (!me->T.transp || uck < 0) {
+ uck = UCTransCharStr(replace_buf, 60, c,
+ me->inUCLYhndl,
+ me->outUCLYhndl, YES);
+ }
+ if (uck == 0) {
+ continue;
+ } else if (uck < 0) {
+ utf_buf[0] = '\0';
+ code = (unsigned char)c;
+ } else {
+ c = replace_buf[0];
+ if (c && replace_buf[1]) {
+ HTChunkPuts(s, replace_buf);
+ continue;
+ }
+ }
+ utf_buf[0] = '\0';
+ code = (unsigned char)c;
+ } /* Next line end of ugly stuff for C0. - KW */
+ } else {
+ utf_buf[0] = '\0';
+ code = (unsigned char)c;
+ }
+ }
+ /*
+ ** Ignore low ISO 646 7-bit control characters
+ ** if they sneaked through (should have been
+ ** filtered by the parser). - FM
+ */
+ if (code < 32 &&
+ c != 9 && c != 10 && c != 13) {
+ continue;
+ }
+ /*
+ ** Ignore 127 if we don't have HTPassHighCtrlRaw
+ ** and it sneaked through (should have been
+ ** filtered by the parser). - FM
+ */
+ if (c == 127 &&
+ !(me->T.transp ||
+ code >= LYlowest_eightbit[me->inUCLYhndl])) {
+ continue;
+ }
+ /*
+ ** Ignore 8-bit control characters 128 - 159 if we don't
+ ** have HTPassHighCtrlRaw set and they sneaked through
+ ** (should have been filtered by the parser). - FM
+ */
+ if (code > 127 && code < 160 &&
+ !(me->T.transp ||
+ code >= LYlowest_eightbit[me->inUCLYhndl])) {
+ continue;
+ }
+ /*
+ ** For 160 (nbsp), substitute Lynx special character
+ ** (or a space if plain_space or hidden is set) if
+ ** HTPassHighCtrlRaw is not set. - FM
+ */
+ if (code == 160) {
+ if (!me->T.pass_160_173_raw) {
+ if (plain_space || hidden) {
+ HTChunkPutc(s, ' ');
+ } else {
+ HTChunkPutc(s, HT_NON_BREAK_SPACE);
+ }
+ } else if (!me->T.output_utf8) {
+ HTChunkPutc(s, ((char)(code & 0xff)));
+ } else if (me->T.decode_utf8 && *utf_buf) {
+ HTChunkPuts(s, utf_buf);
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ } else {
+ HTChunkPutUtf8Char(s, code);
+ }
+ continue;
+ }
+ /*
+ ** For 173 (shy), substitute Lynx special character
+ ** (or skip it if plain_space or hidden is set) if
+ ** HTPassHighCtrlRaw is not set. - FM
+ */
+ if (code == 173) {
+ if (!me->T.pass_160_173_raw) {
+ if (!(plain_space || hidden)) {
+ HTChunkPutc(s, LY_SOFT_HYPHEN);
+ }
+ } else if (!me->T.output_utf8) {
+ HTChunkPutc(s, ((char)(code & 0xff)));
+ } else if (me->T.decode_utf8 && *utf_buf) {
+ HTChunkPuts(s, utf_buf);
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ } else {
+ HTChunkPutUtf8Char(s, code);
+ }
+ continue;
+ }
+ /*
+ ** For 8194 (ensp), 8195 (emsp), or 8201 (thinsp), use
+ ** an ASCII space (32) if plain_space or hidden is TRUE,
+ ** otherwise use the Lynx special character. - FM
+ */
+ if (code == 8194 || code == 8195 || code == 8201) {
+ if (plain_space || hidden) {
+ HTChunkPutc(s, ' ');
+ } else {
+ HTChunkPutc(s, HT_EM_SPACE);
+ }
+ if (me->T.decode_utf8 && *utf_buf) {
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ }
+ continue;
+ }
+ /*
+ ** If we want the raw character, pass it now. - FM
+ */
+ if (me->T.use_raw_char_in && saved_char_in) {
+ HTChunkPutc(s, saved_char_in);
+ continue;
+ }
+ /*
+ ** Seek a translation from the chartrans tables.
+ */
+ if ((chk = (me->T.trans_from_uni && code >= 160)) &&
+ (uck = UCTransUniChar(code, me->outUCLYhndl)) >= 32 &&
+ uck < 256 &&
+ (uck < 127 ||
+ uck >= LYlowest_eightbit[me->outUCLYhndl])) {
+ HTChunkPutc(s, ((char)(uck & 0xff)));
+ continue;
+ } else if (chk &&
+ (uck == -4 ||
+ (me->T.repl_translated_C0 &&
+ uck > 0 && uck < 32)) &&
+ /*
+ ** Not found; look for replacement string.
+ */
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ me->outUCLYhndl,
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string.
+ */
+ HTChunkPuts(s, replace_buf);
+ continue;
+ }
+ /*
+ ** If we want raw UTF-8, output that now. - FM
+ */
+ if (me->T.output_utf8 &&
+ code > 127 && code <= 0x7fffffffL) {
+ if (me->T.decode_utf8 && *utf_buf) {
+ HTChunkPuts(s, utf_buf);
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ } else {
+ HTChunkPutUtf8Char(s, code);
+ }
+ continue;
+ }
+ /*
+ ** If it's any other (> 160) 8-bit character
+ ** and we have not set HTPassEightBitRaw
+ ** nor have the "ISO Latin 1" character set selected,
+ ** back translate for our character set. - FM
+ */
+ if (code > 160 && code < 256 &&
+ me->outUCLYhndl != 0 &&
+ (!(HTPassEightBitRaw ||
+ (me->T.do_8bitraw && !me->T.trans_from_uni)))) {
+ value = (code - 160);
+ name = HTMLGetEntityName(value);
+ for (low = 0, high = HTML_dtd.number_of_entities;
+ high > low;
+ diff < 0 ? (low = j+1) : (high = j)) {
+ /*
+ ** Binary search.
+ */
+ j = (low + (high-low)/2);
+ diff = strcmp(HTML_dtd.entity_names[j], name);
+ if (diff == 0) {
+ HTChunkPuts(s, LYCharSets[me->outUCLYhndl][j]);
+ break;
+ }
+ }
+ if (diff == 0) {
+ continue;
+ }
+ }
+ /*
+ ** If it's ASCII at this point, use it. - FM
+ */
+ if (code < 127 && code > 0) {
+ HTChunkPutc(s, ((char)(code & 0xff)));
+ continue;
+ }
+ /*
+ ** At this point, if we should have translated, the
+ ** translation has failed. We should have sent UTF-8
+ ** output to the parser already, but what the heck,
+ ** try again. - FM
+ */
+ if (me->T.output_utf8 && *utf_buf) {
+ HTChunkPuts(s, utf_buf);
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ continue;
+ }
+#ifdef NOTDEFINED
+ /*
+ ** Check for a strippable koi8-r 8-bit character. - FM
+ */
+ if (me->T.strip_raw_char_in &&
+ (unsigned char)saved_char_in >= 192 &&
+ (unsigned char)saved_char_in < 255 &&
+ saved_char_in) {
+ /*
+ ** KOI8 special: strip high bit, gives (somewhat) readable
+ ** ASCII or KOI7 - it was constructed that way! - KW
+ */
+ HTChunkPutc(s, (saved_char_in & 0x7f));
+ continue;
+ }
+#endif /* NOTDEFINED */
+ /*
+ ** Ignore 8204 (zwnj), 8205 (zwj)
+ ** 8206 (lrm), and 8207 (rlm),
+ ** if we get to here. - FM
+ */
+ if (code == 8204 || code == 8205 ||
+ code == 8206 || code == 8207) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandString: Ignoring '%ld'.\n", code);
+ }
+ if (me->T.decode_utf8 && *utf_buf) {
+ utf_buf[0] == '\0';
+ utf_buf_p = utf_buf;
+ }
+ continue;
+ }
+ /*
+ ** If we don't actually want the character,
+ ** make it safe and output that now. - FM
+ */
+ if ((c_unsign > 0 &&
+ c_unsign < LYlowest_eightbit[me->outUCLYhndl]) ||
+ (me->T.trans_from_uni && !HTPassEightBitRaw)) {
+ /*
+ ** If we do not have the "7-bit approximations" as our
+ ** output character set (in which case we did it already)
+ ** seek a translation for that. Otherwise, or if the
+ ** translation fails, use UHHH notation. - FM
+ */
+ if ((chk = (me->outUCLYhndl !=
+ UCGetLYhndl_byMIME("us-ascii"))) &&
+ (uck = UCTransUniChar(code,
+ UCGetLYhndl_byMIME("us-ascii")))
+ >= 32 && uck < 127) {
+ /*
+ ** Got an ASCII character (yippey). - FM
+ */
+ c = ((char)(uck & 0xff));
+ HTChunkPutc(s, c);
+ continue;
+ } else if ((uck == -4) &&
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ UCGetLYhndl_byMIME("us-ascii"),
+ 0) >= 0)) {
+ /*
+ ** Got a replacement string (yippey). - FM
+ */
+ HTChunkPuts(s, replace_buf);
+ continue;
+ } else {
+ /*
+ ** Out of luck, so use the UHHH notation (ugh). - FM
+ */
+ sprintf(replace_buf, "U%.2lX", code);
+ HTChunkPuts(s, replace_buf);
+ continue;
+ }
+ }
+ /*
+ ** If we get to here and have a monobyte character,
+ ** pass it. - FM
+ */
+ if (c_unsign > 0 && c_unsign < 256) {
+ HTChunkPutc(s, c);
+ }
+ }
+
+ /*
+ ** Terminate the expanded string,
+ ** replace the original, and free
+ ** the chunk. - FM
+ */
+ HTChunkTerminate(s);
+ StrAllocCopy(*str, s->data);
+ HTChunkFree(s);
+}
+#endif /* NOTUSED_FOTEMODS */
+
+/*
+** Get UCS character code for one character from UTF-8 encoded string.
+**
+** On entry:
+** *ppuni should point to beginning of UTF-8 encoding character
+** On exit:
+** *ppuni is advanced to point to the last byte of UTF-8 sequence,
+** if there was a valid one; otherwise unchanged.
+** returns the UCS value
+** returns negative value on error (invalid UTF-8 sequence)
+*/
+PRIVATE UCode_t UCGetUniFromUtf8String ARGS1(char **, ppuni)
+{
+ UCode_t uc_out = 0;
+ char * p = *ppuni;
+ int utf_count, i;
+ if (!(**ppuni&0x80))
+ return (UCode_t) **ppuni; /* ASCII range character */
+ else if (!(**ppuni&0x40))
+ return (-1); /* not a valid UTF-8 start */
+ if ((*p & 0xe0) == 0xc0) {
+ utf_count = 1;
+ } else if ((*p & 0xf0) == 0xe0) {
+ utf_count = 2;
+ } else if ((*p & 0xf8) == 0xf0) {
+ utf_count = 3;
+ } else if ((*p & 0xfc) == 0xf8) {
+ utf_count = 4;
+ } else if ((*p & 0xfe) == 0xfc) {
+ utf_count = 5;
+ } else { /* garbage */
+ return (-1);
+ }
+ for (p = *ppuni, i = 0; i < utf_count ; i++) {
+ if ((*(++p) & 0xc0) != 0x80)
+ return (-1);
+ }
+ p = *ppuni;
+ switch (utf_count) {
+ case 1:
+ uc_out = (((*p&0x1f) << 6) | (*(p+1)&0x3f));
+ break;
+ case 2:
+ uc_out = (((((*p&0x0f) << 6) | (*(p+1)&0x3f)) << 6) | (*(p+2)&0x3f));
+ break;
+ case 3:
+ uc_out = (((((((*p&0x07) << 6) | (*(p+1)&0x3f)) << 6) | (*(p+2)&0x3f)) << 6)
+ | (*(p+3)&0x3f));
+ break;
+ case 4:
+ uc_out = (((((((((*p&0x03) << 6) | (*(p+1)&0x3f)) << 6) | (*(p+2)&0x3f)) << 6)
+ | (*(p+3)&0x3f)) << 6) | (*(p+4)&0x3f));
+ break;
+ case 5:
+ uc_out = (((((((((((*p&0x01) << 6) | (*(p+1)&0x3f)) << 6) | (*(p+2)&0x3f)) << 6)
+ | (*(p+3)&0x3f)) << 6) | (*(p+4)&0x3f)) << 6) | (*(p+5)&0x3f));
+ break;
+ }
+ *ppuni = p + utf_count;
+ return uc_out;
+}
+
+/*
+ * Given an UCS character code, will fill buffer passed in as q with
+ * the code's UTF-8 encoding.
+ * If terminate = YES, terminates string on success and returns pointer
+ * to beginning.
+ * If terminate = NO, does not terminate string, and returns pointer
+ * next char after the UTF-8 put into buffer.
+ * On failure, including invalid code or 7-bit code, returns NULL.
+ */
+PRIVATE char * UCPutUtf8ToBuffer ARGS3(char *, q, UCode_t, code, BOOL, terminate)
+{
+ char *q_in = q;
+ if (!q)
+ return NULL;
+ if (code > 127 && code < 0x7fffffffL) {
+ if (code < 0x800L) {
+ *q++ = (char)(0xc0 | (code>>6));
+ *q++ = (char)(0x80 | (0x3f & (code)));
+ } else if (code < 0x10000L) {
+ *q++ = (char)(0xe0 | (code>>12));
+ *q++ = (char)(0x80 | (0x3f & (code>>6)));
+ *q++ = (char)(0x80 | (0x3f & (code)));
+ } else if (code < 0x200000L) {
+ *q++ = (char)(0xf0 | (code>>18));
+ *q++ = (char)(0x80 | (0x3f & (code>>12)));
+ *q++ = (char)(0x80 | (0x3f & (code>>6)));
+ *q++ = (char)(0x80 | (0x3f & (code)));
+ } else if (code < 0x4000000L) {
+ *q++ = (char)(0xf8 | (code>>24));
+ *q++ = (char)(0x80 | (0x3f & (code>>18)));
+ *q++ = (char)(0x80 | (0x3f & (code>>12)));
+ *q++ = (char)(0x80 | (0x3f & (code>>6)));
+ *q++ = (char)(0x80 | (0x3f & (code)));
+ } else {
+ *q++ = (char)(0xfc | (code>>30));
+ *q++ = (char)(0x80 | (0x3f & (code>>24)));
+ *q++ = (char)(0x80 | (0x3f & (code>>18)));
+ *q++ = (char)(0x80 | (0x3f & (code>>12)));
+ *q++ = (char)(0x80 | (0x3f & (code>>6)));
+ *q++ = (char)(0x80 | (0x3f & (code)));
+ }
+ } else {
+ return NULL;
+ }
+ if (terminate) {
+ *q = '\0';
+ return q_in;
+ } else {
+ return q;
+ }
+}
+
+ /* as in HTParse.c, saves some calls - kw */
+PRIVATE char *hex = "0123456789ABCDEF";
+
+/*
+ * Any raw 8-bit or multibyte characters already have been
+ * handled in relation to the display character set
+ * in SGML_character(), including named and numeric entities.
+ *
+** This function used for translations HTML special fields inside tags
+** (ALT=, VALUE=, etc.) from charset `cs_from' to charset `cs_to'.
+** It also unescapes non-ASCII characters from URL (#fragments !)
+** if st_URL is active.
+**
+** If `do_ent' is YES, it converts named entities
+** and numeric character references (NCRs) to their `cs_to' replacements.
+**
+** Named entities converted to unicodes. NCRs (unicodes) converted
+** by UCdomap.c chartrans functions.
+** ???NCRs with values in the ISO-8859-1 range 160-255 may be converted
+** to their HTML entity names (via old-style entities) and then translated
+** according to the LYCharSets.c array for `cs_out'???.
+**
+** Some characters (see descriptions in `put_special_unicodes' from SGML.c)
+** translated in relation with the state of boolean variables
+** `use_lynx_specials', `plain_space' and `hidden'. It is not clear yet:
+**
+** If plain_space is TRUE, nbsp (160) will be treated as an ASCII
+** space (32). If hidden is TRUE, entities will be translated
+** (if `do_ent' is YES) but escape sequences will be passed unaltered.
+** If `hidden' is FALSE, some characters are converted to Lynx special
+** codes (see `put_special_unicodes') or ASCII space if `plain_space'
+** applies). @@ is `use_lynx_specials' needed, does it have any effect? @@
+** If `use_lynx_specials' is YES, translate byte values 160 and 173
+** meaning U+00A0 and U+00AD given as or converted from raw char input
+** are converted to HT_NON_BREAK_SPACE and LY_SOFT_HYPHEN, respectively
+** (unless input and output charset are both iso-8859-1, for compatibility
+** with previous usage in HTML.c) even if `hidden' or `plain_space' is set.
+**
+** If `Back' is YES, the reverse is done instead i.e. Lynx special codes
+** in the input are translated back to character values.
+**
+** If `Back' is YES, an attempt is made to use UCReverseTransChar() for
+** back translation which may be more efficient. (?)
+**
+** If `stype' is st_URL, non-ASCII characters are URL-encoded instead.
+** The sequence of bytes being URL-encoded is the raw input character if
+** we couldn't translate it from `cs_in' (CJK etc.); otherwise it is the
+** UTF-8 representation if either `cs_to' requires this or if the
+** character's Unicode value is > 255, otherwise it should be the iso-8859-1
+** representation.
+** No general URL-encoding occurs for displayable ASCII characters and
+** spaces and some C0 controls valid in HTML (LF, TAB), it is expected
+** that other functions will take care of that as appropriate.
+**
+** Escape characters (0x1B, '\033') are
+** - URL-encoded if `stype' is st_URL, otherwise
+** - dropped if `stype' is st_other, otherwise (i.e. st_HTML)
+** - passed if `hidden' is TRUE or HTCJK is set, otherwise
+** - dropped.
+**
+** (If `stype' is st_URL or st_other most of the parameters really predefined:
+** cs_from=cs_to, use_lynx_specials=plain_space=NO, and hidden=YES)
+**
+**
+** Returns pointer to the char** passed in
+** if string translated or translation unnecessary,
+** NULL otherwise
+** (in which case something probably went wrong.)
+*/
+
+PRIVATE char ** LYUCFullyTranslateString_1 ARGS9(
+ char **, str,
+ int, cs_from,
+ int, cs_to,
+ BOOLEAN, do_ent,
+ BOOL, use_lynx_specials,
+ BOOLEAN, plain_space,
+ BOOLEAN, hidden,
+ BOOL, Back,
+ CharUtil_st, stype)
+{
+ char * p;
+ char *q, *qs;
+ HTChunk *chunk = NULL;
+ char * cp = 0;
+ char cpe = 0;
+ char *esc = NULL;
+ char replace_buf [64];
+ int uck;
+ int lowest_8;
+ UCode_t code = 0;
+ long int lcode;
+ BOOL output_utf8 = 0, repl_translated_C0 = 0;
+ size_t len;
+ CONST char * name = NULL;
+ BOOLEAN no_bytetrans;
+ UCTransParams T;
+ BOOL from_is_utf8 = FALSE;
+ char * puni;
+ enum _state
+ { S_text, S_esc, S_dollar, S_paren, S_nonascii_text, S_dollar_paren,
+ S_trans_byte, S_check_ent, S_ncr, S_check_uni, S_named, S_check_name,
+ S_recover,
+ S_got_oututf8, S_got_outstring, S_put_urlstring,
+ S_got_outchar, S_put_urlchar, S_next_char, S_done} state = S_text;
+ enum _parsing_what
+ { P_text, P_utf8, P_hex, P_decimal, P_named
+ } what = P_text;
+
+ /*
+ ** Make sure we have a non-empty string. - FM
+ */
+ if (!str || *str == NULL || **str == '\0')
+ return str;
+
+ /*
+ * FIXME: something's wrong with the limit checks here (clearing the
+ * buffer helps).
+ */
+ memset(replace_buf, 0, sizeof(replace_buf));
+
+ /*
+ ** Don't do byte translation
+ ** if original AND target character sets
+ ** are both iso-8859-1,
+ ** or if we are in CJK mode.
+ */
+ no_bytetrans = ((cs_to <= 0 && cs_from == cs_to) ||
+ HTCJK != NOCJK);
+
+ /* No need to translate or examine the string any further */
+ if (!no_bytetrans)
+ no_bytetrans = (!use_lynx_specials && !Back &&
+ UCNeedNotTranslate(cs_from, cs_to));
+
+ /*
+ ** Save malloc/calloc overhead in simple case - kw
+ */
+ if (do_ent && hidden && (stype != st_URL) && (strchr(*str, '&') == NULL))
+ do_ent = FALSE;
+
+ /* Can't do, caller should figure out what to do... */
+ if (!UCCanTranslateFromTo(cs_from, cs_to)) {
+ if (cs_to < 0)
+ return NULL;
+ if (!do_ent && no_bytetrans)
+ return NULL;
+ no_bytetrans = TRUE;
+ } else if (cs_to < 0) {
+ do_ent = FALSE;
+ }
+
+ if (!do_ent && no_bytetrans)
+ return str;
+ p = *str;
+
+ if (!no_bytetrans) {
+ UCTransParams_clear(&T);
+ UCSetTransParams(&T, cs_from, &LYCharSet_UC[cs_from],
+ cs_to, &LYCharSet_UC[cs_to]);
+ from_is_utf8 = (LYCharSet_UC[cs_from].enc == UCT_ENC_UTF8);
+ output_utf8 = T.output_utf8;
+ repl_translated_C0 = T.repl_translated_C0;
+ puni = p;
+ } else if (do_ent) {
+ output_utf8 = (LYCharSet_UC[cs_to].enc == UCT_ENC_UTF8 ||
+ HText_hasUTF8OutputSet(HTMainText));
+ repl_translated_C0 = (LYCharSet_UC[cs_to].enc == UCT_ENC_8BIT_C0);
+ }
+
+ lowest_8 = LYlowest_eightbit[cs_to];
+
+ /*
+ ** Create a buffer string seven times the length of the original,
+ ** so we have plenty of room for expansions. - FM
+ */
+ len = strlen(p) + 16;
+ q = p;
+
+ qs = q;
+
+/* Create the HTChunk only if we need it */
+#define CHUNK (chunk ? chunk : (chunk = HTChunkCreate2(128, len+1)))
+
+#define REPLACE_STRING(s) \
+ if (q != qs) HTChunkPutb(CHUNK, qs, q-qs); \
+ HTChunkPuts(CHUNK, s); \
+ qs = q = *str
+
+#define REPLACE_CHAR(c) if (q > p) { \
+ HTChunkPutb(CHUNK, qs, q-qs); \
+ qs = q = *str; \
+ *q++ = c; \
+ } else \
+ *q++ = c
+
+ /*
+ * Loop through string, making conversions as needed.
+ *
+ * The while() checks for a non-'\0' char only for the normal
+ * text states since other states may temporarily modify p or *p
+ * (which should be restored before S_done!) - kw
+ */
+
+ while (*p || (state != S_text && state != S_nonascii_text)) {
+ switch(state) {
+ case S_text:
+ code = (unsigned char)(*p);
+ if (*p == '\033') {
+ if ((HTCJK != NOCJK && !hidden) || stype != st_HTML) {
+ state = S_esc;
+ if (stype == st_URL) {
+ REPLACE_STRING("%1B");
+ p++;
+ continue;
+ } else if (stype != st_HTML) {
+ p++;
+ continue;
+ } else {
+ *q++ = *p++;
+ continue;
+ }
+ } else if (!hidden) {
+ /*
+ ** CJK handling not on, and not a hidden INPUT,
+ ** so block escape. - FM
+ */
+ state = S_next_char;
+ } else {
+ state = S_trans_byte;
+ }
+ } else {
+ state = (do_ent ? S_check_ent : S_trans_byte);
+ }
+ break;
+
+ case S_esc:
+ if (*p == '$') {
+ state = S_dollar;
+ *q++ = *p++;
+ continue;
+ } else if (*p == '(') {
+ state = S_paren;
+ *q++ = *p++;
+ continue;
+ } else {
+ state = S_text;
+ }
+
+ case S_dollar:
+ if (*p == '@' || *p == 'B' || *p == 'A') {
+ state = S_nonascii_text;
+ *q++ = *p++;
+ continue;
+ } else if (*p == '(') {
+ state = S_dollar_paren;
+ *q++ = *p++;
+ continue;
+ } else {
+ state = S_text;
+ }
+ break;
+
+ case S_dollar_paren:
+ if (*p == 'C') {
+ state = S_nonascii_text;
+ *q++ = *p++;
+ continue;
+ } else {
+ state = S_text;
+ }
+ break;
+
+ case S_paren:
+ if (*p == 'B' || *p == 'J' || *p == 'T') {
+ state = S_text;
+ *q++ = *p++;
+ continue;
+ } else if (*p == 'I') {
+ state = S_nonascii_text;
+ *q++ = *p++;
+ continue;
+ } else {
+ state = S_text;
+ }
+ break;
+
+ case S_nonascii_text:
+ if (*p == '\033') {
+ if ((HTCJK != NOCJK && !hidden) || stype != st_HTML) {
+ state = S_esc;
+ if (stype == st_URL) {
+ REPLACE_STRING("%1B");
+ p++;
+ continue;
+ } else if (stype != st_HTML) {
+ p++;
+ continue;
+ }
+ }
+ }
+ *q++ = *p++;
+ continue;
+
+ case S_trans_byte:
+ /* character translation goes here */
+ /*
+ ** Don't do anything if we have no string,
+ ** or if original AND target character sets
+ ** are both iso-8859-1,
+ ** or if we are in CJK mode.
+ */
+ if (*p == '\0' || no_bytetrans) {
+ state = S_got_outchar;
+ break;
+ }
+
+ if (Back) {
+ int rev_c;
+ if ((*p) == HT_NON_BREAK_SPACE ||
+ (*p) == HT_EM_SPACE) {
+ if (plain_space) {
+ code = *p = ' ';
+ state = S_got_outchar;
+ break;
+ } else {
+ *p = 160;
+ code = 160;
+ if (LYCharSet_UC[cs_to].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[cs_to].like8859 & UCT_R_8859SPECL)) {
+ state = S_got_outchar;
+ break;
+ }
+ }
+ } else if ((*p) == LY_SOFT_HYPHEN) {
+ *p = 173;
+ code = 173;
+ if (LYCharSet_UC[cs_to].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[cs_to].like8859 & UCT_R_8859SPECL)) {
+ state = S_got_outchar;
+ break;
+ }
+ } else if (code < 127 || T.transp) {
+ state = S_got_outchar;
+ break;
+ }
+ rev_c = UCReverseTransChar(*p, cs_to, cs_from);
+ if (rev_c > 127) {
+ *p = rev_c;
+ code = rev_c;
+ state = S_got_outchar;
+ break;
+ }
+ } else if (code < 127) {
+ state = S_got_outchar;
+ break;
+ }
+
+ if (from_is_utf8) {
+ if (((*p)&0xc0)==0xc0) {
+ puni = p;
+ code = UCGetUniFromUtf8String(&puni);
+ if (code <= 0) {
+ code = (unsigned char)(*p);
+ } else {
+ what = P_utf8;
+ }
+ }
+ } else if (use_lynx_specials && !Back &&
+ (code == 160 || code == 173) &&
+ (LYCharSet_UC[cs_from].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[cs_from].like8859 & UCT_R_8859SPECL))) {
+ if (code == 160)
+ code = *p = HT_NON_BREAK_SPACE;
+ else if (code == 173)
+ code = *p = LY_SOFT_HYPHEN;
+ state = S_got_outchar;
+ break;
+ } else if (T.trans_to_uni) {
+ code = UCTransToUni(*p, cs_from);
+ if (code <= 0) {
+ /* What else can we do? */
+ code = (unsigned char)(*p);
+ }
+#ifdef NOTUSED_FOTEMODS
+ } else if (T.strip_raw_char_in &&
+ (unsigned char)(*p) >= 0xc0 &&
+ (unsigned char)(*p) < 255) {
+ code = ((*p & 0x7f));
+ state = S_got_outchar;
+ break;
+#endif /* NOTUSED_FOTEMODS */
+ } else if (!T.trans_from_uni) {
+ state = S_got_outchar;
+ break;
+ }
+ /*
+ ** Substitute Lynx special character for
+ ** 160 (nbsp) if use_lynx_specials is set.
+ */
+ if (use_lynx_specials && !Back &&
+ (code == 160 || code == 173)) {
+ code = ((code==160 ? HT_NON_BREAK_SPACE : LY_SOFT_HYPHEN));
+ state = S_got_outchar;
+ break;
+ }
+
+ state = S_check_uni;
+ break;
+
+ case S_check_ent:
+ if (*p == '&') {
+ char * pp = p + 1;
+ len = strlen(pp);
+ /*
+ ** Check for a numeric entity. - FM
+ */
+ if (*pp == '#' && len > 2 &&
+ (*(pp+1) == 'x' || *(pp+1) == 'X') &&
+ (unsigned char)*(pp+2) < 127 &&
+ isxdigit((unsigned char)*(pp+2))) {
+ what = P_hex;
+ state = S_ncr;
+ } else if (*pp == '#' && len > 2 &&
+ (unsigned char)*(pp+1) < 127 &&
+ isdigit((unsigned char)*(pp+1))) {
+ what = P_decimal;
+ state = S_ncr;
+ } else if ((unsigned char)*pp < 127 &&
+ isalpha((unsigned char)*pp)) {
+ what = P_named;
+ state = S_named;
+ } else {
+ state = S_trans_byte;
+ }
+ } else {
+ state = S_trans_byte;
+ }
+ break;
+
+ case S_ncr:
+ if (what == P_hex) {
+ p += 3;
+ } else { /* P_decimal */
+ p += 2;
+ }
+ cp = p;
+ while (*p && (unsigned char)*p < 127 &&
+ (what == P_hex ? isxdigit((unsigned char)*p) :
+ isdigit((unsigned char)*p))) {
+ p++;
+ }
+ /*
+ ** Save the terminator and isolate the digit(s). - FM
+ */
+ cpe = *p;
+ if (*p)
+ *p++ = '\0';
+ /*
+ ** Show the numeric entity if the value:
+ ** (1) Is greater than 255 and unhandled Unicode.
+ ** (2) Is less than 32, and not valid and we don't
+ ** have HTCJK set.
+ ** (3) Is 127 and we don't have HTPassHighCtrlRaw
+ ** or HTCJK set.
+ ** (4) Is 128 - 159 and we don't have HTPassHighCtrlNum set.
+ */
+ if ((((what == P_hex) ? sscanf(cp, "%lx", &lcode) :
+ sscanf(cp, "%ld", &lcode)) != 1) ||
+ lcode > 0x7fffffffL || lcode < 0) {
+ state = S_recover;
+ break;
+ } else {
+ code = lcode;
+ state = S_check_uni;
+ }
+ break;
+
+ case S_check_uni:
+ /*
+ ** Show the numeric entity if the value:
+ ** (2) Is less than 32, and not valid and we don't
+ ** have HTCJK set.
+ ** (3) Is 127 and we don't have HTPassHighCtrlRaw
+ ** or HTCJK set.
+ ** (4) Is 128 - 159 and we don't have HTPassHighCtrlNum set.
+ */
+ if ((code < 32 &&
+ code != 9 && code != 10 && code != 13 &&
+ HTCJK == NOCJK) ||
+ (code == 127 &&
+ !(HTPassHighCtrlRaw || HTCJK != NOCJK)) ||
+ (code > 127 && code < 160 &&
+ !HTPassHighCtrlNum)) {
+ state = S_recover;
+ break;
+ }
+ /*
+ ** Convert the value as an unsigned char,
+ ** hex escaped if isURL is set and it's
+ ** 8-bit, and then recycle the terminator
+ ** if it is not a semicolon. - FM
+ */
+ if (code > 159 && stype == st_URL) {
+ state = S_got_oututf8;
+ break;
+ }
+ /*
+ ** For 160 (nbsp), use that value if it's
+ ** a hidden INPUT, otherwise use an ASCII
+ ** space (32) if plain_space is TRUE,
+ ** otherwise use the Lynx special character. - FM
+ */
+ if (code == 160) {
+ if (hidden) {
+ ;
+ } else if (plain_space) {
+ code = ' ';
+ } else {
+ code = HT_NON_BREAK_SPACE;
+ }
+ state = S_got_outchar;
+ break;
+ }
+ /*
+ ** For 173 (shy), use that value if it's
+ ** a hidden INPUT, otherwise ignore it
+ ** if plain_space is TRUE, otherwise use
+ ** the Lynx special character. - FM
+ */
+ if (code == 173) {
+ if (plain_space) {
+ replace_buf[0] = '\0';
+ state = S_got_outstring;
+ break;
+ } else if (Back &&
+ !(LYCharSet_UC[cs_to].enc == UCT_ENC_8859 ||
+ (LYCharSet_UC[cs_to].like8859 &
+ UCT_R_8859SPECL))) {
+ ; /* nothing, may be translated later */
+ } else if (hidden || Back) {
+ state = S_got_outchar;
+ break;
+ } else {
+ code = LY_SOFT_HYPHEN;
+ state = S_got_outchar;
+ break;
+ }
+ }
+ /*
+ ** Seek a translation from the chartrans tables.
+ */
+ if ((uck = UCTransUniChar(code,
+ cs_to)) >= 32 &&
+ uck < 256 &&
+ (uck < 127 || uck >= lowest_8)) {
+ code = uck;
+ state = S_got_outchar;
+ break;
+ } else if ((uck == -4 ||
+ (repl_translated_C0 &&
+ uck > 0 && uck < 32)) &&
+ /*
+ ** Not found; look for replacement string.
+ */
+ (uck = UCTransUniCharStr(replace_buf,
+ 60, code,
+ cs_to,
+ 0) >= 0)) {
+ state = S_got_outstring;
+ break;
+ }
+ if (output_utf8 &&
+ code > 127 && code < 0x7fffffffL) {
+ state = S_got_oututf8;
+ break;
+ }
+ /*
+ ** For 8194 (ensp), 8195 (emsp), or 8201 (thinsp),
+ ** use the character reference if it's a hidden INPUT,
+ ** otherwise use an ASCII space (32) if plain_space is
+ ** TRUE, otherwise use the Lynx special character. - FM
+ */
+ if (code == 8194 || code == 8195 || code == 8201) {
+ if (hidden) {
+ state = S_recover;
+ } else if (plain_space) {
+ code = ' ';
+ state = S_got_outchar;
+ } else {
+ code = HT_EM_SPACE;
+ state = S_got_outchar;
+ }
+ break;
+ /*
+ ** Ignore 8204 (zwnj), 8205 (zwj)
+ ** 8206 (lrm), and 8207 (rlm),
+ ** for now, if we got this far without
+ ** finding a representation for them.
+ */
+ } else if (code == 8204 || code == 8205 ||
+ code == 8206 || code == 8207) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYUCFullyTranslateString: Ignoring '%ld'.\n", code);
+ }
+ replace_buf[0] = '\0';
+ state = S_got_outstring;
+ break;
+ /*
+ ** Show the numeric entity if the value:
+ ** (1) Is greater than 255 and unhandled Unicode.
+ */
+ } else if (code > 255) {
+ /*
+ ** Illegal or not yet handled value.
+ ** Return "&#" verbatim and continue
+ ** from there. - FM
+ */
+ state = S_recover;
+ break;
+ /*
+ ** If it's ASCII, or is 8-bit but HTPassEightBitNum
+ ** is set or the character set is "ISO Latin 1",
+ ** use it's value. - FM
+ */
+ } else if (code < 161 ||
+ (code < 256 &&
+ (HTPassEightBitNum ||
+ !strncmp(LYchar_set_names[cs_to],
+ "ISO Latin 1", 11)))) {
+ /*
+ ** No conversion needed.
+ */
+ state = S_got_outchar;
+ break;
+ /*
+ ** If we get to here, convert and handle
+ ** the character as a named entity. - FM
+ */
+ } else {
+ name = HTMLGetEntityName(code - 160);
+ state = S_check_name;
+ break;
+ }
+
+ case S_recover:
+ if (what == P_decimal || what == P_hex) {
+ /*
+ ** Illegal or not yet handled value.
+ ** Return "&#" verbatim and continue
+ ** from there. - FM
+ */
+ *q++ = '&';
+ *q++ = '#';
+ if (what == P_hex)
+ *q++ = 'x';
+ if (cpe != '\0')
+ *(p-1) = cpe;
+ p = cp;
+ state = S_done;
+ } else if (what == P_named) {
+ *cp = cpe;
+ *q++ = '&';
+ state = S_done;
+#ifdef NOTUSED_FOTEMODS
+ } else if (T.strip_raw_char_in &&
+ (unsigned char)(*p) >= 0xc0 &&
+ (unsigned char)(*p) < 255) {
+ code = (((*p) & 0x7f));
+ state = S_got_outchar;
+#endif /* NOTUSED_FOTEMODS */
+ } else if (!T.output_utf8 && stype == st_HTML && !hidden &&
+ !(HTPassEightBitRaw &&
+ (unsigned char)(*p) >= lowest_8)) {
+ sprintf(replace_buf, "U%.2lX", code);
+ state = S_got_outstring;
+ } else {
+ puni = p;
+ code = (unsigned char)(*p);
+ state = S_got_outchar;
+ }
+ break;
+
+ case S_named:
+ cp = ++p;
+ while (*cp && (unsigned char)*cp < 127 &&
+ isalnum((unsigned char)*cp))
+ cp++;
+ cpe = *cp;
+ *cp = '\0';
+/* ppuni = cp - 1; */
+ name = p;
+ state = S_check_name;
+ break;
+
+ case S_check_name:
+ /*
+ ** Seek the Unicode value for the named entity.
+ */
+ if ((code = HTMLGetEntityUCValue(name)) > 0) {
+ state = S_check_uni;
+ break;
+ }
+ /*
+ ** Didn't find the entity.
+ ** Return verbatim.
+ */
+ state = S_recover;
+ break;
+
+ /* * * O U T P U T S T A T E S * * */
+
+ case S_got_oututf8:
+ if (code > 255 ||
+ (code >= 128 && LYCharSet_UC[cs_to].enc == UCT_ENC_UTF8)) {
+ UCPutUtf8ToBuffer(replace_buf, code, YES);
+ state = S_got_outstring;
+ } else {
+ state = S_got_outchar;
+ }
+ break;
+ case S_got_outstring:
+ if (what == P_decimal || what == P_hex) {
+ if (cpe != ';' && cpe != '\0')
+ *(--p) = cpe;
+ p--;
+ } else if (what == P_named) {
+ *cp = cpe;
+ p = (*cp != ';') ? (cp - 1) : cp;
+ } else if (what == P_utf8) {
+ p = puni;
+ }
+ if (replace_buf[0] == '\0') {
+ state = S_next_char;
+ break;
+ }
+ if (stype == st_URL) {
+ code = replace_buf[0]; /* assume string OK if first char is */
+ if (code >= 127 ||
+ (code < 32 && (code != 9 && code != 10 && code != 0))) {
+ state = S_put_urlstring;
+ }
+ }
+ REPLACE_STRING(replace_buf);
+ state = S_next_char;
+ break;
+ case S_put_urlstring:
+ esc = HTEscape(replace_buf, URL_XALPHAS);
+ REPLACE_STRING(esc);
+ FREE(esc);
+ state = S_next_char;
+ break;
+ case S_got_outchar:
+ if (what == P_decimal || what == P_hex) {
+ if (cpe != ';' && cpe != '\0')
+ *(--p) = cpe;
+ p--;
+ } else if (what == P_named) {
+ *cp = cpe;
+ p = (*cp != ';') ? (cp - 1) : cp;
+ } else if (what == P_utf8) {
+ p = puni;
+ }
+ if (stype == st_URL &&
+ /* Not a full HTEscape, only for 8bit and ctrl chars */
+ (code >= 127 ||
+ (code < 32 && (code != 9 && code != 10)))) {
+ state = S_put_urlchar;
+ break;
+ } else if (!hidden && code == 10 && *p == 10
+ && q != qs && *(q-1) == 13) {
+ /*
+ ** If this is not a hidden string, and the current char is
+ ** the LF ('\n') of a CRLF pair, drop the CR ('\r'). - KW
+ */
+ *(q-1) = *p++;
+ state = S_done;
+ break;
+ }
+ *q++ = (char)code;
+ state = S_next_char;
+ break;
+ case S_put_urlchar:
+ *q++ = '%';
+ REPLACE_CHAR(hex[(code >> 4) & 15]);
+ REPLACE_CHAR(hex[(code & 15)]);
+ /* fall through */
+ case S_next_char:
+ p++; /* fall through */
+ case S_done:
+ state = S_text;
+ what = P_text;
+ /* for next round */
+ }
+ }
+
+ *q = '\0';
+ if (chunk) {
+ HTChunkPutb(CHUNK, qs, q-qs + 1); /* also terminates */
+ if (stype == st_URL) {
+ LYTrimHead(chunk->data);
+ LYTrimTail(chunk->data);
+ }
+ StrAllocCopy(*str, chunk->data);
+ HTChunkFree(chunk);
+ } else {
+ if (stype == st_URL) {
+ LYTrimHead(qs);
+ LYTrimTail(qs);
+ }
+ }
+ return str;
+}
+
+#undef REPLACE_CHAR
+#undef REPLACE_STRING
+
+PUBLIC BOOL LYUCFullyTranslateString ARGS7(
+ char **, str,
+ int, cs_from,
+ int, cs_to,
+ BOOL, use_lynx_specials,
+ BOOLEAN, plain_space,
+ BOOLEAN, hidden,
+ CharUtil_st, stype)
+{
+ BOOL ret = YES;
+ /* May reallocate *str even if cs_to == 0 */
+ if (!LYUCFullyTranslateString_1(str, cs_from, cs_to, TRUE,
+ use_lynx_specials, plain_space, hidden,
+ NO, stype)) {
+ ret = NO;
+ }
+ return ret;
+}
+
+PUBLIC BOOL LYUCTranslateBackFormData ARGS4(
+ char **, str,
+ int, cs_from,
+ int, cs_to,
+ BOOLEAN, plain_space)
+{
+ char ** ret;
+ /* May reallocate *str */
+ ret = (LYUCFullyTranslateString_1(str, cs_from, cs_to, FALSE,
+ NO, plain_space, YES,
+ YES, st_HTML));
+ return (ret != NULL);
+}
+
+/*
+** This function processes META tags in HTML streams. - FM
+*/
+PUBLIC void LYHandleMETA ARGS4(
+ HTStructured *, me,
+ CONST BOOL*, present,
+ CONST char **, value,
+ char **, include)
+{
+ char *http_equiv = NULL, *name = NULL, *content = NULL;
+ char *href = NULL, *id_string = NULL, *temp = NULL;
+ char *cp, *cp0, *cp1 = NULL;
+ int url_type = 0, i;
+
+ if (!me || !present)
+ return;
+
+ /*
+ * Load the attributes for possible use by Lynx. - FM
+ */
+ if (present[HTML_META_HTTP_EQUIV] &&
+ value[HTML_META_HTTP_EQUIV] && *value[HTML_META_HTTP_EQUIV]) {
+ StrAllocCopy(http_equiv, value[HTML_META_HTTP_EQUIV]);
+ convert_to_spaces(http_equiv, TRUE);
+ LYUCFullyTranslateString(&http_equiv, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_other);
+ LYTrimHead(http_equiv);
+ LYTrimTail(http_equiv);
+ if (*http_equiv == '\0') {
+ FREE(http_equiv);
+ }
+ }
+ if (present[HTML_META_NAME] &&
+ value[HTML_META_NAME] && *value[HTML_META_NAME]) {
+ StrAllocCopy(name, value[HTML_META_NAME]);
+ convert_to_spaces(name, TRUE);
+ LYUCFullyTranslateString(&name, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_other);
+ LYTrimHead(name);
+ LYTrimTail(name);
+ if (*name == '\0') {
+ FREE(name);
+ }
+ }
+ if (present[HTML_META_CONTENT] &&
+ value[HTML_META_CONTENT] && *value[HTML_META_CONTENT]) {
+ /*
+ * Technically, we should be creating a comma-separated
+ * list, but META tags come one at a time, and we'll
+ * handle (or ignore) them as each is received. Also,
+ * at this point, we only trim leading and trailing
+ * blanks from the CONTENT value, without translating
+ * any named entities or numeric character references,
+ * because how we should do that depends on what type
+ * of information it contains, and whether or not any
+ * of it might be sent to the screen. - FM
+ */
+ StrAllocCopy(content, value[HTML_META_CONTENT]);
+ convert_to_spaces(content, FALSE);
+ LYTrimHead(content);
+ LYTrimTail(content);
+ if (*content == '\0') {
+ FREE(content);
+ }
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "LYHandleMETA: HTTP-EQUIV=\"%s\" NAME=\"%s\" CONTENT=\"%s\"\n",
+ (http_equiv ? http_equiv : "NULL"),
+ (name ? name : "NULL"),
+ (content ? content : "NULL"));
+ }
+
+ /*
+ * Make sure we have META name/value pairs to handle. - FM
+ */
+ if (!(http_equiv || name) || !content)
+ goto free_META_copies;
+
+ /*
+ * Check for a no-cache Pragma
+ * or Cache-Control directive. - FM
+ */
+ if (!strcasecomp((http_equiv ? http_equiv : ""), "Pragma") ||
+ !strcasecomp((http_equiv ? http_equiv : ""), "Cache-Control")) {
+ LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_other);
+ LYTrimHead(content);
+ LYTrimTail(content);
+ if (!strcasecomp(content, "no-cache")) {
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ }
+
+ /*
+ * If we didn't get a Cache-Control MIME header,
+ * and the META has one, convert to lowercase,
+ * store it in the anchor element, and if we
+ * haven't yet set no_cache, check whether we
+ * should. - FM
+ */
+ if ((!me->node_anchor->cache_control) &&
+ !strcasecomp((http_equiv ? http_equiv : ""), "Cache-Control")) {
+ for (i = 0; content[i]; i++)
+ content[i] = TOLOWER(content[i]);
+ StrAllocCopy(me->node_anchor->cache_control, content);
+ if (me->node_anchor->no_cache == FALSE) {
+ cp0 = content;
+ while ((cp = strstr(cp0, "no-cache")) != NULL) {
+ cp += 8;
+ while (*cp != '\0' && WHITE(*cp))
+ cp++;
+ if (*cp == '\0' || *cp == ';') {
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ break;
+ }
+ cp0 = cp;
+ }
+ if (me->node_anchor->no_cache == TRUE)
+ goto free_META_copies;
+ cp0 = content;
+ while ((cp = strstr(cp0, "max-age")) != NULL) {
+ cp += 7;
+ while (*cp != '\0' && WHITE(*cp))
+ cp++;
+ if (*cp == '=') {
+ cp++;
+ while (*cp != '\0' && WHITE(*cp))
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ cp0 = cp;
+ while (isdigit((unsigned char)*cp))
+ cp++;
+ if (*cp0 == '0' && cp == (cp0 + 1)) {
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ break;
+ }
+ }
+ }
+ cp0 = cp;
+ }
+ }
+ }
+
+ /*
+ * Check for an Expires directive. - FM
+ */
+ } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Expires")) {
+ /*
+ * If we didn't get an Expires MIME header,
+ * store it in the anchor element, and if we
+ * haven't yet set no_cache, check whether we
+ * should. Note that we don't accept a Date
+ * header via META tags, because it's likely
+ * to be untrustworthy, but do check for a
+ * Date header from a server when making the
+ * comparison. - FM
+ */
+ LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_other);
+ LYTrimHead(content);
+ LYTrimTail(content);
+ StrAllocCopy(me->node_anchor->expires, content);
+ if (me->node_anchor->no_cache == FALSE) {
+ if (!strcmp(content, "0")) {
+ /*
+ * The value is zero, which we treat as
+ * an absolute no-cache directive. - FM
+ */
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ } else if (me->node_anchor->date != NULL) {
+ /*
+ * We have a Date header, so check if
+ * the value is less than or equal to
+ * that. - FM
+ */
+ if (LYmktime(content, TRUE) <=
+ LYmktime(me->node_anchor->date, TRUE)) {
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ }
+ } else if (LYmktime(content, FALSE) <= 0) {
+ /*
+ * We don't have a Date header, and
+ * the value is in past for us. - FM
+ */
+ me->node_anchor->no_cache = TRUE;
+ HText_setNoCache(me->text);
+ }
+ }
+
+ /*
+ * Check for a text/html Content-Type with a
+ * charset directive, if we didn't already set
+ * the charset via a server's header. - AAC & FM
+ */
+ } else if (!(me->node_anchor->charset && *me->node_anchor->charset) &&
+ !strcasecomp((http_equiv ? http_equiv : ""), "Content-Type")) {
+ LYUCcharset * p_in = NULL;
+ LYUCFullyTranslateString(&content, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_other);
+ LYTrimHead(content);
+ LYTrimTail(content);
+ /*
+ * Force the Content-type value to all lower case. - FM
+ */
+ for (cp = content; *cp; cp++)
+ *cp = TOLOWER(*cp);
+
+ if ((cp = strstr(content, "text/html;")) != NULL &&
+ (cp1 = strstr(content, "charset")) != NULL &&
+ cp1 > cp) {
+ BOOL chartrans_ok = NO;
+ char *cp3 = NULL, *cp4;
+ int chndl;
+
+ cp1 += 7;
+ while (*cp1 == ' ' || *cp1 == '=' || *cp1 == '"')
+ cp1++;
+
+ StrAllocCopy(cp3, cp1); /* copy to mutilate more */
+ for (cp4 = cp3; (*cp4 != '\0' && *cp4 != '"' &&
+ *cp4 != ';' && *cp4 != ':' &&
+ !WHITE(*cp4)); cp4++) {
+ ; /* do nothing */
+ }
+ *cp4 = '\0';
+ cp4 = cp3;
+ chndl = UCGetLYhndl_byMIME(cp3);
+ if (UCCanTranslateFromTo(chndl, current_char_set)) {
+ chartrans_ok = YES;
+ StrAllocCopy(me->node_anchor->charset, cp4);
+ HTAnchor_setUCInfoStage(me->node_anchor, chndl,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_STRUCTURED);
+ } else if (chndl < 0) {
+ /*
+ * Got something but we don't recognize it.
+ */
+ chndl = UCLYhndl_for_unrec;
+ if (UCCanTranslateFromTo(chndl, current_char_set)) {
+ chartrans_ok = YES;
+ HTAnchor_setUCInfoStage(me->node_anchor, chndl,
+ UCT_STAGE_PARSER,
+ UCT_SETBY_STRUCTURED);
+ }
+ }
+ if (chartrans_ok) {
+ LYUCcharset * p_out =
+ HTAnchor_setUCInfoStage(me->node_anchor,
+ current_char_set,
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ p_in = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_PARSER);
+ if (!p_out) {
+ /*
+ * Try again.
+ */
+ p_out = HTAnchor_getUCInfoStage(me->node_anchor,
+ UCT_STAGE_HTEXT);
+ }
+ if (!strcmp(p_in->MIMEname, "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(me->node_anchor,
+ HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_HTEXT),
+ UCT_STAGE_PARSER,
+ UCT_SETBY_DEFAULT);
+ }
+ if (!strcmp(p_out->MIMEname, "x-transparent")) {
+ HTPassEightBitRaw = TRUE;
+ HTAnchor_setUCInfoStage(me->node_anchor,
+ HTAnchor_getUCLYhndl(me->node_anchor,
+ UCT_STAGE_PARSER),
+ UCT_STAGE_HTEXT,
+ UCT_SETBY_DEFAULT);
+ }
+ if (p_in->enc != UCT_ENC_CJK) {
+ HTCJK = NOCJK;
+ if (!(p_in->codepoints &
+ UCT_CP_SUBSETOF_LAT1) &&
+ chndl == current_char_set) {
+ HTPassEightBitRaw = TRUE;
+ }
+ } else if (p_out->enc == UCT_ENC_CJK) {
+ if (LYRawMode) {
+ if ((!strcmp(p_in->MIMEname, "euc-jp") ||
+ !strcmp(p_in->MIMEname, "shift_jis")) &&
+ (!strcmp(p_out->MIMEname, "euc-jp") ||
+ !strcmp(p_out->MIMEname, "shift_jis"))) {
+ HTCJK = JAPANESE;
+ } else if (!strcmp(p_in->MIMEname, "euc-cn") &&
+ !strcmp(p_out->MIMEname, "euc-cn")) {
+ HTCJK = CHINESE;
+ } else if (!strcmp(p_in->MIMEname, "big-5") &&
+ !strcmp(p_out->MIMEname, "big-5")) {
+ HTCJK = TAIPEI;
+ } else if (!strcmp(p_in->MIMEname, "euc-kr") &&
+ !strcmp(p_out->MIMEname, "euc-kr")) {
+ HTCJK = KOREAN;
+ } else {
+ HTCJK = NOCJK;
+ }
+ } else {
+ HTCJK = NOCJK;
+ }
+ }
+ LYGetChartransInfo(me);
+ /*
+ * Fall through to old behavior.
+ */
+ } else if (!strncmp(cp1, "us-ascii", 8) ||
+ !strncmp(cp1, "iso-8859-1", 10)) {
+ StrAllocCopy(me->node_anchor->charset, "iso-8859-1");
+ HTCJK = NOCJK;
+
+ /*
+ * Hope it's a match, for now. - FM
+ */
+ cp1 = &cp4[10];
+ while (*cp1 &&
+ isdigit((unsigned char)(*cp1)))
+ cp1++;
+ *cp1 = '\0';
+ StrAllocCopy(me->node_anchor->charset, cp4);
+ HTPassEightBitRaw = TRUE;
+ HTAlert(me->node_anchor->charset);
+
+ } else if (!strncmp(cp1, "euc-jp", 6) && HTCJK == JAPANESE) {
+ StrAllocCopy(me->node_anchor->charset, "euc-jp");
+
+ } else if (!strncmp(cp1, "shift_jis", 9) && HTCJK == JAPANESE) {
+ StrAllocCopy(me->node_anchor->charset, "shift_jis");
+
+ } else if (!strncmp(cp1, "iso-2022-jp", 11) &&
+ HTCJK == JAPANESE) {
+ StrAllocCopy(me->node_anchor->charset, "iso-2022-jp");
+
+ } else if (!strncmp(cp1, "iso-2022-jp-2", 13) &&
+ HTCJK == JAPANESE) {
+ StrAllocCopy(me->node_anchor->charset, "iso-2022-jp-2");
+
+ } else if (!strncmp(cp1, "euc-kr", 6) && HTCJK == KOREAN) {
+ StrAllocCopy(me->node_anchor->charset, "euc-kr");
+
+ } else if (!strncmp(cp1, "iso-2022-kr", 11) && HTCJK == KOREAN) {
+ StrAllocCopy(me->node_anchor->charset, "iso-2022-kr");
+
+ } else if ((!strncmp(cp1, "big5", 4) ||
+ !strncmp(cp1, "cn-big5", 7)) &&
+ HTCJK == TAIPEI) {
+ StrAllocCopy(me->node_anchor->charset, "big5");
+
+ } else if (!strncmp(cp1, "euc-cn", 6) && HTCJK == CHINESE) {
+ StrAllocCopy(me->node_anchor->charset, "euc-cn");
+
+ } else if ((!strncmp(cp1, "gb2312", 6) ||
+ !strncmp(cp1, "cn-gb", 5)) &&
+ HTCJK == CHINESE) {
+ StrAllocCopy(me->node_anchor->charset, "gb2312");
+
+ } else if (!strncmp(cp1, "iso-2022-cn", 11) && HTCJK == CHINESE) {
+ StrAllocCopy(me->node_anchor->charset, "iso-2022-cn");
+ }
+ FREE(cp3);
+
+ if (TRACE && me->node_anchor->charset) {
+ fprintf(stderr,
+ "LYHandleMETA: New charset: %s\n",
+ me->node_anchor->charset);
+ }
+ }
+ /*
+ * Set the kcode element based on the charset. - FM
+ */
+ HText_setKcode(me->text, me->node_anchor->charset, p_in);
+
+ /*
+ * Check for a Refresh directive. - FM
+ */
+ } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Refresh")) {
+ char *Seconds = NULL;
+
+ /*
+ * Look for the Seconds field. - FM
+ */
+ cp = content;
+ while (*cp && isspace((unsigned char)*cp))
+ cp++;
+ if (*cp && isdigit(*cp)) {
+ cp1 = cp;
+ while (*cp1 && isdigit(*cp1))
+ cp1++;
+ if (*cp1)
+ *cp1++ = '\0';
+ StrAllocCopy(Seconds, cp);
+ }
+ if (Seconds) {
+ /*
+ * We have the seconds field.
+ * Now look for a URL field - FM
+ */
+ while (*cp1) {
+ if (!strncasecomp(cp1, "URL", 3)) {
+ cp = (cp1 + 3);
+ while (*cp && (*cp == '=' || isspace((unsigned char)*cp)))
+ cp++;
+ cp1 = cp;
+ while (*cp1 && !isspace((unsigned char)*cp1))
+ cp1++;
+ *cp1 = '\0';
+ if (*cp)
+ StrAllocCopy(href, cp);
+ break;
+ }
+ cp1++;
+ }
+ if (href) {
+ /*
+ * We found a URL field, so check it out. - FM
+ */
+ if (!(url_type = LYLegitimizeHREF(me, (char**)&href,
+ TRUE, FALSE))) {
+ /*
+ * The specs require a complete URL,
+ * but this is a Netscapism, so don't
+ * expect the author to know that. - FM
+ */
+ HTAlert(REFRESH_URL_NOT_ABSOLUTE);
+ /*
+ * Use the document's address
+ * as the base. - FM
+ */
+ if (*href != '\0') {
+ temp = HTParse(href,
+ me->node_anchor->address, PARSE_ALL);
+ StrAllocCopy(href, temp);
+ FREE(temp);
+ } else {
+ StrAllocCopy(href, me->node_anchor->address);
+ HText_setNoCache(me->text);
+ }
+ }
+ /*
+ * Check whether to fill in localhost. - FM
+ */
+ LYFillLocalFileURL((char **)&href,
+ (me->inBASE ?
+ me->base_href : me->node_anchor->address));
+ /*
+ * Set the no_cache flag if the Refresh URL
+ * is the same as the document's address. - FM
+ */
+ if (!strcmp(href, me->node_anchor->address)) {
+ HText_setNoCache(me->text);
+ }
+ } else {
+ /*
+ * We didn't find a URL field, so use
+ * the document's own address and set
+ * the no_cache flag. - FM
+ */
+ StrAllocCopy(href, me->node_anchor->address);
+ HText_setNoCache(me->text);
+ }
+ /*
+ * Check for an anchor in http or https URLs. - FM
+ */
+ if ((strncmp(href, "http", 4) == 0) &&
+ (cp = strrchr(href, '#')) != NULL) {
+ StrAllocCopy(id_string, cp);
+ *cp = '\0';
+ }
+ if (me->inA) {
+ /*
+ * Ugh! The META tag, which is a HEAD element,
+ * is in an Anchor, which is BODY element. All
+ * we can do is close the Anchor and cross our
+ * fingers. - FM
+ */
+ if (me->inBoldA == TRUE && me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ me->inBoldA = FALSE;
+ HText_endAnchor(me->text, me->CurrentANum);
+ me->inA = FALSE;
+ me->CurrentANum = 0;
+ }
+ me->CurrentA = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id_string, /* Tag */
+ href, /* Addresss */
+ (void *)0); /* Type */
+ if (id_string)
+ *cp = '#';
+ FREE(id_string);
+ LYEnsureSingleSpace(me);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ HTML_put_string(me, "REFRESH(");
+ HTML_put_string(me, Seconds);
+ HTML_put_string(me, " sec):");
+ FREE(Seconds);
+ if (me->inUnderline == FALSE)
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ HTML_put_character(me, ' ');
+ me->in_word = NO;
+ HText_beginAnchor(me->text, me->inUnderline, me->CurrentA);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ HTML_put_string(me, href);
+ FREE(href);
+ if (me->inBoldH == FALSE)
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ HText_endAnchor(me->text, 0);
+ LYEnsureSingleSpace(me);
+ }
+
+ /*
+ * Check for a suggested filename via a Content-Disposition with
+ * a filename=name.suffix in it, if we don't already have it
+ * via a server header. - FM
+ */
+ } else if (!(me->node_anchor->SugFname && *me->node_anchor->SugFname) &&
+ !strcasecomp((http_equiv ?
+ http_equiv : ""), "Content-Disposition")) {
+ cp = content;
+ while (*cp != '\0' && strncasecomp(cp, "filename", 8))
+ cp++;
+ if (*cp != '\0') {
+ cp += 8;
+ while ((*cp != '\0') && (WHITE(*cp) || *cp == '='))
+ cp++;
+ while (*cp != '\0' && WHITE(*cp))
+ cp++;
+ if (*cp != '\0') {
+ StrAllocCopy(me->node_anchor->SugFname, cp);
+ if (*me->node_anchor->SugFname == '\"') {
+ if ((cp = strchr((me->node_anchor->SugFname + 1),
+ '\"')) != NULL) {
+ *(cp + 1) = '\0';
+ HTMIME_TrimDoubleQuotes(me->node_anchor->SugFname);
+ } else {
+ FREE(me->node_anchor->SugFname);
+ }
+ if (me->node_anchor->SugFname != NULL &&
+ *me->node_anchor->SugFname == '\0') {
+ FREE(me->node_anchor->SugFname);
+ }
+ }
+ if ((cp = me->node_anchor->SugFname) != NULL) {
+ while (*cp != '\0' && !WHITE(*cp))
+ cp++;
+ *cp = '\0';
+ if (*me->node_anchor->SugFname == '\0')
+ FREE(me->node_anchor->SugFname);
+ }
+ }
+ }
+ /*
+ * Check for a Set-Cookie directive. - AK
+ */
+ } else if (!strcasecomp((http_equiv ? http_equiv : ""), "Set-Cookie")) {
+ /*
+ * This will need to be updated when Set-Cookie/Set-Cookie2
+ * handling is finalized. For now, we'll still assume
+ * "historical" cookies in META directives. - FM
+ */
+ url_type = is_url(me->inBASE ?
+ me->base_href : me->node_anchor->address);
+ if (url_type == HTTP_URL_TYPE || url_type == HTTPS_URL_TYPE) {
+ LYSetCookie(content,
+ NULL,
+ (me->inBASE ?
+ me->base_href : me->node_anchor->address));
+ }
+ }
+
+ /*
+ * Free the copies. - FM
+ */
+free_META_copies:
+ FREE(http_equiv);
+ FREE(name);
+ FREE(content);
+}
+
+/*
+** This function handles P elements in HTML streams.
+** If start is TRUE it handles a start tag, and if
+** FALSE, an end tag. We presently handle start
+** and end tags identically, but this can lead to
+** a different number of blank lines between the
+** current paragraph and subsequent text when a P
+** end tag is present or not in the markup. - FM
+*/
+PUBLIC void LYHandleP ARGS5(
+ HTStructured *, me,
+ CONST BOOL*, present,
+ CONST char **, value,
+ char **, include,
+ BOOL, start)
+{
+ if (TRUE) {
+ /*
+ * FIG content should be a true block, which like P inherits
+ * the current style. APPLET is like character elements or
+ * an ALT attribute, unless it content contains a block element.
+ * If we encounter a P in either's content, we set flags to treat
+ * the content as a block. - FM
+ */
+ if (start) {
+ if (me->inFIG)
+ me->inFIGwithP = TRUE;
+
+ if (me->inAPPLET)
+ me->inAPPLETwithP = TRUE;
+ }
+
+ UPDATE_STYLE;
+ if (me->List_Nesting_Level >= 0) {
+ /*
+ * We're in a list. Treat P as an instruction to
+ * create one blank line, if not already present,
+ * then fall through to handle attributes, with
+ * the "second line" margins. - FM
+ */
+ if (me->inP) {
+ if (me->inFIG || me->inAPPLET ||
+ me->inCAPTION || me->inCREDIT ||
+ me->sp->style->spaceAfter > 0 ||
+ (start && me->sp->style->spaceBefore > 0)) {
+ LYEnsureDoubleSpace(me);
+ } else {
+ LYEnsureSingleSpace(me);
+ }
+ }
+ } else if (me->sp[0].tag_number == HTML_ADDRESS) {
+ /*
+ * We're in an ADDRESS. Treat P as an instruction
+ * to start a newline, if needed, then fall through
+ * to handle attributes. - FM
+ */
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ }
+ } else {
+ if (start) {
+ if (!(me->inLABEL && !me->inP)) {
+ HText_appendParagraph(me->text);
+ }
+ } else if (me->sp->style->spaceAfter > 0) {
+ LYEnsureDoubleSpace(me);
+ } else {
+ LYEnsureSingleSpace(me);
+ }
+ me->inLABEL = FALSE;
+ }
+ me->in_word = NO;
+
+ if (LYoverride_default_alignment(me)) {
+ me->sp->style->alignment = styles[me->sp[0].tag_number]->alignment;
+ } else if (me->List_Nesting_Level >= 0 ||
+ ((me->Division_Level < 0) &&
+ (!strcmp(me->sp->style->name, "Normal") ||
+ !strcmp(me->sp->style->name, "Preformatted")))) {
+ me->sp->style->alignment = HT_LEFT;
+ } else {
+ me->sp->style->alignment = me->current_default_alignment;
+ }
+
+ if (start) {
+ if (present && present[HTML_P_ALIGN] && value[HTML_P_ALIGN]) {
+ if (!strcasecomp(value[HTML_P_ALIGN], "center") &&
+ !(me->List_Nesting_Level >= 0 && !me->inP))
+ me->sp->style->alignment = HT_CENTER;
+ else if (!strcasecomp(value[HTML_P_ALIGN], "right") &&
+ !(me->List_Nesting_Level >= 0 && !me->inP))
+ me->sp->style->alignment = HT_RIGHT;
+ else if (!strcasecomp(value[HTML_P_ALIGN], "left") ||
+ !strcasecomp(value[HTML_P_ALIGN], "justify"))
+ me->sp->style->alignment = HT_LEFT;
+ }
+
+ CHECK_ID(HTML_P_ID);
+ }
+
+ /*
+ * Mark that we are starting a new paragraph
+ * and don't have any of it's text yet. - FM
+ *
+ */
+ me->inP = FALSE;
+ }
+
+ return;
+}
+
+/*
+** This function handles SELECT elements in HTML streams.
+** If start is TRUE it handles a start tag, and if FALSE,
+** an end tag. - FM
+*/
+PUBLIC void LYHandleSELECT ARGS5(
+ HTStructured *, me,
+ CONST BOOL*, present,
+ CONST char **, value,
+ char **, include,
+ BOOL, start)
+{
+ int i;
+
+ if (start == TRUE) {
+ char *name = NULL;
+ BOOLEAN multiple = NO;
+ char *size = NULL;
+
+ /*
+ * Initialize the disable attribute.
+ */
+ me->select_disabled = FALSE;
+
+ /*
+ * Make sure we're in a form.
+ */
+ if (!me->inFORM) {
+ if (TRACE) {
+ fprintf(stderr,
+ "Bad HTML: SELECT start tag not within FORM tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+
+ /*
+ * We should have covered all crash possibilities with the
+ * current TagSoup parser, so we'll allow it because some
+ * people with other browsers use SELECT for "information"
+ * popups, outside of FORM blocks, though no Lynx user
+ * would do anything that awful, right? - FM
+ *//***
+ return;
+ ***/
+ }
+
+ /*
+ * Check for unclosed TEXTAREA.
+ */
+ if (me->inTEXTAREA) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Missing TEXTAREA end tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * Set to know we are in a select tag.
+ */
+ me->inSELECT = TRUE;
+
+ if (!(present && present[HTML_SELECT_NAME] &&
+ value[HTML_SELECT_NAME] && *value[HTML_SELECT_NAME])) {
+ StrAllocCopy(name, "");
+ } else if (strchr(value[HTML_SELECT_NAME], '&') == NULL) {
+ StrAllocCopy(name, value[HTML_SELECT_NAME]);
+ } else {
+ StrAllocCopy(name, value[HTML_SELECT_NAME]);
+ UNESCAPE_FIELDNAME_TO_STD(&name);
+ }
+ if (present && present[HTML_SELECT_MULTIPLE])
+ multiple=YES;
+ if (present && present[HTML_SELECT_DISABLED])
+ me->select_disabled = TRUE;
+ if (present && present[HTML_SELECT_SIZE] &&
+ value[HTML_SELECT_SIZE] && *value[HTML_SELECT_SIZE]) {
+#ifdef NOTDEFINED
+ StrAllocCopy(size, value[HTML_SELECT_SIZE]);
+#else
+ /*
+ * Let the size be determined by the number of OPTIONs. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "LYHandleSELECT: Ignoring SIZE=\"%s\" for SELECT.\n",
+ (char *)value[HTML_SELECT_SIZE]);
+ }
+#endif /* NOTDEFINED */
+ }
+
+ if (me->inBoldH == TRUE &&
+ (multiple == NO || LYSelectPopups == FALSE)) {
+ HText_appendCharacter(me->text, LY_BOLD_END_CHAR);
+ me->inBoldH = FALSE;
+ me->needBoldH = TRUE;
+ }
+ if (me->inUnderline == TRUE &&
+ (multiple == NO || LYSelectPopups == FALSE)) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_END_CHAR);
+ me->inUnderline = FALSE;
+ }
+
+ if ((multiple == NO && LYSelectPopups == TRUE) &&
+ (me->sp[0].tag_number == HTML_PRE || me->inPRE == TRUE ||
+ !me->sp->style->freeFormat) &&
+ HText_LastLineSize(me->text, FALSE) > (LYcols - 8)) {
+ /*
+ * Force a newline when we're using a popup in
+ * a PRE block and are within 7 columns from the
+ * right margin. This will allow for the '['
+ * popup designator and help avoid a wrap in the
+ * underscore placeholder for the retracted popup
+ * entry in the HText structure. - FM
+ */
+ HTML_put_character(me, '\n');
+ me->in_word = NO;
+ }
+
+ LYCheckForID(me, present, value, (int)HTML_SELECT_ID);
+
+ HText_beginSelect(name, ATTR_CS_IN, multiple, size);
+ FREE(name);
+ FREE(size);
+
+ me->first_option = TRUE;
+ } else {
+ /*
+ * Handle end tag.
+ */
+ char *ptr;
+
+ /*
+ * Make sure we had a select start tag.
+ */
+ if (!me->inSELECT) {
+ if (TRACE) {
+ fprintf(stderr, "Bad HTML: Unmatched SELECT end tag\n");
+ } else if (!me->inBadHTML) {
+ _statusline(BAD_HTML_USE_TRACE);
+ me->inBadHTML = TRUE;
+ sleep(MessageSecs);
+ }
+ return;
+ }
+
+ /*
+ * Set to know that we are no longer in a select tag.
+ */
+ me->inSELECT = FALSE;
+
+ /*
+ * Clear the disable attribute.
+ */
+ me->select_disabled = FALSE;
+
+ /*
+ * Finish the data off.
+ */
+ HTChunkTerminate(&me->option);
+ /*
+ * Finish the previous option.
+ */
+ ptr = HText_setLastOptionValue(me->text,
+ me->option.data,
+ me->LastOptionValue,
+ LAST_ORDER,
+ me->LastOptionChecked,
+ me->UCLYhndl,
+ ATTR_CS_IN);
+ FREE(me->LastOptionValue);
+
+ me->LastOptionChecked = FALSE;
+
+ if (HTCurSelectGroupType == F_CHECKBOX_TYPE ||
+ LYSelectPopups == FALSE) {
+ /*
+ * Start a newline after the last checkbox/button option.
+ */
+ LYEnsureSingleSpace(me);
+ } else {
+ /*
+ * Output popup box with the default option to screen,
+ * but use non-breaking spaces for output.
+ */
+ if (ptr &&
+ me->sp[0].tag_number == HTML_PRE && strlen(ptr) > 6) {
+ /*
+ * The code inadequately handles OPTION fields in PRE tags.
+ * We'll put up a minimum of 6 characters, and if any
+ * more would exceed the wrap column, we'll ignore them.
+ */
+ for (i = 0; i < 6; i++) {
+ if (*ptr == ' ')
+ HText_appendCharacter(me->text, HT_NON_BREAK_SPACE);
+ else
+ HText_appendCharacter(me->text, *ptr);
+ ptr++;
+ }
+ HText_setIgnoreExcess(me->text, TRUE);
+ }
+ for (; ptr && *ptr != '\0'; ptr++) {
+ if (*ptr == ' ')
+ HText_appendCharacter(me->text, HT_NON_BREAK_SPACE);
+ else
+ HText_appendCharacter(me->text, *ptr);
+ }
+ /*
+ * Add end option character.
+ */
+ if (!me->first_option) {
+ HText_appendCharacter(me->text, ']');
+ HText_setLastChar(me->text, ']');
+ me->in_word = YES;
+ }
+ HText_setIgnoreExcess(me->text, FALSE);
+ }
+ HTChunkClear(&me->option);
+
+ if (me->Underline_Level > 0 && me->inUnderline == FALSE) {
+ HText_appendCharacter(me->text, LY_UNDERLINE_START_CHAR);
+ me->inUnderline = TRUE;
+ }
+ if (me->needBoldH == TRUE && me->inBoldH == FALSE) {
+ HText_appendCharacter(me->text, LY_BOLD_START_CHAR);
+ me->inBoldH = TRUE;
+ me->needBoldH = FALSE;
+ }
+ }
+}
+
+/*
+** This function strips white characters and
+** generally fixes up attribute values that
+** were received from the SGML parser and
+** are to be treated as partial or absolute
+** URLs. - FM
+*/
+PUBLIC int LYLegitimizeHREF ARGS4(
+ HTStructured *, me,
+ char **, href,
+ BOOL, force_slash,
+ BOOL, strip_dots)
+{
+ int url_type = 0;
+ char *pound = NULL;
+ char *fragment = NULL;
+
+ if (!me || !href || *href == NULL || *(*href) == '\0')
+ return(url_type);
+
+ LYTrimHead(*href);
+ if (!strncasecomp(*href, "lynxexec:", 9) ||
+ !strncasecomp(*href, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(*href, " \r\n\t");
+ convert_to_spaces(*href, TRUE);
+ } else {
+ /*
+ * Collapse spaces in the actual URL, but just
+ * protect against tabs or newlines in the
+ * fragment, if present. This seeks to cope
+ * with atrocities inflicted on the Web by
+ * authoring tools such as Frontpage. - FM
+ */
+ if ((pound = strchr(*href, '#')) != NULL) {
+ StrAllocCopy(fragment, pound);
+ *pound = '\0';
+ convert_to_spaces(fragment, FALSE);
+ }
+ collapse_spaces(*href);
+ if (fragment != NULL) {
+ StrAllocCat(*href, fragment);
+ FREE(fragment);
+ }
+ }
+ if (*(*href) == '\0')
+ return(url_type);
+ LYUCFullyTranslateString(href, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_URL);
+ url_type = is_url(*href);
+ if (!url_type && force_slash &&
+ (!strcmp(*href, ".") || !strcmp(*href, "..")) &&
+ strncmp((me->inBASE ?
+ me->base_href : me->node_anchor->address),
+ "file:", 5)) {
+ /*
+ * The Fielding RFC/ID for resolving partial HREFs says
+ * that a slash should be on the end of the preceding
+ * symbolic element for "." and "..", but all tested
+ * browsers only do that for an explicit "./" or "../",
+ * so we'll respect the RFC/ID only if force_slash was
+ * TRUE and it's not a file URL. - FM
+ */
+ StrAllocCat(*href, "/");
+ }
+ if ((!url_type && LYStripDotDotURLs && strip_dots && *(*href) == '.') &&
+ !strncasecomp((me->inBASE ?
+ me->base_href : me->node_anchor->address),
+ "http", 4)) {
+ /*
+ * We will be resolving a partial reference versus an http
+ * or https URL, and it has lead dots, which may be retained
+ * when resolving via HTParse(), but the request would fail
+ * if the first element of the resultant path is two dots,
+ * because no http or https server accepts such paths, and
+ * the current URL draft, likely to become an RFC, says that
+ * it's optional for the UA to strip them as a form of error
+ * recovery. So we will, recursively, for http/https URLs,
+ * like the "major market browsers" which made this problem
+ * so common on the Web, but we'll also issue a message about
+ * it, such that the bad partial reference might get corrected
+ * by the document provider. - FM
+ */
+ char *temp = NULL, *path = NULL, *str = "", *cp;
+
+ if (((temp = HTParse(*href,
+ (me->inBASE ?
+ me->base_href : me->node_anchor->address),
+ PARSE_ALL)) != NULL && temp[0] != '\0') &&
+ (path = HTParse(temp, "",
+ PARSE_PATH+PARSE_PUNCTUATION)) != NULL &&
+ !strncmp(path, "/..", 3)) {
+ cp = (path + 3);
+ if (*cp == '/' || *cp == '\0') {
+ if ((me->inBASE ?
+ me->base_href[4] : me->node_anchor->address[4]) == 's') {
+ str = "s";
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "LYLegitimizeHREF: Bad value '%s' for http%s URL.\n",
+ *href, str);
+ fprintf(stderr,
+ " Stripping lead dots.\n");
+ } else if (!me->inBadHREF) {
+ _statusline(BAD_PARTIAL_REFERENCE);
+ me->inBadHREF = TRUE;
+ sleep(AlertSecs);
+ }
+ }
+ if (*cp == '\0') {
+ StrAllocCopy(*href, "/");
+ } else if (*cp == '/') {
+ while (!strncmp(cp, "/..", 3)) {
+ if (*(cp + 3) == '/') {
+ cp += 3;
+ continue;
+ } else if (*(cp + 3) == '\0') {
+ *(cp + 1) = '\0';
+ *(cp + 2) = '\0';
+ }
+ break;
+ }
+ StrAllocCopy(*href, cp);
+ }
+ }
+ FREE(temp);
+ FREE(path);
+ }
+ return(url_type);
+}
+
+/*
+** This function checks for a Content-Base header,
+** and if not present, a Content-Location header
+** which is an absolute URL, and sets the BASE
+** accordingly. If set, it will be replaced by
+** any BASE tag in the HTML stream, itself. - FM
+*/
+PUBLIC void LYCheckForContentBase ARGS1(
+ HTStructured *, me)
+{
+ char *cp = NULL;
+ BOOL present[HTML_BASE_ATTRIBUTES];
+ CONST char *value[HTML_BASE_ATTRIBUTES];
+ int i;
+
+ if (!(me && me->node_anchor))
+ return;
+
+ if (me->node_anchor->content_base != NULL) {
+ /*
+ * We have a Content-Base value. Use it
+ * if it's non-zero length. - FM
+ */
+ if (*me->node_anchor->content_base == '\0')
+ return;
+ StrAllocCopy(cp, me->node_anchor->content_base);
+ collapse_spaces(cp);
+ } else if (me->node_anchor->content_location != NULL) {
+ /*
+ * We didn't have a Content-Base value, but do
+ * have a Content-Location value. Use it if
+ * it's an absolute URL. - FM
+ */
+ if (*me->node_anchor->content_location == '\0')
+ return;
+ StrAllocCopy(cp, me->node_anchor->content_location);
+ collapse_spaces(cp);
+ if (!is_url(cp)) {
+ FREE(cp);
+ return;
+ }
+ } else {
+ /*
+ * We had neither a Content-Base nor
+ * Content-Location value. - FM
+ */
+ return;
+ }
+
+ /*
+ * If we collapsed to a zero-length value,
+ * ignore it. - FM
+ */
+ if (*cp == '\0') {
+ FREE(cp);
+ return;
+ }
+
+ /*
+ * Pass the value to HTML_start_element as
+ * the HREF of a BASE tag. - FM
+ */
+ for (i = 0; i < HTML_BASE_ATTRIBUTES; i++)
+ present[i] = NO;
+ present[HTML_BASE_HREF] = YES;
+ value[HTML_BASE_HREF] = (CONST char *)cp;
+ (*me->isa->start_element)(me, HTML_BASE, present, value,
+ 0, 0);
+ FREE(cp);
+}
+
+/*
+** This function creates NAMEd Anchors if a non-zero-length NAME
+** or ID attribute was present in the tag. - FM
+*/
+PUBLIC void LYCheckForID ARGS4(
+ HTStructured *, me,
+ CONST BOOL *, present,
+ CONST char **, value,
+ int, attribute)
+{
+ HTChildAnchor *ID_A = NULL;
+ char *temp = NULL;
+
+ if (!(me && me->text))
+ return;
+
+ if (present && present[attribute]
+ && value[attribute] && *value[attribute]) {
+ /*
+ * Translate any named or numeric character references. - FM
+ */
+ StrAllocCopy(temp, value[attribute]);
+ LYUCFullyTranslateString(&temp, me->tag_charset, me->tag_charset,
+ NO, NO, YES, st_URL);
+
+ /*
+ * Create the link if we still have a non-zero-length string. - FM
+ */
+ if ((temp[0] != '\0') &&
+ (ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ temp, /* Tag */
+ NULL, /* Addresss */
+ (void *)0))) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+ FREE(temp);
+ }
+}
+
+/*
+** This function creates a NAMEd Anchor for the ID string
+** passed to it directly as an argument. It assumes the
+** does not need checking for character references. - FM
+*/
+PUBLIC void LYHandleID ARGS2(
+ HTStructured *, me,
+ char *, id)
+{
+ HTChildAnchor *ID_A = NULL;
+
+ if (!(me && me->text) ||
+ !(id && *id))
+ return;
+
+ /*
+ * Create the link if we still have a non-zero-length string. - FM
+ */
+ if ((ID_A = HTAnchor_findChildAndLink(
+ me->node_anchor, /* Parent */
+ id, /* Tag */
+ NULL, /* Addresss */
+ (void *)0)) != NULL) { /* Type */
+ HText_beginAnchor(me->text, me->inUnderline, ID_A);
+ HText_endAnchor(me->text, 0);
+ }
+}
+
+/*
+** This function checks whether we want to override
+** the current default alignment for paragraphs and
+** instead use that specified in the element's style
+** sheet. - FM
+*/
+PUBLIC BOOLEAN LYoverride_default_alignment ARGS1(
+ HTStructured *, me)
+{
+ if (!me)
+ return NO;
+
+ switch(me->sp[0].tag_number) {
+ case HTML_BLOCKQUOTE:
+ case HTML_BQ:
+ case HTML_NOTE:
+ case HTML_FN:
+ case HTML_ADDRESS:
+ me->sp->style->alignment = HT_LEFT;
+ return YES;
+ break;
+
+ default:
+ break;
+ }
+ return NO;
+}
+
+/*
+** This function inserts newlines if needed to create double spacing,
+** and sets the left margin for subsequent text to the second line
+** indentation of the current style. - FM
+*/
+PUBLIC void LYEnsureDoubleSpace ARGS1(
+ HTStructured *, me)
+{
+ if (!me || !me->text)
+ return;
+
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ HText_appendCharacter(me->text, '\r');
+ } else if (HText_PreviousLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ } else if (me->List_Nesting_Level >= 0) {
+ HText_NegateLineOne(me->text);
+ }
+ me->in_word = NO;
+ return;
+}
+
+/*
+** This function inserts a newline if needed to create single spacing,
+** and sets the left margin for subsequent text to the second line
+** indentation of the current style. - FM
+*/
+PUBLIC void LYEnsureSingleSpace ARGS1(
+ HTStructured *, me)
+{
+ if (!me || !me->text)
+ return;
+
+ if (HText_LastLineSize(me->text, FALSE)) {
+ HText_setLastChar(me->text, ' '); /* absorb white space */
+ HText_appendCharacter(me->text, '\r');
+ } else if (me->List_Nesting_Level >= 0) {
+ HText_NegateLineOne(me->text);
+ }
+ me->in_word = NO;
+ return;
+}
+
+/*
+** This function resets paragraph alignments for block
+** elements which do not have a defined style sheet. - FM
+*/
+PUBLIC void LYResetParagraphAlignment ARGS1(
+ HTStructured *, me)
+{
+ if (!me)
+ return;
+
+ if (me->List_Nesting_Level >= 0 ||
+ ((me->Division_Level < 0) &&
+ (!strcmp(me->sp->style->name, "Normal") ||
+ !strcmp(me->sp->style->name, "Preformatted")))) {
+ me->sp->style->alignment = HT_LEFT;
+ } else {
+ me->sp->style->alignment = me->current_default_alignment;
+ }
+ return;
+}
+
+/*
+** This example function checks whether the given anchor has
+** an address with a file scheme, and if so, loads it into the
+** the SGML parser's context->url element, which was passed as
+** the second argument. The handle_comment() calling function in
+** SGML.c then calls LYDoCSI() in LYUtils.c to insert HTML markup
+** into the corresponding stream, homologously to an SSI by an
+** HTTP server. - FM
+**
+** For functions similar to this but which depend on details of
+** the HTML handler's internal data, the calling interface should
+** be changed, and functions in SGML.c would have to make sure not
+** to call such functions inappropriately (e.g. calling a function
+** specific to the Lynx_HTML_Handler when SGML.c output goes to
+** some other HTStructured object like in HTMLGen.c), or the new
+** functions could be added to the SGML.h interface.
+*/
+PUBLIC BOOLEAN LYCheckForCSI ARGS2(
+ HTParentAnchor *, anchor,
+ char **, url)
+{
+ if (!(anchor && anchor->address))
+ return FALSE;
+
+ if (strncasecomp(anchor->address, "file:", 5))
+ return FALSE;
+
+ if (!LYisLocalHost(anchor->address))
+ return FALSE;
+
+ StrAllocCopy(*url, anchor->address);
+ return TRUE;
+}
diff --git a/gnu/usr.bin/lynx/src/LYCharUtils.h b/gnu/usr.bin/lynx/src/LYCharUtils.h
new file mode 100644
index 00000000000..5c8f87ba915
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCharUtils.h
@@ -0,0 +1,106 @@
+
+#ifndef LYCHARUTILS_H
+#define LYCHARUTILS_H
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+#define CHECK_ID(code) LYCheckForID(me, present, value, (int)code)
+
+typedef enum {
+ st_HTML = 0, /* attributes and content found in HTML, probably meant for display */
+ st_URL, /* URLs, fragments, NAME and ID */
+ st_other
+} CharUtil_st;
+
+extern BOOL LYUCFullyTranslateString PARAMS((
+ char ** str,
+ int cs_from,
+ int cs_to,
+ BOOL use_lynx_specials,
+ BOOLEAN plain_space,
+ BOOLEAN hidden,
+ CharUtil_st stype));
+extern BOOL LYUCTranslateBackFormData PARAMS((
+ char ** str,
+ int cs_from,
+ int cs_to,
+ BOOLEAN plain_space));
+extern void LYEntify PARAMS((
+ char ** str,
+ BOOLEAN isTITLE));
+extern void LYTrimHead PARAMS((
+ char * str));
+extern void LYTrimTail PARAMS((
+ char * str));
+extern char *LYFindEndOfComment PARAMS((
+ char * str));
+extern void LYFillLocalFileURL PARAMS((
+ char ** href,
+ char * base));
+extern void LYAddMETAcharsetToFD PARAMS((
+ FILE * fd,
+ int disp_chndl));
+
+#ifdef Lynx_HTML_Handler
+extern int OL_CONTINUE; /* flag for whether CONTINUE is set */
+extern int OL_VOID; /* flag for whether a count is set */
+extern void LYZero_OL_Counter PARAMS((
+ HTStructured * me));
+extern char *LYUppercaseA_OL_String PARAMS((
+ int seqnum));
+extern char *LYLowercaseA_OL_String PARAMS((
+ int seqnum));
+extern char *LYUppercaseI_OL_String PARAMS((
+ int seqnum));
+extern char *LYLowercaseI_OL_String PARAMS((
+ int seqnum));
+extern void LYGetChartransInfo PARAMS((
+ HTStructured * me));
+extern void LYHandleMETA PARAMS((
+ HTStructured * me,
+ CONST BOOL* present,
+ CONST char ** value,
+ char ** include));
+extern void LYHandleP PARAMS((
+ HTStructured * me,
+ CONST BOOL* present,
+ CONST char ** value,
+ char ** include,
+ BOOL start));
+extern void LYHandleSELECT PARAMS((
+ HTStructured * me,
+ CONST BOOL* present,
+ CONST char ** value,
+ char ** include,
+ BOOL start));
+extern int LYLegitimizeHREF PARAMS((
+ HTStructured * me,
+ char ** href,
+ BOOL force_slash,
+ BOOL strip_dots));
+extern void LYCheckForContentBase PARAMS((
+ HTStructured * me));
+extern void LYCheckForID PARAMS((
+ HTStructured * me,
+ CONST BOOL * present,
+ CONST char ** value,
+ int attribute));
+extern void LYHandleID PARAMS((
+ HTStructured * me,
+ char * id));
+extern BOOLEAN LYoverride_default_alignment PARAMS((
+ HTStructured * me));
+extern void LYEnsureDoubleSpace PARAMS((
+ HTStructured * me));
+extern void LYEnsureSingleSpace PARAMS((
+ HTStructured * me));
+extern void LYResetParagraphAlignment PARAMS((
+ HTStructured * me));
+extern BOOLEAN LYCheckForCSI PARAMS((
+ HTParentAnchor * anchor,
+ char ** url));
+#endif /* Lynx_HTML_Handler */
+
+#endif /* LYCHARUTILS_H */
diff --git a/gnu/usr.bin/lynx/src/LYClean.c b/gnu/usr.bin/lynx/src/LYClean.c
new file mode 100644
index 00000000000..424560e6708
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYClean.c
@@ -0,0 +1,210 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYSignal.h"
+#include "LYClean.h"
+#include "LYGlobalDefs.h"
+#include "LYStrings.h"
+#include "LYTraversal.h"
+#include "UCAuto.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+BOOLEAN HadVMSInterrupt = FALSE;
+#endif /* VMS */
+
+/*
+ * Interrupt handler. Stop curses and exit gracefully.
+ */
+PUBLIC void cleanup_sig ARGS1(
+ int, sig)
+{
+
+#ifdef IGNORE_CTRL_C
+ if (sig == SIGINT) {
+ /*
+ * Need to rearm the signal.
+ */
+ signal(SIGINT, cleanup_sig);
+ sigint = TRUE;
+ return;
+ }
+#endif /* IGNORE_CTRL_C */
+
+#ifdef VMS
+ if (!dump_output_immediately) {
+ int c;
+
+ /*
+ * Reassert the AST.
+ */
+ (void) signal(SIGINT, cleanup_sig);
+ HadVMSInterrupt = TRUE;
+ if (!LYCursesON)
+ return;
+
+ /*
+ * Refresh screen to get rid of "cancel" message, then query.
+ */
+ lynx_force_repaint();
+ refresh();
+
+ /*
+ * Ask if exit is intended.
+ */
+ if (LYQuitDefaultYes == TRUE) {
+ _statusline(REALLY_EXIT_Y);
+ } else {
+ _statusline(REALLY_EXIT_N);
+ }
+ c = LYgetch();
+ if (LYQuitDefaultYes == TRUE) {
+ if (TOUPPER(c) == 'N' ||
+ c == 7) {
+ return;
+ }
+ } else if (TOUPPER(c) != 'Y') {
+ return;
+ }
+ }
+#endif /* VMS */
+
+ /*
+ * Ignore further interrupts. - mhc: 11/2/91
+ */
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_IGN);
+#endif /* NOSIGHUP */
+
+#ifdef VMS
+ /*
+ * Use ttclose() from cleanup() for VMS if not dumping.
+ */
+ if (dump_output_immediately)
+#else /* Unix: */
+ (void) signal(SIGINT, SIG_IGN);
+#endif /* VMS */
+
+ (void) signal(SIGTERM, SIG_IGN);
+
+ if (traversal)
+ dump_traversal_history();
+
+#ifndef NOSIGHUP
+ if (sig != SIGHUP) {
+#endif /* NOSIGHUP */
+
+ if (!dump_output_immediately) {
+ /*
+ * cleanup() also calls cleanup_files().
+ */
+ cleanup();
+ }
+ if (sig != 0) {
+ printf("\r\nExiting via interrupt: %d\r\n", sig);
+ fflush(stdout);
+ }
+#ifndef NOSIGHUP
+ } else {
+ cleanup_files();
+ }
+#endif /* NOSIGHUP */
+
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP, SIG_DFL);
+#endif /* SIGTSTP */
+ if (sig != 0) {
+ exit(0);
+ }
+}
+
+/*
+ * Called by Interrupt handler or at quit time.
+ * Erases the temporary files that lynx created
+ * temporary files are removed by tempname
+ * which created them.
+ */
+PUBLIC void cleanup_files NOARGS
+{
+ char filename[256];
+
+ tempname(filename, REMOVE_FILES);
+ FREE(lynx_temp_space);
+}
+
+PUBLIC void cleanup NOARGS
+{
+ int i;
+#ifdef VMS
+ extern BOOLEAN DidCleanup;
+#endif /* VMS */
+
+ /*
+ * Cleanup signals - just in case.
+ * Ignore further interrupts. - mhc: 11/2/91
+ */
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_IGN);
+#endif /* NOSIGHUP */
+ (void) signal (SIGTERM, SIG_IGN);
+
+#ifndef VMS /* use ttclose() from cleanup() for VMS */
+ (void) signal (SIGINT, SIG_IGN);
+#endif /* !VMS */
+
+ if (LYCursesON) {
+ move(LYlines-1, 0);
+ clrtoeol();
+
+ lynx_stop_all_colors ();
+ refresh();
+
+ stop_curses();
+ }
+
+#ifdef EXP_CHARTRANS_AUTOSWITCH
+#ifdef LINUX
+ /*
+ * Currently implemented only for LINUX: Restore original font.
+ */
+ UCChangeTerminalCodepage(-1, (LYUCcharset*)0);
+#endif /* LINUX */
+#endif /* EXP_CHARTRANS_AUTOSWITCH */
+
+ cleanup_files();
+ for (i = 0; i < nhist; i++) {
+ FREE(history[i].title);
+ FREE(history[i].address);
+ FREE(history[i].post_data);
+ FREE(history[i].post_content_type);
+ FREE(history[i].bookmark);
+ }
+ nhist = 0;
+#ifdef VMS
+ ttclose();
+ DidCleanup = TRUE;
+#endif /* VMS */
+
+ fflush(stdout);
+ fflush(stderr);
+ if (LYTraceLogFP != NULL) {
+ fclose(LYTraceLogFP);
+ LYTraceLogFP = NULL;
+#if !defined(VMS) || (defined(VMS) && !defined(VAXC) && !defined(UCX))
+ *stderr = LYOrigStderr;
+#endif /* !VMS || (VMS && !VAXC && !UCX) */
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/LYClean.h b/gnu/usr.bin/lynx/src/LYClean.h
new file mode 100644
index 00000000000..e95020109dd
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYClean.h
@@ -0,0 +1,18 @@
+#ifndef LYCLEAN_H
+#define LYCLEAN_H
+
+#ifdef VMS
+extern BOOLEAN HadVMSInterrupt;
+#endif
+
+extern void cleanup_sig PARAMS((int sig));
+extern BOOLEAN setup PARAMS((char *terminal));
+extern void cleanup NOPARAMS;
+extern void cleanup_files NOPARAMS;
+extern void set_alarm PARAMS((int sig));
+extern void reset_alarm NOPARAMS;
+
+#define NEW_FILE 0
+#define REMOVE_FILES 1
+
+#endif /* LYCLEAN_H */
diff --git a/gnu/usr.bin/lynx/src/LYCookie.c b/gnu/usr.bin/lynx/src/LYCookie.c
new file mode 100644
index 00000000000..c7e7fe0a977
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCookie.c
@@ -0,0 +1,2345 @@
+/* Lynx Cookie Support LYCookie.c
+** ===================
+**
+** Author: AMK A.M. Kuchling (amk@magnet.com) 12/25/96
+**
+** Incorporated with mods by FM 01/16/97
+**
+** Based on:
+** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-mgmt-05.txt
+**
+** Updated for:
+** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-02.txt
+** - FM 1997-07-09
+**
+** Updated for:
+** ftp://ds.internic.net/internet-drafts/draft-ietf-http-state-man-mec-03.txt
+** - FM 1997-08-02
+**
+** TO DO: (roughly in order of decreasing priority)
+ * A means to specify "always allow" and "never allow" domains via
+ a configuration file is needed.
+ * Hex escaping isn't considered at all. Any semi-colons, commas,
+ or spaces actually in cookie names or values (i.e., not serving
+ as punctuation for the overall Set-Cookie value) should be hex
+ escaped if not quoted, but presumeably the server is expecting
+ them to be hex escaped in our Cookie request header as well, so
+ in theory we need not unescape them. We'll see how this works
+ out in practice.
+ * The prompt should show more information about the cookie being
+ set in Novice mode.
+ * The truncation heuristic in HTConfirmCookie should probably be
+ smarter, smart enough to leave a really short name/value string
+ alone.
+ * We protect against denial-of-service attacks (see section 6.3.1
+ of the draft) by limiting a domain to 50 cookies, limiting the
+ total number of cookies to 500, and limiting a processed cookie
+ to a maximum of 4096 bytes, but we count on the normal garbage
+ collections to bring us back down under the limits, rather than
+ actively removing cookies and/or domains based on age or frequency
+ of use.
+ * If a cookie has the secure flag set, we presently treat only SSL
+ connections as secure. This may need to be expanded for other
+ secure communication protocols that become standarized.
+ * Cookies could be optionally stored in a file from session to session.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAccess.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYSignal.h"
+#include "LYUtils.h"
+#include "LYCharUtils.h"
+#include "LYClean.h"
+#include "LYGlobalDefs.h"
+#include "LYEdit.h"
+#include "LYStrings.h"
+#include "LYSystem.h"
+#include "GridText.h"
+#include "LYUtils.h"
+#include "LYCharUtils.h"
+#include "LYCookie.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+** The first level of the cookie list is a list indexed by the domain
+** string; cookies with the same domain will be placed in the same
+** list. Thus, finding the cookies that apply to a given URL is a
+** two-level scan; first we check each domain to see if it applies,
+** and if so, then we check the paths of all the cookies on that
+** list. We keep a running total of cookies as we add or delete
+** them
+*/
+PRIVATE HTList *domain_list = NULL;
+PRIVATE HTList *cookie_list = NULL;
+PRIVATE int total_cookies = 0;
+
+struct _cookie {
+ char *lynxID; /* Lynx cookie identifier */
+ char *name; /* Name of this cookie */
+ char *value; /* Value of this cookie */
+ int version; /* Cookie protocol version (=1) */
+ char *comment; /* Comment to show to user */
+ char *commentURL; /* URL for comment to show to user */
+ char *domain; /* Domain for which this cookie is valid */
+ int port; /* Server port from which this cookie was given (usu. 80) */
+ char *PortList;/* List of ports for which cookie can be sent */
+ char *path; /* Path prefix for which this cookie is valid */
+ int pathlen; /* Length of the path */
+ int flags; /* Various flags */
+ time_t expires;/* The time when this cookie expires */
+ BOOL quoted; /* Was a value quoted in the Set-Cookie header? */
+};
+typedef struct _cookie cookie;
+
+#define COOKIE_FLAG_SECURE 1 /* If set, cookie requires secure links */
+#define COOKIE_FLAG_DISCARD 2 /* If set, expire at end of session */
+#define COOKIE_FLAG_EXPIRES_SET 4 /* If set, an expiry date was set */
+#define COOKIE_FLAG_DOMAIN_SET 8 /* If set, an non-default domain was set */
+#define COOKIE_FLAG_PATH_SET 16 /* If set, an non-default path was set */
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+PRIVATE void MemAllocCopy ARGS3(
+ char **, dest,
+ CONST char *, start,
+ CONST char *, end)
+{
+ char *temp;
+
+ if (!(start && end) || (end <= start)) {
+ HTSACopy(dest, "");
+ return;
+ }
+
+ temp = (char *)calloc(1, ((end - start) + 1));
+ if (temp == NULL)
+ outofmem(__FILE__, "MemAllocCopy");
+ LYstrncpy(temp, start, (end - start));
+ HTSACopy(dest, temp);
+ FREE(temp);
+}
+
+PRIVATE cookie * newCookie NOARGS
+{
+ cookie *p = (cookie *)calloc(1, sizeof(cookie));
+ char lynxID[64];
+
+ if (p == NULL)
+ outofmem(__FILE__, "newCookie");
+ sprintf(lynxID, "%p", p);
+ StrAllocCopy(p->lynxID, lynxID);
+ p->port = 80;
+ return p;
+}
+
+PRIVATE void freeCookie ARGS1(
+ cookie *, co)
+{
+ if (co) {
+ FREE(co->lynxID);
+ FREE(co->name);
+ FREE(co->value);
+ FREE(co->comment);
+ FREE(co->commentURL);
+ FREE(co->domain);
+ FREE(co->path);
+ FREE(co->PortList);
+ FREE(co);
+ }
+}
+
+PRIVATE void LYCookieJar_free NOARGS
+{
+ HTList *dl = domain_list;
+ domain_entry *de = NULL;
+ HTList *cl = NULL, *next = NULL;
+ cookie *co = NULL;
+
+ while (dl) {
+ if ((de = dl->object) != NULL) {
+ cl = de->cookie_list;
+ while (cl) {
+ next = cl->next;
+ co = cl->object;
+ if (co) {
+ HTList_removeObject(de->cookie_list, co);
+ freeCookie(co);
+ }
+ cl = next;
+ }
+ FREE(de->domain);
+ HTList_delete(de->cookie_list);
+ de->cookie_list = NULL;
+ }
+ dl = dl->next;
+ }
+ if (dump_output_immediately) {
+ cl = cookie_list;
+ while (cl) {
+ next = cl->next;
+ co = cl->object;
+ if (co) {
+ HTList_removeObject(cookie_list, co);
+ freeCookie(co);
+ }
+ cl = next;
+ }
+ HTList_delete(cookie_list);
+ }
+ cookie_list = NULL;
+ HTList_delete(domain_list);
+ domain_list = NULL;
+}
+
+/*
+** Compare two hostnames as specified in Section 2 of:
+** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-02.txt
+** - AK & FM
+*/
+PRIVATE BOOLEAN host_matches ARGS2(
+ CONST char *, A,
+ CONST char *, B)
+{
+ /*
+ * The following line will handle both numeric IP addresses and
+ * FQDNs. Do numeric addresses require special handling?
+ */
+ if (*B != '.' && !strcmp(A, B))
+ return YES;
+
+ /*
+ * The following will pass a "dotted tail" match to "a.b.c.e"
+ * as described in Section 2 of the -05 draft.
+ */
+ if (*B == '.') {
+ int diff = (strlen(A) - strlen(B));
+ if (diff > 0) {
+ if (!strcmp((A + diff), B))
+ return YES;
+ }
+ }
+ return NO;
+}
+
+/*
+** Compare the current port with a port list as specified in Section 4.3 of:
+** http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-state-man-mec-02.txt
+** - FM
+*/
+PRIVATE BOOLEAN port_matches ARGS2(
+ int, port,
+ CONST char *, list)
+{
+ CONST char *number = list;
+
+ if (!(number && isdigit(*number)))
+ return(FALSE);
+
+ while (*number != '\0') {
+ if (atoi(number) == port) {
+ return(TRUE);
+ }
+ while (isdigit(*number)) {
+ number++;
+ }
+ while (*number != '\0' && !isdigit(*number)) {
+ number++;
+ }
+ }
+
+ return(FALSE);
+}
+
+/*
+** Store a cookie somewhere in the domain list. - AK & FM
+*/
+PRIVATE void store_cookie ARGS3(
+ cookie *, co,
+ CONST char *, hostname,
+ CONST char *, path)
+{
+ HTList *hl, *next;
+ cookie *c2;
+ time_t now = time(NULL);
+ int pos;
+ CONST char *ptr;
+ domain_entry *de = NULL;
+ BOOL Replacement = FALSE;
+
+ if (co == NULL)
+ return;
+
+ /*
+ * Apply sanity checks.
+ *
+ * Section 4.3.2, condition 1: The value for the Path attribute is
+ * not a prefix of the request-URI.
+ */
+ if (strncmp(co->path, path, co->pathlen) != 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Rejecting because '%s' is not a prefix of '%s'.\n",
+ co->path, path);
+ freeCookie(co);
+ co = NULL;
+ return;
+ }
+ /*
+ * The next 4 conditions do NOT apply if the domain is still
+ * the default of request-host.
+ */
+ if (strcmp(co->domain, hostname) != 0) {
+ /*
+ * The hostname does not contain a dot.
+ */
+ if (strchr(hostname, '.') == NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Rejecting because '%s' has no dot.\n",
+ hostname);
+ freeCookie(co);
+ co = NULL;
+ return;
+ }
+
+ /*
+ * Section 4.3.2, condition 2: The value for the Domain attribute
+ * contains no embedded dots or does not start with a dot.
+ * (A dot is embedded if it's neither the first nor last character.)
+ * Note that we added a lead dot ourselves if a domain attribute
+ * value otherwise qualified. - FM
+ */
+ if (co->domain[0] != '.' || co->domain[1] == '\0') {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Rejecting domain '%s'.\n",
+ co->domain);
+ freeCookie(co);
+ co = NULL;
+ return;
+ }
+ ptr = strchr((co->domain + 1), '.');
+ if (ptr == NULL || ptr[1] == '\0') {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Rejecting domain '%s'.\n",
+ co->domain);
+ freeCookie(co);
+ co = NULL;
+ return;
+ }
+
+ /*
+ * Section 4.3.2, condition 3: The value for the request-host does
+ * not domain-match the Domain attribute.
+ */
+ if (!host_matches(hostname, co->domain)) {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Rejecting domain '%s' for host '%s'.\n",
+ co->domain, hostname);
+ freeCookie(co);
+ co = NULL;
+ return;
+ }
+
+ /*
+ * Section 4.3.2, condition 4: The request-host is an HDN (not IP
+ * address) and has the form HD, where D is the value of the Domain
+ * attribute, and H is a string that contains one or more dots.
+ */
+ ptr = ((hostname + strlen(hostname)) - strlen(co->domain));
+ if (strchr(hostname, '.') < ptr) {
+ char *msg = calloc(1,
+ (strlen(co->domain) +
+ strlen(hostname) +
+ strlen(INVALID_COOKIE_DOMAIN_CONFIRMATION) +
+ 1));
+
+ sprintf(msg,
+ INVALID_COOKIE_DOMAIN_CONFIRMATION,
+ co->domain,
+ hostname);
+ if (!HTConfirm(msg)) {
+ if (TRACE) {
+ fprintf(stderr,
+ "store_cookie: Rejecting domain '%s' for host '%s'.\n",
+ co->domain,
+ hostname);
+ }
+ freeCookie(co);
+ co = NULL;
+ FREE(msg);
+ return;
+ }
+ FREE(msg);
+ }
+ }
+
+ /*
+ * Ensure that the domain list exists.
+ */
+ if (domain_list == NULL) {
+ atexit(LYCookieJar_free);
+ domain_list = HTList_new();
+ total_cookies = 0;
+ }
+
+ /*
+ * Look through domain_list to see if the cookie's domain
+ * is already listed.
+ */
+ if (dump_output_immediately) { /* Non-interactive, can't respond */
+ if (cookie_list == NULL)
+ cookie_list = HTList_new();
+ } else {
+ cookie_list = NULL;
+ for (hl = domain_list; hl != NULL; hl = hl->next) {
+ de = (domain_entry *)hl->object;
+ if ((de != NULL && de->domain != NULL) &&
+ !strcmp(co->domain, de->domain)) {
+ cookie_list = de->cookie_list;
+ break;
+ }
+ }
+ if (hl == NULL) {
+ /*
+ * Domain not found; add a new entry for this domain.
+ */
+ de = (domain_entry *)calloc(1, sizeof(domain_entry));
+ if (de == NULL)
+ outofmem(__FILE__, "store_cookie");
+ de->bv = QUERY_USER;
+ cookie_list = de->cookie_list = HTList_new();
+ StrAllocCopy(de->domain, co->domain);
+ HTList_addObject(domain_list, de);
+ }
+ }
+
+ /*
+ * Loop over the cookie list, deleting expired and matching cookies.
+ */
+ hl = cookie_list;
+ pos = 0;
+ while (hl) {
+ c2 = (cookie *)hl->object;
+ next = hl->next;
+ /*
+ * Check if this cookie has expired.
+ */
+ if ((c2 != NULL) &&
+ (c2->flags & COOKIE_FLAG_EXPIRES_SET) &&
+ c2->expires < now) {
+ HTList_removeObject(cookie_list, c2);
+ freeCookie(c2);
+ c2 = NULL;
+ total_cookies--;
+
+ /*
+ * Check if this cookie matches the one we're inserting.
+ */
+ } else if ((c2) &&
+ !strcmp(co->domain, c2->domain) &&
+ !strcmp(co->path, c2->path) &&
+ !strcmp(co->name, c2->name)) {
+ HTList_removeObject(cookie_list, c2);
+ freeCookie(c2);
+ c2 = NULL;
+ total_cookies--;
+ Replacement = TRUE;
+
+ } else if ((c2) && (c2->pathlen) > (co->pathlen)) {
+ pos++;
+ }
+ hl = next;
+ }
+
+ /*
+ * Don't bother to add the cookie if it's already expired.
+ */
+ if ((co->flags & COOKIE_FLAG_EXPIRES_SET) && co->expires < now) {
+ freeCookie(co);
+ co = NULL;
+
+ /*
+ * Don't add the cookie if we're over the domain's limit. - FM
+ */
+ } else if (HTList_count(cookie_list) > 50) {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Domain's cookie limit exceeded! Rejecting cookie.\n");
+ freeCookie(co);
+ co = NULL;
+
+ /*
+ * Don't add the cookie if we're over the total cookie limit. - FM
+ */
+ } else if (total_cookies > 500) {
+ if (TRACE)
+ fprintf(stderr,
+ "store_cookie: Total cookie limit exceeded! Rejecting cookie.\n");
+ freeCookie(co);
+ co = NULL;
+
+ /*
+ * If it's a replacement for a cookie that had not expired,
+ * and never allow has not been set, add it again without
+ * confirmation. - FM
+ */
+ } else if ((Replacement == TRUE && de) && de->bv != REJECT_ALWAYS) {
+ HTList_insertObjectAt(cookie_list, co, pos);
+ total_cookies++;
+
+ /*
+ * Get confirmation if we need it, and add cookie
+ * if confirmed or 'allow' is set to always. - FM
+ */
+ } else if (HTConfirmCookie(de, hostname,
+ co->domain, co->path, co->name, co->value)) {
+ HTList_insertObjectAt(cookie_list, co, pos);
+ total_cookies++;
+ } else {
+ freeCookie(co);
+ co = NULL;
+ }
+}
+
+/*
+** Scan a domain's cookie_list for any cookies we should
+** include in a Cookie: request header. - AK & FM
+*/
+PRIVATE char * scan_cookie_sublist ARGS6(
+ CONST char *, hostname,
+ CONST char *, path,
+ int, port,
+ HTList *, sublist,
+ char *, header,
+ BOOL, secure)
+{
+ HTList *hl = sublist, *next = NULL;
+ cookie *co;
+ time_t now = time(NULL);
+ int len = 0;
+ char crlftab[8];
+
+ sprintf(crlftab, "%c%c%c", CR, LF, '\t');
+ while (hl) {
+ co = (cookie *)hl->object;
+ next = hl->next;
+
+ if (TRACE && co) {
+ fprintf(stderr, "Checking cookie %lx %s=%s\n",
+ (long)hl,
+ (co->name ? co->name : "(no name)"),
+ (co->value ? co->value : "(no value)"));
+ fprintf(stderr, "%s %s %d %s %s %d%s\n",
+ hostname,
+ (co->domain ? co->domain : "(no domain)"),
+ host_matches(hostname, co->domain),
+ path, co->path, ((co->pathlen > 0) ?
+ strncmp(path, co->path, co->pathlen) : 0),
+ ((co->flags & COOKIE_FLAG_SECURE) ?
+ " secure" : ""));
+ }
+ /*
+ * Check if this cookie has expired, and if so, delete it.
+ */
+ if (((co) && (co->flags & COOKIE_FLAG_EXPIRES_SET)) &&
+ co->expires < now) {
+ HTList_removeObject(sublist, co);
+ freeCookie(co);
+ co = NULL;
+ total_cookies--;
+ }
+
+ /*
+ * Check if we have a unexpired match, and handle if we do.
+ */
+ if (((co != NULL) &&
+ host_matches(hostname, co->domain)) &&
+ (co->pathlen == 0 || !strncmp(path, co->path, co->pathlen))) {
+ /*
+ * Skip if the secure flag is set and we don't have
+ * a secure connection. HTTP.c presently treats only
+ * SSL connections as secure. - FM
+ */
+ if ((co->flags & COOKIE_FLAG_SECURE) && secure == FALSE) {
+ hl = next;
+ continue;
+ }
+
+ /*
+ * Skip if we have a port list and the
+ * current port is not listed. - FM
+ */
+ if (co->PortList && !port_matches(port, co->PortList)) {
+ hl = next;
+ continue;
+ }
+
+ /*
+ * Start or append to the request header.
+ */
+ if (header == NULL) {
+ if (co->version > 0) {
+ /*
+ * For Version 1 (or greater) cookies,
+ * the version number goes before the
+ * first cookie.
+ */
+ char version[16];
+ sprintf(version, "$Version=\"%d\"; ", co->version);
+ StrAllocCopy(header, version);
+ len += strlen(header);
+ }
+ } else {
+ /*
+ * There's already cookie data there, so add
+ * a separator (always use a semi-colon for
+ * "backward compatibility"). - FM
+ */
+ StrAllocCat(header, "; ");
+ /*
+ * Check if we should fold the header. - FM
+ */
+ if (len > 800) {
+ StrAllocCat(header, crlftab);
+ len = 0;
+ }
+ }
+ /*
+ * Include the cookie name=value pair.
+ */
+ StrAllocCat(header, co->name);
+ StrAllocCat(header, "=");
+ if (co->quoted) {
+ StrAllocCat(header, "\"");
+ len++;
+ }
+ StrAllocCat(header, co->value);
+ if (co->quoted) {
+ StrAllocCat(header, "\"");
+ len++;
+ }
+ len += (strlen(co->name) + strlen(co->value) + 1);
+ /*
+ * For Version 1 (or greater) cookies, add
+ * $PATH, $PORT and/or $DOMAIN attributes for
+ * the cookie if they were specified via a
+ * server reply header. - FM
+ */
+ if (co->version > 0) {
+ if (co->path && (co->flags & COOKIE_FLAG_PATH_SET)) {
+ /*
+ * Append the path attribute. - FM
+ */
+ StrAllocCat(header, "; $Path=\"");
+ StrAllocCat(header, co->path);
+ StrAllocCat(header, "\"");
+ len += (strlen(co->path) + 10);
+ }
+ if (co->PortList && isdigit((unsigned char)*co->PortList)) {
+ /*
+ * Append the port attribute. - FM
+ */
+ StrAllocCat(header, "; $Port=\"");
+ StrAllocCat(header, co->PortList);
+ StrAllocCat(header, "\"");
+ len += (strlen(co->PortList) + 10);
+ }
+ if (co->domain && (co->flags & COOKIE_FLAG_DOMAIN_SET)) {
+ /*
+ * Append the domain attribute. - FM
+ */
+ StrAllocCat(header, "; $Domain=\"");
+ StrAllocCat(header, co->domain);
+ StrAllocCat(header, "\"");
+ len += (strlen(co->domain) + 12);
+ }
+ }
+ }
+ hl = next;
+ }
+
+ return(header);
+}
+
+/*
+** Process potentially concatenated Set-Cookie2 and/or Set-Cookie
+** headers. - FM
+*/
+PRIVATE void LYProcessSetCookies ARGS6(
+ CONST char *, SetCookie,
+ CONST char *, SetCookie2,
+ CONST char *, address,
+ char *, hostname,
+ char *, path,
+ int, port)
+{
+ CONST char *p, *attr_start, *attr_end, *value_start, *value_end;
+ HTList *CombinedCookies = NULL, *cl = NULL;
+ cookie *cur_cookie = NULL, *co = NULL;
+ int length = 0, url_type = 0;
+ int NumCookies = 0;
+ BOOL MaxAgeAttrSet = FALSE;
+ BOOL Quoted = FALSE;
+
+ if (!(SetCookie && *SetCookie) &&
+ !(SetCookie2 && *SetCookie2)) {
+ /*
+ * Yuk! Garbage in, so nothing out. - FM
+ */
+ return;
+ }
+
+ /*
+ * If we have both Set-Cookie and Set-Cookie2 headers.
+ * process the Set-Cookie2 header. Otherwise, process
+ * whichever of the two headers we do have. Note that
+ * if more than one instance of a valued attribute for
+ * the same cookie is encountered, the value for the
+ * first instance is retained. We only accept up to 50
+ * cookies from the header, and only if a cookie's values
+ * do not exceed the 4096 byte limit on overall size. - FM
+ */
+ CombinedCookies = HTList_new();
+
+ /*
+ * Process the Set-Cookie2 header, if present and not zero-length,
+ * adding each cookie to the CombinedCookies list. - FM
+ */
+ p = (SetCookie2 ? SetCookie2 : "");
+ if (TRACE && SetCookie && *p) {
+ fprintf(stderr, "LYProcessSetCookies: Using Set-Cookie2 header.\n");
+ }
+ while (NumCookies <= 50 && *p) {
+ attr_start = attr_end = value_start = value_end = NULL;
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+ /*
+ * Get the attribute name.
+ */
+ attr_start = p;
+ while (*p != '\0' && !isspace((unsigned char)*p) &&
+ *p != '=' && *p != ';' && *p != ',')
+ p++;
+ attr_end = p;
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+
+ /*
+ * Check for an '=' delimiter, or an 'expires' name followed
+ * by white, since Netscape's bogus parser doesn't require
+ * an '=' delimiter, and 'expires' attributes are being
+ * encountered without them. These shouldn't be in a
+ * Set-Cookie2 header, but we'll assume it's an expires
+ * attribute rather a cookie with that name, since the
+ * attribute mistake rather than name mistake seems more
+ * likely to be made by providers. - FM
+ */
+ if (*p == '=' ||
+ !strncasecomp(attr_start, "Expires", 7)) {
+ /*
+ * Get the value string.
+ */
+ if (*p == '=') {
+ p++;
+ }
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+ /*
+ * Hack alert! We must handle Netscape-style cookies with
+ * "Expires=Mon, 01-Jan-96 13:45:35 GMT" or
+ * "Expires=Mon, 1 Jan 1996 13:45:35 GMT".
+ * No quotes, but there are spaces. Argh...
+ * Anyway, we know it will have at least 3 space separators
+ * within it, and two dashes or two more spaces, so this code
+ * looks for a space after the 5th space separator or dash to
+ * mark the end of the value. - FM
+ */
+ if ((attr_end - attr_start) == 7 &&
+ !strncasecomp(attr_start, "Expires", 7)) {
+ int spaces = 6;
+ value_start = p;
+ if (isdigit((unsigned char)*p)) {
+ /*
+ * No alphabetic day field. - FM
+ */
+ spaces--;
+ } else {
+ /*
+ * Skip the alphabetic day field. - FM
+ */
+ while (*p != '\0' && isalpha((unsigned char)*p)) {
+ p++;
+ }
+ while (*p == ',' || isspace((unsigned char)*p)) {
+ p++;
+ }
+ spaces--;
+ }
+ while (*p != '\0' && *p != ';' && *p != ',' && spaces) {
+ p++;
+ if (isspace((unsigned char)*p)) {
+ while (isspace((unsigned char)*(p + 1)))
+ p++;
+ spaces--;
+ } else if (*p == '-') {
+ spaces--;
+ }
+ }
+ value_end = p;
+ /*
+ * Hack Alert! The port attribute can take a
+ * comma separated list of numbers as a value,
+ * and such values should be quoted, but if
+ * not, make sure we don't treat a number in
+ * the list as the start of a new cookie. - FM
+ */
+ } else if ((attr_end - attr_start) == 4 &&
+ !strncasecomp(attr_start, "port", 4) &&
+ isdigit((unsigned char)*p)) {
+ /*
+ * The value starts as an unquoted number.
+ */
+ CONST char *cp, *cp1;
+ value_start = p;
+ while (1) {
+ while (isdigit((unsigned char)*p))
+ p++;
+ value_end = p;
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '\0' || *p == ';')
+ break;
+ if (*p == ',') {
+ cp = (p + 1);
+ while (*cp != '\0' && isspace((unsigned char)*cp))
+ cp++;
+ if (*cp != '\0' && isdigit((unsigned char)*cp)) {
+ cp1 = cp;
+ while (isdigit((unsigned char)*cp1))
+ cp1++;
+ while (*cp != '\0' && isspace((unsigned char)*cp))
+ cp1++;
+ if (*cp1 == '\0' || *cp1 == ',' || *cp1 == ';') {
+ p = cp;
+ continue;
+ }
+ }
+ }
+ while (*p != '\0' && *p != ';' && *p != ',')
+ p++;
+ value_end = p;
+ /*
+ * Trim trailing spaces.
+ */
+ if ((value_end > value_start) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ while ((value_end > (value_start + 1)) &&
+ isspace((unsigned char)*value_end) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ }
+ }
+ break;
+ }
+ } else if (*p == '"') {
+ /*
+ * It's a quoted string.
+ */
+ p++;
+ value_start = p;
+ while (*p != '\0' && *p != '"')
+ p++;
+ value_end = p;
+ if (*p == '"')
+ p++;
+ } else {
+ /*
+ * Otherwise, it's an unquoted string.
+ */
+ value_start = p;
+ while (*p != '\0' && *p != ';' && *p != ',')
+ p++;
+ value_end = p;
+ /*
+ * Trim trailing spaces.
+ */
+ if ((value_end > value_start) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ while ((value_end > (value_start + 1)) &&
+ isspace((unsigned char)*value_end) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ }
+ }
+ }
+ }
+
+ /*
+ * Check for a separator character, and skip it.
+ */
+ if (*p == ';' || *p == ',')
+ p++;
+
+ /*
+ * Now, we can handle this attribute/value pair.
+ */
+ if (attr_end > attr_start) {
+ int len = (attr_end - attr_start);
+ BOOLEAN known_attr = NO;
+ char *value = NULL;
+
+ if (value_end > value_start) {
+ int value_len = (value_end - value_start);
+
+ if (value_len > 4096) {
+ value_len = 4096;
+ }
+ value = (char *)calloc(1, value_len + 1);
+ if (value == NULL)
+ outofmem(__FILE__, "LYProcessSetCookies");
+ LYstrncpy(value, value_start, value_len);
+ }
+ if (len == 6 && !strncasecomp(attr_start, "secure", 6)) {
+ if (value == NULL) {
+ known_attr = YES;
+ if (cur_cookie != NULL) {
+ cur_cookie->flags |= COOKIE_FLAG_SECURE;
+ }
+ } else {
+ /*
+ * If secure has a value, assume someone
+ * misused it as cookie name. - FM
+ */
+ known_attr = NO;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "discard", 7)) {
+ if (value == NULL) {
+ known_attr = YES;
+ if (cur_cookie != NULL) {
+ cur_cookie->flags |= COOKIE_FLAG_DISCARD;
+ }
+ } else {
+ /*
+ * If discard has a value, assume someone
+ * used it as a cookie name. - FM
+ */
+ known_attr = NO;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "comment", 7)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat comment. - FM
+ */
+ cur_cookie->comment == NULL) {
+ StrAllocCopy(cur_cookie->comment, value);
+ length += strlen(cur_cookie->comment);
+ }
+ } else if (len == 10 && !strncasecomp(attr_start,
+ "commentURL", 10)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat commentURL. - FM
+ */
+ cur_cookie->commentURL == NULL) {
+ /*
+ * We should get only absolute URLs as
+ * values, but will resolve versus the
+ * request's URL just in case. - FM
+ */
+ cur_cookie->commentURL = HTParse(value,
+ address,
+ PARSE_ALL);
+ /*
+ * Accept only URLs for http or https servers. - FM
+ */
+ if ((url_type = is_url(cur_cookie->commentURL)) &&
+ (url_type == HTTP_URL_TYPE ||
+ url_type == HTTPS_URL_TYPE)) {
+ length += strlen(cur_cookie->commentURL);
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting commentURL value '%s'\n",
+ cur_cookie->commentURL);
+ FREE(cur_cookie->commentURL);
+ }
+ }
+ } else if (len == 6 && !strncasecomp(attr_start, "domain", 6)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat domain. - FM
+ */
+ !(cur_cookie->flags & COOKIE_FLAG_DOMAIN_SET)) {
+ length -= strlen(cur_cookie->domain);
+ /*
+ * If the value does not have a lead dot,
+ * but does have an embedded dot, and is
+ * not an exact match to the hostname, nor
+ * is a numeric IP address, add a lead dot.
+ * Otherwise, use the value as is. - FM
+ */
+ if (value[0] != '.' && value[0] != '\0' &&
+ value[1] != '\0' && strcmp(value, hostname)) {
+ char *ptr = strchr(value, '.');
+ if (ptr != NULL && ptr[1] != '\0') {
+ ptr = value;
+ while (*ptr == '.' ||
+ isdigit((unsigned char)*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Adding lead dot for domain value '%s'\n",
+ value);
+ }
+ StrAllocCopy(cur_cookie->domain, ".");
+ StrAllocCat(cur_cookie->domain, value);
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ length += strlen(cur_cookie->domain);
+ cur_cookie->flags |= COOKIE_FLAG_DOMAIN_SET;
+ }
+ } else if (len == 4 && !strncasecomp(attr_start, "path", 4)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat path. - FM
+ */
+ !(cur_cookie->flags & COOKIE_FLAG_PATH_SET)) {
+ length -= strlen(cur_cookie->path);
+ StrAllocCopy(cur_cookie->path, value);
+ length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+ cur_cookie->flags |= COOKIE_FLAG_PATH_SET;
+ }
+ } else if (len == 4 && !strncasecomp(attr_start, "port", 4)) {
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat port. - FM
+ */
+ cur_cookie->PortList == NULL) {
+ char *cp = value;
+ while ((*cp != '\0') &&
+ (isdigit((unsigned char)*cp) ||
+ *cp == ',' || *cp == ' ')) {
+ cp++;
+ }
+ if (*cp == '\0') {
+ StrAllocCopy(cur_cookie->PortList, value);
+ length += strlen(cur_cookie->PortList);
+ known_attr = YES;
+ } else {
+ known_attr = NO;
+ }
+ } else if (cur_cookie != NULL) {
+ /*
+ * Don't process a repeat port. - FM
+ */
+ if (cur_cookie->PortList == NULL) {
+ char temp[256];
+ sprintf(temp, "%d", port);
+ StrAllocCopy(cur_cookie->PortList, temp);
+ length += strlen(cur_cookie->PortList);
+ }
+ known_attr = YES;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "version", 7)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat version. - FM
+ */
+ cur_cookie->version < 1) {
+ int temp = strtol(value, NULL, 10);
+ if (errno != -ERANGE) {
+ cur_cookie->version = temp;
+ }
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "max-age", 7)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat max-age. - FM
+ */
+ !MaxAgeAttrSet) {
+ int temp = strtol(value, NULL, 10);
+ cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+ if (errno == -ERANGE) {
+ cur_cookie->expires = (time_t)0;
+ } else {
+ cur_cookie->expires = (time(NULL) + temp);
+ if (TRACE)
+ fprintf(stderr,
+ "LYSetCookie: expires %ld, %s",
+ (long) cur_cookie->expires,
+ ctime(&cur_cookie->expires));
+ }
+ MaxAgeAttrSet = TRUE;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "expires", 7)) {
+ /*
+ * Convert an 'expires' attribute value if we haven't
+ * received a 'max-age'. Note that 'expires' should not
+ * be used in Version 1 cookies, but it might be used for
+ * "backward compatibility", and, in turn, ill-informed
+ * people surely would start using it instead of, rather
+ * than in addition to, 'max-age'. - FM
+ */
+ known_attr = YES;
+ if ((cur_cookie != NULL && !MaxAgeAttrSet) &&
+ !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) {
+ known_attr = YES;
+ if (value) {
+ cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+ cur_cookie->expires = LYmktime(value, FALSE);
+ if (cur_cookie->expires > 0) {
+ if (TRACE)
+ fprintf(stderr,
+ "LYSetCookie: expires %ld, %s",
+ (long) cur_cookie->expires,
+ ctime(&cur_cookie->expires));
+ }
+ }
+ }
+ }
+
+ /*
+ * If none of the above comparisons succeeded, and we have
+ * a value, then we have an unknown pair of the form 'foo=bar',
+ * which means it's time to create a new cookie. If we don't
+ * have a non-zero-length value, assume it's an error or a
+ * new, unknown attribute which doesn't take a value, and
+ * ignore it. - FM
+ */
+ if (!known_attr && value_end > value_start) {
+ /*
+ * If we've started a cookie, and it's not too big,
+ * save it in the CombinedCookies list. - FM
+ */
+ if (length <= 4096 && cur_cookie != NULL) {
+ /*
+ * Assume version 1 if not set to that or higher. - FM
+ */
+ if (cur_cookie->version < 1) {
+ cur_cookie->version = 1;
+ }
+ HTList_appendObject(CombinedCookies, cur_cookie);
+ } else if (cur_cookie != NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting Set-Cookie2: %s=%s\n",
+ (cur_cookie->name ?
+ cur_cookie->name : "[no name]"),
+ (cur_cookie->value ?
+ cur_cookie->value : "[no value]"));
+ fprintf(stderr,
+ " due to excessive length!\n");
+ }
+ freeCookie(cur_cookie);
+ cur_cookie = NULL;
+ }
+ /*
+ * Start a new cookie. - FM
+ */
+ cur_cookie = newCookie();
+ length = 0;
+ NumCookies++;
+ MemAllocCopy(&(cur_cookie->name), attr_start, attr_end);
+ length += strlen(cur_cookie->name);
+ MemAllocCopy(&(cur_cookie->value), value_start, value_end);
+ length += strlen(cur_cookie->value);
+ StrAllocCopy(cur_cookie->domain, hostname);
+ length += strlen(cur_cookie->domain);
+ StrAllocCopy(cur_cookie->path, path);
+ length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+ cur_cookie->port = port;
+ MaxAgeAttrSet = FALSE;
+ cur_cookie->quoted = TRUE;
+ }
+ FREE(value);
+ }
+ }
+
+ /*
+ * Add any final SetCookie2 cookie to the CombinedCookie list
+ * if we are within the length limit. - FM
+ */
+ if (NumCookies <= 50 && length <= 4096 && cur_cookie != NULL) {
+ if (cur_cookie->version < 1) {
+ cur_cookie->version = 1;
+ }
+ HTList_appendObject(CombinedCookies, cur_cookie);
+ } else if (cur_cookie != NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting Set-Cookie2: %s=%s\n",
+ (cur_cookie->name ? cur_cookie->name : "[no name]"),
+ (cur_cookie->value ? cur_cookie->value : "[no value]"));
+ fprintf(stderr,
+ " due to excessive %s%s%s\n",
+ (length > 4096 ? "length" : ""),
+ (length > 4096 && NumCookies > 50 ? " and " : ""),
+ (NumCookies > 50 ? "number!\n" : "!\n"));
+ }
+ freeCookie(cur_cookie);
+ cur_cookie = NULL;
+ }
+
+ /*
+ * Process the Set-Cookie header, if no non-zero-length Set-Cookie2
+ * header was present. - FM
+ */
+ length = 0;
+ NumCookies = 0;
+ cur_cookie = NULL;
+ p = ((SetCookie && !(SetCookie2 && *SetCookie2)) ? SetCookie : "");
+ if (TRACE && SetCookie2 && *p) {
+ fprintf(stderr, "LYProcessSetCookies: Using Set-Cookie header.\n");
+ }
+ while (NumCookies <= 50 && *p) {
+ attr_start = attr_end = value_start = value_end = NULL;
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+ /*
+ * Get the attribute name.
+ */
+ attr_start = p;
+ while (*p != '\0' && !isspace((unsigned char)*p) &&
+ *p != '=' && *p != ';' && *p != ',')
+ p++;
+ attr_end = p;
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+
+ /*
+ * Check for an '=' delimiter, or an 'expires' name followed
+ * by white, since Netscape's bogus parser doesn't require
+ * an '=' delimiter, and 'expires' attributes are being
+ * encountered without them. - FM
+ */
+ if (*p == '=' ||
+ !strncasecomp(attr_start, "Expires", 7)) {
+ /*
+ * Get the value string.
+ */
+ if (*p == '=') {
+ p++;
+ }
+ while (*p != '\0' && isspace((unsigned char)*p)) {
+ p++;
+ }
+ /*
+ * Hack alert! We must handle Netscape-style cookies with
+ * "Expires=Mon, 01-Jan-96 13:45:35 GMT" or
+ * "Expires=Mon, 1 Jan 1996 13:45:35 GMT".
+ * No quotes, but there are spaces. Argh...
+ * Anyway, we know it will have at least 3 space separators
+ * within it, and two dashes or two more spaces, so this code
+ * looks for a space after the 5th space separator or dash to
+ * mark the end of the value. - FM
+ */
+ if ((attr_end - attr_start) == 7 &&
+ !strncasecomp(attr_start, "Expires", 7)) {
+ int spaces = 6;
+ value_start = p;
+ if (isdigit((unsigned char)*p)) {
+ /*
+ * No alphabetic day field. - FM
+ */
+ spaces--;
+ } else {
+ /*
+ * Skip the alphabetic day field. - FM
+ */
+ while (*p != '\0' && isalpha((unsigned char)*p)) {
+ p++;
+ }
+ while (*p == ',' || isspace((unsigned char)*p)) {
+ p++;
+ }
+ spaces--;
+ }
+ while (*p != '\0' && *p != ';' && *p != ',' && spaces) {
+ p++;
+ if (isspace((unsigned char)*p)) {
+ while (isspace((unsigned char)*(p + 1)))
+ p++;
+ spaces--;
+ } else if (*p == '-') {
+ spaces--;
+ }
+ }
+ value_end = p;
+ /*
+ * Hack Alert! The port attribute can take a
+ * comma separated list of numbers as a value,
+ * and such values should be quoted, but if
+ * not, make sure we don't treat a number in
+ * the list as the start of a new cookie. - FM
+ */
+ } else if ((attr_end - attr_start) == 4 &&
+ !strncasecomp(attr_start, "port", 4) &&
+ isdigit((unsigned char)*p)) {
+ /*
+ * The value starts as an unquoted number.
+ */
+ CONST char *cp, *cp1;
+ value_start = p;
+ while (1) {
+ while (isdigit((unsigned char)*p))
+ p++;
+ value_end = p;
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '\0' || *p == ';')
+ break;
+ if (*p == ',') {
+ cp = (p + 1);
+ while (*cp != '\0' && isspace((unsigned char)*cp))
+ cp++;
+ if (*cp != '\0' && isdigit((unsigned char)*cp)) {
+ cp1 = cp;
+ while (isdigit((unsigned char)*cp1))
+ cp1++;
+ while (*cp != '\0' && isspace((unsigned char)*cp))
+ cp1++;
+ if (*cp1 == '\0' || *cp1 == ',' || *cp1 == ';') {
+ p = cp;
+ continue;
+ }
+ }
+ }
+ while (*p != '\0' && *p != ';' && *p != ',')
+ p++;
+ value_end = p;
+ /*
+ * Trim trailing spaces.
+ */
+ if ((value_end > value_start) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ while ((value_end > (value_start + 1)) &&
+ isspace((unsigned char)*value_end) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ }
+ }
+ break;
+ }
+ } else if (*p == '"') {
+ /*
+ * It's a quoted string.
+ */
+ p++;
+ value_start = p;
+ while (*p != '\0' && *p != '"')
+ p++;
+ value_end = p;
+ if (*p == '"')
+ p++;
+ Quoted = TRUE;
+ } else {
+ /*
+ * Otherwise, it's an unquoted string.
+ */
+ value_start = p;
+ while (*p != '\0' && *p != ';' && *p != ',')
+ p++;
+ value_end = p;
+ /*
+ * Trim trailing spaces.
+ */
+ if ((value_end > value_start) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ while ((value_end > (value_start + 1)) &&
+ isspace((unsigned char)*value_end) &&
+ isspace((unsigned char)*(value_end - 1))) {
+ value_end--;
+ }
+ }
+ }
+ }
+
+ /*
+ * Check for a separator character, and skip it.
+ */
+ if (*p == ';' || *p == ',')
+ p++;
+
+ /*
+ * Now, we can handle this attribute/value pair.
+ */
+ if (attr_end > attr_start) {
+ int len = (attr_end - attr_start);
+ BOOLEAN known_attr = NO;
+ char *value = NULL;
+
+ if (value_end > value_start) {
+ int value_len = (value_end - value_start);
+
+ if (value_len > 4096) {
+ value_len = 4096;
+ }
+ value = (char *)calloc(1, value_len + 1);
+ if (value == NULL)
+ outofmem(__FILE__, "LYProcessSetCookie");
+ LYstrncpy(value, value_start, value_len);
+ }
+ if (len == 6 && !strncasecomp(attr_start, "secure", 6)) {
+ if (value == NULL) {
+ known_attr = YES;
+ if (cur_cookie != NULL) {
+ cur_cookie->flags |= COOKIE_FLAG_SECURE;
+ }
+ } else {
+ /*
+ * If secure has a value, assume someone
+ * misused it as cookie name. - FM
+ */
+ known_attr = NO;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "discard", 7)) {
+ if (value == NULL) {
+ known_attr = YES;
+ if (cur_cookie != NULL) {
+ cur_cookie->flags |= COOKIE_FLAG_DISCARD;
+ }
+ } else {
+ /*
+ * If discard has a value, assume someone
+ * used it as a cookie name. - FM
+ */
+ known_attr = NO;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "comment", 7)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat comment. - FM
+ */
+ cur_cookie->comment == NULL) {
+ StrAllocCopy(cur_cookie->comment, value);
+ length += strlen(cur_cookie->comment);
+ }
+ } else if (len == 10 && !strncasecomp(attr_start,
+ "commentURL", 10)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat commentURL. - FM
+ */
+ cur_cookie->commentURL == NULL) {
+ /*
+ * We should get only absolute URLs as
+ * values, but will resolve versus the
+ * request's URL just in case. - FM
+ */
+ cur_cookie->commentURL = HTParse(value,
+ address,
+ PARSE_ALL);
+ /*
+ * Accept only URLs for http or https servers. - FM
+ */
+ if ((url_type = is_url(cur_cookie->commentURL)) &&
+ (url_type == HTTP_URL_TYPE ||
+ url_type == HTTPS_URL_TYPE)) {
+ length += strlen(cur_cookie->commentURL);
+ } else {
+ if (TRACE)
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting commentURL value '%s'\n",
+ cur_cookie->commentURL);
+ FREE(cur_cookie->commentURL);
+ }
+ }
+ } else if (len == 6 && !strncasecomp(attr_start, "domain", 6)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat domain. - FM
+ */
+ !(cur_cookie->flags & COOKIE_FLAG_DOMAIN_SET)) {
+ length -= strlen(cur_cookie->domain);
+ /*
+ * If the value does not have a lead dot,
+ * but does have an embedded dot, and is
+ * not an exact match to the hostname, nor
+ * is a numeric IP address, add a lead dot.
+ * Otherwise, use the value as is. - FM
+ */
+ if (value[0] != '.' && value[0] != '\0' &&
+ value[1] != '\0' && strcmp(value, hostname)) {
+ char *ptr = strchr(value, '.');
+ if (ptr != NULL && ptr[1] != '\0') {
+ ptr = value;
+ while (*ptr == '.' ||
+ isdigit((unsigned char)*ptr))
+ ptr++;
+ if (*ptr != '\0') {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Adding lead dot for domain value '%s'\n",
+ value);
+ }
+ StrAllocCopy(cur_cookie->domain, ".");
+ StrAllocCat(cur_cookie->domain, value);
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ } else {
+ StrAllocCopy(cur_cookie->domain, value);
+ }
+ length += strlen(cur_cookie->domain);
+ cur_cookie->flags |= COOKIE_FLAG_DOMAIN_SET;
+ }
+ } else if (len == 4 && !strncasecomp(attr_start, "path", 4)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat path. - FM
+ */
+ !(cur_cookie->flags & COOKIE_FLAG_PATH_SET)) {
+ length -= strlen(cur_cookie->path);
+ StrAllocCopy(cur_cookie->path, value);
+ length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+ cur_cookie->flags |= COOKIE_FLAG_PATH_SET;
+ }
+ } else if (len == 4 && !strncasecomp(attr_start, "port", 4)) {
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat port. - FM
+ */
+ cur_cookie->PortList == NULL) {
+ char *cp = value;
+ while ((*cp != '\0') &&
+ (isdigit((unsigned char)*cp) ||
+ *cp == ',' || *cp == ' ')) {
+ cp++;
+ }
+ if (*cp == '\0') {
+ StrAllocCopy(cur_cookie->PortList, value);
+ length += strlen(cur_cookie->PortList);
+ known_attr = YES;
+ } else {
+ known_attr = NO;
+ }
+ } else if (cur_cookie != NULL) {
+ /*
+ * Don't process a repeat port. - FM
+ */
+ if (cur_cookie->PortList == NULL) {
+ char temp[256];
+ sprintf(temp, "%d", port);
+ StrAllocCopy(cur_cookie->PortList, temp);
+ length += strlen(cur_cookie->PortList);
+ }
+ known_attr = YES;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "version", 7)) {
+ known_attr = YES;
+ if (cur_cookie != NULL && value &&
+ /*
+ * Don't process a repeat version. - FM
+ */
+ cur_cookie->version < 0) {
+ int temp = strtol(value, NULL, 10);
+ if (errno != -ERANGE) {
+ cur_cookie->version = temp;
+ }
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "max-age", 7)) {
+ known_attr = YES;
+ if ((cur_cookie != NULL) && !MaxAgeAttrSet && value) {
+ int temp = strtol(value, NULL, 10);
+ cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+ if (errno == -ERANGE) {
+ cur_cookie->expires = (time_t)0;
+ } else {
+ cur_cookie->expires = (time(NULL) + temp);
+ }
+ MaxAgeAttrSet = TRUE;
+ }
+ } else if (len == 7 && !strncasecomp(attr_start, "expires", 7)) {
+ /*
+ * Convert an 'expires' attribute value if we haven't
+ * received a 'max-age'. Note that 'expires' should not
+ * be used in Version 1 cookies, but it might be used for
+ * "backward compatibility", and, in turn, ill-informed
+ * people surely would start using it instead of, rather
+ * than in addition to, 'max-age'. - FM
+ */
+ known_attr = YES;
+ if ((cur_cookie != NULL) && !(MaxAgeAttrSet) &&
+ !(cur_cookie->flags & COOKIE_FLAG_EXPIRES_SET)) {
+ if (value) {
+ cur_cookie->flags |= COOKIE_FLAG_EXPIRES_SET;
+ cur_cookie->expires = LYmktime(value, FALSE);
+ }
+ }
+ }
+
+ /*
+ * If none of the above comparisons succeeded, and we have
+ * a value, then we have an unknown pair of the form 'foo=bar',
+ * which means it's time to create a new cookie. If we don't
+ * have a non-zero-length value, assume it's an error or a
+ * new, unknown attribute which doesn't take a value, and
+ * ignore it. - FM
+ */
+ if (!known_attr && value_end > value_start) {
+ /*
+ * If we've started a cookie, and it's not too big,
+ * save it in the CombinedCookies list. - FM
+ */
+ if (length <= 4096 && cur_cookie != NULL) {
+ /*
+ * If we had a Set-Cookie2 header, make sure
+ * the version is at least 1, and mark it for
+ * quoting. - FM
+ */
+ if (SetCookie2 != NULL) {
+ if (cur_cookie->version < 1) {
+ cur_cookie->version = 1;
+ }
+ cur_cookie->quoted = TRUE;
+ }
+ HTList_appendObject(CombinedCookies, cur_cookie);
+ } else if (cur_cookie != NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting Set-Cookie: %s=%s\n",
+ (cur_cookie->name ?
+ cur_cookie->name : "[no name]"),
+ (cur_cookie->value ?
+ cur_cookie->value : "[no value]"));
+ fprintf(stderr,
+ " due to excessive length!\n");
+ }
+ freeCookie(cur_cookie);
+ cur_cookie = NULL;
+ }
+ /*
+ * Start a new cookie. - FM
+ */
+ cur_cookie = newCookie();
+ length = 0;
+ MemAllocCopy(&(cur_cookie->name), attr_start, attr_end);
+ length += strlen(cur_cookie->name);
+ MemAllocCopy(&(cur_cookie->value), value_start, value_end);
+ length += strlen(cur_cookie->value);
+ StrAllocCopy(cur_cookie->domain, hostname);
+ length += strlen(cur_cookie->domain);
+ StrAllocCopy(cur_cookie->path, path);
+ length += (cur_cookie->pathlen = strlen(cur_cookie->path));
+ cur_cookie->port = port;
+ MaxAgeAttrSet = FALSE;
+ cur_cookie->quoted = Quoted;
+ Quoted = FALSE;
+ }
+ FREE(value);
+ }
+ }
+
+ /*
+ * Handle the final Set-Cookie cookie if within length limit. - FM
+ */
+ if (NumCookies <= 50 && length <= 4096 && cur_cookie != NULL) {
+ if (SetCookie2 != NULL) {
+ if (cur_cookie->version < 1) {
+ cur_cookie->version = 1;
+ }
+ cur_cookie->quoted = TRUE;
+ }
+ HTList_appendObject(CombinedCookies, cur_cookie);
+ } else if (cur_cookie != NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYProcessSetCookies: Rejecting Set-Cookie: %s=%s\n",
+ (cur_cookie->name ? cur_cookie->name : "[no name]"),
+ (cur_cookie->value ? cur_cookie->value : "[no value]"));
+ fprintf(stderr,
+ " due to excessive %s%s%s\n",
+ (length > 4096 ? "length" : ""),
+ (length > 4096 && NumCookies > 50 ? " and " : ""),
+ (NumCookies > 50 ? "number!\n" : "!\n"));
+ }
+ freeCookie(cur_cookie);
+ cur_cookie = NULL;
+ }
+
+ /*
+ * OK, now we can actually store any cookies
+ * in the CombinedCookies list. - FM
+ */
+ cl = CombinedCookies;
+ while (NULL != (co = (cookie *)HTList_nextObject(cl))) {
+ if (TRACE) {
+ fprintf(stderr, "LYProcessSetCookie: attr=value pair: '%s=%s'\n",
+ (co->name ? co->name : "[no name]"),
+ (co->value ? co->value : "[no value]"));
+ if (co->expires > 0) {
+ fprintf(stderr, " expires: %ld, %s\n",
+ (long)co->expires,
+ ctime(&co->expires));
+ }
+ }
+ if (!strncasecomp(address, "https:", 6) &&
+ LYForceSSLCookiesSecure == TRUE &&
+ !(co->flags & COOKIE_FLAG_SECURE)) {
+ co->flags |= COOKIE_FLAG_SECURE;
+ if (TRACE) {
+ fprintf(stderr,
+ " Forced the 'secure' flag on.\n");
+ }
+ }
+ store_cookie(co, hostname, path);
+ }
+ HTList_delete(CombinedCookies);
+ CombinedCookies = NULL;
+
+ return;
+}
+
+/*
+** Entry function for handling Set-Cookie: and/or Set-Cookie2:
+** reply headers. They may have been concatenated as comma
+** separated lists in HTTP.c or HTMIME.c. - FM
+*/
+PUBLIC void LYSetCookie ARGS3(
+ CONST char *, SetCookie,
+ CONST char *, SetCookie2,
+ CONST char *, address)
+{
+ BOOL BadHeaders = FALSE;
+ char *hostname = NULL, *path = NULL, *ptr;
+ int port = 80;
+
+ /*
+ * Get the hostname, port and path of the address, and report
+ * the Set-Cookie and/or Set-Cookie2 header(s) if trace mode is
+ * on, but set the cookie(s) only if LYSetCookies is TRUE. - FM
+ */
+ if (((hostname = HTParse(address, "", PARSE_HOST)) != NULL) &&
+ (ptr = strchr(hostname, ':')) != NULL) {
+ /*
+ * Replace default port number.
+ */
+ *ptr = '\0';
+ ptr++;
+ port = atoi(ptr);
+ } else if (!strncasecomp(address, "https:", 6)) {
+ port = 443;
+ }
+ if (((path = HTParse(address, "",
+ PARSE_PATH|PARSE_PUNCTUATION)) != NULL) &&
+ (ptr = strrchr(path, '/')) != NULL) {
+ if (ptr == path) {
+ *(ptr+1) = '\0'; /* Leave a single '/' alone */
+ } else {
+ *ptr = '\0';
+ }
+ }
+ if (!(SetCookie && *SetCookie) &&
+ !(SetCookie2 && *SetCookie2)) {
+ /*
+ * Yuk, something must have gone wrong in
+ * HTMIME.c or HTTP.c because both SetCookie
+ * and SetCookie2 are NULL or zero-length. - FM
+ */
+ BadHeaders = TRUE;
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "LYSetCookie called with host '%s', path '%s',\n",
+ (hostname ? hostname : ""),
+ (path ? path : ""));
+ if (SetCookie) {
+ fprintf(stderr, " and Set-Cookie: '%s'\n",
+ (SetCookie ? SetCookie : ""));
+ }
+ if (SetCookie2) {
+ fprintf(stderr, " and Set-Cookie2: '%s'\n",
+ (SetCookie2 ? SetCookie2 : ""));
+ }
+ if (LYSetCookies == FALSE || BadHeaders == TRUE) {
+ fprintf(stderr,
+ " Ignoring this Set-Cookie/Set-Cookie2 request.\n");
+ }
+ }
+
+ /*
+ * We're done if LYSetCookies is off or we have bad headers. - FM
+ */
+ if (LYSetCookies == FALSE || BadHeaders == TRUE) {
+ FREE(hostname);
+ FREE(path);
+ return;
+ }
+
+ /*
+ * Process the header(s).
+ */
+ LYProcessSetCookies(SetCookie, SetCookie2, address, hostname, path, port);
+ FREE(hostname);
+ FREE(path);
+ return;
+}
+
+/*
+** Entry function from creating a Cookie: request header
+** if needed. - AK & FM
+*/
+PUBLIC char * LYCookie ARGS4(
+ CONST char *, hostname,
+ CONST char *, path,
+ int, port,
+ BOOL, secure)
+{
+ char *header = NULL;
+ HTList *hl = domain_list, *next = NULL;
+ domain_entry *de;
+
+ if (TRACE) {
+ fprintf(stderr,
+ "LYCookie: Searching for '%s:%d', '%s'.\n",
+ (hostname ? hostname : "(null)"),
+ port,
+ (path ? path : "(null)"));
+ }
+
+ /*
+ * Search the cookie_list elements in the domain_list
+ * for any cookies associated with the //hostname:port/path
+ */
+ while (hl) {
+ de = (domain_entry *)hl->object;
+ next = hl->next;
+
+ if (de != NULL) {
+ if (!HTList_isEmpty(de->cookie_list)) {
+ /*
+ * Scan the domain's cookie_list for
+ * any cookies we should include in
+ * our request header.
+ */
+ header = scan_cookie_sublist(hostname, path, port,
+ de->cookie_list, header, secure);
+ } else if (de->bv == QUERY_USER) {
+ /*
+ * No cookies in this domain, and no default
+ * accept/reject choice was set by the user,
+ * so delete the domain. - FM
+ */
+ FREE(de->domain);
+ HTList_delete(de->cookie_list);
+ de->cookie_list = NULL;
+ HTList_removeObject(domain_list, de);
+ de = NULL;
+ }
+ }
+ hl = next;
+ }
+ if (header)
+ return(header);
+
+ /*
+ * If we didn't set a header, perhaps all the cookies have
+ * expired and we deleted the last of them above, so check
+ * if we should delete and NULL the domain_list. - FM
+ */
+ if (domain_list) {
+ if (HTList_isEmpty(domain_list)) {
+ HTList_delete(domain_list);
+ domain_list = NULL;
+ }
+ }
+ return(NULL);
+}
+
+/* LYHandleCookies - F.Macrides (macrides@sci.wfeb.edu)
+** ---------------
+**
+** Lists all cookies by domain, and allows deletions of
+** individual cookies or entire domains, and changes of
+** 'allow' settings. The list is invoked via the COOKIE_JAR
+** command (Ctrl-K), and deletions or changes of 'allow'
+** settings are done by activating links in that list.
+** The procedure uses a LYNXCOOKIE: internal URL scheme.
+**
+** Semantics:
+** LYNXCOOKIE:/ Create and load the Cookie Jar Page.
+** LYNXCOOKIE://domain Manipulate the domain.
+** LYNXCOOKIE://domain/lynxID Delete cookie with lynxID in domain.
+**
+** New functions can be added as extensions to the path, and/or by
+** assigning meanings to ;parameters, a ?searchpart, and/or #fragments.
+*/
+PRIVATE int LYHandleCookies ARGS4 (
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ HTFormat format_in = WWW_HTML;
+ HTStream *target = NULL;
+ char buf[1024];
+ char *domain = NULL;
+ char *lynxID = NULL;
+ HTList *dl, *cl, *next;
+ domain_entry *de;
+ cookie *co;
+ char *name = NULL, *value = NULL, *path = NULL;
+ char *comment = NULL, *Address = NULL, *Title = NULL;
+ int ch;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ /*
+ * Check whether we have something to do. - FM
+ */
+ if (domain_list == NULL) {
+ HTProgress(COOKIE_JAR_IS_EMPTY);
+ sleep(MessageSecs);
+ return(HT_NO_DATA);
+ }
+
+ /*
+ * If there's a domain string in the "host" field of the
+ * LYNXCOOKIE: URL, this is a request to delete something
+ * or change and 'allow' setting. - FM
+ */
+ if ((domain = HTParse(arg, "", PARSE_HOST)) != NULL) {
+ if (*domain == '\0') {
+ FREE(domain);
+ } else {
+ /*
+ * If there is a path string (not just a slash) in the
+ * LYNXCOOKIE: URL, that's a cookie's lynxID and this
+ * is a request to delete it from the Cookie Jar. - FM
+ */
+ if ((lynxID = HTParse(arg, "", PARSE_PATH)) != NULL) {
+ if (*lynxID == '\0') {
+ FREE(lynxID);
+ }
+ }
+ }
+ }
+ if (domain) {
+ /*
+ * Seek the domain in the domain_list structure. - FM
+ */
+ for (dl = domain_list; dl != NULL; dl = dl->next) {
+ de = dl->object;
+ if (!(de && de->domain))
+ /*
+ * First object in the list always is empty. - FM
+ */
+ continue;
+ if (!strcmp(domain, de->domain)) {
+ /*
+ * We found the domain. Check
+ * whether a lynxID is present. - FM
+ */
+ if (lynxID) {
+ /*
+ * Seek and delete the cookie with this lynxID
+ * in the domain's cookie list. - FM
+ */
+ for (cl = de->cookie_list; cl != NULL; cl = cl->next) {
+ if ((co = (cookie *)cl->object) == NULL)
+ /*
+ * First object is always empty. - FM
+ */
+ continue;
+ if (!strcmp(lynxID, co->lynxID)) {
+ /*
+ * We found the cookie.
+ * Delete it if confirmed. - FM
+ */
+ if (HTConfirm(DELETE_COOKIE_CONFIRMATION) == FALSE)
+ return(HT_NO_DATA);
+ HTList_removeObject(de->cookie_list, co);
+ freeCookie(co);
+ co = NULL;
+ total_cookies--;
+ if ((de->bv == QUERY_USER &&
+ HTList_isEmpty(de->cookie_list)) &&
+ HTConfirm(DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
+ /*
+ * No more cookies in this domain, no
+ * default accept/reject choice was set
+ * by the user, and got confirmation on
+ * deleting the domain, so do it. - FM
+ */
+ FREE(de->domain);
+ HTList_delete(de->cookie_list);
+ de->cookie_list = NULL;
+ HTList_removeObject(domain_list, de);
+ de = NULL;
+ HTProgress(DOMAIN_EATEN);
+ } else {
+ HTProgress(COOKIE_EATEN);
+ }
+ sleep(MessageSecs);
+ break;
+ }
+ }
+ } else {
+ /*
+ * Prompt whether to delete all of the cookies in
+ * this domain, or the domain if no cookies in it,
+ * or to change its 'allow' setting, or to cancel,
+ * and then act on the user's response. - FM
+ */
+ if (HTList_isEmpty(de->cookie_list)) {
+ _statusline(DELETE_DOMAIN_SET_ALLOW_OR_CANCEL);
+ } else {
+ _statusline(DELETE_COOKIES_SET_ALLOW_OR_CANCEL);
+ }
+ while (1) {
+ ch = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ ch = 'C';
+ }
+#endif /* VMS */
+ switch(TOUPPER(ch)) {
+ case 'A':
+ /*
+ * Set to accept all cookies
+ * from this domain. - FM
+ */
+ de->bv = QUERY_USER;
+ _user_message(ALWAYS_ALLOWING_COOKIES,
+ de->domain);
+ sleep(MessageSecs);
+ return(HT_NO_DATA);
+
+ case 'C':
+ case 7: /* Ctrl-G */
+ case 3: /* Ctrl-C */
+ /*
+ * Cancelled. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(MessageSecs);
+ return(HT_NO_DATA);
+
+ case 'D':
+ if (HTList_isEmpty(de->cookie_list)) {
+ /*
+ * We had an empty domain, so we
+ * were asked to delete it. - FM
+ */
+ FREE(de->domain);
+ HTList_delete(de->cookie_list);
+ de->cookie_list = NULL;
+ HTList_removeObject(domain_list, de);
+ de = NULL;
+ HTProgress(DOMAIN_EATEN);
+ sleep(MessageSecs);
+ break;
+ }
+Delete_all_cookies_in_domain:
+ /*
+ * Delete all cookies in this domain. - FM
+ */
+ cl = de->cookie_list;
+ while (cl) {
+ next = cl->next;
+ co = cl->object;
+ if (co) {
+ HTList_removeObject(de->cookie_list,
+ co);
+ freeCookie(co);
+ co = NULL;
+ total_cookies--;
+ }
+ cl = next;
+ }
+ HTProgress(DOMAIN_COOKIES_EATEN);
+ sleep(MessageSecs);
+ /*
+ * If a default accept/reject
+ * choice is set, we're done. - FM
+ */
+ if (de->bv != QUERY_USER)
+ return(HT_NO_DATA);
+ /*
+ * Check whether to delete
+ * the empty domain. - FM
+ */
+ if(HTConfirm(
+ DELETE_EMPTY_DOMAIN_CONFIRMATION)) {
+ FREE(de->domain);
+ HTList_delete(de->cookie_list);
+ de->cookie_list = NULL;
+ HTList_removeObject(domain_list, de);
+ de = NULL;
+ HTProgress(DOMAIN_EATEN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case 'P':
+ /*
+ * Set to prompt for cookie acceptence
+ * from this domain. - FM
+ */
+ de->bv = QUERY_USER;
+ _user_message(PROMTING_TO_ALLOW_COOKIES,
+ de->domain);
+ sleep(MessageSecs);
+ return(HT_NO_DATA);
+
+ case 'V':
+ /*
+ * Set to reject all cookies
+ * from this domain. - FM
+ */
+ de->bv = REJECT_ALWAYS;
+ _user_message(NEVER_ALLOWING_COOKIES,
+ de->domain);
+ sleep(MessageSecs);
+ if ((!HTList_isEmpty(de->cookie_list)) &&
+ HTConfirm(DELETE_ALL_COOKIES_IN_DOMAIN))
+ goto Delete_all_cookies_in_domain;
+ return(HT_NO_DATA);
+
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ if (HTList_isEmpty(domain_list)) {
+ /*
+ * There are no more domains left,
+ * so delete the domain_list. - FM
+ */
+ HTList_delete(domain_list);
+ domain_list = NULL;
+ HTProgress(ALL_COOKIES_EATEN);
+ sleep(MessageSecs);
+ }
+ return(HT_NO_DATA);
+ }
+
+ /*
+ * If we get to here, it was a LYNXCOOKIE:/ URL
+ * for creating and displaying the Cookie Jar Page,
+ * or we didn't find the domain or cookie in a
+ * deletion request. Set up an HTML stream and
+ * return an updated Cookie Jar Page. - FM
+ */
+ target = HTStreamStack(format_in,
+ format_out,
+ sink, anAnchor);
+ if (!target || target == NULL) {
+ sprintf(buf, CANNOT_CONVERT_I_TO_O,
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ HTAlert(buf);
+ return(HT_NOT_LOADED);
+ }
+
+ /*
+ * Load HTML strings into buf and pass buf
+ * to the target for parsing and rendering. - FM
+ */
+ sprintf(buf, "<HEAD>\n<TITLE>%s</title>\n</HEAD>\n<BODY>\n",
+ COOKIE_JAR_TITLE);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "<H1>%s</H1>\n", REACHED_COOKIE_JAR_PAGE);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ sprintf(buf, "<H2>%s Version %s</H2>\n", LYNX_NAME, LYNX_VERSION);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "<NOTE>%s\n", ACTIVATE_TO_GOBBLE);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ sprintf(buf, "%s</NOTE>\n", OR_CHANGE_ALLOW);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "<DL COMPACT>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ for (dl = domain_list; dl != NULL; dl = dl->next) {
+ de = dl->object;
+ if (de == NULL)
+ /*
+ * First object always is NULL. - FM
+ */
+ continue;
+
+ /*
+ * Show the domain link and 'allow' setting. - FM
+ */
+ sprintf(buf, "<DT><A HREF=\"LYNXCOOKIE://%s/\">Domain=%s</A>\n",
+ de->domain, de->domain);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ switch (de->bv) {
+ case (ACCEPT_ALWAYS):
+ sprintf(buf, COOKIES_ALWAYS_ALLOWED);
+ break;
+ case (REJECT_ALWAYS):
+ sprintf(buf, COOKIES_NEVER_ALLOWED);
+ break;
+ case (QUERY_USER):
+ sprintf(buf, COOKIES_ALLOWED_VIA_PROMPT);
+ break;
+ }
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ /*
+ * Show the domain's cookies. - FM
+ */
+ for (cl = de->cookie_list; cl != NULL; cl = cl->next) {
+ if ((co = (cookie *)cl->object) == NULL)
+ /*
+ * First object is always NULL. - FM
+ */
+ continue;
+
+ /*
+ * Show the name=value pair. - FM
+ */
+ if (co->name) {
+ StrAllocCopy(name, co->name);
+ LYEntify(&name, TRUE);
+ } else {
+ StrAllocCopy(name, NO_NAME);
+ }
+ if (co->value) {
+ StrAllocCopy(value, co->value);
+ LYEntify(&value, TRUE);
+ } else {
+ StrAllocCopy(value, NO_VALUE);
+ }
+ sprintf(buf, "<DD><A HREF=\"LYNXCOOKIE://%s/%s\">%s=%s</A>\n",
+ de->domain, co->lynxID, name, value);
+ FREE(name);
+ FREE(value);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ /*
+ * Show the path, port, secure and discard setting. - FM
+ */
+ if (co->path) {
+ StrAllocCopy(path, co->path);
+ LYEntify(&path, TRUE);
+ } else {
+ StrAllocCopy(path, "/");
+ }
+ sprintf(buf, "<DD>Path=%s\n<DD>Port: %d Secure: %s Discard: %s\n",
+ path, co->port,
+ ((co->flags & COOKIE_FLAG_SECURE) ? "YES" : "NO"),
+ ((co->flags & COOKIE_FLAG_DISCARD) ? "YES" : "NO"));
+ FREE(path);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ /*
+ * Show the list of acceptable ports, if present. - FM
+ */
+ if (co->PortList) {
+ sprintf(buf, "<DD>PortList=\"%s\"\n", co->PortList);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+
+ /*
+ * Show the commentURL, if we have one. - FM
+ */
+ if (co->commentURL) {
+ StrAllocCopy(Address, co->commentURL);
+ LYEntify(&Address, FALSE);
+ StrAllocCopy(Title, co->commentURL);
+ LYEntify(&Title, TRUE);
+ sprintf(buf,
+ "<DD>CommentURL: <A href=\"%s\">%s</A>\n",
+ Address,
+ Title);
+ FREE(Address);
+ FREE(Title);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+
+ /*
+ * Show the comment, if we have one. - FM
+ */
+ if (co->comment) {
+ StrAllocCopy(comment, co->comment);
+ LYEntify(&comment, TRUE);
+ sprintf(buf, "<DD>Comment: %s\n", comment);
+ FREE(comment);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+
+ /*
+ * Show the Maximum Gobble Date. - FM
+ */
+ sprintf(buf, "<DD><EM>Maximum Gobble Date:</EM> %s%s",
+ ((co->expires > 0 &&
+ !(co->flags & COOKIE_FLAG_DISCARD))
+ ?
+ ctime(&co->expires) : END_OF_SESSION),
+ ((co->expires > 0 &&
+ !(co->flags & COOKIE_FLAG_DISCARD))
+ ?
+ "" : "\n"));
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+ sprintf(buf, "</DT>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+ sprintf(buf, "</DL>\n</BODY>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ /*
+ * Free the target to complete loading of the
+ * Cookie Jar Page, and report a successful load. - FM
+ */
+ (*target->isa->_free)(target);
+ return(HT_LOADED);
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _LYCOOKIE_C_GLOBALDEF_1_INIT { "LYNXCOOKIE",LYHandleCookies,0}
+GLOBALDEF (HTProtocol,LYLynxCookies,_LYCOOKIE_C_GLOBALDEF_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol LYLynxCookies = {"LYNXCOOKIE",LYHandleCookies,0};
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/src/LYCookie.h b/gnu/usr.bin/lynx/src/LYCookie.h
new file mode 100644
index 00000000000..9900a01756f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCookie.h
@@ -0,0 +1,24 @@
+
+#ifndef LYCOOKIES_H
+#define LYCOOKIES_H
+
+extern void LYSetCookie PARAMS((
+ CONST char * SetCookie,
+ CONST char * SetCookie2,
+ CONST char * address));
+extern char *LYCookie PARAMS((
+ CONST char * hostname,
+ CONST char * partialpath,
+ int port,
+ BOOL secure));
+
+typedef enum {ACCEPT_ALWAYS, REJECT_ALWAYS, QUERY_USER} behaviour;
+
+struct _domain_entry {
+ char * domain; /* Domain for which these cookies are valid */
+ behaviour bv;
+ HTList * cookie_list;
+};
+typedef struct _domain_entry domain_entry;
+
+#endif /* LYCOOKIES_H */
diff --git a/gnu/usr.bin/lynx/src/LYCurses.c b/gnu/usr.bin/lynx/src/LYCurses.c
new file mode 100644
index 00000000000..9defcfa2adc
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCurses.c
@@ -0,0 +1,1825 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYCurses.h"
+#include "LYStyle.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYMainLoop.h"
+#include "LYSignal.h"
+#include "LYClean.h"
+#include "LYReadCFG.h"
+#include "LYStrings.h"
+#include "LYCharSets.h"
+#include "UCAux.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+#if defined(VMS) && defined(__GNUC__)
+#include <gnu_hacks.h>
+#undef LINES
+#undef COLS
+#define LINES lines
+#define COLS cols
+extern int _NOSHARE(LINES);
+extern int _NOSHARE(COLS);
+#endif /* VMS && __GNUC__ */
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+#include "LYHash.h"
+#endif
+
+#if defined(COLOR_CURSES)
+int lynx_has_color = FALSE;
+#endif
+
+#define COLOR_BKGD ((COLOR_PAIRS >= 9) ? COLOR_PAIR(9) : A_NORMAL)
+
+/*
+ * These are routines to start and stop curses and to cleanup
+ * the screen at the end.
+ */
+
+PRIVATE int dumbterm PARAMS((char *terminal));
+BOOLEAN LYCursesON = FALSE;
+
+#if USE_COLOR_TABLE || defined(USE_SLANG)
+PRIVATE int Current_Attr;
+#endif
+
+#ifdef USE_SLANG
+PUBLIC unsigned int Lynx_Color_Flags = 0;
+PUBLIC BOOLEAN FullRefresh = FALSE;
+PUBLIC int curscr = 0;
+#ifdef SLANG_MBCS_HACK
+/*
+ * Will be set by size_change. - KW
+ */
+PUBLIC int PHYSICAL_SLtt_Screen_Cols = 10;
+#endif /* SLANG_MBCS_HACK */
+
+PUBLIC void LY_SLrefresh NOARGS
+{
+ if (FullRefresh) {
+ SLsmg_suspend_smg();
+ SLsmg_resume_smg();
+ FullRefresh = FALSE;
+ } else {
+ SLsmg_refresh();
+ }
+
+ return;
+}
+
+/* the following renamed from LY_SLclear since it is more like erase()
+ described in curses man pages than like clear(); but for USE_SLANG
+ clear() is still a macro calling this, and will do the same thing as
+ erase(). - kw */
+PUBLIC void LY_SLerase NOARGS
+{
+ SLsmg_gotorc (0, 0);
+ SLsmg_erase_eos ();
+}
+
+#ifdef VMS
+PUBLIC void VTHome NOARGS
+{
+ printf("\033[;H");
+
+ return;
+}
+#endif /* VMS */
+
+PUBLIC void LYaddAttr ARGS1(
+ int, a)
+{
+ Current_Attr |= a;
+ SLsmg_set_color(Current_Attr);
+}
+
+PUBLIC void LYsubAttr ARGS1(
+ int, a)
+{
+ Current_Attr &= ~a;
+ SLsmg_set_color(Current_Attr);
+}
+
+PUBLIC void lynx_setup_colors NOARGS
+{
+ SLtt_set_color(0, NULL, DEFAULT_FG, DEFAULT_BG);
+ SLtt_set_color(1, NULL, "blue", DEFAULT_BG); /* bold */
+ SLtt_set_color(2, NULL, "yellow", "blue"); /* reverse */
+ SLtt_set_color(4, NULL, "magenta", DEFAULT_BG); /* underline */
+ /*
+ * The other objects are '|'ed together to get rest.
+ */
+ SLtt_set_color(3, NULL, "green", DEFAULT_BG); /* bold-reverse */
+ SLtt_set_color(5, NULL, "blue", DEFAULT_BG); /* bold-underline */
+ SLtt_set_color(6, NULL, "red", DEFAULT_BG); /* reverse-underline */
+ SLtt_set_color(7, NULL, "magenta", "cyan"); /* reverse-underline-bold */
+
+ /*
+ * Now set monochrome attributes.
+ */
+ SLtt_set_mono(1, NULL, SLTT_BOLD_MASK);
+ SLtt_set_mono(2, NULL, SLTT_REV_MASK);
+ SLtt_set_mono(3, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK);
+ SLtt_set_mono(4, NULL, SLTT_ULINE_MASK);
+ SLtt_set_mono(5, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK);
+ SLtt_set_mono(6, NULL, SLTT_ULINE_MASK | SLTT_REV_MASK);
+ SLtt_set_mono(7, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK);
+}
+
+PRIVATE void sl_suspend ARGS1(
+ int, sig)
+{
+#ifdef SIGSTOP
+#ifndef VMS
+ int r, c;
+
+ lynx_enable_mouse (0);
+ if (sig == SIGTSTP)
+ SLsmg_suspend_smg();
+ SLang_reset_tty();
+ kill(getpid(),SIGSTOP);
+#if SLANG_VERSION > 9929
+ SLang_init_tty(-1, 0, 1);
+#else
+ SLang_init_tty(3, 0, 1);
+#endif /* SLANG_VERSION > 9929 */
+ signal(SIGTSTP, sl_suspend);
+#ifndef _WINDOWS
+ SLtty_set_suspend_state(1);
+#endif
+ if (sig == SIGTSTP)
+ SLsmg_resume_smg();
+ /*
+ * Get new window size in case it changed.
+ */
+ r = SLtt_Screen_Rows;
+ c = SLtt_Screen_Cols;
+ size_change(0);
+ if ((r != SLtt_Screen_Rows) || (c != SLtt_Screen_Cols)) {
+ recent_sizechange = TRUE;
+ }
+ lynx_enable_mouse (1);
+#endif /* !VMS */
+#endif /* SIGSTOP */
+ return;
+}
+
+#else /* Not slang: */
+
+#ifdef VMS
+/*
+** This function boxes windows with graphic characters for
+** VMS curses. Pass it the window, it's height, and it's
+** width. - FM
+*/
+PUBLIC void VMSbox ARGS3(
+ WINDOW *, win,
+ int, height,
+ int, width)
+{
+ int i;
+
+ wmove(win, 0, 0);
+ waddstr(win, "\033)0\016l");
+ for (i = 1; i < width; i++)
+ waddch(win, 'q');
+ waddch(win, 'k');
+ for (i = 1; i < height-1; i++) {
+ wmove(win, i, 0);
+ waddch(win, 'x');
+ wmove(win, i, width-1);
+ waddch(win, 'x');
+ }
+ wmove(win, i, 0);
+ waddch(win, 'm');
+ for (i = 1; i < width; i++)
+ waddch(win, 'q');
+ waddstr(win, "j\017");
+}
+#else
+/*
+** This function boxes windows for non-VMS (n)curses.
+** Pass it the window. - FM
+*/
+PUBLIC void LYbox ARGS2(
+ WINDOW *, win,
+ BOOLEAN, formfield)
+{
+ /*
+ * If the terminal is in UTF-8 mode, it probably cannot understand
+ * box drawing characters as (n)curses handles them. (This may also
+ * be true for other display character sets, but isn't currently
+ * checked.) In that case, substitute ASCII characters for BOXVERT
+ * and BOXHORI if they were defined to 0 for automatic use of box
+ * drawing characters. They'll stay as they are otherwise. - KW & FM
+ */
+ int boxvert, boxhori;
+
+ UCSetBoxChars(current_char_set, &boxvert, &boxhori, BOXVERT, BOXHORI);
+#ifdef CSS
+ if (formfield)
+ wcurses_css(win, "frame", ABS_ON);
+#endif
+ /*
+ * If we don't have explicitly specified characters for either
+ * vertical or horizontal lines, the characters that box() would
+ * use for the corners probably also won't work well. So we
+ * specify our own ASCII characters for the corners and call
+ * wborder() instead of box(). - kw
+ */
+#ifdef HAVE_WBORDER
+ if (!boxvert || !boxhori)
+ box(win, boxvert, boxhori);
+ else if (boxvert == '*' || boxhori == '*')
+ wborder(win, boxvert, boxvert, boxhori, boxhori, '*', '*', '*', '*');
+ else
+ wborder(win, boxvert, boxvert, boxhori, boxhori, '/', '\\', '\\', '/');
+#else
+ box(win, boxvert, boxhori);
+#endif
+#ifdef CSS
+ if (formfield)
+ wcurses_css(win, "frame", ABS_OFF);
+#endif
+}
+#endif /* VMS */
+#endif /* USE_SLANG */
+
+#if defined(USE_COLOR_STYLE)
+PRIVATE int last_styles[128];
+PRIVATE int last_ptr=0;
+#endif
+
+#if defined(USE_COLOR_STYLE)
+/* Ok, explanation of the USE_COLOR_STYLE styles. The basic styles (ie non
+ * HTML) are set the same as the SLANG version for ease of programming. The
+ * other styles are simply the HTML enum from HTMLDTD.h + 16.
+ */
+PUBLIC HTCharStyle displayStyles[DSTYLE_ELEMENTS];
+
+/*
+ * set a style's attributes - RP
+ */
+PUBLIC void setStyle ARGS4(int,style,int,color,int,cattr,int,mono)
+{
+ displayStyles[style].color=color;
+ displayStyles[style].cattr=cattr;
+ displayStyles[style].mono=mono;
+}
+
+PUBLIC void setHashStyle ARGS5(int,style,int,color,int,cattr,int,mono,char*,element)
+{
+ bucket* ds=&hashStyles[style];
+ if (TRACE)
+ fprintf(stderr, "CSS(SET): <%s> hash=%d, ca=%d, ma=%d\n", element, style, color, mono);
+ ds->color=color;
+ ds->cattr=cattr;
+ ds->mono=mono;
+ ds->code=style;
+ FREE(ds->name);
+ ds->name=malloc(sizeof(char)*(strlen(element)+2));
+ strcpy(ds->name, element);
+}
+
+/*
+ * set the curses attributes to be color or mono - RP
+ */
+PRIVATE int LYAttrset ARGS3(WINDOW*,win,int,color,int,mono)
+{
+ if (TRACE)
+ fprintf(stderr, "CSS:LYAttrset (%d, %d)\n", color, mono);
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON && color > -1)
+ {
+ wattrset(win,color);
+ return color;
+ }
+ if (mono > -1)
+ {
+ wattrset(win,mono);
+ return mono;
+ }
+ wattrset(win,A_NORMAL);
+ return A_NORMAL;
+}
+
+PUBLIC void curses_w_style ARGS4(WINDOW*,win,int,style,int,dir,int,previous)
+{
+ int YP,XP;
+ bucket* ds=&hashStyles[style];
+
+ if (!ds->name)
+ {
+ if (TRACE)
+ fprintf(stderr, "CSS.CS:Style %d not configured\n",style);
+ return;
+ }
+ if (TRACE)
+ fprintf(stderr, "CSS.CS:<%s%s> (%d)\n",(dir?"":"/"),ds->name,ds->code);
+
+ getyx (win, YP, XP);
+
+ if (style == s_normal && dir)
+ {
+ wattrset(win,A_NORMAL);
+ if (win==stdscr) cached_styles[YP][XP]=s_normal;
+ return;
+ }
+
+ switch (dir)
+ {
+ /* ABS_OFF is the same as STACK_OFF for the moment */
+ case STACK_OFF:
+ if (last_ptr)
+ LYAttrset(win,last_styles[--last_ptr],-1);
+ else
+ LYAttrset(win,A_NORMAL,-1);
+ return;
+
+ case STACK_ON: /* remember the current attributes */
+ if (last_ptr > 127) {
+ if (TRACE)
+ fprintf(stderr,"........... %s (0x%x) %s\r\n",
+ "attribute cache FULL, dropping last",
+ last_styles[last_ptr],
+ "in LynxChangStyle(curses_w_style)");
+ last_ptr--;
+ }
+ last_styles[last_ptr++] = getattrs(stdscr);
+ /* don't cache style changes for active links */
+ if (style != s_alink)
+ {
+ if (TRACE)
+ fprintf(stderr, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP);
+ if (win==stdscr) cached_styles[YP][XP]=style;
+ LYAttrset(win, ds->color, ds->mono);
+ }
+ else
+ {
+ LYAttrset(win, ds->color, ds->mono);
+ }
+ return;
+
+ case ABS_ON: /* change without remembering the previous style */
+ /* don't cache style changes for active links */
+ if (style != s_alink)
+ {
+ if (TRACE)
+ fprintf(stderr, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP);
+ if (win==stdscr) cached_styles[YP][XP]=style;
+ LYAttrset(win, ds->color, ds->mono);
+ }
+ else
+ {
+ LYAttrset(win, ds->color, ds->mono);
+ }
+ return;
+ }
+}
+
+/*
+ * wrapper function to set on-screen styles - RP
+ */
+PUBLIC void wcurses_css ARGS3(WINDOW *,win,char*,name,int,dir)
+{
+ int try_again=1;
+ while (try_again)
+ {
+ int tmpHash=hash_code(name);
+ if (TRACE)
+ fprintf(stderr, "CSSTRIM:trying to set [%s] style - ", name);
+ if (tmpHash==NOSTYLE) {
+ char *class=strrchr(name, '.');
+ if (TRACE) fprintf(stderr, "undefined, trimming at %p\n", class);
+ if (class) *class='\0';
+ else try_again=0;
+ } else {
+ if (TRACE) fprintf(stderr, "ok (%d)\n", hash_code(name));
+ curses_w_style(win, hash_code(name), dir, 0);
+ try_again=0;
+ }
+ }
+}
+
+PUBLIC void curses_css ARGS2(char *,name,int,dir)
+{
+ wcurses_css(stdscr, name, dir);
+}
+
+PUBLIC void curses_style ARGS3(int,style,int,dir,int,previous)
+{
+ curses_w_style(stdscr, style, dir, previous);
+}
+
+#ifdef NOT_USED
+void attribute ARGS2(int,style,int,dir)
+{
+ curses_style(style, dir, 0);
+}
+#endif
+#endif /* USE_COLOR_STYLE */
+
+#if USE_COLOR_TABLE && defined(COLOR_CURSES)
+/*
+ * This block of code is designed to produce the same color effects using SVr4
+ * curses as the slang library's implementation in this module. That maps the
+ * SGR codes into a 0-7 index into the color table, with special treatment for
+ * backgrounds. There's a bit of convoluted (but necessary) code handling the
+ * special case of initialization before 'initscr()' is called.
+ * 1997/1/19 - T.E.Dickey <dickey@clark.net>
+ */
+PRIVATE int lynx_called_initscr;
+
+PRIVATE struct {
+ int fg, bg;
+ chtype attr;
+} lynx_color_cfg[] = {
+ /*0*/ { DEFAULT_FG, DEFAULT_BG, A_NORMAL}, /* A_NORMAL */
+ /*1*/ { COLOR_BLUE, DEFAULT_BG, A_NORMAL}, /* A_BOLD */
+ /*2*/ { COLOR_YELLOW, COLOR_BLUE, A_BOLD}, /* A_REVERSE */
+ /*3*/ { COLOR_GREEN, DEFAULT_BG, A_NORMAL}, /* A_REVERSE | A_BOLD */
+ /*4*/ { COLOR_MAGENTA, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE */
+ /*5*/ { COLOR_BLUE, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE | A_BOLD */
+ /*6*/ { COLOR_RED, DEFAULT_BG, A_NORMAL}, /* A_UNDERLINE | A_REVERSE */
+ /*7*/ { COLOR_MAGENTA, COLOR_CYAN, A_NORMAL} /* A_UNDERLINE | A_BOLD | A_REVERSE */
+};
+
+/*
+ * Hold the codes for color-pairs here until 'initscr()' is called.
+ */
+PRIVATE struct {
+ int fg;
+ int bg;
+} lynx_color_pairs[25];
+
+/*
+ * Map the SGR attributes (0-7) into ANSI colors, modified with the actual BOLD
+ * attribute we'll get 16 colors.
+ */
+PRIVATE void LYsetWAttr ARGS1(WINDOW *, win)
+{
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
+ int code = 0;
+ int attr = A_NORMAL;
+ int offs = 1;
+ static int have_underline = -1;
+ static int no_color_video = -1;
+
+ if (have_underline < 0) {
+#ifndef DOSPATH
+ have_underline = tigetstr("smul") != 0;
+#else
+ have_underline = 1;
+#endif /* DOSPATH */
+ }
+
+#if ( !defined(__DJGPP__) && !defined(_WINDOWS) )
+ if (no_color_video < 0) {
+ no_color_video = tigetnum("ncv");
+ }
+ if (no_color_video < 0)
+ no_color_video = 0;
+#endif /* !__DJGPP__ and !_WINDOWS */
+
+ if (Current_Attr & A_BOLD)
+ code |= 1;
+ if (Current_Attr & A_REVERSE)
+ code |= 2;
+ if (Current_Attr & A_UNDERLINE)
+ code |= 4;
+ attr = lynx_color_cfg[code].attr;
+
+ /*
+ * FIXME: no_color_video isn't implemented (97/4/14) in ncurses 4.x,
+ * but may be in SVr4 (which would make this redundant for the latter).
+ */
+ if ((Current_Attr & A_BOLD) && !(no_color_video & 33)) {
+ attr |= A_BOLD;
+ }
+
+ if ((Current_Attr == A_UNDERLINE) && !(no_color_video & 2)) {
+ attr |= A_UNDERLINE;
+ }
+
+ if (code+offs < COLOR_PAIRS) {
+ attr |= COLOR_PAIR(code+offs);
+ }
+
+ wattrset(win, attr);
+ } else {
+ wattrset(win, Current_Attr);
+ }
+}
+
+PRIVATE void lynx_map_color ARGS1(int, n)
+{
+ int m;
+
+ lynx_color_pairs[n+1].fg = lynx_color_cfg[n].fg;
+ lynx_color_pairs[n+1].bg = lynx_color_cfg[n].bg;
+
+ lynx_color_pairs[n+9].fg = lynx_color_cfg[n].fg;
+ lynx_color_pairs[n+9].bg = lynx_color_cfg[0].bg;
+
+ lynx_color_pairs[n+17].fg = lynx_color_cfg[n].bg;
+ lynx_color_pairs[n+17].bg = lynx_color_cfg[n].bg;
+
+ if (lynx_called_initscr) {
+ for (m = 0; m <= 16; m += 8) {
+ int pair = n + m + 1;
+ if (pair < COLOR_PAIRS)
+ init_pair(pair,
+ lynx_color_pairs[pair].fg,
+ lynx_color_pairs[pair].bg);
+ }
+ if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
+ bkgd(COLOR_BKGD | ' ');
+ }
+}
+
+PUBLIC int lynx_chg_color ARGS3(
+ int, color,
+ int, fg,
+ int, bg
+ )
+{
+ if (color >= 0 && color < 8) {
+ lynx_color_cfg[color].fg = (fg > 7) ? (fg & 7) : fg;
+ lynx_color_cfg[color].bg = (bg > 7) ? (bg & 7) : bg;
+ lynx_color_cfg[color].attr = ((fg > 7) && (fg & 8)) ? A_BOLD : A_NORMAL;
+ lynx_map_color(color);
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+PUBLIC void lynx_set_color ARGS1(int, a)
+{
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
+ attrset(lynx_color_cfg[a].attr
+ | (((a+1) < COLOR_PAIRS)
+ ? COLOR_PAIR(a+1)
+ : A_NORMAL));
+ }
+}
+
+PUBLIC void lynx_standout ARGS1(int, flag)
+{
+ if (flag)
+ LYaddAttr(A_REVERSE);
+ else
+ LYsubAttr(A_REVERSE);
+}
+
+PRIVATE void lynx_init_colors NOARGS
+{
+ if (lynx_has_color) {
+ size_t n, m;
+
+ lynx_color_cfg[0].fg = default_fg;
+ lynx_color_cfg[0].bg = default_bg;
+
+ for (n = 0; n < sizeof(lynx_color_cfg)/sizeof(lynx_color_cfg[0]); n++) {
+ for (m = 0; m <= 16; m += 8) {
+ int pair = n + m + 1;
+ if (pair < COLOR_PAIRS)
+ init_pair(pair,
+ lynx_color_pairs[pair].fg,
+ lynx_color_pairs[pair].bg);
+ }
+ if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
+ bkgd(COLOR_BKGD | ' ');
+ }
+ } else if (LYShowColor != SHOW_COLOR_NEVER) {
+ LYShowColor = SHOW_COLOR_OFF;
+ }
+}
+
+PUBLIC void lynx_setup_colors NOARGS
+{
+ int n;
+ for (n = 0; n < 8; n++)
+ lynx_map_color(n);
+}
+#endif /* USE_COLOR_TABLE */
+
+#if defined (DJGPP) && !defined (USE_SLANG)
+/*
+ * Sorry about making a completely new function,
+ * but the real one is messy! WB
+ */
+PUBLIC void start_curses NOARGS
+{
+ static BOOLEAN first_time = TRUE;
+
+ if(first_time)
+ {
+ initscr(); /* start curses */
+ first_time = FALSE;
+ cbreak();
+ keypad(stdscr, TRUE);
+ fflush(stdin);
+ fflush(stdout);
+ if (has_colors()) {
+ lynx_has_color = TRUE;
+ start_color();
+ }
+ lynx_init_colors();
+ lynx_called_initscr = TRUE;
+
+ /* Inform pdcurses that we're interested in knowing when mouse
+ buttons are clicked. Maybe someday pdcurses will support it.
+ */
+ if (LYUseMouse)
+ lynx_enable_mouse (1);
+
+ } else sock_init();
+
+ LYCursesON = TRUE;
+ clear();
+ noecho();
+}
+#else
+PUBLIC void start_curses NOARGS
+{
+#ifdef USE_SLANG
+ static int slinit;
+
+ if (LYCursesON)
+ return;
+
+ if (slinit == 0) {
+ SLtt_get_terminfo();
+#ifdef UNIX
+#if SLANG_VERSION >= 9935
+ SLang_TT_Read_FD = fileno(stdin);
+#endif /* SLANG_VERSION >= 9935 */
+#endif /* UNIX */
+
+ /*
+ * Check whether a saved show_color:off override is in effect. - kw
+ */
+ if (LYrcShowColor == SHOW_COLOR_NEVER) {
+ SLtt_Use_Ansi_Colors = 0;
+ }
+ /*
+ * Check whether we're forcing color on. - FM
+ */
+ if ((LYShowColor > 1) && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
+ SLtt_Use_Ansi_Colors = 1;
+ /*
+ * Check whether a -nocolor override is in effect. - kw
+ */
+ if (Lynx_Color_Flags & SL_LYNX_OVERRIDE_COLOR)
+ SLtt_Use_Ansi_Colors = 0;
+ /*
+ * Make sure our flags are in register. - FM
+ */
+ if (SLtt_Use_Ansi_Colors == 1) {
+ if (LYShowColor != SHOW_COLOR_ALWAYS) {
+ LYShowColor = SHOW_COLOR_ON;
+ }
+ } else {
+ if (LYShowColor != SHOW_COLOR_NEVER) {
+ LYShowColor = SHOW_COLOR_OFF;
+ }
+ }
+ size_change(0);
+
+ SLtt_add_color_attribute(4, SLTT_ULINE_MASK);
+ SLtt_add_color_attribute(5, SLTT_ULINE_MASK);
+ /*
+ * If set, the blink escape sequence will turn on high
+ * intensity background (rxvt and maybe Linux console).
+ */
+ if (LYShowColor && (Lynx_Color_Flags & SL_LYNX_USE_BLINK)) {
+ SLtt_Blink_Mode = 1;
+ } else {
+ SLtt_Blink_Mode = 0;
+ }
+ }
+ slinit = 1;
+ Current_Attr = 0;
+#ifndef VMS
+#if SLANG_VERSION > 9929
+ SLang_init_tty(-1, 0, 1);
+#else
+ SLang_init_tty(3, 0, 1);
+#endif /* SLANG_VERSION > 9929 */
+#endif /* !VMS */
+ SLsmg_init_smg();
+ SLsmg_Display_Eight_Bit = LYlowest_eightbit[current_char_set];
+ if (SLsmg_Display_Eight_Bit > 191)
+ SLsmg_Display_Eight_Bit = 191; /* may print ctrl chars otherwise - kw */
+ scrollok(0,0);
+ SLsmg_Backspace_Moves = 1;
+#ifndef VMS
+#ifndef _WINDOWS
+ SLtty_set_suspend_state(1);
+#endif /* !_WINDOWS */
+#ifdef SIGTSTP
+ if (!no_suspend)
+ signal(SIGTSTP, sl_suspend);
+#endif /* SIGTSTP */
+ signal(SIGINT, cleanup_sig);
+#endif /* !VMS */
+
+ lynx_enable_mouse (1);
+
+#else /* Using curses: */
+
+#ifdef VMS
+ /*
+ * If we are VMS then do initsrc() everytime start_curses()
+ * is called!
+ */
+ initscr(); /* start curses */
+#else /* Unix: */
+ static BOOLEAN first_time = TRUE;
+
+ if (first_time) {
+ /*
+ * If we're not VMS then only do initscr() one time,
+ * and one time only!
+ */
+ if (initscr() == NULL) { /* start curses */
+ fprintf(stderr,
+ "Terminal initialisation failed - unknown terminal type?\n");
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* !NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+ (void) signal(SIGINT, SIG_DFL);
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit (-1);
+ }
+#if defined(SIGWINCH) && defined(NCURSES_VERSION)
+ size_change(0);
+#endif /* SIGWINCH */
+
+ /*
+ * This is a workaround for a bug in SVr4 curses, observed on Solaris
+ * 2.4: if your terminal's alternate-character set contains codes in
+ * the range 128-255, they'll be sign-extended in the acs_map[] table,
+ * which in turn causes their values to be emitted as 255 (0xff).
+ * "Fix" this by forcing the table to 8-bit codes (it has to be
+ * anyway).
+ */
+#if defined(ALT_CHAR_SET) && !defined(NCURSES_VERSION)
+ {
+ int n;
+ for (n = 0; n < 128; n++)
+ if (acs_map[n] & 0x80) {
+ acs_map[n] &= 0xff;
+ acs_map[n] |= A_ALTCHARSET;
+ }
+ }
+#endif
+
+#if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
+ if (has_colors()) {
+ lynx_has_color = TRUE;
+ start_color();
+#if HAVE_USE_DEFAULT_COLORS
+ if (use_default_colors() == OK) {
+ default_fg = DEFAULT_COLOR;
+ default_bg = DEFAULT_COLOR;
+ }
+#endif /* HAVE_USE_DEFAULT_COLORS */
+ }
+#endif /* USE_COLOR_STYLE || USE_COLOR_TABLE */
+
+#ifdef USE_COLOR_STYLE
+ parse_userstyles();
+#endif
+ first_time = FALSE;
+#if USE_COLOR_TABLE
+ lynx_init_colors();
+ lynx_called_initscr = TRUE;
+#endif /* USE_COLOR_TABLE */
+ }
+#endif /* VMS */
+
+ /* nonl(); */ /* seems to slow things down */
+
+#ifdef VMS
+ crmode();
+ raw();
+#else
+#if HAVE_CBREAK
+ cbreak();
+#else
+ crmode();
+#endif /* HAVE_CBREAK */
+ signal(SIGINT, cleanup_sig);
+#endif /* VMS */
+
+ noecho();
+
+#if HAVE_KEYPAD
+ keypad(stdscr,TRUE);
+#endif /* HAVE_KEYPAD */
+
+ lynx_enable_mouse (1);
+
+ fflush(stdin);
+ fflush(stdout);
+ fflush(stderr);
+#endif /* USE_SLANG */
+
+#ifdef _WINDOWS
+ clear();
+#endif
+
+ LYCursesON = TRUE;
+}
+#endif /* defined (DJGPP) && !defined (USE_SLANG) */
+
+PUBLIC void lynx_enable_mouse ARGS1(int,state)
+{
+ if (LYUseMouse == 0)
+ return;
+
+#ifdef USE_SLANG_MOUSE
+ SLtt_set_mouse_mode (state, 0);
+ SLtt_flush_output ();
+#else
+#ifdef NCURSES_MOUSE_VERSION
+ /* Inform ncurses that we're interested in knowing when mouse
+ button 1 is clicked */
+#ifndef _WINDOWS
+ if (state)
+ mousemask(BUTTON1_CLICKED | BUTTON3_CLICKED, NULL);
+ else
+ mousemask(0, NULL);
+#else
+ if (state) mouse_set(BUTTON1_CLICKED && BUTTON2_CLICKED && BUTTON3_CLICKED);
+#endif /* !_WINDOWS */
+#endif /* NCURSES_MOUSE_VERSION */
+
+#if defined(DJGPP) && !defined(USE_SLANG)
+ if (state)
+ mouse_set(BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED);
+#endif
+#endif /* NOT USE_SLANG_MOUSE */
+}
+
+PUBLIC void stop_curses NOARGS
+{
+ echo();
+#ifdef DJGPP
+ sock_exit();
+#endif
+#if defined (DOSPATH) && !defined(USE_SLANG)
+ clrscr();
+#else
+
+ /*
+ * Fixed for better dumb terminal support.
+ * 05-28-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+ if(LYCursesON == TRUE) {
+ lynx_enable_mouse (0);
+ endwin(); /* stop curses */
+ }
+
+ fflush(stdout);
+#endif /* DJGPP */
+ fflush(stderr);
+
+ LYCursesON = FALSE;
+
+#if defined(SIGTSTP) && defined(USE_SLANG)
+#ifndef VMS
+ if (!no_suspend)
+ signal(SIGTSTP, SIG_DFL);
+#endif /* !VMS */
+#endif /* SIGTSTP && USE_SLANG */
+
+#ifndef VMS
+ signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+}
+
+#ifdef VMS
+/*
+ * Check terminal type, start curses & setup terminal.
+ */
+PUBLIC BOOLEAN setup ARGS1(
+ char *, terminal)
+{
+ int c;
+ int status;
+ char *dummy, *cp, term[81];
+#ifdef USE_SLANG
+ extern void longname();
+#endif /* USE_SLANG */
+
+ /*
+ * If the display was not set by a command line option then
+ * see if it is available from the environment.
+ */
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
+ StrAllocCopy(display, cp);
+ } else {
+ FREE(display);
+ }
+
+ /*
+ * Get terminal type, and convert to lower case.
+ */
+ term[0] = '\0';
+ longname(dummy, term);
+ if (term[0] == '\0' && (form_get_data || form_post_data)) {
+ /*
+ * Some yoyo used these under conditions which require
+ * -dump, so force that mode here. - FM
+ */
+ dump_output_immediately = TRUE;
+ LYcols = 80;
+ if (keypad_mode == NUMBERS_AS_ARROWS)
+ keypad_mode = LINKS_ARE_NUMBERED;
+ status = mainloop();
+ (void) signal (SIGHUP, SIG_DFL);
+ (void) signal (SIGTERM, SIG_DFL);
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(status);
+ }
+ for (cp = term; *cp != '\0'; cp++)
+ if (isupper(*cp))
+ *cp = TOLOWER(*cp);
+
+ printf("Terminal = %s\n", term);
+ sleep(InfoSecs);
+ if ((strlen(term) < 5) ||
+ strncmp(term, "vt", 2) || !isdigit(term[2])) {
+ printf(
+ "You must use a vt100, 200, etc. terminal with this program.\n");
+ printf("Proceed (n/y)? ");
+ c = getchar();
+ if (c != 'y' && c != 'Y') {
+ printf("\n");
+ return(FALSE);
+ }
+ strcpy(term,"vt100");
+ }
+
+ ttopen();
+ start_curses();
+
+ LYlines = LINES;
+ LYcols = COLS;
+ if (LYlines <= 0)
+ LYlines = 24;
+ if (LYcols <= 0)
+ LYcols = 80;
+
+ return(TRUE);
+}
+
+#else /* Not VMS: */
+
+/*
+ * Check terminal type, start curses & setup terminal.
+ */
+PUBLIC BOOLEAN setup ARGS1(
+ char *, terminal)
+{
+ static char term_putenv[120];
+ char buffer[120];
+ char *cp;
+#if defined(HAVE_SIZECHANGE) && !defined(USE_SLANG) && defined(NOTDEFINED)
+/*
+ * Hack to deal with a problem in sysV curses, that screen can't be
+ * resized to greater than the size used by initscr, which can only
+ * be called once. So set environment variables LINES and COLUMNS
+ * to some suitably large size to force initscr to allocate enough
+ * space. Later we get the real window size for setting LYlines
+ * and LYcols. - AJL & FM
+ *
+ * Has problems, so we don't use this hack, but the code is here
+ * if someone wants to play with it some more. - FM
+ */
+ char *lines_putenv = NULL;
+ char *cols_putenv = NULL;
+
+ if (getenv("LINES") == NULL && getenv("COLUMNS") == NULL) {
+ StrAllocCopy(lines_putenv, "LINES=120");
+ (void) putenv(lines_putenv);
+ StrAllocCopy(cols_putenv, "COLUMNS=240");
+ (void) putenv(cols_putenv);
+ }
+#endif /* HAVE_SIZECHANGE && !USE_SLANG && NOTDEFINED */
+
+ /*
+ * If the display was not set by a command line option then
+ * see if it is available from the environment .
+ */
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
+ StrAllocCopy(display, cp);
+ } else {
+ FREE(display);
+ }
+
+ if (terminal != NULL) {
+ sprintf(term_putenv, "TERM=%s", terminal);
+ (void) putenv(term_putenv);
+ }
+
+ /*
+ * Query the terminal type.
+ */
+ if (dumbterm(getenv("TERM"))) {
+ char *s;
+
+ printf("\n\n Your Terminal type is unknown!\n\n");
+ printf(" Enter a terminal type: [vt100] ");
+ *buffer = '\0';
+ fgets(buffer, sizeof(buffer), stdin);
+ if ((s = strchr(buffer, '\n')) != NULL)
+ *s = '\0';
+
+ if (strlen(buffer) == 0)
+ strcpy(buffer,"vt100");
+
+ sprintf(term_putenv,"TERM=%s", buffer);
+ putenv(term_putenv);
+ printf("\nTERMINAL TYPE IS SET TO %s\n",getenv("TERM"));
+ sleep(MESSAGESECS);
+ }
+
+ start_curses();
+
+#if HAVE_TTYTYPE
+ /*
+ * Get terminal type (strip 'dec-' from vms style types).
+ */
+ if (strncmp((CONST char*)ttytype, "dec-vt", 6) == 0) {
+ (void) setterm(ttytype + 4);
+ }
+#endif /* HAVE_TTYTYPE */
+
+#if defined(HAVE_SIZECHANGE) && !defined(USE_SLANG) && defined(NOTDEFINED)
+ if (lines_putenv != NULL) {
+ /*
+ * Use SIGWINCH handler to set the true window size. - AJL && FM
+ *
+ * Has problems, so we don't use this hack, but the code is here
+ * if someone wants to play with it some more. - FM
+ */
+ size_change(0);
+ lines_putenv[6] = '\0';
+ (void) putenv(lines_putenv);
+ cols_putenv[8] = '\0';
+ (void) putenv(cols_putenv);
+ FREE(lines_putenv);
+ FREE(cols_putenv);
+ } else {
+ LYlines = LINES;
+ LYcols = COLS;
+ }
+#else
+ LYlines = LINES;
+ LYcols = COLS;
+#endif /* HAVE_SIZECHANGE && !USE_SLANG && USE_NOTDEFINED */
+ if (LYlines <= 0)
+ LYlines = 24;
+ if (LYcols <= 0)
+ LYcols = 80;
+
+ return(1);
+}
+
+PRIVATE int dumbterm ARGS1(
+ char *, terminal)
+{
+ int dumb = FALSE;
+
+ /*
+ * Began checking for terminal == NULL in case that TERM environment
+ * variable is not set. Thanks to Dick Wesseling (ftu@fi.ruu.nl).
+ */
+ if (terminal == NULL ||
+ !strcasecomp(terminal, "network") ||
+ !strcasecomp(terminal, "unknown") ||
+ !strcasecomp(terminal, "dialup") ||
+ !strcasecomp(terminal, "dumb") ||
+ !strcasecomp(terminal, "switch") ||
+ !strcasecomp(terminal, "ethernet") )
+ dumb = TRUE;
+ return(dumb);
+}
+
+#ifdef FANCY_CURSES
+#ifndef USE_COLOR_STYLE
+#if USE_COLOR_TABLE
+PUBLIC void LYaddWAttr ARGS2(
+ WINDOW *, win,
+ int, a)
+{
+ Current_Attr |= a;
+ LYsetWAttr(win);
+}
+
+PUBLIC void LYaddAttr ARGS1(
+ int, a)
+{
+ LYaddWAttr(stdscr, a);
+}
+
+PUBLIC void LYsubWAttr ARGS2(
+ WINDOW *, win,
+ int, a)
+{
+ Current_Attr &= ~a;
+ LYsetWAttr(win);
+}
+
+PUBLIC void LYsubAttr ARGS1(
+ int, a)
+{
+ LYsubWAttr(stdscr, a);
+}
+#endif /* USE_COLOR_TABLE */
+#endif /* !USE_COLOR_STYLE */
+#endif /* FANCY_CURSES */
+#endif /* VMS */
+
+PUBLIC void LYstartTargetEmphasis NOARGS
+{
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ start_bold();
+ start_reverse();
+#endif /* FANCY_CURSES || USE_SLANG */
+ start_underline();
+}
+
+PUBLIC void LYstopTargetEmphasis NOARGS
+{
+ stop_underline();
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ stop_reverse();
+ stop_bold();
+#endif /* FANCY_CURSES || USE_SLANG */
+}
+
+#ifdef VMS
+/*
+ * Cut-down termio --
+ * Do character-oriented stream input for Jeff.
+ * Code ripped off from Micro-Emacs 3.7 by Daniel Lawrence.
+ *
+ * Ever-so-slightly modified by Kathryn Huxtable. 29-Jan-1991.
+ * Cut down for Lou. 8 Sep 1992.
+ * Cut down farther for Lou. 19 Apr 1993.
+ * We don't set PASSALL or PASTHRU since we don't
+ * want to block CTRL/C, CTRL/Y, CTRL/S or CTRL/Q.
+ * Simply setting NOECHO and doing timed reads
+ * is sufficient.
+ * Further mods by Fote. 29-June-1993
+ * ttopen() and ttclose() are now terminal initialization
+ * and restoration procedures, called once at startup
+ * and at exit, respectively, of the LYNX image.
+ * ttclose() should be called before an exit from LYNX
+ * no matter how the exit is invoked.
+ * setup(terminal) does the ttopen().
+ * cleanup() calls cleanup_files() and ttclose().
+ * ttgetc() now handles NOECHO and NOFLITR (instead of
+ * setting the terminal itself to NOECHO in ttopen()).
+ * VMSsignal() added for handling both Ctrl-C *and* Ctrl-Y
+ * interrupts, and disabling system response to Ctrl-T.
+ * Further mods by Fote. 15-Dec-1993
+ * Added edit handler in ttopen() which will invoke
+ * VMSexit() and behave intelligently on ACCVIO's.
+ * Further mods by Fote. 29-Dec-1993
+ * Simplified ttgetc().
+ * Further mods by Fote. 16-Jan-1994
+ * Added code in ttopen() which will invoke VMSVersion()
+ * to get the version of VMS as VersionVMS for use by
+ * by new or modified interrupt or spawning routines.
+ * Further mods by Fote. 27-Jan-1994
+ * Added back a typeahead() which supports 'z' or 'Z' as
+ * an "Zap transfer" command via HTCheckForInterrupt()
+ * in LYUtils.c.
+ */
+
+#include <descrip.h>
+#include <iodef.h>
+#include <ssdef.h>
+#include <stdlib.h>
+#include <msgdef.h>
+#include <ttdef.h>
+#include <tt2def.h>
+#include <libclidef.h>
+#include <lib$routines.h>
+#include <starlet.h>
+#include <clidef.h>
+#include <syidef.h>
+#ifdef signal
+#undef signal
+#endif /* signal */
+#include <signal.h>
+#ifdef system
+#undef system
+#endif /* system */
+#include <processes.h>
+#include "LYVMSdef.h"
+
+#define EFN 0 /* Event flag */
+
+static unsigned char buffer[20]; /* Input buffer */
+static int in_pos, in_len; /* For escape sequences */
+static int oldmode[3]; /* Old TTY mode bits */
+static int newmode[3]; /* New TTY mode bits */
+static short iochan; /* TTY I/O channel */
+static $DESCRIPTOR(term_nam_dsc,"TT"); /* Descriptor for iochan */
+static unsigned long mask = LIB$M_CLI_CTRLY|LIB$M_CLI_CTRLT; /* ^Y and ^T */
+static unsigned long old_msk; /* Saved control mask */
+static short trap_flag = FALSE; /* TRUE if AST is set */
+BOOLEAN DidCleanup = FALSE; /* Exit handler flag */
+static char VersionVMS[20]; /* Version of VMS */
+
+PUBLIC int VMSVersion ARGS2(
+ char *, VerString,
+ int, VerLen)
+{
+ unsigned long status, itm_cod = SYI$_VERSION;
+ int i, verlen = 0;
+ struct dsc$descriptor version;
+ char *m;
+
+ version.dsc$a_pointer = VerString;
+ version.dsc$w_length = VerLen - 1;
+ version.dsc$b_dtype = DSC$K_DTYPE_B;
+ version.dsc$b_class = DSC$K_CLASS_S;
+
+ status = lib$getsyi(&itm_cod, 0, &version, &verlen, 0, 0);
+ if (!(status&1) || verlen == 0)
+ return 0;
+
+ /*
+ * Cut out trailing spaces
+ */
+ for (m = VerString+verlen, i = verlen-1; i > 0 && VerString[i] == ' '; --i)
+ *(--m) = '\0';
+
+ return strlen(VerString)+1; /* Transmit ending 0 too */
+}
+
+PUBLIC void VMSexit NOARGS
+{
+ /*
+ * If we get here and DidCleanup is not set, it was via an
+ * ACCVIO, or outofmemory forced exit, so make *sure* we
+ * attempt a cleanup and reset the terminal.
+ */
+ if (!DidCleanup) {
+ if (LYOutOfMemory == FALSE) {
+ fprintf(stderr,
+"\nA Fatal error has occurred in %s Ver. %s\n", LYNX_NAME, LYNX_VERSION);
+ fprintf(stderr,
+"\nPlease notify your system administrator to confirm a bug, and if\n");
+ fprintf(stderr,
+"confirmed, to notify the lynx-dev list. Bug reports should have concise\n");
+ fprintf(stderr,
+"descriptions of the command and/or URL which causes the problem, the\n");
+ fprintf(stderr,
+"operating system name with version number, the TCPIP implementation, the\n");
+ fprintf(stderr,
+"TRACEBACK if it can be captured, and any other relevant information.\n");
+
+ if (LYTraceLogFP == NULL) {
+ fprintf(stderr,"\nPress RETURN to clean up: ");
+ (void) getchar();
+ }
+ } else if (LYCursesON) {
+ _statusline(MEMORY_EXHAUSTED_ABORT);
+ sleep(AlertSecs);
+ }
+ cleanup();
+ }
+ if (LYOutOfMemory == TRUE) {
+ printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
+ fflush(stdout);
+ fflush(stderr);
+ }
+}
+
+/*
+ * TTOPEN --
+ * This function is called once to set up the terminal
+ * device streams. It translates TT until it finds
+ * the terminal, then assigns a channel to it, sets it
+ * to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt
+ * handling.
+ */
+PUBLIC int ttopen NOARGS
+{
+ extern void cleanup_sig();
+ int iosb[2];
+ int status;
+ static unsigned long condition;
+ static struct _exit_block {
+ unsigned long forward;
+ unsigned long address;
+ unsigned long zero;
+ unsigned long condition;
+ } exit_handler_block;
+
+ status = sys$assign( &term_nam_dsc, &iochan, 0, 0 );
+ if( status != SS$_NORMAL )
+ exit( status );
+
+ status = sys$qiow( EFN, iochan, IO$_SENSEMODE, &iosb, 0, 0,
+ &oldmode, sizeof(oldmode), 0, 0, 0, 0 );
+ if( status != SS$_NORMAL )
+ exit( status );
+
+ status = iosb[0] & 0xFFFF;
+ if( status != SS$_NORMAL )
+ exit( status );
+
+ newmode[0] = oldmode[0];
+ newmode[1] = oldmode[1];
+ newmode[2] = oldmode[2] | TT2$M_EDIT;
+
+ status = sys$qiow( EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
+ &newmode, sizeof(newmode), 0, 0, 0, 0 );
+ if( status != SS$_NORMAL )
+ exit( status );
+
+ status = iosb[0] & 0xFFFF;
+ if( status != SS$_NORMAL )
+ exit( status );
+
+ /*
+ * Declare the exit handler block.
+ */
+ exit_handler_block.forward = 0;
+ exit_handler_block.address = (unsigned long) &VMSexit;
+ exit_handler_block.zero = 0;
+ exit_handler_block.condition = (unsigned long) &condition;
+ status = sys$dclexh(&exit_handler_block);
+ if (status != SS$_NORMAL)
+ exit( status );
+
+ /*
+ * Set the AST.
+ */
+ lib$disable_ctrl(&mask, &old_msk);
+ trap_flag = TRUE;
+ status = sys$qiow ( EFN, iochan,
+ IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST,
+ &iosb, 0, 0,
+ &cleanup_sig, SIGINT, 0, 0, 0, 0 );
+ if ( status != SS$_NORMAL ) {
+ lib$enable_ctrl(&old_msk);
+ exit ( status );
+ }
+
+ /*
+ * Get the version of VMS.
+ */
+ if (VMSVersion(VersionVMS, 20) < 3)
+ /*
+ * Load zeros on error.
+ */
+ strcpy(VersionVMS, "V0.0-0");
+
+ return(0);
+} /* ttopen */
+
+/*
+ * TTCLOSE --
+ * This function gets called just before we go back home
+ * to the command interpreter. It puts the terminal back
+ * in a reasonable state.
+ */
+PUBLIC int ttclose NOARGS
+{
+ int status;
+ int iosb[1];
+
+ status = sys$qiow( EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
+ &oldmode, sizeof(oldmode), 0, 0, 0, 0 );
+
+ if( status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL )
+ exit( status );
+
+ if (trap_flag) {
+ status = sys$dassgn (iochan);
+ status = lib$enable_ctrl(&old_msk);
+ trap_flag = FALSE;
+ }
+ return(0);
+} /* ttclose */
+
+/*
+ * TTGETC --
+ * Read a character from the terminal, with NOECHO and NOFILTR.
+ */
+PUBLIC int ttgetc NOARGS
+{
+ int status;
+ unsigned short iosb[4];
+
+ if (in_pos < in_len)
+ return(buffer[in_pos++]);
+
+ status = sys$qiow(EFN, iochan,
+ IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,
+ &iosb, 0, 0,
+ &buffer, 1, 0, 0, 0, 0);
+ if ((status&1) == 1)
+ status = iosb[0];
+ if (status == SS$_PARTESCAPE) {
+ /*
+ * Escape sequence in progress. Fake a successful read.
+ */
+ status = 1;
+ }
+ if ((status&1) != 1 && status != SS$_DATAOVERUN)
+ exit(status);
+ in_pos = 1;
+ in_len = iosb[1] + iosb[3];
+ return(buffer[0]);
+}
+
+/*
+ * TYPEAHEAD -- Fote Macrides 27-Jan-1994
+ * Check whether a keystroke has been entered, and return
+ * it, or -1 if none was entered.
+ */
+PUBLIC int typeahead NOARGS
+{
+ int status;
+ unsigned short iosb[4];
+
+ if (dump_output_immediately)
+ return -1;
+
+ if (in_pos < in_len)
+ return(buffer[in_pos++]);
+
+again:
+ status = sys$qiow (EFN, iochan,
+ IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO|IO$M_NOFILTR,
+ &iosb, 0, 0,
+ &buffer, 1, 0, 0, 0, 0);
+ if ((status&1) == 1)
+ status = iosb[0];
+ if (status == SS$_PARTESCAPE) {
+ /*
+ * Escape sequence in progress, finish reading it.
+ */
+ goto again;
+ }
+
+ in_pos = 1;
+ in_len = iosb[1] + iosb[3];
+ if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN)
+ return(-1);
+ return (buffer[0]);
+}
+
+/*
+ * VMSSIGNAL -- Fote Macrides 29-Jun-1993
+ * Sets up AST for both Ctrl-C and Ctrl-Y, with system response
+ * to Ctrl-T disabled. If called with a sig other than SIGINT,
+ * it will use the C library's system(sig, func).
+ * The equivalent of VMSsignal(SIGINT, cleanup_sig) is done on
+ * intialization by ttopen(), so don't do it again.
+ * VMSsignal(SIGINT, SIG_DFL) is treated as a call to ttclose().
+ * Call VMSsignal(SIGINT, SIG_IGN) before system() calls to
+ * enable Ctrl-C and Ctrl-Y in the subprocess, and then call
+ * VMSsignal(SIG_INT, cleanup_sig) on return from the subprocess.
+ * For func's which set flags and do not invoke an exit from
+ * LYNX, the func should reassert itself.
+ * The VMS signal() calls do not fully emulate the Unix calls,
+ * and VMSsignal() is just a "helper", also not a full emulation.
+ */
+
+PUBLIC void *VMSsignal (sig,func)
+int sig;
+void (*func)();
+{
+ int status;
+ short iosb[4];
+ static int SIG_IGN_flag;
+
+ /*
+ * Pass all signals other than SIGINT to signal().
+ * Also pass SIGINT to signal() if we're dumping.
+ */
+ if (sig != SIGINT || dump_output_immediately) {
+ signal(sig, func);
+ return;
+ }
+
+ /*
+ * If func is SIG_DFL, treat it as ttclose().
+ */
+ if (func == SIG_DFL) {
+ ttclose();
+ return;
+ }
+
+ /*
+ * Clear any previous AST.
+ */
+ if (trap_flag) {
+ status = sys$dassgn (iochan);
+ status = lib$enable_ctrl(&old_msk);
+ trap_flag = FALSE;
+ }
+
+ /*
+ * If func is SIG_IGN, leave the TT channel closed and the
+ * system response to interrupts enabled for system() calls.
+ */
+ if (func == SIG_IGN)
+ return;
+
+ /*
+ * If we get to here, we have a LYNX func, so set the AST.
+ */
+ lib$disable_ctrl(&mask, &old_msk);
+ trap_flag = TRUE;
+ status = sys$assign (&term_nam_dsc, &iochan, 0, 0 );
+ status = sys$qiow ( EFN, iochan,
+ IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST,
+ &iosb, 0, 0,
+ func, SIGINT, 0, 0, 0, 0 );
+
+} /* VMSsignal */
+
+/*
+ * DCLspawn_exception, spawn_DCLprocess, DCLsystem -- F.Macrides 16-Jan-1994
+ * Exception-handler routines for regulating interrupts and enabling
+ * Control-T during spawns. Includes TRUSTED flag for versions of VMS
+ * which require it in captive accounts. This code should be used
+ * instead of the VAXC or DECC system(), by including LYSystem.h in
+ * modules which have system() calls. It helps ensure that we return
+ * to Lynx instead of breaking out to DCL if a user issues interrupts
+ * or generates an ACCVIO during spawns.
+ */
+#ifdef __DECC
+PRIVATE unsigned int DCLspawn_exception ARGS2(
+ void *, sigarr,
+ void *, mecharr)
+{
+#else
+PRIVATE int DCLspawn_exception ARGS2(
+ void *, sigarr,
+ void *, mecharr)
+{
+#endif /* __DECC */
+ int status;
+
+ status = lib$sig_to_ret(sigarr, mecharr);
+ return(SS$_UNWIND);
+}
+
+PRIVATE int spawn_DCLprocess ARGS1(
+ char *, command)
+{
+ int status;
+ unsigned long Status = 0;
+ /*
+ * Keep DECC from complaining.
+ */
+ struct dsc$descriptor_s command_desc;
+ command_desc.dsc$w_length = strlen(command);
+ command_desc.dsc$b_class = DSC$K_CLASS_S;
+ command_desc.dsc$b_dtype = DSC$K_DTYPE_T;
+ command_desc.dsc$a_pointer = command;
+
+ VAXC$ESTABLISH(DCLspawn_exception);
+
+#ifdef __ALPHA /** OpenVMS/AXP lacked the TRUSTED flag before v6.1 **/
+ if (VersionVMS[1] > '6' ||
+ (VersionVMS[1] == '6' && VersionVMS[2] == '.' &&
+ VersionVMS[3] >= '1')) {
+#else
+ if (VersionVMS[1] >= '6') {
+#endif /* __ALPHA */
+ /*
+ * Include TRUSTED flag.
+ */
+ unsigned long trusted = CLI$M_TRUSTED;
+ status = lib$spawn(&command_desc,0,0,&trusted,
+ 0,0,&Status);
+ /*
+ * If it was invalid, try again without the flag.
+ */
+ if (status == LIB$_INVARG)
+ status = lib$spawn(&command_desc,0,0,0,
+ 0,0,&Status );
+ } else
+ status = lib$spawn(&command_desc,0,0,0,
+ 0,0,&Status);
+ /*
+ * Return -1 on error.
+ */
+ if ((status&1) != 1 || (Status&1) != 1)
+ return(-1);
+ /*
+ * Return 0 on success.
+ */
+ return(0);
+}
+
+PUBLIC int DCLsystem ARGS1(
+ char *, command)
+{
+ int status;
+ extern void controlc();
+
+ VMSsignal(SIGINT, SIG_IGN);
+ status = spawn_DCLprocess(command);
+ VMSsignal(SIGINT, cleanup_sig);
+ /*
+ * Returns 0 on success, -1 any error.
+ */
+ return(status);
+}
+#endif /* VMS */
+
+PUBLIC void lynx_force_repaint NOARGS
+{
+#if defined(COLOR_CURSES)
+ chtype a;
+#ifndef USE_COLOR_STYLE
+ if (LYShowColor >= SHOW_COLOR_ON)
+ a = COLOR_BKGD;
+ else
+#endif
+ a = A_NORMAL;
+ bkgdset(a | ' ');
+#ifndef USE_COLOR_STYLE
+ bkgd(a | ' ');
+#endif
+ attrset(a);
+#endif /* COLOR_CURSES */
+ clearok(curscr, TRUE);
+}
+
+PUBLIC void lynx_start_title_color NOARGS
+{
+}
+
+PUBLIC void lynx_stop_title_color NOARGS
+{
+}
+
+PUBLIC void lynx_start_link_color ARGS2(
+ int, flag,
+ int, pending)
+{
+ if (flag) {
+ /* makes some terminals work wrong because
+ * they can't handle two attributes at the
+ * same time
+ */
+ /* start_bold(); */
+ start_reverse();
+#if defined(USE_SLANG)
+ if (SLtt_Use_Ansi_Colors)
+ start_underline ();
+#endif /* USE_SLANG */
+#if defined(FANCY_CURSES) && defined(COLOR_CURSES)
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ start_underline ();
+#endif /* USE_SLANG */
+ } else {
+ start_bold();
+ /*
+ * Make sure when flag is OFF that "unhighlighted" links
+ * will be underlined if appropriate. - LE & FM
+ */
+ if (pending)
+ start_underline();
+ }
+}
+
+PUBLIC void lynx_stop_link_color ARGS2(
+ int, flag,
+ int, pending)
+{
+#ifdef USE_COLOR_STYLE
+ LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_OFF, 0);
+#else
+ if (flag) {
+ stop_reverse();
+#if defined(USE_SLANG)
+ if (SLtt_Use_Ansi_Colors)
+ stop_underline ();
+#endif /* USE_SLANG */
+#if defined(FANCY_CURSES) && defined(COLOR_CURSES)
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ stop_underline ();
+#endif /* FANCY_CURSES && COLOR_CURSES */
+ } else {
+ stop_bold();
+ /*
+ * If underlining was turned on above, turn it off. - LE & FM
+ */
+ if (pending)
+ stop_underline();
+ }
+#endif
+}
+
+
+PUBLIC void lynx_stop_target_color NOARGS
+{
+ stop_underline();
+ stop_reverse();
+ stop_bold();
+}
+
+PUBLIC void lynx_start_target_color NOARGS
+{
+ start_bold();
+ start_reverse();
+ start_underline();
+}
+
+
+PUBLIC void lynx_start_status_color NOARGS
+{
+#if USE_COLOR_TABLE && defined(COLOR_CURSES)
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ lynx_set_color (2);
+ else
+#endif
+ start_reverse ();
+}
+
+PUBLIC void lynx_stop_status_color NOARGS
+{
+#if USE_COLOR_TABLE && defined(COLOR_CURSES)
+ if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ lynx_set_color (0);
+ else
+#endif
+ stop_reverse ();
+}
+
+PUBLIC void lynx_start_h1_color NOARGS
+{
+ if (bold_H1 || bold_headers)
+ start_bold();
+}
+
+PUBLIC void lynx_stop_h1_color NOARGS
+{
+ if (bold_H1 || bold_headers)
+ stop_bold();
+}
+
+PUBLIC void lynx_start_prompt_color NOARGS
+{
+ start_reverse ();
+}
+
+PUBLIC void lynx_stop_prompt_color NOARGS
+{
+ stop_reverse ();
+}
+
+PUBLIC void lynx_start_radio_color NOARGS
+{
+ start_bold ();
+}
+
+PUBLIC void lynx_stop_radio_color NOARGS
+{
+ stop_bold ();
+}
+
+PUBLIC void lynx_stop_all_colors NOARGS
+{
+ stop_underline ();
+ stop_reverse ();
+ stop_bold ();
+}
diff --git a/gnu/usr.bin/lynx/src/LYCurses.h b/gnu/usr.bin/lynx/src/LYCurses.h
new file mode 100644
index 00000000000..41d04aea62d
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYCurses.h
@@ -0,0 +1,381 @@
+#ifndef LYCURSES_H
+#define LYCURSES_H
+
+#include "userdefs.h"
+
+/*
+ * The simple color scheme maps the 8 combinations of bold/underline/reverse
+ * to the standard 8 ANSI colors (with some variations based on context).
+ */
+#undef USE_COLOR_TABLE
+
+#ifndef USE_COLOR_STYLE
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+#define USE_COLOR_TABLE 1
+#endif
+#endif
+
+#ifdef TRUE
+#undef TRUE /* to prevent parse error :( */
+#endif /* TRUE */
+#ifdef FALSE
+#undef FALSE /* to prevent parse error :( */
+#endif /* FALSE */
+
+#ifdef USE_SLANG
+#if defined(UNIX) && !defined(unix)
+#define unix
+#endif /* UNIX && !unix */
+#ifdef va_start
+#undef va_start /* not used, undef to avoid warnings on some systems */
+#endif /* va_start */
+#include <slang.h>
+
+#else /* Using curses: */
+
+#ifdef VMS
+#define FANCY_CURSES
+#endif /* VMS */
+
+/*
+ * CR may be defined before the curses.h include occurs.
+ * There is a conflict between the termcap char *CR and the define.
+ * Assuming that the definition of CR will always be carriage return.
+ * 06-09-94 Lynx 2-3-1 Garrett Arch Blythe
+ */
+#ifdef CR
+#undef CR /* to prevent parse error :( */
+#define REDEFINE_CR
+#endif /* CR */
+
+#ifdef HZ
+#undef HZ /* to prevent parse error :( */
+#endif /* HZ */
+
+/* SunOS 4.x has a redefinition between ioctl.h and termios.h */
+#if defined(sun) && !defined(__SVR4)
+#undef NL0
+#undef NL1
+#undef CR0
+#undef CR1
+#undef CR2
+#undef CR3
+#undef TAB0
+#undef TAB1
+#undef TAB2
+#undef XTABS
+#undef BS0
+#undef BS1
+#undef FF0
+#undef FF1
+#undef ECHO
+#undef NOFLSH
+#undef TOSTOP
+#undef FLUSHO
+#undef PENDIN
+#endif
+
+#ifdef HAVE_CONFIG_H
+# ifdef HAVE_NCURSES_H
+# include <ncurses.h>
+# else
+# ifdef HAVE_CURSESX_H
+# include <cursesX.h> /* Ultrix */
+# else
+# ifdef HAVE_JCURSES_H
+# include <jcurses.h> /* sony_news */
+# else
+# include <curses.h> /* default */
+# endif
+# endif
+# endif
+
+# if defined(wgetbkgd) && !defined(getbkgd)
+# define getbkgd(w) wgetbkgd(w) /* workaround pre-1.9.9g bug */
+# endif
+
+# ifdef NCURSES
+extern void LYsubwindow PARAMS((WINDOW * param));
+# endif /* NCURSES */
+
+#else
+# if defined(VMS) && defined(__GNUC__)
+# include "LYGCurses.h"
+# else
+# include <curses.h> /* everything else */
+# endif /* VMS && __GNUC__ */
+#endif /* HAVE_CONFIG_H */
+
+#ifdef VMS
+extern void VMSbox PARAMS((WINDOW *win, int height, int width));
+#else
+extern void LYbox PARAMS((WINDOW *win, BOOLEAN formfield));
+#endif /* VMS */
+#endif /* USE_SLANG */
+
+
+/* Both slang and curses: */
+#ifndef TRUE
+#define TRUE 1
+#endif /* !TRUE */
+#ifndef FALSE
+#define FALSE 0
+#endif /* !FALSE */
+
+#ifdef REDEFINE_CR
+#define CR FROMASCII('\015')
+#endif /* REDEFINE_CR */
+
+#ifdef ALT_CHAR_SET
+#define BOXVERT 0 /* use alt char set for popup window vertical borders */
+#define BOXHORI 0 /* use alt char set for popup window vertical borders */
+#endif
+
+#ifndef BOXVERT
+#define BOXVERT '*' /* character for popup window vertical borders */
+#endif
+#ifndef BOXHORI
+#define BOXHORI '*' /* character for popup window horizontal borders */
+#endif
+
+#ifndef KEY_DOWN
+#undef HAVE_KEYPAD /* avoid confusion with bogus 'keypad()' */
+#endif
+
+extern int LYlines; /* replaces LINES */
+extern int LYcols; /* replaces COLS */
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+extern void start_curses NOPARAMS;
+extern void stop_curses NOPARAMS;
+extern BOOLEAN setup PARAMS((char *terminal));
+extern void LYstartTargetEmphasis NOPARAMS;
+extern void LYstopTargetEmphasis NOPARAMS;
+
+#ifdef VMS
+extern void VMSexit();
+extern int ttopen();
+extern int ttclose();
+extern int ttgetc();
+extern void *VMSsignal PARAMS((int sig, void (*func)()));
+#endif /* VMS */
+
+#if defined(USE_COLOR_STYLE)
+extern void curses_css PARAMS((char * name, int dir));
+extern void curses_style PARAMS((int style, int dir, int previous));
+extern void curses_w_style PARAMS((WINDOW* win, int style, int dir, int previous));
+extern void setHashStyle PARAMS((int style, int color, int cattr, int mono, char* element));
+extern void setStyle PARAMS((int style, int color, int cattr, int mono));
+extern void wcurses_css PARAMS((WINDOW * win, char* name, int dir));
+#define LynxChangeStyle curses_style
+#else
+extern int slang_style PARAMS((int style, int dir, int previous));
+#define LynxChangeStyle slang_style
+#endif /* USE_COLOR_STYLE */
+
+#if USE_COLOR_TABLE
+extern void LYaddAttr PARAMS((int a));
+extern void LYsubAttr PARAMS((int a));
+extern void lynx_setup_colors NOPARAMS;
+extern unsigned int Lynx_Color_Flags;
+#endif
+
+#ifdef USE_SLANG
+#if !defined(VMS) && !defined(DJGPP)
+#define USE_SLANG_MOUSE 1
+#endif /* USE_SLANG */
+
+#define SL_LYNX_USE_COLOR 1
+#define SL_LYNX_USE_BLINK 2
+#define SL_LYNX_OVERRIDE_COLOR 4
+#define start_bold() LYaddAttr(1)
+#define start_reverse() LYaddAttr(2)
+#define start_underline() LYaddAttr(4)
+#define stop_bold() LYsubAttr(1)
+#define stop_reverse() LYsubAttr(2)
+#define stop_underline() LYsubAttr(4)
+
+#ifdef FANCY_CURSES
+#undef FANCY_CURSES
+#endif /* FANCY_CURSES */
+
+/*
+ * Map some curses functions to slang functions.
+ */
+#define stdscr NULL
+#ifdef SLANG_MBCS_HACK
+extern int PHYSICAL_SLtt_Screen_Cols;
+#define COLS PHYSICAL_SLtt_Screen_Cols
+#else
+#define COLS SLtt_Screen_Cols
+#endif /* SLANG_MBCS_HACK */
+#define LINES SLtt_Screen_Rows
+#define move SLsmg_gotorc
+#define addstr SLsmg_write_string
+extern void LY_SLerase NOPARAMS;
+#define erase LY_SLerase
+#define clear LY_SLerase
+#define standout SLsmg_reverse_video
+#define standend SLsmg_normal_video
+#define clrtoeol SLsmg_erase_eol
+
+#ifdef SLSMG_NEWLINE_SCROLLS
+#define scrollok(a,b) SLsmg_Newline_Behavior \
+ = ((b) ? SLSMG_NEWLINE_SCROLLS : SLSMG_NEWLINE_MOVES)
+#else
+#define scrollok(a,b) SLsmg_Newline_Moves = ((b) ? 1 : -1)
+#endif
+
+#define addch SLsmg_write_char
+#define echo()
+#define printw SLsmg_printf
+
+extern int curscr;
+extern BOOLEAN FullRefresh;
+#ifdef clearok
+#undef clearok
+#endif /* clearok */
+#define clearok(a,b) { FullRefresh = (BOOLEAN)b; }
+extern void LY_SLrefresh NOPARAMS;
+#ifdef refresh
+#undef refresh
+#endif /* refresh */
+#define refresh LY_SLrefresh
+
+#ifdef VMS
+extern void VTHome NOPARAMS;
+#define endwin() clear(),refresh(),SLsmg_reset_smg(),VTHome()
+#else
+#define endwin SLsmg_reset_smg(),SLang_reset_tty
+#endif /* VMS */
+
+#else /* Define curses functions: */
+
+#ifdef FANCY_CURSES
+
+#ifdef VMS
+/*
+ * For VMS curses, [w]setattr() and [w]clrattr()
+ * add and subtract, respectively, the attributes
+ * _UNDERLINE, _BOLD, _REVERSE, and _BLINK. - FM
+ */
+#ifdef UNDERLINE_LINKS
+#define start_bold() setattr(_UNDERLINE)
+#define stop_bold() clrattr(_UNDERLINE)
+#define start_underline() setattr(_BOLD)
+#define stop_underline() clrattr(_BOLD)
+#else /* not UNDERLINE_LINKS */
+#define start_bold() setattr(_BOLD)
+#define stop_bold() clrattr(_BOLD)
+#define start_underline() setattr(_UNDERLINE)
+#define stop_underline() clrattr(_UNDERLINE)
+#endif /* UNDERLINE_LINKS */
+#define start_reverse() setattr(_REVERSE)
+#define wstart_reverse(a) wsetattr(a, _REVERSE)
+#define wstop_underline(a) wclrattr(a, _UNDERLINE)
+#define stop_reverse() clrattr(_REVERSE)
+#define wstop_reverse(a) wclrattr(a, _REVERSE)
+
+#else /* Not VMS: */
+
+/*
+ * For Unix FANCY_FANCY curses we interpose
+ * our own functions to add or subtract the
+ * A_foo attributes. - FM
+ */
+#if USE_COLOR_TABLE
+extern void LYaddWAttr PARAMS((WINDOW *win, int a));
+extern void LYaddAttr PARAMS((int a));
+extern void LYsubWAttr PARAMS((WINDOW *win, int a));
+extern void LYsubAttr PARAMS((int a));
+extern void LYaddWAttr PARAMS((WINDOW *win, int a));
+extern void LYsubWAttr PARAMS((WINDOW *win, int a));
+extern void lynx_set_color PARAMS((int a));
+extern void lynx_standout PARAMS((int a));
+extern int lynx_chg_color PARAMS((int, int, int));
+#undef standout
+#define standout() lynx_standout(TRUE)
+#undef standend
+#define standend() lynx_standout(FALSE)
+#else
+#define LYaddAttr attrset
+#define LYaddWAttr wattrset
+#define LYsubAttr attroff
+#define LYsubWAttr wattroff
+#endif
+
+#ifdef UNDERLINE_LINKS
+#define start_bold() LYaddAttr(A_UNDERLINE)
+#define stop_bold() LYsubAttr(A_UNDERLINE)
+#define start_underline() LYaddAttr(A_BOLD)
+#define stop_underline() LYsubAttr(A_BOLD)
+#else /* not UNDERLINE_LINKS: */
+#define start_bold() LYaddAttr(A_BOLD)
+#define stop_bold() LYsubAttr(A_BOLD)
+#define start_underline() LYaddAttr(A_UNDERLINE)
+#define stop_underline() LYsubAttr(A_UNDERLINE)
+#endif /* UNDERLINE_LINKS */
+#if defined(SNAKE) && defined(HP_TERMINAL)
+#define start_reverse() LYaddWAttr(stdscr, A_DIM)
+#define wstart_reverse(a) LYaddWAttr(a, A_DIM)
+#define stop_reverse() LYsubWAttr(stdscr, A_DIM)
+#define wstop_reverse(a) LYsubWAttr(a, A_DIM)
+#else
+#define start_reverse() LYaddAttr(A_REVERSE)
+#define wstart_reverse(a) LYaddWAttr(a, A_REVERSE)
+#define stop_reverse() LYsubAttr(A_REVERSE)
+#define wstop_reverse(a) LYsubWAttr(a, A_REVERSE)
+#endif /* SNAKE && HP_TERMINAL */
+#endif /* VMS */
+
+#else /* Not FANCY_CURSES: */
+
+/*
+ * We only have [w]standout() and [w]standin(),
+ * so we'll use them synonymously for bold and
+ * reverse, and ignore underline. - FM
+ */
+#define start_bold() standout()
+#define start_underline() /* nothing */
+#define start_reverse() standout()
+#define wstart_reverse(a) wstandout(a)
+#define stop_bold() standend()
+#define stop_underline() /* nothing */
+#define stop_reverse() standend()
+#define wstop_reverse(a) wstandend(a)
+
+#endif /* FANCY_CURSES */
+#endif /* USE_SLANG */
+
+#ifdef USE_SLANG
+#define LYGetYX(y, x) y = SLsmg_get_row(), x = SLsmg_get_column()
+#else
+#ifdef getyx
+#define LYGetYX(y, x) getyx(stdscr, y, x)
+#else
+#define LYGetYX(y, x) y = stdscr->_cury, x = stdscr->_curx
+#endif /* getyx */
+#endif /* USE_SLANG */
+
+extern void lynx_enable_mouse PARAMS((int));
+extern void lynx_force_repaint NOPARAMS;
+extern void lynx_start_title_color NOPARAMS;
+extern void lynx_stop_title_color NOPARAMS;
+extern void lynx_start_link_color PARAMS((int flag, int pending));
+extern void lynx_stop_link_color PARAMS((int flag, int pending));
+extern void lynx_stop_target_color NOPARAMS;
+extern void lynx_start_target_color NOPARAMS;
+extern void lynx_start_status_color NOPARAMS;
+extern void lynx_stop_status_color NOPARAMS;
+extern void lynx_start_h1_color NOPARAMS;
+extern void lynx_stop_h1_color NOPARAMS;
+extern void lynx_start_prompt_color NOPARAMS;
+extern void lynx_stop_prompt_color NOPARAMS;
+extern void lynx_start_radio_color NOPARAMS;
+extern void lynx_stop_radio_color NOPARAMS;
+extern void lynx_stop_all_colors NOPARAMS;
+
+#endif /* LYCURSES_H */
diff --git a/gnu/usr.bin/lynx/src/LYDownload.c b/gnu/usr.bin/lynx/src/LYDownload.c
new file mode 100644
index 00000000000..bc047b87a41
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYDownload.c
@@ -0,0 +1,698 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTList.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYStrings.h"
+#include "LYClean.h"
+#include "LYGetFile.h"
+#include "LYDownload.h"
+#include "LYSystem.h"
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * LYDownload takes a URL and downloads it using a user selected
+ * download program
+ *
+ * It parses an incoming link that looks like
+ *
+ * LYNXDOWNLOAD://Method=<#>/File=<STRING>/SugFile=<STRING>
+ */
+#ifdef VMS
+#define COPY_COMMAND "copy/nolog/noconf %s %s"
+PUBLIC BOOLEAN LYDidRename = FALSE;
+#endif /* VMS */
+
+PRIVATE char LYValidDownloadFile[256] = "\0";
+
+PUBLIC void LYDownload ARGS1(
+ char *, line)
+{
+ char *Line = NULL, *method, *file, *sug_file = NULL;
+ int method_number;
+ int count;
+ char buffer[512];
+ char command[512];
+ char *cp, *cp1;
+ lynx_html_item_type *download_command = 0;
+ int c, len;
+ FILE *fp;
+ int ch, recall;
+ int FnameTotal;
+ int FnameNum;
+ BOOLEAN FirstRecall = TRUE;
+ BOOLEAN SecondS = FALSE;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+ LYDidRename = FALSE;
+#endif /* VMS */
+
+ /*
+ * Make sure we have a valid download
+ * file comparison string loaded via
+ * the download options menu. - FM
+ */
+ if (LYValidDownloadFile[0] == '\0') {
+ goto failed;
+ }
+
+ /*
+ * Make a copy of the LYNXDOWNLOAD
+ * internal URL for parsing. - FM
+ */
+ StrAllocCopy(Line, line);
+
+ /*
+ * Parse out the sug_file, Method and the File.
+ */
+ if ((sug_file = (char *)strstr(Line, "SugFile=")) != NULL) {
+ *(sug_file-1) = '\0';
+ /*
+ * Go past "SugFile=".
+ */
+ sug_file += 8;
+ }
+
+ if ((file = (char *)strstr(Line, "File=")) == NULL)
+ goto failed;
+ *(file-1) = '\0';
+ /*
+ * Go past "File=".
+ */
+ file += 5;
+
+ /*
+ * Make sure that the file string is the one from
+ * the last displayed download options menu. - FM
+ */
+ if (strcmp(file, LYValidDownloadFile)) {
+ goto failed;
+ }
+
+#ifdef DIRED_SUPPORT
+ if (!strncmp(file, "file://localhost", 16))
+ file += 16;
+ else if (!strncmp(file, "file:", 5))
+ file += 5;
+ HTUnEscape(file);
+#endif /* DIRED_SUPPORT */
+
+ if ((method = (char *)strstr(Line, "Method=")) == NULL)
+ goto failed;
+ /*
+ * Go past "Method=".
+ */
+ method += 7;
+ method_number = atoi(method);
+
+ /*
+ * Set up the sug_filenames recall buffer.
+ */
+ FnameTotal = (sug_filenames ? HTList_count(sug_filenames) : 0);
+ recall = ((FnameTotal >= 1) ? RECALL : NORECALL);
+ FnameNum = FnameTotal;
+
+ if (method_number < 0) {
+ /*
+ * Write to local file.
+ */
+ _statusline(FILENAME_PROMPT);
+retry:
+ if (sug_file)
+ LYstrncpy(buffer, sug_file, ((sizeof(buffer)/2) - 1));
+ else
+ *buffer = '\0';
+check_recall:
+ if ((ch = LYgetstr(buffer,
+ VISIBLE, (sizeof(buffer)/2), recall)) < 0 ||
+ *buffer == '\0' || ch == UPARROW || ch == DNARROW) {
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the last Fname in the list. - FM
+ */
+ FnameNum = 0;
+ } else {
+ /*
+ * Go back to the previous Fname in the list. - FM
+ */
+ FnameNum++;
+ }
+ if (FnameNum >= FnameTotal) {
+ /*
+ * Reset the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto retry;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(buffer, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the first Fname in the list. - FM
+ */
+ FnameNum = FnameTotal - 1;
+ } else {
+ /*
+ * Advance to the next Fname in the list. - FM
+ */
+ FnameNum--;
+ }
+ if (FnameNum < 0) {
+ /*
+ * Set the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto retry;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(buffer, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_recall;
+ }
+ }
+
+ /*
+ * Save cancelled.
+ */
+ goto cancelled;
+ }
+
+ if (no_dotfiles || !show_dotfiles) {
+ if (*buffer == '.' ||
+#ifdef VMS
+ ((cp = strrchr(buffer, ':')) && *(cp+1) == '.') ||
+ ((cp = strrchr(buffer, ']')) && *(cp+1) == '.') ||
+#endif /* VMS */
+ ((cp = strrchr(buffer, '/')) && *(cp+1) == '.')) {
+ HTAlert(FILENAME_CANNOT_BE_DOT);
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+ }
+ /*
+ * Cancel if the user entered "/dev/null" on Unix,
+ * or an "nl:" path (case-insensitive) on VMS. - FM
+ */
+#ifdef VMS
+ if (!strncasecomp(buffer, "nl:", 3) ||
+ !strncasecomp(buffer, "/nl/", 4))
+#else
+ if (!strcmp(buffer, "/dev/null"))
+#endif /* VMS */
+ {
+ goto cancelled;
+ }
+ if ((cp = strchr(buffer, '~'))) {
+ *(cp++) = '\0';
+ strcpy(command, buffer);
+ if ((len = strlen(command)) > 0 && command[len-1] == '/')
+ command[len-1] = '\0';
+#ifdef DOSPATH
+ strcat(command, HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ strcat(command, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ strcat(command, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ strcat(command, cp);
+ strcpy(buffer, command);
+ }
+#ifdef VMS
+ if (strchr(buffer, '/') != NULL) {
+ strcpy(command, HTVMS_name("", buffer));
+ strcpy(buffer, command);
+ }
+ if (buffer[0] != '/' && strchr(buffer, ':') == NULL) {
+ strcpy(command, "sys$disk:");
+ if (strchr(buffer, ']') == NULL)
+ strcat(command, "[]");
+ strcat(command, buffer);
+ strcpy(buffer, command);
+ }
+#else
+ if (*buffer != '/')
+ cp = getenv("PWD");
+ else
+ cp = NULL;
+ if (cp) {
+ sprintf(command, "%s/%s", cp, buffer);
+#ifdef DOSPATH
+ strcpy(buffer, HTDOS_name(command));
+#else
+ strcpy(buffer, command);
+#endif
+ }
+#endif /* VMS */
+
+ /*
+ * See if it already exists.
+ */
+ if ((fp = fopen(buffer, "r")) != NULL) {
+ fclose(fp);
+
+#ifdef VMS
+ _statusline(FILE_EXISTS_HPROMPT);
+#else
+ _statusline(FILE_EXISTS_OPROMPT);
+#endif /* VMS */
+ c = 0;
+ while(TOUPPER(c)!='Y' && TOUPPER(c)!='N' && c != 7 && c != 3)
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ FREE(Line);
+ return;
+ }
+#endif /* VMS */
+
+ if (c == 7 || c == 3) { /* Control-G or Control-C */
+ goto cancelled;
+ }
+
+ if (TOUPPER(c) == 'N') {
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+ }
+
+ /*
+ * See if we can write to it.
+ */
+ if ((fp = fopen(buffer, "w")) != NULL) {
+ fclose(fp);
+ remove(buffer);
+ } else {
+ HTAlert(CANNOT_WRITE_TO_FILE);
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+ SecondS = TRUE;
+
+ _statusline(SAVING);
+ sleep(InfoSecs);
+#ifdef VMS
+ /*
+ * Try rename() first. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "command: rename(%s, %s)\n", file, buffer);
+ if (rename(file, buffer)) {
+ /*
+ * Failed. Use spawned COPY_COMMAND. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, " FAILED!\n");
+ sprintf(command, COPY_COMMAND, file, buffer);
+ if (TRACE)
+ fprintf(stderr, "command: %s\n", command);
+ fflush(stderr);
+ fflush(stdout);
+ stop_curses();
+ system(command);
+ fflush(stdout);
+ fflush(stderr);
+ start_curses();
+ } else {
+ /*
+ * We don't have the temporary file (it was renamed to
+ * a permanent file), so set a flag to pop out of the
+ * download menu. - FM
+ */
+ LYDidRename = TRUE;
+ }
+ chmod(buffer, HIDE_CHMOD);
+#else /* Unix: */
+ /*
+ * Prevent spoofing of the shell.
+ */
+ cp = quote_pathname(file);
+ cp1 = quote_pathname(buffer);
+ sprintf(command, "%s %s %s", COPY_PATH, cp, cp1);
+ FREE(cp);
+ FREE(cp1);
+ if (TRACE)
+ fprintf(stderr, "command: %s\n", command);
+ fflush(stderr);
+ fflush(stdout);
+ stop_curses();
+ system(command);
+ fflush(stdout);
+ fflush(stderr);
+ start_curses();
+#if defined(UNIX)
+ LYRelaxFilePermissions(buffer);
+#endif /* defined(UNIX) */
+#endif /* VMS */
+
+ } else {
+ /*
+ * Use configured download commands.
+ */
+ buffer[0] = '\0';
+ for (count = 0, download_command=downloaders;
+ count < method_number;
+ count++, download_command = download_command->next)
+ ; /* null body */
+
+ /*
+ * Commands have the form "command %s [etc]"
+ * where %s is the filename.
+ */
+ if (download_command->command != NULL) {
+ /*
+ * Check for two '%s' and ask for the local filename if
+ * there is.
+ */
+ char *first_s = strstr(download_command->command, "%s");
+ if (first_s && strstr(first_s+1, "%s")) {
+ _statusline(FILENAME_PROMPT);
+ again: if (sug_file)
+ strcpy(buffer, sug_file);
+ else
+ *buffer = '\0';
+ check_again:
+ if ((ch = LYgetstr(buffer, VISIBLE,
+ sizeof(buffer), recall)) < 0 ||
+ *buffer == '\0' || ch == UPARROW || ch == DNARROW) {
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the last Fname in the list. - FM
+ */
+ FnameNum = 0;
+ } else {
+ /*
+ * Go back to the previous Fname
+ * in the list. - FM
+ */
+ FnameNum++;
+ }
+ if (FnameNum >= FnameTotal) {
+ /*
+ * Reset the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto again;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(buffer, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_again;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the first Fname in the list. - FM
+ */
+ FnameNum = FnameTotal - 1;
+ } else {
+ /*
+ * Advance to the next Fname in the list. - FM
+ */
+ FnameNum--;
+ }
+ if (FnameNum < 0) {
+ /*
+ * Set the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto again;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(buffer, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_again;
+ }
+ }
+
+ /*
+ * Download cancelled.
+ */
+ goto cancelled;
+ }
+
+ if (no_dotfiles || !show_dotfiles) {
+ if (*buffer == '.' ||
+#ifdef VMS
+ ((cp = strrchr(buffer, ':')) && *(cp+1) == '.') ||
+ ((cp = strrchr(buffer, ']')) && *(cp+1) == '.') ||
+#endif /* VMS */
+ ((cp = strrchr(buffer, '/')) && *(cp+1) == '.')) {
+ HTAlert(FILENAME_CANNOT_BE_DOT);
+ _statusline(NEW_FILENAME_PROMPT);
+ goto again;
+ }
+ }
+ /*
+ * Cancel if the user entered "/dev/null" on Unix,
+ * or an "nl:" path (case-insensitive) on VMS. - FM
+ */
+#ifdef VMS
+ if (!strncasecomp(buffer, "nl:", 3) ||
+ !strncasecomp(buffer, "/nl/", 4))
+#else
+ if (!strcmp(buffer, "/dev/null"))
+#endif /* VMS */
+ {
+ goto cancelled;
+ }
+ SecondS = TRUE;
+ }
+
+ /*
+ * The following is considered a bug by the community.
+ * If the command only takes one argument on the command
+ * line, then the suggested file name is not used.
+ * It actually is not a bug at all and does as it should,
+ * putting both names on the command line.
+ */
+#ifdef VMS
+ sprintf(command, download_command->command, file, buffer,
+ "", "", "", "", "", "", "", "", "", "");
+#else /* Unix: */
+ /*
+ * Prevent spoofing of the shell.
+ */
+ cp = quote_pathname(file);
+ cp1 = quote_pathname(buffer);
+ sprintf(command, download_command->command, cp, cp1,
+ "", "", "", "", "", "", "", "", "", "");
+ FREE(cp);
+ FREE(cp1);
+#endif /* VMS */
+
+ } else {
+ _statusline(MISCONF_DOWNLOAD_COMMAND);
+ sleep(AlertSecs);
+ goto failed;
+ }
+
+ if (TRACE)
+ fprintf(stderr, "command: %s\n", command);
+ stop_curses();
+ fflush(stderr);
+ fflush(stdout);
+ system(command);
+ fflush(stderr);
+ fflush(stdout);
+ start_curses();
+ /* don't remove(file); */
+ }
+
+ if (SecondS == TRUE) {
+#ifdef VMS
+ if (0 == strncasecomp(buffer, "sys$disk:", 9)) {
+ if (0 == strncmp((buffer+9), "[]", 2)) {
+ HTAddSugFilename(buffer+11);
+ } else {
+ HTAddSugFilename(buffer+9);
+ }
+ } else {
+ HTAddSugFilename(buffer);
+ }
+#else
+ HTAddSugFilename(buffer);
+#endif /* VMS */
+ }
+ FREE(Line);
+ return;
+
+failed:
+ _statusline(CANNOT_DOWNLOAD_FILE);
+ sleep(AlertSecs);
+ FREE(Line);
+ return;
+
+cancelled:
+ _statusline(CANCELLING);
+ sleep(InfoSecs);
+ FREE(Line);
+ return;
+}
+
+/*
+ * LYdownload_options writes out the current download choices to
+ * a file so that the user can select printers in the same way that
+ * they select all other links. Download links look like:
+ * LYNXDOWNLOAD://Method=<#>/File=<STRING>/SugFile=<STRING>
+ */
+PUBLIC int LYdownload_options ARGS2(
+ char **, newfile,
+ char *, data_file)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ static char download_filename[256];
+ char *sug_filename = NULL;
+ FILE *fp0;
+ lynx_html_item_type *cur_download;
+ int count;
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ first = FALSE;
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(download_filename, "file://localhost/%s", tempfile);
+#else
+ sprintf(download_filename, "file://localhost%s", tempfile);
+#endif /* VMS */
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ /*
+ * Get a suggested filename.
+ */
+ StrAllocCopy(sug_filename, *newfile);
+ change_sug_filename(sug_filename);
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(-1);
+ }
+
+ LYstrncpy(LYValidDownloadFile,
+ data_file,
+ (sizeof(LYValidDownloadFile) - 1));
+ StrAllocCopy(*newfile, download_filename);
+ LYforce_no_cache = TRUE; /* don't cache this doc */
+
+ fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+ DOWNLOAD_OPTIONS_TITLE);
+
+ fprintf(fp0,"<h1>Download Options (%s Version %s)</h1><pre>\n",
+ LYNX_NAME, LYNX_VERSION);
+
+
+ fprintf(fp0, " You have the following download choices.\n");
+ fprintf(fp0, " Please select one:\n\n");
+
+ if(!no_disk_save && !child_lynx)
+#ifdef DIRED_SUPPORT
+ /*
+ * Disable save to disk option for local files.
+ */
+ if (!lynx_edit_mode)
+#endif /* DIRED_SUPPORT */
+ fprintf(fp0," \
+<a href=\"LYNXDOWNLOAD://Method=-1/File=%s/SugFile=%s%s\">Save to disk</a>\n",
+ data_file, (lynx_save_space ? lynx_save_space : ""), sug_filename);
+#ifdef DIRED_SUPPORT
+ else {}
+#endif /* DIRED_SUPPORT */
+ else
+ fprintf(fp0," Save to disk disabled.\n");
+
+ if (downloaders != NULL) {
+ for (count = 0, cur_download = downloaders; cur_download != NULL;
+ cur_download = cur_download->next, count++) {
+ if (!no_download || cur_download->always_enabled) {
+ fprintf(fp0," \
+<a href=\"LYNXDOWNLOAD://Method=%d/File=%s/SugFile=%s\">",
+ count,data_file, sug_filename);
+ fprintf(fp0, (cur_download->name ?
+ cur_download->name : "No Name Given"));
+ fprintf(fp0,"</a>\n");
+ }
+ }
+ } else {
+ fprintf(fp0, "\n\
+No other download methods have been defined yet. You may define\n\
+an unlimited number of download methods using the lynx.cfg file.\n");
+ }
+ fprintf(fp0, "</pre>\n</body>\n");
+ fclose(fp0);
+
+ /*
+ * Free off temp copy.
+ */
+ FREE(sug_filename);
+
+ return(0);
+}
diff --git a/gnu/usr.bin/lynx/src/LYDownload.h b/gnu/usr.bin/lynx/src/LYDownload.h
new file mode 100644
index 00000000000..21cd30dd481
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYDownload.h
@@ -0,0 +1,15 @@
+
+#ifndef LYDOWNLOAD_H
+#define LYDOWNLOAD_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern void LYDownload PARAMS((char *line));
+extern int LYdownload_options PARAMS((char **newfile, char *data_file));
+
+#define DOWNLOAD_OPTIONS_TITLE "Lynx Download Options"
+
+#endif /* LYDOWNLOAD_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYEdit.c b/gnu/usr.bin/lynx/src/LYEdit.c
new file mode 100644
index 00000000000..2ab96cf4970
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYEdit.c
@@ -0,0 +1,189 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYSignal.h"
+#include "LYUtils.h"
+#include "LYClean.h"
+#include "LYGlobalDefs.h"
+#include "LYEdit.h"
+#include "LYStrings.h"
+#include "LYSystem.h"
+#ifdef VMS
+#include <unixio.h>
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * In edit mode invoke either emacs, vi, pico, jove, jed sedt or the
+ * default editor to display and edit the current file.
+ * For emacs, vi, pico, jove and jed, Lynx will open the file to the
+ * same line that the screen cursor is on when editing is invoked.
+ * Returns FALSE if file is uneditable.
+ */
+PUBLIC int edit_current_file ARGS3(
+ char *, newfile,
+ int, cur,
+ int, lineno)
+{
+ char command[512];
+ char *filename = NULL;
+ char *colon, *number_sign;
+ FILE *fp;
+
+ /*
+ * If its a remote file then we can't edit it.
+ */
+ if (!LYisLocalFile(newfile)) {
+ _statusline(CANNOT_EDIT_REMOTE_FILES);
+ sleep(MessageSecs);
+ return FALSE;
+ }
+
+ /*
+ * If there's a fragment, trim it. - FM
+ */
+ number_sign = strchr(newfile, '#');
+ if (number_sign)
+ *number_sign = '\0';
+
+ /*
+ * On Unix, first try to open it as a completely referenced file,
+ * then via the path alone.
+ *
+ * On VMS, only try the path.
+ */
+#if !defined (VMS) && !defined (DOSPATH)
+ colon = strchr(newfile, ':');
+ StrAllocCopy(filename, (colon + 1));
+ HTUnEscape(filename);
+ if ((fp = fopen(filename, "r")) == NULL) {
+ FREE(filename);
+#endif /* !VMS */
+ filename = HTParse(newfile, "", PARSE_PATH+PARSE_PUNCTUATION);
+ HTUnEscape(filename);
+#ifdef DOSPATH
+ if (strlen(filename)>1) filename++;
+#endif
+#ifdef DOSPATH
+ if ((fp = fopen(HTDOS_name(filename),"r")) == NULL) {
+#else
+#ifdef VMS
+ if ((fp = fopen(HTVMS_name("", filename), "r")) == NULL) {
+#else
+ if ((fp = fopen(filename, "r")) == NULL) {
+#endif /* VMS */
+#endif /* DOSPATH */
+ HTAlert(COULD_NOT_ACCESS_FILE);
+ FREE(filename);
+ goto failure;
+ }
+#if !defined (VMS) && !defined (DOSPATH)
+ }
+#endif /* !VMS */
+ fclose(fp);
+
+#if defined(VMS) || defined(CANT_EDIT_UNWRITABLE_FILES)
+ /*
+ * Don't allow editing if user lacks append access.
+ */
+#ifdef DOSPATH
+ if ((fp = fopen(HTDOS_name("", filename), "a")) == NULL) {
+#else
+#ifdef VMS
+ if ((fp = fopen(HTVMS_name("", filename), "a")) == NULL) {
+#else
+ if ((fp = fopen(filename, "a")) == NULL) {
+#endif /* VMS */
+#endif /* DOSPATH */
+ _statusline(NOAUTH_TO_EDIT_FILE);
+ sleep(MessageSecs);
+ goto failure;
+ }
+ fclose(fp);
+#endif /* VMS || CANT_EDIT_UNWRITABLE_FILES */
+
+ /*
+ * Make sure cur is at least zero. - FM
+ */
+ if (cur < 0) {
+ cur = 0;
+ }
+
+ /*
+ * Set up the command for the editor. - FM
+ */
+#ifdef VMS
+ if ((strstr(editor, "sedt") || strstr(editor, "SEDT")) &&
+ ((lineno - 1) + (nlinks ? links[cur].ly : 0)) > 0) {
+ sprintf(command, "%s %s -%d",
+ editor,
+ HTVMS_name("", filename),
+ ((lineno - 1) + (nlinks ? links[cur].ly : 0)));
+ } else {
+ sprintf(command, "%s %s", editor, HTVMS_name("", filename));
+ }
+#else
+ if (strstr(editor, "emacs") || strstr(editor, "vi") ||
+ strstr(editor, "pico") || strstr(editor, "jove") ||
+ strstr(editor, "jed"))
+ sprintf(command, "%s +%d \"%s\"",
+ editor,
+ (lineno + (nlinks ? links[cur].ly : 0)),
+#ifdef DOSPATH
+ HTDOS_name(filename));
+#else
+ filename);
+#endif /* DOSPATH */
+ else
+#ifdef __DJGPP__
+ sprintf(command, "%s %s", editor, HTDOS_name(filename));
+#else
+ sprintf(command, "%s \"%s\"", editor,
+#ifdef DOSPATH
+ HTDOS_name(filename));
+#else
+ filename);
+#endif /* DOSPATH */
+#endif /* __DJGPP__ */
+#endif /* VMS */
+ if (TRACE) {
+ fprintf(stderr, "LYEdit: %s\n", command);
+ sleep(MessageSecs);
+ }
+ FREE(filename);
+
+ /*
+ * Invoke the editor. - FM
+ */
+ fflush(stderr);
+ fflush(stdout);
+ stop_curses();
+ system(command);
+ fflush(stdout);
+ fflush(stderr);
+ start_curses();
+
+ /*
+ * Restore the fragment if there was one. - FM
+ */
+ if (number_sign)
+ *number_sign = '#';
+ return TRUE;
+
+failure:
+ /*
+ * Restore the fragment if there was one. - FM
+ */
+ if (number_sign)
+ *number_sign = '#';
+ return FALSE;
+}
diff --git a/gnu/usr.bin/lynx/src/LYEdit.h b/gnu/usr.bin/lynx/src/LYEdit.h
new file mode 100644
index 00000000000..08c07625081
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYEdit.h
@@ -0,0 +1,7 @@
+
+#ifndef LYEDIT_H
+#define LYEDIT_H
+
+extern int edit_current_file PARAMS((char *newfile, int cur, int lineno));
+
+#endif /* LYEDIT_H */
diff --git a/gnu/usr.bin/lynx/src/LYEditmap.c b/gnu/usr.bin/lynx/src/LYEditmap.c
new file mode 100644
index 00000000000..54c146ff9f4
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYEditmap.c
@@ -0,0 +1,150 @@
+/* LYEditMap.c
+ Keybindings for line and form editting.
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYStrings.h"
+
+PUBLIC int current_lineedit = 0; /* Index into LYLineEditors[] */
+
+/*
+ * See LYStrings.h for the LYE definitions.
+ */
+PRIVATE char DefaultEditBinding[]={
+
+LYE_NOP, LYE_BOL, LYE_DELPW, LYE_ABORT,
+/* nul ^A ^B ^C */
+
+LYE_DELC, LYE_EOL, LYE_DELNW, LYE_ABORT,
+/* ^D ^E ^F ^G */
+
+LYE_DELP, LYE_ENTER, LYE_ENTER, LYE_LOWER,
+/* bs tab nl ^K */
+
+LYE_NOP, LYE_ENTER, LYE_FORWW, LYE_ABORT,
+/* ^L cr ^N ^O */
+
+LYE_BACKW, LYE_NOP, LYE_DELN, LYE_NOP,
+/* ^P XON ^R XOFF */
+
+LYE_UPPER, LYE_ERASE, LYE_LKCMD, LYE_NOP,
+/* ^T ^U ^V ^W */
+
+LYE_ERASE, LYE_NOP, LYE_NOP, LYE_NOP,
+/* ^X ^Y ^Z ESC */
+
+LYE_NOP, LYE_NOP, LYE_NOP, LYE_NOP,
+/* ^\ ^] ^^ ^_ */
+
+/* sp .. RUBOUT */
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_DELP,
+
+/* 80..9F ISO-8859-1 8-bit escape characters. */
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_AIX,
+/* 97 AIX */
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+
+/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+LYE_CHAR, LYE_CHAR, LYE_CHAR, LYE_CHAR,
+
+/* 100..10E function key definitions in LYStrings.h */
+LYE_NOP, LYE_NOP, LYE_FORW, LYE_BACK,
+/* UPARROW DNARROW RTARROW LTARROW */
+
+LYE_NOP, LYE_NOP, LYE_BOL, LYE_EOL,
+/* PGDOWN PGUP HOME END */
+
+LYE_NOP, LYE_TAB, LYE_BOL, LYE_EOL,
+/* F1 Do key Find key Select key */
+
+LYE_NOP, LYE_DELP, LYE_NOP, LYE_NOP,
+/* Insert key Remove key DO_NOTHING ... */
+};
+
+/*
+ * Add your favorite key binding HERE
+ */
+
+
+/*
+ * Add the array name to LYLineEditors
+ */
+
+PUBLIC char * LYLineEditors[]={
+ DefaultEditBinding, /* You can't please everyone, so you ... DW */
+};
+
+/*
+ * Add the name that the user will see below.
+ * The order of LYLineEditors and LyLineditNames MUST be the same
+ */
+PUBLIC char * LYLineeditNames[]={
+ "Default Binding ",
+ (char *) 0
+};
+
+/*
+ * Dummy initializer to ensure this module is linked
+ * if the external model is common block, and the
+ * module is ever placed in a library. - FM
+ */
+PUBLIC int LYEditmapDeclared NOPARAMS
+{
+ int status = 1;
+
+ return status;
+}
+
diff --git a/gnu/usr.bin/lynx/src/LYExtern.c b/gnu/usr.bin/lynx/src/LYExtern.c
new file mode 100644
index 00000000000..9e793a04791
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYExtern.c
@@ -0,0 +1,97 @@
+/*
+ External application support.
+ This feature allows lynx to pass a given URL to an external program.
+ It was written for three reasons.
+ 1) To overcome the deficiency of Lynx_386 not supporting ftp and news.
+ External programs can be used instead by passing the URL.
+
+ 2) To allow for background transfers in multitasking systems.
+ I use wget for http and ftp transfers via the external command.
+
+ 3) To allow for new URLs to be used through lynx.
+ URLs can be made up such as mymail: to spawn desired applications
+ via the external command.
+
+ See lynx.cfg for other info.
+*/
+
+#include "tcp.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYExtern.h"
+#include "LYCurses.h"
+
+#include "LYLeaks.h"
+
+#ifdef USE_EXTERNALS
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+void run_external ARGS1(char *, c)
+{
+ char command[1024];
+ lynx_html_item_type *externals2=0;
+
+ if (externals == NULL) return;
+
+ for(externals2=externals; externals2 != NULL;
+ externals2=externals2->next)
+ {
+
+#ifdef _WINDOWS
+ if (!strnicmp(externals2->name,c,strlen(externals2->name)))
+#else
+ if (!strncasecomp(externals2->name,c,strlen(externals2->name)))
+#endif
+ {
+ char *cp;
+
+ if(no_externals && !externals2->always_enabled)
+ {
+ statusline(EXTERNALS_DISABLED);
+ sleep(MessageSecs);
+ return;
+ }
+
+ /* Too dangerous to leave any URL that may come along unquoted.
+ * They often contain '&', ';', and '?' chars, and who knows
+ * what else may occur.
+ * Prevent spoofing of the shell.
+ * Dunno how this needs to be modified for VMS or DOS. - kw
+ */
+#if defined(VMS) || defined(DOSPATH)
+ sprintf(command, externals2->command, c);
+#else /* Unix or DOS/Win: */
+ cp = quote_pathname(c);
+ sprintf(command, externals2->command, cp);
+ FREE(cp);
+#endif /* VMS */
+
+ if (*command != '\0')
+ {
+
+ statusline(command);
+ sleep(MessageSecs);
+
+ stop_curses();
+ fflush(stdout);
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(0);
+ _go32_want_ctrl_break(1);
+#endif /* __DJGPP__ */
+ system(command);
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(1);
+ _go32_want_ctrl_break(0);
+#endif /* __DJGPP__ */
+
+ fflush(stdout);
+ start_curses();
+ }
+
+ return;
+ }
+ }
+
+ return;
+}
+#endif /* USE_EXTERNALS */
diff --git a/gnu/usr.bin/lynx/src/LYExtern.h b/gnu/usr.bin/lynx/src/LYExtern.h
new file mode 100644
index 00000000000..09983b47c98
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYExtern.h
@@ -0,0 +1,10 @@
+#ifndef EXTERNALS_H
+#define EXTERNALS_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+void run_external PARAMS((char * c));
+
+#endif /* EXTERNALS_H */
diff --git a/gnu/usr.bin/lynx/src/LYForms.c b/gnu/usr.bin/lynx/src/LYForms.c
new file mode 100644
index 00000000000..0387ad1ddeb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYForms.c
@@ -0,0 +1,1503 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTCJK.h"
+#include "HTTP.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "GridText.h"
+#include "LYCharSets.h"
+#include "UCAux.h"
+#include "LYUtils.h"
+#include "LYStructs.h" /* includes HTForms.h */
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "LYKeymap.h"
+#include "LYSignal.h"
+
+#include "LYLeaks.h"
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+#include "LYHash.h"
+#endif
+
+extern HTCJKlang HTCJK;
+
+PRIVATE int form_getstr PARAMS((
+ struct link * form_link));
+PRIVATE int popup_options PARAMS((
+ int cur_selection,
+ OptionType * list,
+ int ly,
+ int lx,
+ int width,
+ int i_length,
+ int disabled));
+
+PUBLIC int change_form_link ARGS6(
+ struct link *, form_link,
+ int, mode,
+ document *, newdoc,
+ BOOLEAN *, refresh_screen,
+ char *, link_name,
+ char *, link_value)
+{
+ FormInfo *form = form_link->form;
+ int c = DO_NOTHING;
+ int OrigNumValue;
+
+ /*
+ * If there is no form to perform action on, don't do anything.
+ */
+ if (form == NULL) {
+ return(c);
+ }
+
+ /*
+ * Move to the link position.
+ */
+ move(form_link->ly, form_link->lx);
+
+ switch(form->type) {
+ case F_CHECKBOX_TYPE:
+ if (form->disabled == YES)
+ break;
+ if (form->num_value) {
+ form_link->hightext = unchecked_box;
+ form->num_value = 0;
+ } else {
+ form_link->hightext = checked_box;
+ form->num_value = 1;
+ }
+ break;
+
+ case F_OPTION_LIST_TYPE:
+ if (!form->select_list) {
+ HTAlert(BAD_HTML_NO_POPUP);
+ c = DO_NOTHING;
+ break;
+ }
+
+ if (form->disabled == YES) {
+ int dummy;
+ dummy = popup_options(form->num_value, form->select_list,
+ form_link->ly, form_link->lx, form->size,
+ form->size_l, form->disabled);
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ if (!enable_scrollback)
+#if defined(VMS) && !defined(USE_SLANG)
+ c = DO_NOTHING;
+#else
+ c = 23; /* CTRL-W refresh without clearok */
+#endif /* VMS && !USE_SLANG */
+ else
+#endif /* FANCY_CURSES || USE_SLANG */
+ c = 12; /* CTRL-L for repaint */
+ break;
+ }
+ OrigNumValue = form->num_value;
+ form->num_value = popup_options(form->num_value, form->select_list,
+ form_link->ly, form_link->lx, form->size,
+ form->size_l, form->disabled);
+
+ {
+ OptionType * opt_ptr = form->select_list;
+ int i;
+ for (i = 0; i < form->num_value; i++, opt_ptr = opt_ptr->next)
+ ; /* null body */
+ /*
+ * Set the name.
+ */
+ form->value = opt_ptr->name;
+ /*
+ * Set the value.
+ */
+ form->cp_submit_value = opt_ptr->cp_submit_value;
+ /*
+ * Set charset in which we have the submit value. - kw
+ */
+ form->value_cs = opt_ptr->value_cs;
+ }
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ if (!enable_scrollback)
+#if defined(VMS) && !defined(USE_SLANG)
+ if (form->num_value == OrigNumValue)
+ c = DO_NOTHING;
+ else
+#endif /* VMS && !USE_SLANG*/
+ c = 23; /* CTRL-W refresh without clearok */
+ else
+#endif /* FANCY_CURSES || USE_SLANG */
+ c = 12; /* CTRL-L for repaint */
+ break;
+
+ case F_RADIO_TYPE:
+ if (form->disabled == YES)
+ break;
+ /*
+ * Radio buttons must have one and
+ * only one down at a time!
+ */
+ if (form->num_value) {
+ _statusline(NEED_CHECKED_RADIO_BUTTON);
+ sleep(MessageSecs);
+
+ } else {
+ int i;
+ /*
+ * Run though list of the links on the screen and
+ * unselect any that are selected. :)
+ */
+ lynx_start_radio_color ();
+ for (i = 0; i < nlinks; i++) {
+ if (links[i].type == WWW_FORM_LINK_TYPE &&
+ links[i].form->type == F_RADIO_TYPE &&
+ links[i].form->number == form->number &&
+ /*
+ * If it has the same name and its on...
+ */
+ !strcmp(links[i].form->name, form->name) &&
+ links[i].form->num_value) {
+ move(links[i].ly, links[i].lx);
+ addstr(unchecked_radio);
+ links[i].hightext = unchecked_radio;
+ }
+ }
+ lynx_stop_radio_color ();
+ /*
+ * Will unselect other button and select this one.
+ */
+ HText_activateRadioButton(form);
+ /*
+ * Now highlight this one.
+ */
+ form_link->hightext = checked_radio;
+ }
+ break;
+
+ case F_TEXT_TYPE:
+ case F_TEXTAREA_TYPE:
+ case F_PASSWORD_TYPE:
+ c = form_getstr(form_link);
+ if (form->type == F_PASSWORD_TYPE)
+ form_link->hightext = STARS(strlen(form->value));
+ else
+ form_link->hightext = form->value;
+ break;
+
+ case F_RESET_TYPE:
+ if (form->disabled == YES)
+ break;
+ HText_ResetForm(form);
+ *refresh_screen = TRUE;
+ break;
+
+ case F_TEXT_SUBMIT_TYPE:
+ c = form_getstr(form_link);
+ if (form->disabled == YES &&
+ (c == '\r' || c == '\n')) {
+ c = '\t';
+ break;
+ }
+ if (c == '\r' || c == '\n') {
+ form_link->hightext = form->value;
+ if (!form->submit_action || *form->submit_action == '\0') {
+ _statusline(NO_FORM_ACTION);
+ sleep(MessageSecs);
+ c = DO_NOTHING;
+ break;
+ } else if (form->submit_method == URL_MAIL_METHOD && no_mail) {
+ HTAlert(FORM_MAILTO_DISALLOWED);
+ c = DO_NOTHING;
+ break;
+ } else {
+ if (form->no_cache &&
+ form->submit_method != URL_MAIL_METHOD) {
+ LYforce_no_cache = TRUE;
+ reloading = TRUE;
+ }
+ HText_SubmitForm(form, newdoc, link_name, form->value);
+ }
+ if (form->submit_method == URL_MAIL_METHOD) {
+ *refresh_screen = TRUE;
+ } else {
+ /*
+ * Returns new document URL.
+ */
+ newdoc->link = 0;
+ newdoc->internal_link = FALSE;
+ }
+ c = DO_NOTHING;
+ break;
+ } else {
+ form_link->hightext = form->value;
+ }
+ break;
+
+ case F_SUBMIT_TYPE:
+ case F_IMAGE_SUBMIT_TYPE:
+ if (form->disabled == YES)
+ break;
+ if (form->no_cache &&
+ form->submit_method != URL_MAIL_METHOD) {
+ LYforce_no_cache = TRUE;
+ reloading = TRUE;
+ }
+ HText_SubmitForm(form, newdoc, link_name, link_value);
+ if (form->submit_method == URL_MAIL_METHOD)
+ *refresh_screen = TRUE;
+ else {
+ /* returns new document URL */
+ newdoc->link = 0;
+ newdoc->internal_link = FALSE;
+ }
+ break;
+
+ }
+
+ return(c);
+}
+
+PRIVATE int form_getstr ARGS1(
+ struct link *, form_link)
+{
+ FormInfo *form = form_link->form;
+ char *value = form->value;
+ int ch;
+ int far_col;
+ int max_length;
+ int startcol, startline;
+ BOOL HaveMaxlength = FALSE;
+ int action;
+
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif
+
+ EditFieldData MyEdit;
+ BOOLEAN Edited = FALSE; /* Value might be updated? */
+
+ /*
+ * Get the initial position of the cursor.
+ */
+ LYGetYX(startline, startcol);
+ if ((startcol + form->size) > (LYcols - 1))
+ far_col = (LYcols - 1);
+ else
+ far_col = (startcol + form->size);
+
+ /*
+ * Make sure the form field value does not exceed our buffer. - FM
+ */
+ max_length = ((form->maxlength > 0 &&
+ form->maxlength < sizeof(MyEdit.buffer)) ?
+ form->maxlength :
+ (sizeof(MyEdit.buffer) - 1));
+ if (strlen(form->value) > max_length) {
+ /*
+ * We can't fit the entire value into the editing buffer,
+ * so enter as much of the tail as fits. - FM
+ */
+ value += (strlen(form->value) - max_length);
+ if (!form->disabled &&
+ !(form->submit_method == URL_MAIL_METHOD && no_mail)) {
+ /*
+ * If we can edit it, report that we are using the tail. - FM
+ */
+ _statusline(FORM_VALUE_TOO_LONG);
+ sleep(MessageSecs);
+ switch(form->type) {
+ case F_PASSWORD_TYPE:
+ statusline(FORM_LINK_PASSWORD_MESSAGE);
+ break;
+ case F_TEXT_SUBMIT_TYPE:
+ if (form->submit_method == URL_MAIL_METHOD) {
+ statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG);
+ } else if (form->no_cache) {
+ statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE);
+ } else {
+ statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE);
+ }
+ break;
+ case F_TEXT_TYPE:
+ case F_TEXTAREA_TYPE:
+ statusline(FORM_LINK_TEXT_MESSAGE);
+ break;
+ default:
+ break;
+ }
+ move(startline, startcol);
+ }
+ }
+
+ /*
+ * Print panned line
+ */
+ LYSetupEdit(&MyEdit, value, max_length, (far_col - startcol));
+ MyEdit.pad = '_';
+ MyEdit.hidden = (form->type == F_PASSWORD_TYPE);
+ LYRefreshEdit(&MyEdit);
+
+ /*
+ * And go for it!
+ */
+ for (;;) {
+again:
+ ch = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ ch = 7;
+ }
+#endif /* VMS */
+
+ /*
+ * Filter out global navigation keys that should not be passed
+ * to line editor, and LYK_REFRESH.
+ */
+ action = EditBinding(ch);
+ if (action == LYE_ENTER)
+ break;
+ if (action == LYE_LKCMD) {
+ _statusline(ENTER_LYNX_COMMAND);
+ ch = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ ch = 7;
+ }
+#endif /* VMS */
+ break;
+ }
+ if (action == LYE_AIX &&
+ (HTCJK == NOCJK && LYlowest_eightbit[current_char_set] > 0x97))
+ break;
+ if (action == LYE_TAB) {
+ ch = (int)('\t');
+ break;
+ }
+ if (action == LYE_ABORT) {
+ return(DO_NOTHING);
+ }
+ if (keymap[ch + 1] == LYK_REFRESH)
+ break;
+ switch (ch) {
+ case DNARROW:
+ case UPARROW:
+ case PGUP:
+ case PGDOWN:
+#ifdef NOTDEFINED
+ case HOME:
+ case END:
+ case FIND_KEY:
+ case SELECT_KEY:
+#endif /* NOTDEFINED */
+ goto breakfor;
+
+ /*
+ * Left arrrow in column 0 deserves special treatment here,
+ * else you can get trapped in a form without submit button!
+ */
+ case LTARROW:
+ if (MyEdit.pos == 0) {
+ int c = 'Y'; /* Go back immediately if no changes */
+ if (strcmp(MyEdit.buffer, value)) {
+ _statusline(PREV_DOC_QUERY);
+ c = LYgetch();
+ }
+ if (TOUPPER(c) == 'Y') {
+ return(ch);
+ } else {
+ if (form->disabled == YES)
+ _statusline(ARROWS_OR_TAB_TO_MOVE);
+ else
+ _statusline(ENTER_TEXT_ARROWS_OR_TAB);
+ }
+ }
+ /* fall through */
+
+ default:
+ if (form->disabled == YES)
+ goto again;
+ /*
+ * Make sure the statusline uses editmode help.
+ */
+ LYLineEdit(&MyEdit, ch, TRUE);
+ if (MyEdit.strlen >= max_length) {
+ HaveMaxlength = TRUE;
+ } else if (HaveMaxlength &&
+ MyEdit.strlen < max_length) {
+ HaveMaxlength = FALSE;
+ _statusline(ENTER_TEXT_ARROWS_OR_TAB);
+ }
+ if (strcmp(value, MyEdit.buffer)) {
+ Edited = TRUE;
+ }
+ LYRefreshEdit(&MyEdit);
+ }
+ }
+breakfor:
+ if (Edited) {
+ char *p;
+
+ /*
+ * Load the new value.
+ */
+ if (value == form->value) {
+ /*
+ * The previous value did fit in the line buffer,
+ * so replace it with the new value. - FM
+ */
+ StrAllocCopy(form->value, MyEdit.buffer);
+ } else {
+ /*
+ * Combine the modified tail with the unmodified head. - FM
+ */
+ form->value[(strlen(form->value) - strlen(value))] = '\0';
+ StrAllocCat(form->value, MyEdit.buffer);
+ _statusline(FORM_TAIL_COMBINED_WITH_HEAD);
+ sleep(MessageSecs);
+ }
+
+ /*
+ * Remove trailing spaces
+ *
+ * Do we really need to do that here? Trailing spaces will only
+ * be there if user keyed them in. Rather rude to throw away
+ * their hard earned spaces. Better deal with trailing spaces
+ * when submitting the form????
+ */
+ p = &(form->value[strlen(form->value)]);
+ while ((p != form->value) && (p[-1] == ' '))
+ p--;
+ *p = '\0';
+
+ /*
+ * If the field has been changed, assume that it is now in
+ * current display character set, even if for some reason
+ * it wasn't! Hopefully a user will only submit the form
+ * if the non-ASCII characters are displayed correctly, which
+ * means (assuming that the display character set has been set
+ * truthfully) the user confirms by changing the field that
+ * the character encoding is right. - kw
+ */
+ if (form->value && *form->value)
+ form->value_cs = current_char_set;
+ }
+ return(ch);
+}
+
+/*
+** This function prompts for an option or page number.
+** If a 'g' or 'p' suffix is included, that will be
+** loaded into c. Otherwise, c is zeroed. - FM & LE
+*/
+PRIVATE int get_popup_option_number ARGS1(
+ int *, c)
+{
+ char temp[120];
+
+ /*
+ * Load the c argument into the prompt buffer.
+ */
+ temp[0] = *c;
+ temp[1] = '\0';
+ _statusline(SELECT_OPTION_NUMBER);
+
+ /*
+ * Get the number, possibly with a suffix, from the user.
+ */
+ if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || *temp == 0) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ *c = '\0';
+ return(0);
+ }
+
+ /*
+ * If we had a 'g' or 'p' suffix, load it into c.
+ * Otherwise, zero c. Then return the number.
+ */
+ if (strchr(temp, 'g') != NULL || strchr(temp, 'G') != NULL) {
+ *c = 'g';
+ } else if (strchr(temp, 'p') != NULL || strchr(temp, 'P') != NULL) {
+ *c = 'p';
+ } else {
+ *c = '\0';
+ }
+ return(atoi(temp));
+}
+
+/* Use this rather than the 'wprintw()' function to write a blank-padded
+ * string to the given window, since someone's asserted that printw doesn't
+ * handle 8-bit characters unlike addstr (though more info would be useful).
+ *
+ * We're blank-filling so that with SVr4 curses, it'll show the background
+ * color to a uniform width in the popup-menu.
+ */
+#ifndef USE_SLANG
+PRIVATE void paddstr ARGS3(
+ WINDOW *, the_window,
+ int, width,
+ char *, the_string)
+{
+ width -= strlen(the_string);
+ waddstr(the_window, the_string);
+ while (width-- > 0)
+ waddstr(the_window, " ");
+}
+#endif
+
+
+PRIVATE int popup_options ARGS7(
+ int, cur_selection,
+ OptionType *, list,
+ int, ly,
+ int, lx,
+ int, width,
+ int, i_length,
+ int, disabled)
+{
+ /*
+ * Revamped to handle within-tag VALUE's, if present,
+ * and to position the popup window appropriately,
+ * taking the user_mode setting into account. -- FM
+ */
+ int c = 0, cmd = 0, i = 0, j = 0;
+ int orig_selection = cur_selection;
+#ifndef USE_SLANG
+ WINDOW * form_window;
+#endif /* !USE_SLANG */
+ int num_options = 0, top, bottom, length = -1;
+ OptionType * opt_ptr = list;
+ int window_offset = 0;
+ int lines_to_show;
+ int npages;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
+ static char prev_target[512]; /* Search string buffer */
+ static char prev_target_buffer[512]; /* Next search buffer */
+ static BOOL first = TRUE;
+ char *cp;
+ int ch = 0, recall;
+ int QueryTotal;
+ int QueryNum;
+ BOOLEAN FirstRecall = TRUE;
+ OptionType * tmp_ptr;
+ BOOLEAN ReDraw = FALSE;
+ int number;
+ char buffer[512];
+
+ /*
+ * Initialize the search string buffer. - FM
+ */
+ if (first) {
+ *prev_target_buffer = '\0';
+ first = FALSE;
+ }
+ *prev_target = '\0';
+ QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
+ recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+
+ /*
+ * Set lines_to_show based on the user_mode global.
+ */
+ if (user_mode == NOVICE_MODE)
+ lines_to_show = LYlines-4;
+ else
+ lines_to_show = LYlines-2;
+
+ /*
+ * Counting the number of options to be displayed.
+ * num_options ranges 0...n
+ */
+ for (; opt_ptr->next; num_options++, opt_ptr = opt_ptr->next)
+ ; /* null body */
+
+ /*
+ * Let's assume for the sake of sanity that ly is the number
+ * corresponding to the line the selection box is on.
+ * Let's also assume that cur_selection is the number of the
+ * item that should be initially selected, as 0 beign the
+ * first item.
+ * So what we have, is the top equal to the current screen line
+ * subtracting the cur_selection + 1 (the one must be for the
+ * top line we will draw in a box). If the top goes under 0,
+ * consider it 0.
+ */
+ top = ly - (cur_selection + 1);
+ if (top < 0)
+ top = 0;
+
+ /*
+ * Check and see if we need to put the i_length parameter up to
+ * the number of real options.
+ */
+ if (!i_length) {
+ i_length = num_options;
+ } else {
+ /*
+ * Otherwise, it is really one number too high.
+ */
+ i_length--;
+ }
+
+ /*
+ * The bottom is the value of the top plus the number of options
+ * to view plus 3 (one for the top line, one for the bottom line,
+ * and one to offset the 0 counted in the num_options).
+ */
+ bottom = top + i_length + 3;
+
+ /*
+ * Hmm... If the bottom goes beyond the number of lines available,
+ */
+ if (bottom > lines_to_show) {
+ /*
+ * Position the window at the top if we have more
+ * options than will fit in the window.
+ */
+ if (i_length+3 > lines_to_show) {
+ top = 0;
+ bottom = top + i_length+3;
+ if (bottom > lines_to_show)
+ bottom = lines_to_show + 1;
+ } else {
+ /*
+ * Try to position the window so that the selected option will
+ * appear where the selection box currently is positioned.
+ * It could end up too high, at this point, but we'll move it
+ * down latter, if that has happened.
+ */
+ top = (lines_to_show + 1) - (i_length + 3);
+ bottom = (lines_to_show + 1);
+ }
+ }
+
+ /*
+ * This is really fun, when the length is 4, it means 0-4, or 5.
+ */
+ length = (bottom - top) - 2;
+
+ /*
+ * Move the window down if it's too high.
+ */
+ if (bottom < ly + 2) {
+ bottom = ly + 2;
+ if (bottom > lines_to_show + 1)
+ bottom = lines_to_show + 1;
+ top = bottom - length - 2;
+ }
+
+ /*
+ * Set up the overall window, including the boxing characters ('*'),
+ * if it all fits. Otherwise, set up the widest window possible. - FM
+ */
+#ifdef USE_SLANG
+ SLsmg_fill_region(top, lx - 1, bottom - top, width + 4, ' ');
+#else
+ if (!(form_window = newwin(bottom - top, width + 4, top, lx - 1)) &&
+ !(form_window = newwin(bottom - top, 0, top, 0))) {
+ HTAlert(POPUP_FAILED);
+ return(orig_selection);
+ }
+ scrollok(form_window, TRUE);
+#ifdef PDCURSES
+ keypad(form_window, TRUE);
+#endif /* PDCURSES */
+#ifdef NCURSES
+ LYsubwindow(form_window);
+#endif
+#if defined(HAVE_GETBKGD) /* not defined in ncurses 1.8.7 */
+ wbkgd(form_window, getbkgd(stdscr));
+ wbkgdset(form_window, getbkgd(stdscr));
+#endif
+#endif /* USE_SLANG */
+
+ /*
+ * Set up the window_offset for options.
+ * cur_selection ranges from 0...n
+ * length ranges from 0...m
+ */
+ if (cur_selection >= length) {
+ window_offset = cur_selection - length + 1;
+ }
+
+ /*
+ * Compute the number of popup window pages. - FM
+ */
+ npages = ((num_options + 1) > length) ?
+ (((num_options + 1) + (length - 1))/(length))
+ : 1;
+/*
+ * OH! I LOVE GOTOs! hack hack hack
+ * 07-11-94 GAB
+ * MORE hack hack hack
+ * 09-05-94 FM
+ */
+redraw:
+ opt_ptr = list;
+
+ /*
+ * Display the boxed options.
+ */
+ for (i = 0; i <= num_options; i++, opt_ptr = opt_ptr->next) {
+ if (i >= window_offset && i - window_offset < length) {
+#ifdef USE_SLANG
+ SLsmg_gotorc(top + ((i + 1) - window_offset), (lx - 1 + 2));
+ SLsmg_write_nstring(opt_ptr->name, width);
+#else
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ paddstr(form_window, width, opt_ptr->name);
+#endif /* USE_SLANG */
+ }
+ }
+#ifdef USE_SLANG
+ SLsmg_draw_box(top, (lx - 1), (bottom - top), (width + 4));
+#else
+#ifdef VMS
+ VMSbox(form_window, (bottom - top), (width + 4));
+#else
+ LYbox(form_window, TRUE);
+#endif /* VMS */
+ wrefresh(form_window);
+#endif /* USE_SLANG */
+ opt_ptr = NULL;
+
+ /*
+ * Loop on user input.
+ */
+ while (cmd != LYK_ACTIVATE) {
+
+ /*
+ * Unreverse cur selection.
+ */
+ if (opt_ptr != NULL) {
+#ifdef USE_SLANG
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+ SLsmg_write_nstring(opt_ptr->name, width);
+#else
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ paddstr(form_window, width, opt_ptr->name);
+#endif /* USE_SLANG */
+ }
+
+ opt_ptr = list;
+
+ for (i = 0; i < cur_selection; i++, opt_ptr = opt_ptr->next)
+ ; /* null body */
+
+#ifdef USE_SLANG
+ SLsmg_set_color(2);
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+ SLsmg_write_nstring(opt_ptr->name, width);
+ SLsmg_set_color(0);
+ /*
+ * If LYShowCursor is ON, move the cursor to the left
+ * of the current option, so that blind users, who are
+ * most likely to have LYShowCursor ON, will have it's
+ * string spoken or passed to the braille interface as
+ * each option is made current. Otherwise, move it to
+ * the bottom, right column of the screen, to "hide"
+ * the cursor as for the main document, and let sighted
+ * users rely on the current option's highlighting or
+ * color without the distraction of a blinking cursor
+ * in the window. - FM
+ */
+ if (LYShowCursor)
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 1));
+ else
+ SLsmg_gotorc((LYlines - 1), (LYcols - 1));
+ SLsmg_refresh();
+#else
+ wstart_reverse(form_window);
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ paddstr(form_window, width, opt_ptr->name);
+ wstop_reverse(form_window);
+ /*
+ * If LYShowCursor is ON, move the cursor to the left
+ * of the current option, so that blind users, who are
+ * most likely to have LYShowCursor ON, will have it's
+ * string spoken or passed to the braille interface as
+ * each option is made current. Otherwise, leave it to
+ * the right of the current option, since we can't move
+ * it out of the window, and let sighted users rely on
+ * the highlighting of the current option without the
+ * distraction of a blinking cursor preceding it. - FM
+ */
+ if (LYShowCursor)
+ wmove(form_window, ((i + 1) - window_offset), 1);
+ wrefresh(form_window);
+#endif /* USE_SLANG */
+
+ c = LYgetch();
+ if (c == 3 || c == 7) /* Control-C or Control-G */
+ cmd = LYK_QUIT;
+ else
+ cmd = keymap[c+1];
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ cmd = LYK_QUIT;
+ }
+#endif /* VMS */
+
+ switch(cmd) {
+ case LYK_F_LINK_NUM:
+ c = '\0';
+ case LYK_1:
+ case LYK_2:
+ case LYK_3:
+ case LYK_4:
+ case LYK_5:
+ case LYK_6:
+ case LYK_7:
+ case LYK_8:
+ case LYK_9:
+ /*
+ * Get a number from the user, possibly with
+ * a 'g' or 'p' suffix (which will be loaded
+ * into c). - FM & LE
+ */
+ number = get_popup_option_number((int *)&c);
+
+ /*
+ * Check for a 'p' suffix. - FM
+ */
+ if (c == 'p') {
+ /*
+ * Treat 1 or less as the first page. - FM
+ */
+ if (number <= 1) {
+ if (window_offset == 0) {
+ _statusline(ALREADY_AT_OPTION_BEGIN);
+ sleep(MessageSecs);
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ break;
+ }
+ window_offset = 0;
+ cur_selection = 0;
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * Treat a number equal to or greater than the
+ * number of pages as the last page. - FM
+ */
+ if (number >= npages) {
+ if (window_offset >= ((num_options - length) + 1)) {
+ _statusline(ALREADY_AT_OPTION_END);
+ sleep(MessageSecs);
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ break;
+ }
+ window_offset = ((npages - 1) * length);
+ if (window_offset > (num_options - length)) {
+ window_offset = (num_options - length + 1);
+ }
+ if (cur_selection < window_offset)
+ cur_selection = window_offset;
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * We want an intermediate page. - FM
+ */
+ if (((number - 1) * length) == window_offset) {
+ sprintf(buffer, ALREADY_AT_OPTION_PAGE, number);
+ _statusline(buffer);
+ sleep(MessageSecs);
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ break;
+ }
+ cur_selection = window_offset = ((number - 1) * length);
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ goto redraw;
+
+ }
+
+ /*
+ * Check for a positive number, which signifies
+ * that an option should be sought. - FM
+ */
+ if (number > 0) {
+ /*
+ * Decrement the number so as to correspond
+ * with our cur_selection values. - FM
+ */
+ number--;
+
+ /*
+ * If the number is in range and had no legal
+ * suffix, select the indicated option. - FM
+ */
+ if (number <= num_options && c == '\0') {
+ cur_selection = number;
+ cmd = LYK_ACTIVATE;
+ break;
+ }
+
+ /*
+ * Verify that we had a 'g' suffix,
+ * and act on the number. - FM
+ */
+ if (c == 'g') {
+ if (cur_selection == number) {
+ /*
+ * The option already is current. - FM
+ */
+ sprintf(buffer,
+ OPTION_ALREADY_CURRENT, (number + 1));
+ _statusline(buffer);
+ sleep(MessageSecs);
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ break;
+ }
+
+ if (number <= num_options) {
+ /*
+ * The number is in range and had a 'g'
+ * suffix, so make it the current option,
+ * scrolling if needed. - FM
+ */
+ j = (number - cur_selection);
+ cur_selection = number;
+ if ((j > 0) &&
+ (cur_selection - window_offset) >= length) {
+ window_offset += j;
+ if (window_offset > (num_options - length + 1))
+ window_offset = (num_options - length + 1);
+ } else if ((cur_selection - window_offset) < 0) {
+ window_offset -= abs(j);
+ if (window_offset < 0)
+ window_offset = 0;
+ }
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * Not in range. - FM
+ */
+ _statusline(BAD_OPTION_NUM_ENTERED);
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * Restore the popup statusline. - FM
+ */
+ if (disabled) {
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ } else {
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ }
+ break;
+
+ case LYK_PREV_LINK:
+ case LYK_UP_LINK:
+
+ if (cur_selection > 0)
+ cur_selection--;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_selection - window_offset) < 0) {
+ window_offset--;
+ goto redraw;
+ }
+ break;
+
+ case LYK_NEXT_LINK:
+ case LYK_DOWN_LINK:
+ if (cur_selection < num_options)
+ cur_selection++;
+
+ /*
+ * Scroll the window down if necessary
+ */
+ if ((cur_selection - window_offset) >= length) {
+ window_offset++;
+ goto redraw;
+ }
+ break;
+
+ case LYK_NEXT_PAGE:
+ /*
+ * Okay, are we on the last page of the list?
+ * If not then,
+ */
+ if (window_offset != (num_options - length + 1)) {
+ /*
+ * Modify the current selection to not be a
+ * coordinate in the list, but a coordinate
+ * on the item selected in the window.
+ */
+ cur_selection -= window_offset;
+
+ /*
+ * Page down the proper length for the list.
+ * If simply to far, back up.
+ */
+ window_offset += length;
+ if (window_offset > (num_options - length)) {
+ window_offset = (num_options - length + 1);
+ }
+
+ /*
+ * Readjust the current selection to be a
+ * list coordinate rather than window.
+ * Redraw this thing.
+ */
+ cur_selection += window_offset;
+ goto redraw;
+ }
+ else if (cur_selection < num_options) {
+ /*
+ * Already on last page of the list so just
+ * redraw it with the last item selected.
+ */
+ cur_selection = num_options;
+ }
+ break;
+
+ case LYK_PREV_PAGE:
+ /*
+ * Are we on the first page of the list?
+ * If not then,
+ */
+ if (window_offset != 0) {
+ /*
+ * Modify the current selection to not be a
+ * list coordinate, but a window coordinate.
+ */
+ cur_selection -= window_offset;
+
+ /*
+ * Page up the proper length.
+ * If too far, back up.
+ */
+ window_offset -= length;
+ if (window_offset < 0) {
+ window_offset = 0;
+ }
+
+ /*
+ * Readjust the current selection.
+ */
+ cur_selection += window_offset;
+ goto redraw;
+ } else if (cur_selection > 0) {
+ /*
+ * Already on the first page so just
+ * back up to the first item.
+ */
+ cur_selection = 0;
+ }
+ break;
+
+ case LYK_HOME:
+ cur_selection = 0;
+ if (window_offset > 0) {
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_END:
+ cur_selection = num_options;
+ if (window_offset != (num_options - length + 1)) {
+ window_offset = (num_options - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_DOWN_TWO:
+ cur_selection += 2;
+ if (cur_selection > num_options)
+ cur_selection = num_options;
+
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_selection - window_offset) >= length) {
+ window_offset += 2;
+ if (window_offset > (num_options - length + 1))
+ window_offset = (num_options - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_UP_TWO:
+ cur_selection -= 2;
+ if (cur_selection < 0)
+ cur_selection = 0;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_selection - window_offset) < 0) {
+ window_offset -= 2;
+ if (window_offset < 0)
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_DOWN_HALF:
+ cur_selection += (length/2);
+ if (cur_selection > num_options)
+ cur_selection = num_options;
+
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_selection - window_offset) >= length) {
+ window_offset += (length/2);
+ if (window_offset > (num_options - length + 1))
+ window_offset = (num_options - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_UP_HALF:
+ cur_selection -= (length/2);
+ if (cur_selection < 0)
+ cur_selection = 0;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_selection - window_offset) < 0) {
+ window_offset -= (length/2);
+ if (window_offset < 0)
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_REFRESH:
+ lynx_force_repaint();
+ refresh();
+ break;
+
+ case LYK_NEXT:
+ if (recall && *prev_target_buffer == '\0') {
+ /*
+ * We got a 'n'ext command with no prior query
+ * specified within the popup window. See if
+ * one was entered when the popup was retracted,
+ * and if so, assume that's what's wanted. Note
+ * that it will become the default within popups,
+ * unless another is entered within a popup. If
+ * the within popup default is to be changed at
+ * that point, use WHEREIS ('/') and enter it,
+ * or the up- or down-arrow keys to seek any of
+ * the previously entered queries, regardless of
+ * whether they were entered within or outside
+ * of a popup window. - FM
+ */
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ 0)) != NULL) {
+ strcpy(prev_target_buffer, cp);
+ QueryNum = 0;
+ FirstRecall = FALSE;
+ }
+ }
+ strcpy(prev_target, prev_target_buffer);
+ case LYK_WHEREIS:
+ if (*prev_target == '\0' ) {
+ _statusline(ENTER_WHEREIS_QUERY);
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ }
+
+check_recall:
+ if (*prev_target == '\0' &&
+ !(recall && (ch == UPARROW || ch == DNARROW))) {
+ /*
+ * No entry. Simply break. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or
+ * last query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = (QueryTotal - 1);
+ QueryNum > 0; QueryNum--) {
+ if ((cp = (char *)HTList_objectAt(
+ search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = 0;
+ }
+ } else {
+ /*
+ * Go back to the previous query in the list. - FM
+ */
+ QueryNum++;
+ }
+ if (QueryNum >= QueryTotal)
+ /*
+ * Roll around to the last query in the list. - FM
+ */
+ QueryNum = 0;
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer && QueryTotal == 2) ||
+ (!(*prev_target_buffer) &&
+ QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer), recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or
+ * first query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = 0;
+ QueryNum < (QueryTotal - 1); QueryNum++) {
+ if ((cp = (char *)HTList_objectAt(
+ search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = (QueryTotal - 1);
+ }
+ } else {
+ /*
+ * Advance to the next query in the list. - FM
+ */
+ QueryNum--;
+ }
+ if (QueryNum < 0)
+ /*
+ * Roll around to the first query in the list. - FM
+ */
+ QueryNum = (QueryTotal - 1);
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer &&
+ QueryTotal == 2) ||
+ (!(*prev_target_buffer) &&
+ QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ goto check_recall;
+ }
+ }
+ /*
+ * Replace the search string buffer with the new target. - FM
+ */
+ strcpy(prev_target_buffer, prev_target);
+ HTAddSearchQuery(prev_target_buffer);
+
+ /*
+ * Start search at the next option. - FM
+ */
+ for (j = 1, tmp_ptr = opt_ptr->next;
+ tmp_ptr != NULL; tmp_ptr = tmp_ptr->next, j++) {
+ if (case_sensitive) {
+ if (strstr(tmp_ptr->name, prev_target_buffer) != NULL)
+ break;
+ } else {
+ if (LYstrstr(tmp_ptr->name, prev_target_buffer) != NULL)
+ break;
+ }
+ }
+ if (tmp_ptr != NULL) {
+ /*
+ * We have a hit, so make that option the current. - FM
+ */
+ cur_selection += j;
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_selection - window_offset) >= length) {
+ window_offset += j;
+ if (window_offset > (num_options - length + 1))
+ window_offset = (num_options - length + 1);
+ ReDraw = TRUE;
+ }
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * If we started at the beginning, it can't be present. - FM
+ */
+ if (cur_selection == 0) {
+ _user_message(STRING_NOT_FOUND, prev_target_buffer);
+ sleep(MessageSecs);
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * Search from the beginning to the current option. - FM
+ */
+ for (j = 0, tmp_ptr = list;
+ j < cur_selection; tmp_ptr = tmp_ptr->next, j++) {
+ if (case_sensitive) {
+ if (strstr(tmp_ptr->name, prev_target_buffer) != NULL)
+ break;
+ } else {
+ if (LYstrstr(tmp_ptr->name, prev_target_buffer) != NULL)
+ break;
+ }
+ }
+ if (j < cur_selection) {
+ /*
+ * We have a hit, so make that option the current. - FM
+ */
+ j = (cur_selection - j);
+ cur_selection -= j;
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_selection - window_offset) < 0) {
+ window_offset -= j;
+ if (window_offset < 0)
+ window_offset = 0;
+ ReDraw = TRUE;
+ }
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * Didn't find it in the preceding options either. - FM
+ */
+ _user_message(STRING_NOT_FOUND, prev_target_buffer);
+ sleep(MessageSecs);
+
+restore_popup_statusline:
+ /*
+ * Restore the popup statusline and
+ * reset the search variables. - FM
+ */
+ if (disabled)
+ _statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ else
+ _statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ *prev_target = '\0';
+ QueryTotal = (search_queries ? HTList_count(search_queries)
+ : 0);
+ recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+ if (ReDraw == TRUE) {
+ ReDraw = FALSE;
+ goto redraw;
+ }
+ break;
+
+ case LYK_QUIT:
+ case LYK_ABORT:
+ case LYK_PREV_DOC:
+ cur_selection = orig_selection;
+ cmd = LYK_ACTIVATE; /* to exit */
+ break;
+ }
+
+ }
+#ifndef USE_SLANG
+ delwin(form_window);
+#ifdef NCURSES
+ LYsubwindow(0);
+#endif
+#endif /* !USE_SLANG */
+
+ return(disabled ? orig_selection : cur_selection);
+}
diff --git a/gnu/usr.bin/lynx/src/LYGCurses.h b/gnu/usr.bin/lynx/src/LYGCurses.h
new file mode 100644
index 00000000000..3944e8073ce
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYGCurses.h
@@ -0,0 +1,251 @@
+#ifndef __CURSES_LOADED
+#define __CURSES_LOADED 1
+
+#include <ssdef.h>
+#include <stdio.h>
+#include <smgdef.h>
+
+#define reg register
+
+#ifndef TRUE
+#define TRUE (1)
+#define FALSE (0)
+#endif
+#define ERR (0)
+#define OK (1)
+
+#define _SUBWIN 0001
+#define _ENDLINE 0002
+#define _FULLWIN 0004
+#define _SCROLLWIN 0010
+#define _FLUSH 0020
+#define _STANDOUT 0200
+
+#define _NOECHO 001
+#define _NONL 002
+#define _NOCRMODE 004
+#define _NORAW 010
+
+#define _BLINK SMG$M_BLINK
+#define _BOLD SMG$M_BOLD
+#define _REVERSE SMG$M_REVERSE
+#define _UNDERLINE SMG$M_UNDERLINE
+
+struct _win_st
+{
+ int _cur_y, _cur_x;
+ int _max_y, _max_x;
+ int _beg_y, _beg_x;
+ short _flags;
+ char _clear, _leave, _scroll, _wrap;
+ char **_y;
+ short *_firstch, *_lastch;
+ struct _win_st *_next, *_parent, *_child;
+ int _id;
+};
+
+
+struct _kb_st
+{
+ int _id;
+ unsigned char _flags;
+ struct
+ {
+ unsigned short length;
+ unsigned char type;
+ unsigned char class;
+ char *address;
+ } _buffer_desc;
+ int _count;
+ char *_ptr;
+};
+
+struct _pb_st
+{
+ int _id;
+ int _rows, _cols;
+ union SMGDEF *_attr;
+ int _attr_size;
+};
+
+#define _KEYBOARD struct _kb_st
+#define WINDOW struct _win_st
+#define _PASTEBOARD struct _pb_st
+
+
+extern int LINES __asm("_$$PsectAttributes_NOSHR$$LINES");
+extern int COLS __asm("_$$PsectAttributes_NOSHR$$COLS");
+extern WINDOW *stdscr __asm("_$$PsectAttributes_NOSHR$$stdscr");
+extern WINDOW *curscr __asm("_$$PsectAttributes_NOSHR$$curscr");
+extern _KEYBOARD *stdkb __asm("_$$PsectAttributes_NOSHR$$stdkb");
+extern _PASTEBOARD *stdpb __asm("_$$PsectAttributes_NOSHR$$stdpb");
+
+#define getch() wgetch (stdscr)
+#define addch(ch) waddch (stdscr, ch)
+#define addstr(string) waddstr (stdscr, string)
+#define move(y, x) wmove (stdscr, y, x)
+#define refresh() wrefresh (stdscr)
+#define clear() wclear (stdscr)
+#define clrtobot() wclrtobot (stdscr)
+#define clrtoeol() wclrtoeol (stdscr)
+#define delch() wdelch (stdscr)
+#define erase() werase (stdscr)
+#define insch(ch) winsch (stdscr, ch)
+#define insertln() winsertln (stdscr)
+#define standout() wstandout (stdscr)
+#define standend() wstandend (stdscr)
+#define getstr(string) wgetstr (stdscr, string)
+#define inch() winch (stdscr)
+#define setattr(attr) wsetattr (stdscr, attr)
+#define clrattr(attr) wclrattr (stdscr, attr)
+#define deleteln() wdeleteln (stdscr)
+#define insstr(string) winsstr (stdscr, string)
+
+#define mvwaddch(win,y,x,ch) (wmove(win,y,x)==ERR)?ERR:waddch(win,ch)
+#define mvwgetch(win,y,x) (wmove(win,y,x)==ERR)?ERR:wgetch(win)
+#define mvwaddstr(win,y,x,str) (wmove(win,y,x)==ERR)?ERR:waddstr(win,str)
+#define mvwinsstr(win,y,x,str) (wmove(win,y,x)==ERR)?ERR:winsstr(win,str)
+#define mvwgetstr(win,y,x,str) (wmove(win,y,x)==ERR)?ERR:wgetstr(win,str)
+#define mvwinch(win,y,x) (wmove(win,y,x)==ERR)?ERR:winch(win)
+#define mvwdelch(win,y,x) (wmove(win,y,x)==ERR)?ERR:wdelch(win)
+#define mvwinsch(win,y,x,ch) (wmove(win,y,x)==ERR)?ERR:winsch(win,ch)
+#define mvwdeleteln(win,y,x) (wmove(win,y,x)==ERR)?ERR:wdeleteln(win)
+#define mvaddch(y,x,ch) mvwaddch (stdscr, y, x, ch)
+#define mvgetch(y,x) mvwgetch (stdscr, y, x)
+#define mvaddstr(y,x,str) mvwaddstr (stdscr, y, x, str)
+#define mvinsstr(y,x,str) mvwinsstr (stdscr, y, x, str)
+#define mvgetstr(y,x,str) mvwgetstr (stdscr, y, x, str)
+#define mvinch(y,x) mvwinch (stdscr, y, x)
+#define mvdelch(y,x) mvwdelch (stdscr, y, x)
+#define mvinsch(y,x,ch) mvwinsch (stdscr, y, x, ch)
+#define mvdeleteln(y,x) mvwdeleteln (stdscr, y, x)
+#define mvcur(ly,lx,ny,nx) wmove (stdscr, ny, nx)
+#pragma standard
+
+#define clearok(win, bf) (win->_clear = bf)
+#define leaveok(win, bf) (win->_leave = bf)
+#define scrollok(win, bf) (win->_scroll = bf)
+#define wrapok(win, bf) (win->_wrap = bf)
+#define flushok(win,bf) (bf ? win->_flags |= _FLUSH : (win->_flags &= ~_FLUSH))
+#define getyx(win,y,x) y = win->_cur_y, x = win->_cur_x
+
+#define echo() (stdkb->_flags &= ~_NOECHO)
+#define noecho() (stdkb->_flags |= _NOECHO)
+#define nl() (stdkb->_flags &= ~_NONL)
+#define nonl() (stdkb->_flags |= _NONL)
+#define crmode() ((stdkb->_flags &= ~_NOCRMODE), nonl ())
+#define nocrmode() (stdkb->_flags |= _NOCRMODE)
+#define raw() (stdkb->_flags &= ~_NORAW)
+#define noraw() (stdkb->_flags |= _NORAW)
+
+#define check(status) if (!(status & SS$_NORMAL)) \
+ { c$$translate (status); \
+ return ERR; \
+ }
+
+#define bool int
+
+int waddch (WINDOW *win, char ch);
+
+int waddstr (WINDOW *win, char *str);
+
+int box (WINDOW *win, char vert, char hor);
+
+int wclear (WINDOW *win);
+
+int wclrattr (WINDOW *win, int attr);
+
+int wclrtobot (WINDOW *win);
+
+int wclrtoeol (WINDOW *win);
+
+int wdelch (WINDOW *win);
+
+int wdeleteln (WINDOW *win);
+
+int delwin (WINDOW *win);
+
+int endwin (void);
+
+int werase (WINDOW *win);
+
+int wgetch (WINDOW *win);
+
+int wgetstr (WINDOW *win, char *str);
+
+char winch (WINDOW *win);
+
+WINDOW *initscr (void);
+
+int winsch (WINDOW *win, char ch);
+
+int winsertln (WINDOW *win);
+
+int winsstr (WINDOW *win, char *str);
+
+int longname (char *termbuf, char *name);
+
+int mvwin (WINDOW *win, int st_row, int st_col);
+
+int wmove (WINDOW *win, int y, int x);
+
+WINDOW *newwin (int numlines, int numcols, int begin_y, int begin_x);
+
+int overlay (WINDOW *win1, WINDOW *win2);
+
+int overwrite (WINDOW *win1, WINDOW *win2);
+
+#pragma NOSTANDARD
+#undef printw
+#undef wprintw
+#undef wscanw
+#undef scanw
+#pragma STANDARD
+
+int printw (char *format_spec, ...);
+
+int wprintw (WINDOW *win, char *format_spec, ...);
+
+int wrefresh (WINDOW *win);
+
+int wscanw (WINDOW *win, char *format_spec, ...);
+
+int scanw (char *fmt, int arg1);
+
+int scroll (WINDOW *win);
+
+int wsetattr (WINDOW *win, int attr);
+
+WINDOW *subwin (WINDOW *win, int numlines, int numcols,
+ int begin_y, int begin_x);
+
+int wstandend (WINDOW *win);
+
+int wstandout (WINDOW *win);
+
+int touchwin (WINDOW *win);
+
+#if defined(CC$mixed_float) || defined(CC$VAXCSHR)
+
+#ifndef CC$gfloat
+#define CC$gfloat 0
+#endif
+
+#if CC$gfloat
+
+#define printw vaxc$gprintw
+#define scanw vaxc$gscanw
+#define wprintw vaxc$gwprintw
+#define wscanw vaxc$gwscanw
+
+#else
+
+#define printw vaxc$dprintw
+#define scanw vaxc$dscanw
+#define wprintw vaxc$dwprintw
+#define wscanw vaxc$dwscanw
+
+#endif
+#endif
+
+#endif /* __CURSES_LOADED */
diff --git a/gnu/usr.bin/lynx/src/LYGetFile.c b/gnu/usr.bin/lynx/src/LYGetFile.c
new file mode 100644
index 00000000000..2bec52b31fb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYGetFile.c
@@ -0,0 +1,1389 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTP.h"
+#include "HTAnchor.h" /* Anchor class */
+#include "HTAccess.h"
+#include "HTParse.h"
+#include "LYCurses.h"
+#include "GridText.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h"
+#include "HTAlert.h"
+#include "LYSignal.h"
+#include "LYGetFile.h"
+#include "LYPrint.h"
+#include "LYHistory.h"
+#include "LYStrings.h"
+#include "LYClean.h"
+#include "LYDownload.h"
+#include "LYNews.h"
+#include "LYMail.h"
+#include "LYSystem.h"
+#include "LYKeymap.h"
+#include "LYBookmark.h"
+#include "LYMap.h"
+#include "LYList.h"
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+#ifdef DIRED_SUPPORT
+#include "LYLocal.h"
+#endif /* DIRED_SUPPORT */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+#include <syslog.h>
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PRIVATE int fix_http_urls PARAMS((document *doc));
+extern char * WWW_Download_File;
+#ifdef VMS
+extern BOOLEAN LYDidRename;
+#endif /* VMS */
+
+#if 0 /* UNUSED */
+#ifdef DIRED_SUPPORT
+PRIVATE char * LYSanctify ARGS1(
+ char *, href)
+{
+ int i;
+ char *p, *cp, *tp;
+ char address_buffer[1024];
+
+ i = (strlen(href) - 1);
+ while (i && href[i] == '/') href[i--] = '\0';
+
+ if ((cp = (char *)strchr(href,'~')) != NULL) {
+ if (!strncmp(href, "file://localhost/", 17))
+ tp = (href + 17);
+ else
+ tp = (href + 5);
+ if ((cp - tp) && *(cp-1) != '/')
+ return href;
+ LYstrncpy(address_buffer, href, (cp - href));
+ if (address_buffer[(strlen(address_buffer) - 1)] == '/')
+ address_buffer[(strlen(address_buffer) - 1)] = '\0';
+ p = (char *)Home_Dir();
+ strcat(address_buffer, p);
+ if (strlen(++cp))
+ strcat(address_buffer, cp);
+ if (strcmp(href, address_buffer))
+ StrAllocCopy(href, address_buffer);
+ }
+ return href;
+}
+#endif /* DIRED_SUPPORT */
+#endif
+
+
+PUBLIC BOOLEAN getfile ARGS1(
+ document *, doc)
+{
+ int url_type = 0;
+ char *cp = NULL;
+ char *temp = NULL;
+ DocAddress WWWDoc; /* a WWW absolute doc address struct */
+
+ /*
+ * Reset LYCancelDownload to prevent unwanted delayed effect. - KW
+ */
+ if (LYCancelDownload) {
+ if (TRACE)
+ fprintf(stderr,
+ "getfile: resetting LYCancelDownload to FALSE\n");
+ LYCancelDownload = FALSE;
+ }
+
+ /*
+ * Reset fake 'Z' to prevent unwanted delayed effect. - kw
+ */
+ LYFakeZap(NO);
+
+Try_Redirected_URL:
+ /*
+ * Load the WWWDoc struct in case we need to use it.
+ */
+ WWWDoc.address = doc->address;
+ WWWDoc.post_data = doc->post_data;
+ WWWDoc.post_content_type = doc->post_content_type;
+ WWWDoc.bookmark = doc->bookmark;
+ WWWDoc.isHEAD = doc->isHEAD;
+ WWWDoc.safe = doc->safe;
+
+ /*
+ * Reset WWW_Download_File just in case.
+ */
+ FREE(WWW_Download_File);
+
+ /*
+ * Reset redirect_post_content just in case.
+ */
+ redirect_post_content = FALSE;
+
+ if (TRACE) {
+ fprintf(stderr,"getfile: getting %s\n\n",doc->address);
+ }
+
+ /*
+ * Protect against denial of service attacks
+ * via the port 19 CHARGEN service, and block
+ * connections to the port 25 ESMTP service.
+ * Also reject any likely spoof attempts via
+ * wrap arounds at 65536. - FM
+ */
+ if ((temp = HTParse(doc->address, "", PARSE_HOST)) != NULL &&
+ strlen(temp) > 3) {
+ char *cp1;
+
+ if ((cp1 = strchr(temp, '@')) == NULL)
+ cp1 = temp;
+ if ((cp = strrchr(cp1, ':')) != NULL) {
+ long int value;
+
+ cp++;
+ if (sscanf(cp, "%ld", &value) == 1) {
+ if (value == 19 || value == 65555) {
+ HTAlert(PORT_NINETEEN_INVALID);
+ FREE(temp);
+ return(NULLFILE);
+ }
+ if (value == 25 || value == 65561) {
+ HTAlert(PORT_TWENTYFIVE_INVALID);
+ FREE(temp);
+ return(NULLFILE);
+ }
+ if (value > 65535 || value < 0) {
+ char msg[265];
+ sprintf(msg, PORT_INVALID, (unsigned long)value);
+ HTAlert(msg);
+ FREE(temp);
+ return(NULLFILE);
+ }
+ } else if (isdigit((unsigned char)*cp)) {
+ HTAlert(URL_PORT_BAD);
+ FREE(temp);
+ return(NULLFILE);
+ }
+ }
+ }
+ cp = NULL;
+ FREE(temp);
+
+ /*
+ * Check to see if this is a universal document ID
+ * that lib WWW wants to handle.
+ *
+ * Some special URL's we handle ourselves. :)
+ */
+ if ((url_type = is_url(doc->address)) != 0) {
+ if (LYValidate && !LYPermitURL) {
+ if (!(url_type == HTTP_URL_TYPE ||
+ url_type == HTTPS_URL_TYPE ||
+ url_type == LYNXHIST_URL_TYPE ||
+ url_type == LYNXKEYMAP_URL_TYPE ||
+ url_type == LYNXIMGMAP_URL_TYPE ||
+ url_type == LYNXCOOKIE_URL_TYPE ||
+ 0==strncasecomp(WWWDoc.address, helpfilepath,
+ strlen(helpfilepath)) ||
+ (lynxlistfile != NULL &&
+ 0==strncasecomp(WWWDoc.address, lynxlistfile,
+ strlen(lynxlistfile))) ||
+ (lynxlinksfile != NULL &&
+ 0==strncasecomp(WWWDoc.address, lynxlinksfile,
+ strlen(lynxlinksfile))) ||
+ (lynxjumpfile != NULL &&
+ 0==strncasecomp(WWWDoc.address, lynxjumpfile,
+ strlen(lynxjumpfile))))) {
+ _statusline(NOT_HTTP_URL_OR_ACTION);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ }
+ }
+ if (traversal) {
+ /*
+ * Only traverse http URLs.
+ */
+ if (url_type != HTTP_URL_TYPE &&
+ url_type != LYNXIMGMAP_URL_TYPE)
+ return(NULLFILE);
+ } else if (check_realm && !LYPermitURL && !LYJumpFileURL) {
+ if (!(0==strncmp(startrealm, WWWDoc.address,
+ strlen(startrealm)) ||
+ url_type == LYNXHIST_URL_TYPE ||
+ url_type == LYNXKEYMAP_URL_TYPE ||
+ url_type == LYNXIMGMAP_URL_TYPE ||
+ url_type == LYNXCOOKIE_URL_TYPE ||
+ url_type == LYNXPRINT_URL_TYPE ||
+ url_type == LYNXDOWNLOAD_URL_TYPE ||
+ url_type == MAILTO_URL_TYPE ||
+ url_type == NEWSPOST_URL_TYPE ||
+ url_type == NEWSREPLY_URL_TYPE ||
+ url_type == SNEWSPOST_URL_TYPE ||
+ url_type == SNEWSREPLY_URL_TYPE ||
+ (!LYUserSpecifiedURL &&
+ (url_type == LYNXEXEC_URL_TYPE ||
+ url_type == LYNXPROG_URL_TYPE ||
+ url_type == LYNXCGI_URL_TYPE)) ||
+ (WWWDoc.bookmark != NULL &&
+ *WWWDoc.bookmark != '\0') ||
+ 0==strncasecomp(WWWDoc.address, helpfilepath,
+ strlen(helpfilepath)) ||
+ (lynxlistfile != NULL &&
+ 0==strncasecomp(WWWDoc.address, lynxlistfile,
+ strlen(lynxlistfile))) ||
+ (lynxjumpfile != NULL &&
+ 0==strncasecomp(WWWDoc.address, lynxjumpfile,
+ strlen(lynxjumpfile))))) {
+ _statusline(NOT_IN_STARTING_REALM);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ }
+ }
+ if (WWWDoc.post_data &&
+ url_type != HTTP_URL_TYPE &&
+ url_type != HTTPS_URL_TYPE &&
+ url_type != LYNXCGI_URL_TYPE &&
+ url_type != LYNXIMGMAP_URL_TYPE &&
+ url_type != GOPHER_URL_TYPE &&
+ url_type != CSO_URL_TYPE &&
+ url_type != PROXY_URL_TYPE &&
+ !(url_type == FILE_URL_TYPE &&
+ *(LYlist_temp_url()) &&
+ !strncmp(WWWDoc.address, LYlist_temp_url(),
+ strlen(LYlist_temp_url())))) {
+ if (TRACE)
+ fprintf(stderr,
+ "getfile: dropping post_data!\n");
+ HTAlert("POST not supported for this URL - ignoring POST data!");
+ FREE(doc->post_data);
+ FREE(doc->post_content_type);
+ WWWDoc.post_data = NULL;
+ WWWDoc.post_content_type = NULL;
+ }
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ syslog(LOG_INFO|LOG_LOCAL5, "%s", doc->address);
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+ if (url_type == UNKNOWN_URL_TYPE ||
+ url_type == AFS_URL_TYPE ||
+ url_type == PROSPERO_URL_TYPE) {
+ HTAlert(UNSUPPORTED_URL_SCHEME);
+ return(NULLFILE);
+
+ } else if (url_type == DATA_URL_TYPE) {
+ HTAlert(UNSUPPORTED_DATA_URL);
+ return(NULLFILE);
+
+ } else if (url_type == LYNXPRINT_URL_TYPE) {
+ return(printfile(doc));
+
+ } else if (url_type == NEWSPOST_URL_TYPE ||
+ url_type == NEWSREPLY_URL_TYPE ||
+ url_type == SNEWSPOST_URL_TYPE ||
+ url_type == SNEWSREPLY_URL_TYPE) {
+
+ if (no_newspost) {
+ _statusline(NEWSPOSTING_DISABLED);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ } else {
+ HTLoadAbsolute(&WWWDoc);
+ return(NULLFILE);
+ }
+
+ } else if (url_type == LYNXDOWNLOAD_URL_TYPE) {
+ LYDownload(doc->address);
+#ifdef VMS
+ if (LYDidRename) {
+ /*
+ * The temporary file was saved to disk via a
+ * rename(), so we can't access the temporary
+ * file again via the download menu. Clear the
+ * flag, and return NULLFILE to pop. - FM
+ */
+ LYDidRename = FALSE;
+ return(NULLFILE);
+ } else {
+ return(NORMAL);
+ }
+#else
+ return(NORMAL);
+#endif /* VMS */
+ } else if (url_type == LYNXDIRED_URL_TYPE) {
+#ifdef DIRED_SUPPORT
+ if (no_dired_support) {
+ _statusline(DIRED_DISABLED);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ } else {
+ local_dired(doc);
+ WWWDoc.address = doc->address;
+ WWWDoc.post_data = doc->post_data;
+ WWWDoc.post_content_type = doc->post_content_type;
+ WWWDoc.bookmark = doc->bookmark;
+ WWWDoc.isHEAD = doc->isHEAD;
+ WWWDoc.safe = doc->safe;
+
+ if (!HTLoadAbsolute(&WWWDoc))
+ return(NOT_FOUND);
+ return(NORMAL);
+ }
+#else
+ _statusline(DIRED_DISABLED);
+ sleep(MessageSecs);
+ return(NULLFILE);
+#endif /* DIRED_SUPPORT */
+
+ } else if (url_type == LYNXHIST_URL_TYPE) {
+ /*
+ * 'doc' will change to the new file
+ * if we had a successful LYpop_num(),
+ * and the return value will be FALSE
+ * if we had a cancel. - FM
+ */
+ if ((historytarget(doc) == FALSE) ||
+ !doc || !doc->address) {
+ HTMLSetCharacterHandling(current_char_set);
+ return(NOT_FOUND);
+ }
+
+ /*
+ * We changed it so reload.
+ */
+ WWWDoc.address = doc->address;
+ WWWDoc.post_data = doc->post_data;
+ WWWDoc.post_content_type = doc->post_content_type;
+ WWWDoc.bookmark = doc->bookmark;
+ WWWDoc.isHEAD = doc->isHEAD;
+ WWWDoc.safe = doc->safe;
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (doc->internal_link && !reloading) {
+ LYinternal_flag = TRUE;
+ }
+#endif
+
+ if (!HTLoadAbsolute(&WWWDoc)) {
+ HTMLSetCharacterHandling(current_char_set);
+ return(NOT_FOUND);
+ }
+ HTMLSetCharacterHandling(current_char_set);
+ return(NORMAL);
+
+ } else if (url_type == LYNXEXEC_URL_TYPE ||
+ url_type == LYNXPROG_URL_TYPE) {
+#ifdef EXEC_LINKS
+ if (no_exec &&
+ !exec_ok(HTLoadedDocumentURL(),
+ doc->address+9, ALWAYS_EXEC_PATH)) {
+ statusline(EXECUTION_DISABLED);
+ sleep(MessageSecs);
+ } else if (no_bookmark_exec &&
+ HTLoadedDocumentBookmark()) {
+ statusline(BOOKMARK_EXEC_DISABLED);
+ sleep(MessageSecs);
+ } else if (local_exec || (local_exec_on_local_files &&
+ exec_ok(HTLoadedDocumentURL(),
+ doc->address+9, EXEC_PATH))) {
+
+ char *p, addressbuf[1024];
+
+ /*
+ * Bug puts slash on end if none is in the string.
+ */
+ char *last_slash = strrchr(doc->address,'/');
+ if (last_slash-doc->address==strlen(doc->address)-1)
+ doc->address[strlen(doc->address)-1] = '\0';
+
+ p = doc->address;
+ /*
+ * Convert '~' to $HOME.
+ */
+ if ((cp = strchr(doc->address, '~'))) {
+ strncpy(addressbuf, doc->address, cp-doc->address);
+ addressbuf[cp - doc->address] = '\0';
+#ifdef DOSPATH
+ p = HTDOS_wwwName((char *)Home_Dir());
+#else
+#ifdef VMS
+ p = HTVMS_wwwName((char *)Home_Dir());
+#else
+ p = (char *)Home_Dir();
+#endif /* VMS */
+#endif /* DOSPATH */
+ strcat(addressbuf, p);
+ strcat(addressbuf, cp+1);
+ p = addressbuf;
+ }
+ /*
+ * Show URL before executing it.
+ */
+ statusline(doc->address);
+ sleep(InfoSecs);
+ stop_curses();
+ /*
+ * Run the command.
+ */
+ if (strstr(p,"//") == p+9)
+ system(p+11);
+ else
+ system(p+9);
+ if (url_type != LYNXPROG_URL_TYPE) {
+ /*
+ * Make sure user gets to see screen output.
+ */
+#ifndef VMS
+ signal(SIGINT, SIG_IGN);
+#endif /* !VMS */
+ printf("\n%s", RETURN_TO_LYNX);
+ fflush(stdout);
+ LYgetch();
+#ifdef VMS
+ {
+ extern BOOLEAN HadVMSInterrupt;
+ HadVMSInterrupt = FALSE;
+ }
+#endif /* VMS */
+ }
+ start_curses();
+ LYAddVisitedLink(doc);
+
+ } else {
+ char buf[512];
+
+ sprintf(buf,
+ EXECUTION_DISABLED_FOR_FILE,
+ key_for_func(LYK_OPTIONS));
+ _statusline(buf);
+ sleep(AlertSecs);
+ }
+#else /* no exec_links */
+ _statusline(EXECUTION_NOT_COMPILED);
+ sleep(MessageSecs);
+#endif /* EXEC_LINKS */
+ return(NULLFILE);
+
+ } else if (url_type == MAILTO_URL_TYPE) {
+ if (no_mail) {
+ _statusline(MAIL_DISABLED);
+ sleep(MessageSecs);
+ } else {
+ HTParentAnchor *tmpanchor;
+ CONST char *title;
+
+ title = "";
+ if ((tmpanchor = HTAnchor_parent(
+ HTAnchor_findAddress(&WWWDoc)
+ )) != NULL) {
+ if (HTAnchor_title(tmpanchor)) {
+ title = HTAnchor_title(tmpanchor);
+ }
+ }
+ cp = (char *)strchr(doc->address,':')+1;
+ reply_by_mail(cp,
+ ((HTMainAnchor && !LYUserSpecifiedURL) ?
+ (char *)HTMainAnchor->address :
+ (char *)doc->address),
+ title);
+ }
+ return(NULLFILE);
+
+ /*
+ * From here on we could have a remote host,
+ * so check if that's allowed.
+ */
+ } else if (local_host_only &&
+ url_type != NEWS_URL_TYPE &&
+ url_type != LYNXKEYMAP_URL_TYPE &&
+ url_type != LYNXIMGMAP_URL_TYPE &&
+ url_type != LYNXCOOKIE_URL_TYPE &&
+ url_type != LYNXCGI_URL_TYPE &&
+ !(LYisLocalHost(doc->address) ||
+ LYisLocalAlias(doc->address))) {
+ statusline(ACCESS_ONLY_LOCALHOST);
+ sleep(MessageSecs);
+ return(NULLFILE);
+
+ /*
+ * Disable www telnet access if not telnet_ok.
+ */
+ } else if (url_type == TELNET_URL_TYPE ||
+ url_type == TN3270_URL_TYPE ||
+ url_type == TELNET_GOPHER_URL_TYPE) {
+ if (!telnet_ok) {
+ _statusline(TELNET_DISABLED);
+ sleep(MessageSecs);
+ } else if (no_telnet_port && strchr(doc->address+7, ':')) {
+ statusline(TELNET_PORT_SPECS_DISABLED);
+ sleep(MessageSecs);
+ } else {
+ stop_curses();
+ HTLoadAbsolute(&WWWDoc);
+ start_curses();
+ fflush(stdout);
+ LYAddVisitedLink(doc);
+ }
+ return(NULLFILE);
+
+ /*
+ * Disable www news access if not news_ok.
+ */
+ } else if (url_type == NEWS_URL_TYPE && !news_ok) {
+ _statusline(NEWS_DISABLED);
+ sleep(MessageSecs);
+ return(NULLFILE);
+
+ } else if (url_type == RLOGIN_URL_TYPE) {
+ if (!rlogin_ok) {
+ statusline(RLOGIN_DISABLED);
+ sleep(MessageSecs);
+ } else {
+ stop_curses();
+ HTLoadAbsolute(&WWWDoc);
+ fflush(stdout);
+ start_curses();
+ LYAddVisitedLink(doc);
+ }
+ return(NULLFILE);
+
+ /*
+ * If its a gopher index type and there isn't a search
+ * term already attached then do this. Otherwise
+ * just load it!
+ */
+ } else if (url_type == INDEX_GOPHER_URL_TYPE &&
+ strchr(doc->address,'?') == NULL) {
+ int status;
+ /*
+ * Make sure we don't have a gopher+ escaped tab
+ * instead of a gopher0 question mark delimiting
+ * the search term. - FM
+ */
+ if ((cp = strstr(doc->address, "%09")) != NULL) {
+ *cp = '\0';
+ StrAllocCopy(temp, doc->address);
+ cp += 3;
+ if (*cp && strncmp(cp, "%09", 3)) {
+ StrAllocCat(temp, "?");
+ StrAllocCat(temp, cp);
+ if ((cp = strstr(temp, "%09")) != NULL) {
+ *cp = '\0';
+ }
+ }
+ StrAllocCopy(doc->address, temp);
+ FREE(temp);
+ goto Try_Redirected_URL;
+ }
+ /*
+ * Load it because the do_www_search routine
+ * uses the base url of the currently loaded
+ * document :(
+ */
+ if (!HTLoadAbsolute(&WWWDoc))
+ return(NOT_FOUND);
+ status = do_www_search(doc);
+ if (status == NULLFILE) {
+ LYpop(doc);
+ WWWDoc.address = doc->address;
+ WWWDoc.post_data = doc->post_data;
+ WWWDoc.post_content_type = doc->post_content_type;
+ WWWDoc.bookmark = doc->bookmark;
+ WWWDoc.isHEAD = doc->isHEAD;
+ WWWDoc.safe = doc->safe;
+ status = HTLoadAbsolute(&WWWDoc);
+ }
+ return(status);
+
+ } else {
+
+ if (url_type == FTP_URL_TYPE && !ftp_ok) {
+ statusline(FTP_DISABLED);
+ sleep(MessageSecs);
+ return(NULLFILE);
+ }
+
+ if (url_type == HTML_GOPHER_URL_TYPE) {
+ char *tmp=NULL;
+ /*
+ * If tuple's Path=GET%20/... convert to an http URL.
+ */
+ if ((cp=strchr(doc->address+9, '/')) != NULL &&
+ 0==strncmp(++cp, "hGET%20/", 8)) {
+ StrAllocCopy(tmp, "http://");
+ if (TRACE)
+ fprintf(stderr,
+ "getfile: URL '%s'\n",
+ doc->address);
+ *cp = '\0';
+ StrAllocCat(tmp, doc->address+9);
+ /*
+ * If the port is defaulted, it should stay 70.
+ */
+ if (strchr(tmp+6, ':') == NULL) {
+ StrAllocCat(tmp, "70/");
+ tmp[strlen(tmp)-4] = ':';
+ }
+ if (strlen(cp+7) > 1)
+ StrAllocCat(tmp, cp+8);
+ StrAllocCopy(doc->address, tmp);
+ if (TRACE)
+ fprintf(stderr, " changed to '%s'\n",
+ doc->address);
+ FREE(tmp);
+ url_type = HTTP_URL_TYPE;
+ }
+ }
+ if (url_type == HTTP_URL_TYPE ||
+ url_type == HTTPS_URL_TYPE ||
+ url_type == FTP_URL_TYPE ||
+ url_type == CSO_URL_TYPE)
+ fix_http_urls(doc);
+ WWWDoc.address = doc->address; /* possible reload */
+#ifdef DIRED_SUPPORT
+ lynx_edit_mode = FALSE;
+#endif /* DIRED_SUPPORT */
+
+ if (url_type == FILE_URL_TYPE) {
+ /*
+ * If a file URL has a '~' as the lead character
+ * of its first symbolic element, convert the '~'
+ * to Home_Dir(), then append the rest of of path,
+ * if present, skipping "user" if "~user" was
+ * entered, simplifying, and eliminating any
+ * residual relative elements. - FM
+ */
+ if (((cp = HTParse(doc->address, "",
+ PARSE_PATH+PARSE_ANCHOR+PARSE_PUNCTUATION))
+ != NULL) &&
+ !strncmp(cp, "/~", 2)) {
+ char *cp1 = strstr(doc->address, "/~");
+ char *cp2;
+
+ if (TRACE)
+ fprintf(stderr, "getfile: URL '%s'\n",
+ doc->address);
+ *cp1 = '\0';
+ cp1 += 2;
+ StrAllocCopy(temp, doc->address);
+#ifdef DOSPATH
+ StrAllocCat(temp, "/");
+ StrAllocCat(temp, HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ StrAllocCat(temp,
+ HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(temp, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ if ((cp2 = strchr(cp1, '/')) != NULL) {
+ LYTrimRelFromAbsPath(cp2);
+ StrAllocCat(temp, cp2);
+ }
+ StrAllocCopy(doc->address, temp);
+ FREE(temp);
+ if (TRACE)
+ fprintf(stderr, " changed to '%s'\n",
+ doc->address);
+ WWWDoc.address = doc->address;
+ }
+ FREE(cp);
+ }
+ if (TRACE && LYTraceLogFP == NULL)
+ sleep(MessageSecs);
+ user_message(WWW_WAIT_MESSAGE, doc->address);
+#ifdef NOTDEFINED
+ sleep(InfoSecs);
+#endif /* NOTDEFINED */
+ if (TRACE) {
+#ifdef USE_SLANG
+ if (LYCursesON) {
+ addstr("*\n");
+ refresh();
+ }
+#endif /* USE_SLANG */
+ fprintf(stderr,"\n");
+ }
+ if ((LYNoRefererHeader == FALSE &&
+ LYNoRefererForThis == FALSE) &&
+ (url_type == HTTP_URL_TYPE ||
+ url_type == HTTPS_URL_TYPE) &&
+ (cp = strchr(HTLoadedDocumentURL(), '?')) != NULL &&
+ strchr(cp, '=') != NULL) {
+ /*
+ * Don't send a Referer header if the URL is
+ * the reply from a form with method GET, in
+ * case the content has personal data (e.g.,
+ * a password or credit card number) which
+ * would become visible in logs. - FM
+ */
+ LYNoRefererForThis = TRUE;
+ }
+ cp = NULL;
+ if (!HTLoadAbsolute(&WWWDoc)) {
+ /*
+ * Check for redirection.
+ */
+ if (use_this_url_instead != NULL) {
+ char *pound;
+
+ if (!is_url(use_this_url_instead)) {
+ /*
+ * The server did not return a complete
+ * URL in its Location: header, probably
+ * due to a FORM or other CGI script written
+ * by someone who doesn't know that the http
+ * protocol requires that it be a complete
+ * URL, or using a server which does not treat
+ * such a redirect string from the script as
+ * an instruction to resolve it versus the
+ * initial request, check authentication with
+ * that URL, and then act on it without
+ * returning redirection to us. We'll
+ * violate the http protocol and resolve it
+ * ourselves using the URL of the original
+ * request as the BASE, rather than doing
+ * the RIGHT thing and returning an invalid
+ * address message. - FM
+ */
+ HTAlert(LOCATION_NOT_ABSOLUTE);
+ temp = HTParse(use_this_url_instead,
+ WWWDoc.address,
+ PARSE_ALL);
+ if (temp && *temp) {
+ StrAllocCopy(use_this_url_instead, temp);
+ }
+ FREE(temp);
+ }
+ HTMLSetCharacterHandling(current_char_set);
+ url_type = is_url(use_this_url_instead);
+ if (url_type == LYNXDOWNLOAD_URL_TYPE ||
+ url_type == LYNXEXEC_URL_TYPE ||
+ url_type == LYNXPROG_URL_TYPE ||
+#ifdef DIRED_SUPPORT
+ url_type == LYNXDIRED_URL_TYPE ||
+#endif /* DIRED_SUPPORT */
+ url_type == LYNXPRINT_URL_TYPE ||
+ url_type == LYNXHIST_URL_TYPE ||
+ url_type == LYNXCOOKIE_URL_TYPE ||
+ (LYValidate &&
+ url_type != HTTP_URL_TYPE &&
+ url_type != HTTPS_URL_TYPE) ||
+ ((no_file_url || no_goto_file) &&
+ url_type == FILE_URL_TYPE) ||
+ (no_goto_lynxcgi &&
+ url_type == LYNXCGI_URL_TYPE) ||
+ (no_goto_cso &&
+ url_type == CSO_URL_TYPE) ||
+ (no_goto_finger &&
+ url_type == FINGER_URL_TYPE) ||
+ (no_goto_ftp &&
+ url_type == FTP_URL_TYPE) ||
+ (no_goto_gopher &&
+ url_type == GOPHER_URL_TYPE) ||
+ (no_goto_http &&
+ url_type == HTTP_URL_TYPE) ||
+ (no_goto_https &&
+ url_type == HTTPS_URL_TYPE) ||
+ (no_goto_mailto &&
+ url_type == MAILTO_URL_TYPE) ||
+ (no_goto_news &&
+ url_type == NEWS_URL_TYPE) ||
+ (no_goto_nntp &&
+ url_type == NNTP_URL_TYPE) ||
+ (no_goto_rlogin &&
+ url_type == RLOGIN_URL_TYPE) ||
+ (no_goto_snews &&
+ url_type == SNEWS_URL_TYPE) ||
+ (no_goto_telnet &&
+ url_type == TELNET_URL_TYPE) ||
+ (no_goto_tn3270 &&
+ url_type == TN3270_URL_TYPE) ||
+ (no_goto_wais &&
+ url_type == WAIS_URL_TYPE)) {
+ /*
+ * Some schemes are not acceptable from
+ * server redirections. - KW & FM
+ */
+ HTAlert(ILLEGAL_REDIRECTION_URL);
+ if (LYCursesON) {
+ _user_message(WWW_ILLEGAL_URL_MESSAGE,
+ use_this_url_instead);
+ sleep(AlertSecs);
+ } else {
+ fprintf(stderr,
+ "Illegal Redirection URL: %s",
+ use_this_url_instead);
+ }
+ FREE(use_this_url_instead);
+ return(NULLFILE);
+ }
+ if ((pound = strchr(doc->address, '#')) != NULL &&
+ strchr(use_this_url_instead, '#') == NULL) {
+ /*
+ * Our requested URL had a fragment
+ * associated with it, and the redirection
+ * URL doesn't, so we'll append the fragment
+ * associated with the original request. If
+ * it's bogus for the redirection URL, we'll
+ * be positioned at the top of that document,
+ * so there's no harm done. - FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "getfile: Adding fragment '%s' to redirection URL.\n",
+ pound);
+ }
+ StrAllocCat(use_this_url_instead, pound);
+ }
+ if (TRACE && LYTraceLogFP == NULL)
+ sleep(MessageSecs);
+ _user_message(WWW_USING_MESSAGE,
+ use_this_url_instead);
+ sleep(InfoSecs);
+ if (TRACE)
+ fprintf(stderr, "\n");
+ StrAllocCopy(doc->address,
+ use_this_url_instead);
+ FREE(use_this_url_instead);
+ if (redirect_post_content == FALSE) {
+ /*
+ * Freeing the content also yields
+ * a GET request. - FM
+ */
+ FREE(doc->post_data);
+ FREE(doc->post_content_type);
+ }
+ /*
+ * Go to top to check for URL's which get
+ * special handling and/or security checks
+ * in Lynx. - FM
+ */
+ goto Try_Redirected_URL;
+ }
+ HTMLSetCharacterHandling(current_char_set);
+ return(NOT_FOUND);
+ }
+
+ lynx_mode = NORMAL_LYNX_MODE;
+
+ /*
+ * Some URL's don't actually return a document
+ * compare doc->address with the document that is
+ * actually loaded and return NULL if not
+ * loaded. If www_search_result is not -1
+ * then this is a reference to a named anchor
+ * within the same document. Do NOT return
+ * NULL.
+ */
+ {
+ char *pound;
+ /*
+ * Check for a #fragment selector.
+ */
+ pound = (char *)strchr(doc->address, '#');
+
+ /*
+ * Check to see if there is a temp
+ * file waiting for us to download.
+ */
+ if (WWW_Download_File) {
+ HTParentAnchor *tmpanchor;
+ char *fname = NULL;
+
+ HTMLSetCharacterHandling(current_char_set);
+ /*
+ * Check for a suggested filename from
+ * the Content-Dispostion header. - FM
+ */
+ if (((tmpanchor = HTAnchor_parent(
+ HTAnchor_findAddress(&WWWDoc)
+ )) != NULL) &&
+ HTAnchor_SugFname(tmpanchor) != NULL) {
+ StrAllocCopy(fname,
+ HTAnchor_SugFname(tmpanchor));
+ } else {
+ StrAllocCopy(fname, doc->address);
+ }
+ /*
+ * Check whether this is a compressed file,
+ * which we don't uncompress for downloads,
+ * and adjust any suffix appropriately. - FM
+ */
+ if (tmpanchor != NULL) {
+ HTCheckFnameForCompression(&fname, tmpanchor,
+ FALSE);
+ }
+ if (LYdownload_options(&fname,
+ WWW_Download_File) < 0) {
+ FREE(fname);
+ return(NOT_FOUND);
+ }
+ LYAddVisitedLink(doc);
+ StrAllocCopy(doc->address, fname);
+ FREE(fname);
+ doc->internal_link = FALSE;
+ WWWDoc.address = doc->address;
+ FREE(doc->post_data);
+ WWWDoc.post_data = NULL;
+ FREE(doc->post_content_type);
+ WWWDoc.post_content_type = NULL;
+ WWWDoc.bookmark = doc->bookmark = FALSE;
+ WWWDoc.isHEAD = doc->isHEAD = FALSE;
+ WWWDoc.safe = doc->safe = FALSE;
+ HTOutputFormat = WWW_PRESENT;
+ if (!HTLoadAbsolute(&WWWDoc))
+ return(NOT_FOUND);
+ else
+ return(NORMAL);
+
+ } else if (pound == NULL &&
+ /*
+ * HTAnchor hash-table searches are now
+ * case-sensitive (hopefully, without
+ * anchor deletion problems), so this
+ * is too. - FM
+ */
+ (strcmp(doc->address,
+ HTLoadedDocumentURL()) ||
+ /*
+ * Also check the post_data elements. - FM
+ */
+ strcmp((doc->post_data ?
+ doc->post_data : ""),
+ HTLoadedDocumentPost_data()) ||
+ /*
+ * Also check the isHEAD element. - FM
+ */
+ doc->isHEAD != HTLoadedDocumentIsHEAD())) {
+ HTMLSetCharacterHandling(current_char_set);
+ /*
+ * Nothing needed to be shown.
+ */
+ LYAddVisitedLink(doc);
+ return(NULLFILE);
+
+ } else {
+ /*
+ * May set www_search_result.
+ */
+ if (pound != NULL)
+ HTFindPoundSelector(pound+1);
+ HTMLSetCharacterHandling(current_char_set);
+ return(NORMAL);
+ }
+ }
+ }
+ } else {
+ if (TRACE && LYTraceLogFP == NULL)
+ sleep(MessageSecs);
+ _user_message(WWW_BAD_ADDR_MESSAGE, doc->address);
+ if (TRACE)
+ fprintf(stderr,"\n");
+ sleep(MessageSecs);
+ return(NULLFILE);
+ }
+}
+
+/*
+ * The user wants to select a link or page by number.
+ * If follow_link_number returns DO_LINK_STUFF do_link
+ * will be run immediately following its execution.
+ * If follow_link_number returns DO_GOTOLINK_STUFF
+ * it has updated the passed in doc for positioning on a link.
+ * If follow_link_number returns DO_GOTOPAGE_STUFF
+ * it has set doc->line to the top line of the desired page
+ * for displaying that page.
+ * If follow_link_number returns PRINT_ERROR an error message
+ * will be given to the user.
+ * If follow_link_number returns DO_FORMS_STUFF some forms stuff
+ * will be done. (Not yet implemented.)
+ * If follow_link_number returns DO_NOTHING nothing special
+ * will run after it.
+ */
+PUBLIC int follow_link_number ARGS4(
+ int, c,
+ int, cur,
+ document *, doc,
+ int *, num)
+{
+ char temp[120];
+ int new_top, new_link;
+ BOOL want_go;
+
+ temp[0] = c;
+ temp[1] = '\0';
+ *num = -1;
+ _statusline(FOLLOW_LINK_NUMBER);
+ /*
+ * Get the number, possibly with a letter suffix, from the user.
+ */
+ if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 || *temp == 0) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(DO_NOTHING);
+ }
+ *num = atoi(temp);
+
+ /*
+ * Check if we had a 'p' or 'P' following the number as
+ * a flag for displaying the page with that number. - FM
+ */
+ if (strchr(temp, 'p') != NULL || strchr(temp, 'P') != NULL) {
+ int nlines = HText_getNumOfLines();
+ int npages = ((nlines + 1) > display_lines) ?
+ (((nlines + 1) + (display_lines - 1))/(display_lines))
+ : 1;
+ if (*num < 1)
+ *num = 1;
+ doc->line = (npages <= 1) ?
+ 1 :
+ ((*num <= npages) ? (((*num - 1) * display_lines) + 1)
+ : (((npages - 1) * display_lines) + 1));
+ return(DO_GOTOPAGE_STUFF);
+ }
+
+ /*
+ * Check if we want to make the link corresponding to the
+ * number the current link, rather than ACTIVATE-ing it.
+ */
+ want_go = (strchr(temp, 'g') != NULL || strchr(temp, 'G') != NULL);
+
+ /*
+ * If we have a valid number, act on it.
+ */
+ if (*num > 0) {
+ int info;
+ /*
+ * Get the lname, and hightext, directly from www
+ * structures and add it to the cur link so that
+ * we can pass it transparently on to getfile(),
+ * and load new_top and new_link if we instead want
+ * to make the link number current. These things
+ * are done so that a link can be selected anywhere
+ * in the current document, whether it is displayed
+ * on the screen or not!
+ */
+ if ((info = HTGetLinkInfo(*num,
+ want_go,
+ &new_top,
+ &new_link,
+ &links[cur].hightext,
+ &links[cur].lname)) == WWW_INTERN_LINK_TYPE) {
+ links[cur].type = WWW_INTERN_LINK_TYPE;
+ return(DO_LINK_STUFF);
+ } else if (info == LINK_LINE_FOUND) {
+ doc->line = new_top + 1;
+ doc->link = new_link;
+ return(DO_GOTOLINK_STUFF);
+ } else if (info) {
+ links[cur].type = WWW_LINK_TYPE;
+ return(DO_LINK_STUFF);
+ } else {
+ return(PRINT_ERROR);
+ }
+ } else {
+ return(PRINT_ERROR);
+ }
+}
+
+#if defined(EXEC_LINKS) || defined(LYNXCGI_LINKS)
+
+struct trust {
+ char *src;
+ char *path;
+ int type;
+ struct trust *next;
+};
+
+static struct trust trusted_exec_default = {
+ "file://localhost/", "", EXEC_PATH, NULL
+};
+static struct trust always_trusted_exec_default = {
+ "none", "", ALWAYS_EXEC_PATH, NULL
+};
+static struct trust trusted_cgi_default = {
+ "", "", CGI_PATH, NULL
+};
+
+static struct trust *trusted_exec = &trusted_exec_default;
+static struct trust *always_trusted_exec = &always_trusted_exec_default;
+static struct trust *trusted_cgi = &trusted_cgi_default;
+
+PRIVATE void LYTrusted_free NOARGS
+{
+ struct trust *cur;
+ struct trust *next;
+
+ if (trusted_exec != &trusted_exec_default) {
+ cur = trusted_exec;
+ while (cur) {
+ FREE(cur->src);
+ FREE(cur->path);
+ next = cur->next;
+ FREE(cur);
+ cur = next;
+ }
+ }
+
+ if (always_trusted_exec != &always_trusted_exec_default) {
+ cur = always_trusted_exec;
+ while (cur) {
+ FREE(cur->src);
+ FREE(cur->path);
+ next = cur->next;
+ FREE(cur);
+ cur = next;
+ }
+ }
+
+ if (trusted_cgi != &trusted_cgi_default) {
+ cur = trusted_cgi;
+ while (cur) {
+ FREE(cur->src);
+ FREE(cur->path);
+ next = cur->next;
+ FREE(cur);
+ cur = next;
+ }
+ }
+
+ return;
+}
+
+PUBLIC void add_trusted ARGS2(
+ char *, str,
+ int, type)
+{
+ struct trust *tp;
+ char *path;
+ char *src = str;
+ int Type = type;
+ static BOOLEAN first = TRUE;
+
+ if (!src)
+ return;
+ if (first) {
+ atexit(LYTrusted_free);
+ first = FALSE;
+ }
+
+ path = strchr(src, '\t');
+ if (path)
+ *path++ = '\0';
+ else
+ path = "";
+
+ tp = (struct trust *)malloc(sizeof(*tp));
+ if (tp == NULL)
+ outofmem(__FILE__, "add_trusted");
+ tp->src = NULL;
+ tp->path = NULL;
+ tp->type = Type;
+ StrAllocCopy(tp->src, src);
+ StrAllocCopy(tp->path, path);
+ if (Type == EXEC_PATH) {
+ if (trusted_exec == &trusted_exec_default)
+ tp->next = NULL;
+ else
+ tp->next = trusted_exec;
+ trusted_exec = tp;
+ } else if (Type == ALWAYS_EXEC_PATH) {
+ if (always_trusted_exec == &always_trusted_exec_default)
+ tp->next = NULL;
+ else
+ tp->next = always_trusted_exec;
+ always_trusted_exec = tp;
+ } else if (Type == CGI_PATH) {
+ if (trusted_cgi == &trusted_cgi_default)
+ tp->next = NULL;
+ else
+ tp->next = trusted_cgi;
+ trusted_cgi = tp;
+ }
+}
+
+/*
+ * Check to see if the supplied paths is allowed to be executed.
+ */
+PUBLIC BOOLEAN exec_ok ARGS3(
+ CONST char *, source,
+ CONST char *, link,
+ int, type)
+{
+ struct trust *tp;
+ CONST char *cp;
+ int Type = type;
+
+ /*
+ * Always OK if it is a jump file shortcut.
+ */
+ if (LYJumpFileURL)
+ return TRUE;
+
+ /*
+ * Choose the trust structure based on the type.
+ */
+ if (Type == EXEC_PATH) {
+ tp = trusted_exec;
+ } else if (Type == ALWAYS_EXEC_PATH) {
+ tp = always_trusted_exec;
+ } else if (Type == CGI_PATH) {
+ tp = trusted_cgi;
+ } else {
+ HTAlert(MALFORMED_EXEC_REQUEST);
+ return FALSE;
+ }
+
+#ifdef VMS
+ /*
+ * Security: reject on relative path.
+ */
+ if ((cp = strchr(link, '[')) != NULL) {
+ char *cp1;
+ if (((cp1 = strchr(cp, '-')) != NULL) &&
+ strchr(cp1, ']') != NULL) {
+ while (cp1[1] == '-')
+ cp1++;
+ if (cp1[1] == ']' ||
+ cp1[1] == '.') {
+ HTAlert(RELPATH_IN_EXEC_LINK);
+ return FALSE;
+ }
+ }
+ }
+#else
+ /*
+ * Security: reject on relative path.
+ */
+ if (strstr(link, "../") != NULL) {
+ HTAlert(RELPATH_IN_EXEC_LINK);
+ return FALSE;
+ }
+
+ /*
+ * Security: reject on strange character.
+ */
+ for (cp = link; *cp != '\0'; cp++) {
+ if (!isalnum(*cp) &&
+ *cp != '_' && *cp != '-' && *cp != ' ' &&
+ *cp != ':' && *cp != '.' && *cp != '/' &&
+ *cp != '@' && *cp != '~' && *cp != '$' &&
+ *cp != '&' && *cp != '+' && *cp != '=' &&
+ *cp != '\t') {
+ char buf[128];
+
+ sprintf(buf,
+ BADCHAR_IN_EXEC_LINK,
+ *cp);
+ HTAlert(buf);
+ return FALSE;
+ }
+ }
+#endif /* VMS */
+
+check_tp_for_entry:
+ while (tp) {
+ if (tp->type == Type) {
+ char CONST *command = link;
+
+ if (strstr(command,"//") == link) {
+ command += 2;
+ }
+#ifdef VMS
+ if (strncasecomp(source, tp->src, strlen(tp->src)) == 0 &&
+ strncasecomp(command, tp->path, strlen(tp->path)) == 0)
+#else
+ if (strncmp(source, tp->src, strlen(tp->src)) == 0 &&
+ strncmp(command, tp->path, strlen(tp->path)) == 0)
+#endif /* VMS */
+ return TRUE;
+ }
+ tp = tp->next;
+ }
+ if (Type == EXEC_PATH &&
+ always_trusted_exec != &always_trusted_exec_default) {
+ Type = ALWAYS_EXEC_PATH;
+ tp = always_trusted_exec;
+ goto check_tp_for_entry;
+ }
+ if (!(no_exec && type == ALWAYS_EXEC_PATH))
+ HTAlert(BADLOCPATH_IN_EXEC_LINK);
+ return FALSE;
+}
+#endif /* EXEC_LINKS || LYNXCGI_LINKS */
+
+PRIVATE int fix_http_urls ARGS1(
+ document *, doc)
+{
+ char *slash;
+
+ /*
+ * If it's an ftp URL with a trailing slash, trim it off.
+ */
+ if (!strncmp(doc->address, "ftp", 3) &&
+ doc->address[strlen(doc->address)-1] == '/') {
+ char * proxy;
+ char *path = HTParse(doc->address, "", PARSE_PATH|PARSE_PUNCTUATION);
+
+ /*
+ * If the path is a lone slash, we're done. - FM
+ */
+ if (path) {
+ if (path[0] == '/' && path[1] == '\0') {
+ FREE(path);
+ return 0;
+ }
+ FREE(path);
+ }
+
+ /*
+ * If we're proxying ftp, don't trim anything. - KW
+ */
+ if (((proxy = (char *)getenv("ftp_proxy")) != NULL) &&
+ *proxy != '\0' && !override_proxy(doc->address))
+ return 0;
+
+ /*
+ * If we get to here, trim the trailing slash. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "fix_http_urls: URL '%s'\n", doc->address);
+ doc->address[strlen(doc->address)-1] = '\0';
+ if (TRACE) {
+ fprintf(stderr, " changed to '%s'\n", doc->address);
+ if (!LYTraceLogFP)
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * If there isn't a slash besides the two at the beginning, append one.
+ */
+ if ((slash = strrchr(doc->address, '/')) != NULL) {
+ if (*(slash-1) != '/' || *(slash-2) != ':') {
+ return(0);
+ }
+ }
+ if (TRACE)
+ fprintf(stderr, "fix_http_urls: URL '%s'\n", doc->address);
+ StrAllocCat(doc->address, "/");
+ if (TRACE) {
+ fprintf(stderr, " changed to '%s'\n",doc->address);
+ if (!LYTraceLogFP)
+ sleep(MessageSecs);
+ }
+
+ return(1);
+}
diff --git a/gnu/usr.bin/lynx/src/LYGetFile.h b/gnu/usr.bin/lynx/src/LYGetFile.h
new file mode 100644
index 00000000000..8ddfb99910b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYGetFile.h
@@ -0,0 +1,30 @@
+
+#ifndef LYGETFILE_H
+#define LYGETFILE_H
+
+#define NOT_FOUND 0
+#define NORMAL 1
+#define NULLFILE 3
+
+extern BOOLEAN getfile PARAMS((document *doc));
+extern int follow_link_number PARAMS((
+ int c,
+ int cur,
+ document * doc,
+ int * num));
+extern void add_trusted PARAMS((char *str, int type));
+extern BOOLEAN exec_ok PARAMS((CONST char *source, CONST char *linkpath, int type));
+
+/* values for follow_link_number() */
+#define DO_LINK_STUFF 1
+#define DO_GOTOLINK_STUFF 2
+#define DO_GOTOPAGE_STUFF 3
+#define DO_FORMS_STUFF 4
+#define PRINT_ERROR 5
+
+/* values for add_trusted() and exec_ok() */
+#define EXEC_PATH 0
+#define ALWAYS_EXEC_PATH 1
+#define CGI_PATH 2
+
+#endif /* LYGETFILE_H */
diff --git a/gnu/usr.bin/lynx/src/LYGlobalDefs.h b/gnu/usr.bin/lynx/src/LYGlobalDefs.h
new file mode 100644
index 00000000000..80cba70605a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYGlobalDefs.h
@@ -0,0 +1,340 @@
+/* global variable definitions */
+
+#ifndef LYGLOBALDEFS_H
+#define LYGLOBALDEFS_H
+
+#ifndef USERDEFS_H
+#include "userdefs.h"
+#endif /* USERDEFS_H */
+
+#ifndef HTUTILS_H
+#include "HTUtils.h"
+#endif /* HTUTILS_H */
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+#ifdef SOCKS
+extern BOOLEAN socks_flag;
+#endif /* SOCKS */
+
+#ifdef IGNORE_CTRL_C
+extern BOOLEAN sigint;
+#endif /* IGNORE_CTRL_C */
+
+#ifdef VMS
+extern char *mail_adrs;
+extern BOOLEAN UseFixedRecords; /* convert binary files to FIXED 512 records */
+#endif /* VMS */
+
+#ifndef VMS
+extern char *NNTPSERVER_putenv_cmd;
+extern char *http_proxy_putenv_cmd;
+extern char *https_proxy_putenv_cmd;
+extern char *ftp_proxy_putenv_cmd;
+extern char *gopher_proxy_putenv_cmd;
+extern char *cso_proxy_putenv_cmd;
+extern char *news_proxy_putenv_cmd;
+extern char *newspost_proxy_putenv_cmd;
+extern char *newsreply_proxy_putenv_cmd;
+extern char *snews_proxy_putenv_cmd;
+extern char *snewspost_proxy_putenv_cmd;
+extern char *snewsreply_proxy_putenv_cmd;
+extern char *nntp_proxy_putenv_cmd;
+extern char *wais_proxy_putenv_cmd;
+extern char *finger_proxy_putenv_cmd;
+extern char *no_proxy_putenv_cmd;
+extern char *list_format;
+#endif /* !VMS */
+
+#ifdef VMS
+extern char *LYCSwingPath;
+#endif /* VMS */
+
+#ifdef DIRED_SUPPORT
+extern BOOLEAN lynx_edit_mode;
+extern BOOLEAN no_dired_support;
+extern BOOLEAN dir_list_style;
+extern HTList *tagged;
+#define FILES_FIRST 1
+#define MIXED_STYLE 2
+#ifdef OK_OVERRIDE
+extern BOOLEAN prev_lynx_edit_mode;
+#endif /* OK_OVERRIDE */
+#ifdef OK_PERMIT
+extern BOOLEAN no_change_exec_perms;
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
+
+extern int HTCacheSize; /* the number of documents cached in memory */
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+extern int HTVirtualMemorySize; /* bytes allocated and not yet freed */
+#endif /* VMS && VAXC && !__DECC */
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+extern BOOLEAN local_exec; /* TRUE to enable local program execution */
+extern BOOLEAN local_exec_on_local_files; /* TRUE to enable local program *
+ * execution in local files only */
+#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */
+
+#if defined(LYNXCGI_LINKS) && !defined(VMS) /* WebSter Mods -jkt */
+extern char *LYCgiDocumentRoot; /* DOCUMENT_ROOT in the lynxcgi env */
+#endif /* LYNXCGI_LINKS */
+
+/* Values to which keypad_mode can be set */
+#define NUMBERS_AS_ARROWS 0
+#define LINKS_ARE_NUMBERED 1
+#define LINKS_AND_FORM_FIELDS_ARE_NUMBERED 2
+
+#define HIDDENLINKS_MERGE 0
+#define HIDDENLINKS_SEPARATE 1
+#define HIDDENLINKS_IGNORE 2
+
+#define NOVICE_MODE 0
+#define INTERMEDIATE_MODE 1
+#define ADVANCED_MODE 2
+extern BOOLEAN LYUseNoviceLineTwo; /* True if TOGGLE_HELP is not mapped */
+
+#define MAX_LINE 1024 /* Hope that no window is larger than this */
+extern char star_string[MAX_LINE + 1]; /* from GridText.c */
+#define STARS(n) \
+ ((n) >= MAX_LINE ? star_string : &star_string[(MAX_LINE-1)] - (n))
+#define DIRNAMESIZE 256
+
+#define SHOW_COLOR_UNKNOWN (-1)
+#define SHOW_COLOR_NEVER 0
+#define SHOW_COLOR_OFF 1
+#define SHOW_COLOR_ON 2
+#define SHOW_COLOR_ALWAYS 3
+extern int LYShowColor; /* Show color or monochrome? */
+extern int LYChosenShowColor; /* extended color/monochrome choice */
+extern int LYrcShowColor; /* ... as read or last written */
+
+extern BOOLEAN LYShowCursor; /* Show the cursor or hide it? */
+extern BOOLEAN LYUseDefShoCur; /* Command line -show_cursor toggle */
+extern BOOLEAN LYCursesON; /* start_curses()->TRUE, stop_curses()->FALSE */
+extern BOOLEAN LYUserSpecifiedURL; /* URL from a goto or document? */
+extern BOOLEAN LYJumpFileURL; /* URL from the jump file shortcuts? */
+extern BOOLEAN jump_buffer; /* TRUE if offering default shortcut */
+extern BOOLEAN goto_buffer; /* TRUE if offering default goto URL */
+extern char *LYRequestTitle; /* newdoc.title in calls to getfile() */
+extern char *jumpprompt; /* The default jump statusline prompt */
+extern int more; /* is there more document to display? */
+extern int display_lines; /* number of lines in the display */
+extern int www_search_result;
+extern char *checked_box; /* form boxes */
+extern char *unchecked_box; /* form boxes */
+extern char *checked_radio; /* form radio buttons */
+extern char *unchecked_radio; /* form radio buttons */
+extern char *empty_string;
+extern char *LynxHome;
+extern char *startfile;
+extern char *helpfile;
+extern char *helpfilepath;
+extern char *lynxjumpfile;
+extern char *lynxlistfile;
+extern char *lynxlinksfile;
+extern char *display;
+extern char *language;
+extern char *pref_charset; /* Lynx's preferred character set - MM */
+extern BOOLEAN LYNewsPosting; /* News posting supported if TRUE */
+extern char *LynxSigFile; /* Signature file, in or off home */
+extern char *system_mail;
+extern char *system_mail_flags;
+extern char *lynx_temp_space;
+extern char *lynx_save_space;
+extern BOOLEAN LYforce_HTML_mode;
+extern BOOLEAN LYforce_no_cache;
+extern BOOLEAN LYoverride_no_cache; /* don't need fresh copy, from history */
+extern BOOLEAN LYinternal_flag; /* don't need fresh copy, was internal link */
+extern BOOLEAN LYresubmit_posts;
+extern BOOLEAN user_mode; /* novice or advanced */
+extern BOOLEAN is_www_index;
+extern BOOLEAN dump_output_immediately;
+extern int dump_output_width;
+extern BOOLEAN lynx_mode;
+extern BOOLEAN bold_headers;
+extern BOOLEAN bold_H1;
+extern BOOLEAN bold_name_anchors;
+extern BOOLEAN recent_sizechange;
+extern BOOLEAN telnet_ok;
+extern BOOLEAN news_ok;
+extern BOOLEAN ftp_ok;
+extern BOOLEAN rlogin_ok;
+extern BOOLEAN no_print; /* TRUE to disable printing */
+extern BOOLEAN system_editor; /* True if locked-down editor */
+extern BOOLEAN child_lynx; /* TRUE to exit with an arrow */
+extern BOOLEAN error_logging; /* TRUE to mail error messages */
+extern BOOLEAN check_mail; /* TRUE to report unread/new mail messages */
+extern BOOLEAN vi_keys; /* TRUE to turn on vi-like key movement */
+extern BOOLEAN emacs_keys; /* TRUE to turn on emacs-like key movement */
+extern BOOLEAN keypad_mode; /* is set to either NUMBERS_AS_ARROWS *
+ * or LINKS_ARE_NUMBERED */
+extern BOOLEAN case_sensitive; /* TRUE to turn on case sensitive search */
+extern BOOLEAN no_inside_telnet; /* this and following are restrictions */
+extern BOOLEAN no_outside_telnet;
+extern BOOLEAN no_telnet_port;
+extern BOOLEAN no_inside_news;
+extern BOOLEAN no_outside_news;
+extern BOOLEAN no_inside_ftp;
+extern BOOLEAN no_outside_ftp;
+extern BOOLEAN no_inside_rlogin;
+extern BOOLEAN no_outside_rlogin;
+extern BOOLEAN no_suspend;
+extern BOOLEAN no_editor;
+extern BOOLEAN no_shell;
+extern BOOLEAN no_bookmark;
+extern BOOLEAN no_multibook;
+extern BOOLEAN no_bookmark_exec;
+extern BOOLEAN no_option_save;
+extern BOOLEAN no_print;
+extern BOOLEAN no_download;
+extern BOOLEAN no_disk_save;
+extern BOOLEAN no_exec;
+extern BOOLEAN no_lynxcgi;
+extern BOOLEAN exec_frozen;
+extern BOOLEAN no_goto;
+extern BOOLEAN no_goto_cso;
+extern BOOLEAN no_goto_file;
+extern BOOLEAN no_goto_finger;
+extern BOOLEAN no_goto_ftp;
+extern BOOLEAN no_goto_gopher;
+extern BOOLEAN no_goto_http;
+extern BOOLEAN no_goto_https;
+extern BOOLEAN no_goto_lynxcgi;
+extern BOOLEAN no_goto_lynxexec;
+extern BOOLEAN no_goto_lynxprog;
+extern BOOLEAN no_goto_mailto;
+extern BOOLEAN no_goto_news;
+extern BOOLEAN no_goto_nntp;
+extern BOOLEAN no_goto_rlogin;
+extern BOOLEAN no_goto_snews;
+extern BOOLEAN no_goto_telnet;
+extern BOOLEAN no_goto_tn3270;
+extern BOOLEAN no_goto_wais;
+extern BOOLEAN no_jump;
+extern BOOLEAN no_file_url;
+extern BOOLEAN no_newspost;
+extern BOOLEAN no_mail;
+extern BOOLEAN no_dotfiles;
+extern BOOLEAN no_useragent;
+extern BOOLEAN no_statusline;
+extern BOOLEAN no_filereferer;
+extern BOOLEAN local_host_only;
+extern BOOLEAN override_no_download;
+extern BOOLEAN show_dotfiles; /* From rcfile if no_dotfiles is false */
+extern char *indexfile;
+extern char *personal_mail_address;
+extern char *homepage; /* startfile or command line argument */
+extern char *editor; /* if non empty it enables edit mode with
+ * the editor that is named */
+extern char *jumpfile;
+extern char *bookmark_page;
+extern char *BookmarkPage;
+extern char *personal_type_map;
+extern char *global_type_map;
+extern char *global_extension_map;
+extern char *personal_extension_map;
+extern char *LYHostName;
+extern char *LYLocalDomain;
+extern BOOLEAN use_underscore;
+extern BOOLEAN nolist;
+extern BOOLEAN historical_comments;
+extern BOOLEAN minimal_comments;
+extern BOOLEAN soft_dquotes;
+extern BOOLEAN LYCancelDownload;
+extern BOOLEAN LYValidate;
+extern BOOLEAN LYPermitURL;
+extern BOOLEAN enable_scrollback; /* Clear screen before displaying new page */
+extern BOOLEAN keep_mime_headers; /* Include mime headers and *
+ * force source dump */
+extern BOOLEAN no_url_redirection; /* Don't follow URL redirections */
+extern char *form_post_data; /* User data for post form */
+extern char *form_get_data; /* User data for get form */
+extern char *http_error_file; /* Place HTTP status code in this file */
+extern char *authentication_info[2]; /* Id:Password for protected documents */
+extern char *proxyauth_info[2]; /* Id:Password for protected proxy server */
+extern BOOLEAN HEAD_request; /* Do a HEAD request */
+extern BOOLEAN scan_for_buried_news_references;
+extern BOOLEAN bookmark_start; /* Use bookmarks as startfile */
+extern BOOLEAN clickable_images;
+extern BOOLEAN pseudo_inline_alts;
+extern BOOLEAN crawl;
+extern BOOLEAN traversal;
+extern BOOLEAN check_realm;
+extern char * startrealm;
+extern BOOLEAN more_links;
+extern int ccount;
+extern BOOLEAN LYCancelledFetch;
+extern char * LYToolbarName;
+extern int InfoSecs;
+extern int MessageSecs;
+extern int AlertSecs;
+extern char * LYUserAgent; /* Lynx User-Agent header */
+extern char * LYUserAgentDefault; /* Lynx default User-Agent header */
+extern BOOLEAN LYNoRefererHeader; /* Never send Referer header? */
+extern BOOLEAN LYNoRefererForThis; /* No Referer header for this URL? */
+extern BOOLEAN LYNoFromHeader; /* Never send From header? */
+extern BOOLEAN LYListNewsNumbers;
+extern BOOLEAN LYUseMouse;
+extern BOOLEAN LYListNewsDates;
+extern BOOLEAN LYRawMode;
+extern BOOLEAN LYDefaultRawMode;
+extern BOOLEAN LYUseDefaultRawMode;
+extern char *UCAssume_MIMEcharset;
+extern char *UCAssume_localMIMEcharset;
+extern char *UCAssume_unrecMIMEcharset;
+extern BOOLEAN LYisConfiguredForX;
+extern char *URLDomainPrefixes;
+extern char *URLDomainSuffixes;
+extern BOOLEAN startfile_ok;
+extern BOOLEAN LYSelectPopups; /* Cast popups to radio buttons? */
+extern BOOLEAN LYUseDefSelPop; /* Command line -popup toggle */
+extern int LYMultiBookmarks; /* Multi bookmark support on? */
+extern BOOLEAN LYMBMBlocked; /* Force MBM support off? */
+extern BOOLEAN LYMBMAdvanced; /* MBM statusline for ADVANCED? */
+extern int LYStatusLine; /* Line for statusline() or -1 */
+extern BOOLEAN LYCollapseBRs; /* Collapse serial BRs? */
+extern BOOLEAN LYSetCookies; /* Process Set-Cookie headers? */
+extern char *XLoadImageCommand; /* Default image viewer for X */
+#ifdef USE_EXTERNALS
+extern BOOLEAN no_externals; /* don't allow the use of externals */
+#endif
+extern BOOLEAN LYNoISMAPifUSEMAP; /* Omit ISMAP link if MAP present? */
+extern int LYHiddenLinks;
+
+extern BOOL New_DTD;
+
+#define BOOKMARK_TITLE "Bookmark file"
+#define MOSAIC_BOOKMARK_TITLE "Converted Mosaic Hotlist"
+#define MBM_V_MAXFILES 25 /* Max number of sub-bookmark files */
+/*
+ * Arrays that holds the names of sub-bookmark files
+ * and their descriptions.
+ */
+extern char *MBM_A_subbookmark[MBM_V_MAXFILES+1];
+extern char *MBM_A_subdescript[MBM_V_MAXFILES+1];
+extern FILE *LYTraceLogFP; /* Pointer for TRACE log */
+extern char *LYTraceLogPath; /* Path for TRACE log */
+extern BOOLEAN LYUseTraceLog; /* Use a TRACE log? */
+extern FILE LYOrigStderr; /* Original stderr pointer */
+extern BOOLEAN LYSeekFragMAPinCur;
+extern BOOLEAN LYSeekFragAREAinCur;
+extern BOOLEAN LYStripDotDotURLs; /* Try to fix ../ in some URLs? */
+extern BOOLEAN LYForceSSLCookiesSecure;
+extern BOOLEAN LYNoCc;
+extern BOOLEAN LYPreparsedSource; /* Show source as preparsed? */
+extern BOOLEAN LYPrependBaseToSource;
+extern BOOLEAN LYPrependCharsetToSource;
+extern BOOLEAN LYQuitDefaultYes;
+
+#ifdef RAWDOSKEYHACK
+extern BOOLEAN raw_dos_key_hack; /* Turn on and off DOS key hack */
+#endif /* RAWDOSKEYHACK */
+
+#ifndef VMS
+extern BOOLEAN LYNoCore;
+#endif /* !VMS */
+
+#endif /* LYGLOBALDEFS_H */
diff --git a/gnu/usr.bin/lynx/src/LYHash.c b/gnu/usr.bin/lynx/src/LYHash.c
new file mode 100644
index 00000000000..a6eea95f594
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYHash.c
@@ -0,0 +1,51 @@
+/* A hash table for the (fake) CSS support in Lynx-rp
+** (c) 1996 Rob Partington
+*/
+
+#include "LYStructs.h"
+#include "LYCurses.h"
+#include "AttrList.h"
+#include "SGML.h"
+#include "HTMLDTD.h"
+
+#include "LYHash.h"
+
+#ifdef NOT_USED
+
+PUBLIC int hash_table[CSHASHSIZE]; /* 32K should be big enough */
+
+PUBLIC int hash_code_rp ARGS1(char*,string)
+{
+ char* hash_ptr = string;
+ int hash_tmp = 0xC00A | ((*hash_ptr) << 4);
+
+ while (*hash_ptr++)
+ {
+ hash_tmp ^= (((*hash_ptr)<<4) ^ ((*hash_ptr)<<12));
+ hash_tmp >>= 1;
+ }
+ return (hash_tmp % CSHASHSIZE);
+}
+#endif
+
+/*
+ * This is the same function as the private HASH_FUNCTION() in HTAnchor.c,
+ * but with a different value for HASH_SIZE.
+ */
+
+#ifdef NOT_USED
+#define HASH_SIZE 8193 /* Arbitrary prime. Memory/speed tradeoff */
+#else
+#define HASH_SIZE CSHASHSIZE
+#endif
+
+PUBLIC int hash_code ARGS1 (char*, string)
+{
+ int hash;
+ unsigned char *p;
+
+ for (p = (unsigned char *)string, hash = 0; *p; p++)
+ hash = (int) (hash * 3 + (*(unsigned char *)p)) % HASH_SIZE;
+
+ return hash;
+}
diff --git a/gnu/usr.bin/lynx/src/LYHash.h b/gnu/usr.bin/lynx/src/LYHash.h
new file mode 100644
index 00000000000..00f8066c5e2
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYHash.h
@@ -0,0 +1,39 @@
+#if !defined(_LYHASH_H_)
+#define _LYHASH_H_ 1
+
+struct _hashbucket {
+ char *name; /* name of this item */
+ int code; /* code of this item */
+ int color; /* color highlighting to be done */
+ int mono; /* mono highlighting to be done */
+ int cattr; /* attributes to go with the color */
+ struct _hashbucket *next; /* next item */
+};
+
+typedef struct _hashbucket bucket;
+
+#if !defined(CSHASHSIZE)
+#ifdef NOT_USED
+#define CSHASHSIZE 32768
+#else
+#define CSHASHSIZE 8193
+#endif
+#endif
+
+#define NOSTYLE -1
+
+extern bucket hashStyles[CSHASHSIZE];
+extern int hash_code PARAMS((char* string));
+#ifdef NOT_USED
+extern int hash_table[CSHASHSIZE]; /* 32K should be big enough */
+#endif
+
+extern int s_alink, s_a, s_status,
+ s_label, s_value, s_high,
+ s_normal, s_alert, s_title;
+#define CACHEW 128
+#define CACHEH 64
+
+extern unsigned cached_styles[CACHEH][CACHEW];
+
+#endif /* _LYHASH_H_ */
diff --git a/gnu/usr.bin/lynx/src/LYHistory.c b/gnu/usr.bin/lynx/src/LYHistory.c
new file mode 100644
index 00000000000..bccb2ec81fa
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYHistory.c
@@ -0,0 +1,647 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTP.h"
+#include "HTAlert.h"
+#include "HText.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYHistory.h"
+#include "LYPrint.h"
+#include "LYDownload.h"
+#include "LYKeymap.h"
+#include "LYList.h"
+#include "LYShowInfo.h"
+#include "LYSignal.h"
+#include "LYStrings.h"
+#include "LYCharUtils.h"
+
+#ifdef DIRED_SUPPORT
+#include "LYUpload.h"
+#include "LYLocal.h"
+#endif /* DIRED_SUPPORT */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC HTList * Visited_Links = NULL; /* List of safe popped docs. */
+
+/*
+ * Utility for freeing the list of visited links. - FM
+ */
+PRIVATE void Visited_Links_free NOARGS
+{
+ VisitedLink *vl;
+ HTList *cur = Visited_Links;
+
+ if (!cur)
+ return;
+
+ while (NULL != (vl = (VisitedLink *)HTList_nextObject(cur))) {
+ FREE(vl->address);
+ FREE(vl->title);
+ FREE(vl);
+ }
+ HTList_delete(Visited_Links);
+ Visited_Links = NULL;
+ return;
+}
+
+/*
+ * Utility for listing visited links, making any repeated
+ * links the most current in the list. - FM
+ */
+PUBLIC void LYAddVisitedLink ARGS1(
+ document *, doc)
+{
+ VisitedLink *new;
+ VisitedLink *old;
+ HTList *cur;
+
+ if (!(doc->address && *doc->address))
+ return;
+
+ /*
+ * Exclude POST or HEAD replies, and bookmark, menu
+ * or list files. - FM
+ */
+ if (doc->post_data || doc->isHEAD || doc->bookmark ||
+ !strcmp((doc->title ? doc->title : ""), HISTORY_PAGE_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), PRINT_OPTIONS_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), DOWNLOAD_OPTIONS_TITLE) ||
+#ifdef DIRED_SUPPORT
+ !strcmp((doc->title ? doc->title : ""), DIRED_MENU_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), UPLOAD_OPTIONS_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), PERMIT_OPTIONS_TITLE) ||
+#endif /* DIRED_SUPPORT */
+ !strcmp((doc->title ? doc->title : ""), CURRENT_KEYMAP_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), LIST_PAGE_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), SHOWINFO_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), COOKIE_JAR_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), VISITED_LINKS_TITLE) ||
+ !strcmp((doc->title ? doc->title : ""), LYNX_TRACELOG_TITLE)) {
+ return;
+ }
+
+ if ((new = (VisitedLink *)calloc(1, sizeof(*new))) == NULL)
+ outofmem(__FILE__, "HTAddVisitedLink");
+ StrAllocCopy(new->address, doc->address);
+ StrAllocCopy(new->title, (doc->title ? doc->title : "(no title)"));
+
+ if (!Visited_Links) {
+ Visited_Links = HTList_new();
+ atexit(Visited_Links_free);
+ HTList_addObject(Visited_Links, new);
+ return;
+ }
+
+ cur = Visited_Links;
+ while (NULL != (old = (VisitedLink *)HTList_nextObject(cur))) {
+ if (!strcmp((old->address ? old->address : ""),
+ (new->address ? new->address : "")) &&
+ !strcmp((old->title ? new->title : ""),
+ (new->title ? new->title : ""))) {
+ FREE(old->address);
+ FREE(old->title);
+ HTList_removeObject(Visited_Links, old);
+ FREE(old);
+ break;
+ }
+ }
+ HTList_addObject(Visited_Links, new);
+
+ return;
+}
+
+/*
+ * Push the current filename, link and line number onto the history list.
+ */
+PUBLIC void LYpush ARGS2(
+ document *, doc,
+ BOOLEAN, force_push)
+{
+ /*
+ * Don't push NULL file names.
+ */
+ if (*doc->address == '\0')
+ return;
+
+ /*
+ * Check whether this is a document we
+ * don't push unless forced. - FM
+ */
+ if (!force_push) {
+ /*
+ * Don't push the history, printer, or download lists.
+ */
+ if (!strcmp(doc->title, HISTORY_PAGE_TITLE) ||
+ !strcmp(doc->title, PRINT_OPTIONS_TITLE) ||
+ !strcmp(doc->title, DOWNLOAD_OPTIONS_TITLE)) {
+ if (!LYforce_no_cache)
+ LYoverride_no_cache = TRUE;
+ return;
+ }
+
+#ifdef DIRED_SUPPORT
+ /*
+ * Don't push DIRED menu, upload or permit lists.
+ */
+ if (!strcmp(doc->title, DIRED_MENU_TITLE) ||
+ !strcmp(doc->title, UPLOAD_OPTIONS_TITLE) ||
+ !strcmp(doc->title, PERMIT_OPTIONS_TITLE)) {
+ if (!LYforce_no_cache)
+ LYoverride_no_cache = TRUE;
+ return;
+ }
+#endif /* DIRED_SUPPORT */
+ }
+
+ /*
+ * If file is identical to one before it, don't push it.
+ */
+ if (nhist> 1 &&
+ STREQ(history[nhist-1].address, doc->address) &&
+ !strcmp(history[nhist-1].post_data ?
+ history[nhist-1].post_data : "",
+ doc->post_data ?
+ doc->post_data : "") &&
+ !strcmp(history[nhist-1].bookmark ?
+ history[nhist-1].bookmark : "",
+ doc->bookmark ?
+ doc->bookmark : "") &&
+ history[nhist-1].isHEAD == doc->isHEAD) {
+ if (history[nhist-1].internal_link == doc->internal_link) {
+ /* But it is nice to have the last position remembered!
+ - kw */
+ history[nhist-1].link = doc->link;
+ history[nhist-1].page = doc->line;
+ return;
+ }
+ }
+
+#ifdef NOTDEFINED
+/*
+** The following segment not used any more - What's it good for,
+** anyway?? Doing a pop when a push is requested is confusing,
+** also to the user. Moreover, the way it was done seems to cause
+** a memory leak. - KW
+*/ /*
+ * If file is identical to one two before it, don't push it.
+ */
+ if (nhist > 2 &&
+ STREQ(history[nhist-2].address, doc->address) &&
+ !strcmp(history[nhist-2].post_data ?
+ history[nhist-2].post_data : "",
+ doc->post_data ?
+ doc->post_data : "") &&
+ !strcmp(history[nhist-2].bookmark ?
+ history[nhist-2].bookmark : "",
+ doc->bookmark ?
+ doc->bookmark : "") &&
+ history[nhist-2].isHEAD == doc->isHEAD) {
+ /*
+ * Pop one off the stack.
+ */
+ nhist--;
+ return;
+ }
+#endif /* NOTDEFINED */
+
+ /*
+ * OK, push it if we have stack space.
+ */
+ if (nhist < MAXHIST) {
+ history[nhist].link = doc->link;
+ history[nhist].page = doc->line;
+ history[nhist].title = NULL;
+ StrAllocCopy(history[nhist].title, doc->title);
+ history[nhist].address = NULL;
+ StrAllocCopy(history[nhist].address, doc->address);
+ history[nhist].post_data = NULL;
+ StrAllocCopy(history[nhist].post_data, doc->post_data);
+ history[nhist].post_content_type = NULL;
+ StrAllocCopy(history[nhist].post_content_type, doc->post_content_type);
+ history[nhist].bookmark = NULL;
+ StrAllocCopy(history[nhist].bookmark, doc->bookmark);
+ history[nhist].isHEAD = doc->isHEAD;
+ history[nhist].safe = doc->safe;
+
+ history[nhist].internal_link = FALSE; /* by default */
+ history[nhist].intern_seq_start = -1; /* by default */
+ if (doc->internal_link) {
+ /* Now some tricky stuff: if the caller thinks that the doc
+ to push was the result of following an internal
+ (fragment) link, we check whether we believe it.
+ It is only accepted as valid if the immediately preceding
+ item on the history stack is actually the same document
+ except for fragment and location info. I.e. the Parent
+ Anchors are the same.
+ Also of course this requires that this is not the first
+ history item. - kw */
+ if (nhist > 0) {
+ DocAddress WWWDoc;
+ HTParentAnchor *thisparent, *thatparent = NULL;
+ WWWDoc.address = doc->address;
+ WWWDoc.post_data = doc->post_data;
+ WWWDoc.post_content_type = doc->post_content_type;
+ WWWDoc.bookmark = doc->bookmark;
+ WWWDoc.isHEAD = doc->isHEAD;
+ WWWDoc.safe = doc->safe;
+ thisparent =
+ HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ /* Now find the ParentAnchor for the previous history
+ ** item - kw
+ */
+ if (thisparent) {
+ /* If the last-pushed item is a LYNXIMGMAP but THIS one
+ ** isn't, compare the physical URLs instead. - kw
+ */
+ if (0==strncmp(history[nhist-1].address,"LYNXIMGMAP:",11) &&
+ 0!=strncmp(doc->address,"LYNXIMGMAP:",11)) {
+ WWWDoc.address = history[nhist-1].address + 11;
+ /*
+ ** If THIS item is a LYNXIMGMAP but the last-pushed one
+ ** isn't, fake it by using THIS item's address for
+ ** thatparent... - kw
+ */
+ } else if ((0==strncmp(doc->address,"LYNXIMGMAP:",11) &&
+ 0!=strncmp(history[nhist-1].address,"LYNXIMGMAP:",11))) {
+ char *temp = NULL;
+ StrAllocCopy(temp, "LYNXIMGMAP:");
+ StrAllocCat(temp, doc->address+11);
+ WWWDoc.address = temp;
+ WWWDoc.post_content_type = history[nhist-1].post_content_type;
+ WWWDoc.bookmark = history[nhist-1].bookmark;
+ WWWDoc.isHEAD = history[nhist-1].isHEAD;
+ WWWDoc.safe = history[nhist-1].safe;
+ thatparent =
+ HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ FREE(temp);
+ } else {
+ WWWDoc.address = history[nhist-1].address;
+ }
+ if (!thatparent) { /* if not yet done */
+ WWWDoc.post_data = history[nhist-1].post_data;
+ WWWDoc.post_content_type = history[nhist-1].post_content_type;
+ WWWDoc.bookmark = history[nhist-1].bookmark;
+ WWWDoc.isHEAD = history[nhist-1].isHEAD;
+ WWWDoc.safe = history[nhist-1].safe;
+ thatparent =
+ HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ }
+ /* In addition to equality of the ParentAnchors, require
+ ** that IF we have a HTMainText (i.e. it wasn't just
+ ** HTuncache'd by mainloop), THEN it has to be consistent
+ ** with what we are trying to push.
+ ** This may be overkill... - kw
+ */
+ if (thatparent == thisparent &&
+ (!HTMainText || HTMainAnchor == thisparent)
+ ) {
+ history[nhist].internal_link = TRUE;
+ history[nhist].intern_seq_start =
+ history[nhist-1].intern_seq_start >= 0 ?
+ history[nhist-1].intern_seq_start : nhist-1;
+ if (TRACE) {
+ fprintf(stderr,
+ "\nLYpush: pushed as internal link, OK\n");
+ }
+ }
+ }
+ }
+ if (!history[nhist].internal_link) {
+ if (TRACE) {
+ fprintf(stderr,
+ "\nLYpush: push as internal link requested, %s\n",
+ "but didn't check out!");
+ }
+ }
+ }
+ nhist++;
+ if (TRACE) {
+ fprintf(stderr,
+ "\nLYpush: address:%s\n title:%s\n",
+ doc->address, doc->title);
+ }
+ } else {
+ if (LYCursesON) {
+ _statusline(MAXHIST_REACHED);
+ sleep(AlertSecs);
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "\nLYpush: MAXHIST reached for:\n address:%s\n title:%s\n",
+ doc->address, doc->title);
+ }
+ }
+}
+
+/*
+ * Pop the previous filename, link and line number from the history list.
+ */
+PUBLIC void LYpop ARGS1(
+ document *, doc)
+{
+ if (nhist > 0) {
+ nhist--;
+ doc->link = history[nhist].link;
+ doc->line = history[nhist].page;
+ FREE(doc->title);
+ doc->title = history[nhist].title; /* will be freed later */
+ FREE(doc->address);
+ doc->address = history[nhist].address; /* will be freed later */
+ FREE(doc->post_data);
+ doc->post_data = history[nhist].post_data;
+ FREE(doc->post_content_type);
+ doc->post_content_type = history[nhist].post_content_type;
+ FREE(doc->bookmark);
+ doc->bookmark = history[nhist].bookmark; /* will be freed later */
+ doc->isHEAD = history[nhist].isHEAD;
+ doc->safe = history[nhist].safe;
+ doc->internal_link = history[nhist].internal_link;
+ if (TRACE) {
+ fprintf(stderr,
+ "LYpop: address:%s\n title:%s\n",
+ doc->address, doc->title);
+ }
+ }
+}
+
+/*
+ * Pop the specified hist entry, link and line number from the history
+ * list but don't actually remove the entry, just return it.
+ * (This procedure is badly named :)
+ */
+PUBLIC void LYpop_num ARGS2(
+ int, number,
+ document *, doc)
+{
+ if (number >= 0 && nhist > number) {
+ doc->link = history[number].link;
+ doc->line = history[number].page;
+ StrAllocCopy(doc->title, history[number].title);
+ StrAllocCopy(doc->address, history[number].address);
+ StrAllocCopy(doc->post_data, history[number].post_data);
+ StrAllocCopy(doc->post_content_type, history[number].post_content_type);
+ StrAllocCopy(doc->bookmark, history[number].bookmark);
+ doc->isHEAD = history[number].isHEAD;
+ doc->safe = history[number].safe;
+ doc->internal_link = history[number].internal_link; /* ?? */
+ }
+}
+
+/*
+ * This procedure outputs the history buffer into a temporary file.
+ */
+PUBLIC int showhistory ARGS1(
+ char **, newfile)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ static char hist_filename[256];
+ char *Title = NULL;
+ int x = 0;
+ FILE *fp0;
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ /*
+ * Make the file a URL now.
+ */
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(hist_filename,"file://localhost/%s", tempfile);
+#else
+ sprintf(hist_filename,"file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(-1);
+ }
+
+ StrAllocCopy(*newfile, hist_filename);
+ LYforce_HTML_mode = TRUE; /* force this file to be HTML */
+ LYforce_no_cache = TRUE; /* force this file to be new */
+
+ fprintf(fp0, "<head>\n");
+ LYAddMETAcharsetToFD(fp0, -1);
+ fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
+ HISTORY_PAGE_TITLE);
+ fprintf(fp0, "<h1>You have reached the History Page</h1>\n");
+ fprintf(fp0, "<h2>%s Version %s</h2>\n<pre>", LYNX_NAME, LYNX_VERSION);
+ fprintf(fp0, "<em>You selected:</em>\n");
+ for (x = nhist-1; x >= 0; x--) {
+ /*
+ * The number of the document in the hist stack,
+ * its title in a link, and its address. - FM
+ */
+ if (history[x].title != NULL) {
+ StrAllocCopy(Title, history[x].title);
+ LYEntify(&Title, TRUE);
+ } else {
+ StrAllocCopy(Title, "(no title)");
+ }
+ fprintf(fp0,
+ "%s<em>%d</em>. <tab id=t%d><a href=\"LYNXHIST:%d\">%s</a>\n",
+ (x > 99 ? "" : x < 10 ? " " : " "),
+ x, x, x, Title);
+ if (history[x].address != NULL) {
+ StrAllocCopy(Title, history[x].address);
+ LYEntify(&Title, TRUE);
+ } else {
+ StrAllocCopy(Title, "(no address)");
+ }
+ if (history[x].internal_link) {
+ if (history[x].intern_seq_start == history[nhist-1].intern_seq_start)
+ StrAllocCat(Title, " (internal)");
+ else
+ StrAllocCat(Title, " (was internal)");
+ }
+ fprintf(fp0, "<tab to=t%d>%s\n", x, Title);
+ }
+
+ fprintf(fp0,"</pre>\n</body>\n");
+
+ fclose(fp0);
+ FREE(Title);
+ return(0);
+}
+
+/*
+ * This function makes the history page seem like any other type of
+ * file since more info is needed than can be provided by the normal
+ * link structure. We saved out the history number to a special URL.
+ * The info looks like: LYNXHIST:#
+ */
+PUBLIC BOOLEAN historytarget ARGS1(
+ document *, newdoc)
+{
+ int number;
+ DocAddress WWWDoc;
+ HTParentAnchor *tmpanchor;
+ HText *text;
+ BOOLEAN treat_as_intern = FALSE;
+
+ if ((!newdoc || !newdoc->address) ||
+ strlen(newdoc->address) < 10 || !isdigit(*(newdoc->address+9)))
+ return(FALSE);
+
+ if ((number = atoi(newdoc->address+9)) > nhist || number < 0)
+ return(FALSE);
+
+ LYpop_num(number, newdoc);
+ if (((newdoc->internal_link &&
+ history[number].intern_seq_start == history[nhist-1].intern_seq_start) ||
+ (number < nhist-1 &&
+ history[nhist-1].internal_link &&
+ number == history[nhist-1].intern_seq_start))
+ && !(LYforce_no_cache == TRUE && LYoverride_no_cache == FALSE)) {
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ LYforce_no_cache = FALSE;
+ LYinternal_flag = TRUE;
+ newdoc->internal_link = TRUE;
+ treat_as_intern = TRUE;
+#endif
+ } else {
+ newdoc->internal_link = FALSE;
+ }
+ /*
+ * If we have POST content, and have LYresubmit_posts set
+ * or have no_cache set or do not still have the text cached,
+ * ask the user whether to resubmit the form. - FM
+ */
+ if (newdoc->post_data != NULL) {
+ WWWDoc.address = newdoc->address;
+ WWWDoc.post_data = newdoc->post_data;
+ WWWDoc.post_content_type = newdoc->post_content_type;
+ WWWDoc.bookmark = newdoc->bookmark;
+ WWWDoc.isHEAD = newdoc->isHEAD;
+ WWWDoc.safe = newdoc->safe;
+ tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ text = (HText *)HTAnchor_document(tmpanchor);
+ if (((((LYresubmit_posts == TRUE) ||
+ (LYforce_no_cache == TRUE &&
+ LYoverride_no_cache == FALSE)) &&
+ !(treat_as_intern && !reloading)) ||
+ text == NULL) &&
+ (!strncmp(newdoc->address, "LYNXIMGMAP:", 11) ||
+ HTConfirm(CONFIRM_POST_RESUBMISSION) == TRUE)) {
+ LYforce_no_cache = TRUE;
+ LYoverride_no_cache = FALSE;
+ } else if (text != NULL) {
+ LYforce_no_cache = FALSE;
+ LYoverride_no_cache = TRUE;
+ } else {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(FALSE);
+ }
+ }
+
+ if (number != 0)
+ StrAllocCat(newdoc->title," (From History)");
+ return(TRUE);
+}
+
+/*
+ * This procedure outputs the Visited Links
+ * list into a temporary file. - FM
+ */
+PUBLIC int LYShowVisitedLinks ARGS1(
+ char **, newfile)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ static char vl_filename[256];
+ char *Title = NULL;
+ char *Address = NULL;
+ int x;
+ FILE *fp0;
+ VisitedLink *vl;
+ HTList *cur = Visited_Links;
+
+ if (!cur)
+ return(-1);
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ /*
+ * Make the file a URL now.
+ */
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(vl_filename,"file://localhost/%s", tempfile);
+#else
+ sprintf(vl_filename,"file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(-1);
+ }
+
+ StrAllocCopy(*newfile, vl_filename);
+ LYforce_HTML_mode = TRUE; /* force this file to be HTML */
+ LYforce_no_cache = TRUE; /* force this file to be new */
+
+ fprintf(fp0, "<head>\n");
+ LYAddMETAcharsetToFD(fp0, -1);
+ fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
+ VISITED_LINKS_TITLE);
+ fprintf(fp0, "<h1>You have reached the Visited Links Page</h1>\n");
+ fprintf(fp0, "<h2>%s Version %s</h2>\n<pre>", LYNX_NAME, LYNX_VERSION);
+ fprintf(fp0,
+ "<em>You visited (POSTs, bookmark, menu and list files excluded):</em>\n");
+ x = HTList_count(Visited_Links);
+ while (NULL != (vl = (VisitedLink *)HTList_nextObject(cur))) {
+ /*
+ * The number of the document (most recent highest),
+ * its title in a link, and its address. - FM
+ */
+ x--;
+ if (vl->title != NULL && *vl->title != '\0') {
+ StrAllocCopy(Title, vl->title);
+ LYEntify(&Title, TRUE);
+ } else {
+ StrAllocCopy(Title , "(no title)");
+ }
+ if (vl->address != NULL && *vl->address != '\0') {
+ StrAllocCopy(Address, vl->address);
+ LYEntify(&Address, FALSE);
+ fprintf(fp0,
+ "%s<em>%d</em>. <tab id=t%d><a href=\"%s\">%s</a>\n",
+ (x > 99 ? "" : x < 10 ? " " : " "),
+ x, x, Address, Title);
+ } else {
+ fprintf(fp0,
+ "%s<em>%d</em>. <tab id=t%d><em>%s</em>\n",
+ (x > 99 ? "" : x < 10 ? " " : " "),
+ x, x, Title);
+ }
+ if (Address != NULL) {
+ StrAllocCopy(Address, vl->address);
+ LYEntify(&Address, TRUE);
+ }
+ fprintf(fp0, "<tab to=t%d>%s\n", x,
+ ((Address != NULL) ? Address : "(no address)"));
+ }
+
+ fprintf(fp0,"</pre>\n</body>\n");
+
+ fclose(fp0);
+ FREE(Title);
+ FREE(Address);
+ return(0);
+}
diff --git a/gnu/usr.bin/lynx/src/LYHistory.h b/gnu/usr.bin/lynx/src/LYHistory.h
new file mode 100644
index 00000000000..caac9605f58
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYHistory.h
@@ -0,0 +1,20 @@
+
+#ifndef LYHISTORY_H
+#define LYHISTORY_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern void LYAddVisitedLink PARAMS((document *doc));
+extern void LYpush PARAMS((document *doc, BOOLEAN force_push));
+extern void LYpop PARAMS((document *doc));
+extern void LYpop_num PARAMS((int number, document *doc));
+extern int showhistory PARAMS((char **newfile));
+extern BOOLEAN historytarget PARAMS((document *newdoc));
+extern int LYShowVisitedLinks PARAMS((char **newfile));
+
+#define HISTORY_PAGE_TITLE "Lynx History Page"
+#define VISITED_LINKS_TITLE "Lynx Visited Links Page"
+
+#endif /* LYHISTORY_H */
diff --git a/gnu/usr.bin/lynx/src/LYJump.c b/gnu/usr.bin/lynx/src/LYJump.c
new file mode 100644
index 00000000000..e01000992b4
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYJump.c
@@ -0,0 +1,498 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "LYJump.h"
+#include "LYKeymap.h"
+#include "LYSignal.h"
+#include "GridText.h"
+
+#include "LYLeaks.h"
+
+#ifdef VMS
+#include <fab.h>
+#endif /* VMS */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+struct JumpTable *JThead = NULL;
+
+PRIVATE int LYCompare PARAMS ((CONST void *e1, CONST void *e2));
+PRIVATE unsigned LYRead_Jumpfile PARAMS ((struct JumpTable *jtp));
+
+PUBLIC void LYJumpTable_free NOARGS
+{
+ struct JumpTable *cur = JThead;
+ struct JumpTable *next;
+
+ while (cur) {
+ next = cur->next;
+ FREE(cur->msg);
+ FREE(cur->file);
+ FREE(cur->shortcut);
+ if (cur->history) {
+ char *shortcut;
+ HTList *current = cur->history;
+
+ while (NULL != (shortcut = (char *)HTList_nextObject(current))) {
+ FREE(shortcut);
+ }
+ HTList_delete(cur->history);
+ cur->history = NULL;
+ }
+ FREE(cur->table);
+ FREE(cur->mp);
+ FREE(cur);
+ cur = next;
+ }
+ JThead = NULL;
+ return;
+}
+
+/*
+ * Utility for listing shortcuts, making any repeated
+ * shortcut the most current in the list. - FM
+ */
+PUBLIC void LYAddJumpShortcut ARGS2(HTList *, historyp, char *,shortcut)
+{
+ char *new;
+ char *old;
+ HTList *cur = historyp;
+
+ if (!historyp || !(shortcut && *shortcut))
+ return;
+
+ if ((new = (char *)calloc(1, (strlen(shortcut) + 1))) == NULL)
+ outofmem(__FILE__, "HTAddJumpShortcut");
+ strcpy(new, shortcut);
+
+ while (NULL != (old = (char *)HTList_nextObject(cur))) {
+ if (!strcmp(old, new)) {
+ HTList_removeObject(historyp, old);
+ FREE(old);
+ break;
+ }
+ }
+ HTList_addObject(historyp, new);
+
+ return;
+}
+
+PUBLIC BOOL LYJumpInit ARGS1 (char *, config)
+{
+ struct JumpTable *jtp;
+ char *cp;
+
+ /*
+ * Create a JumpTable structure.
+ */
+ jtp = (struct JumpTable *) calloc(1, sizeof(*jtp));
+ if (jtp == NULL) {
+ perror("Out of memory in LYJumpInit");
+ return FALSE;
+ }
+
+ /*
+ * config is JUMPFILE:path[:optional_key[:optional_prompt]]
+ *
+ * Skip JUMPFILE.
+ */
+ cp = strtok(config, ":\n");
+ if (!cp) {
+ FREE(jtp);
+ return FALSE;
+ }
+
+ /*
+ * Get the path.
+ */
+ cp = strtok(NULL, ":\n");
+ if (!cp) {
+ FREE(jtp);
+ return FALSE;
+ }
+ StrAllocCopy(jtp->file, cp);
+ if (!JThead)
+ atexit(LYJumpTable_free);
+
+ /*
+ * Get the key, if present.
+ */
+ cp = strtok(NULL, ":\n");
+
+ /*
+ * If no key, check whether we are resetting the default jumps file.
+ */
+ if (!cp && JThead) {
+ struct JumpTable *jtptmp = JThead;
+ jumpfile = jtp->file;
+ FREE(jtp);
+ while (jtptmp && jtptmp->key)
+ jtptmp = jtptmp->next;
+ if (!jtptmp)
+ return FALSE;
+ StrAllocCopy(jtptmp->file, jumpfile);
+ StrAllocCopy(jtptmp->msg, jumpprompt);
+ return TRUE;
+ }
+
+ /*
+ * If a key is present and we have no default, create one,
+ * using the path from config, and the current jumpprompt.
+ */
+ if (cp && !JThead) {
+ JThead = jtp;
+ StrAllocCopy(JThead->msg, jumpprompt);
+ if (!jumpfile)
+ StrAllocCopy(jumpfile, JThead->file);
+ jtp = (struct JumpTable *) calloc(1, sizeof(*jtp));
+ if (jtp == NULL) {
+ perror("Out of memory in LYJumpInit");
+ return FALSE;
+ }
+ StrAllocCopy(jtp->file, JThead->file);
+ }
+
+ /*
+ * Complete the initialization of config.
+ */
+ if (cp) {
+ jtp->key = remap(cp, "JUMP"); /* key is present, (re)map it */
+ cp = strtok(NULL, "\n"); /* get prompt, if present */
+ if (cp && *cp)
+ StrAllocCopy(jtp->msg, cp); /* prompt is present, load it */
+ else
+ cp = NULL;
+ }
+ if (!cp) /* no prompt, use default */
+ StrAllocCopy(jtp->msg, jumpprompt);
+ if (jtp->msg[strlen(jtp->msg)-1] != ' ') /* ensure a trailing space */
+ StrAllocCat(jtp->msg, " ");
+ jtp->history = HTList_new();
+ jtp->next = JThead;
+ JThead = jtp;
+ return TRUE;
+}
+
+PUBLIC char *LYJump ARGS1(int, key)
+{
+ JumpDatum seeking;
+ JumpDatum *found;
+ static char buf[124];
+ char *bp, *cp;
+ struct JumpTable *jtp;
+ int ch, recall;
+ int ShortcutTotal;
+ int ShortcutNum;
+ BOOLEAN FirstShortcutRecall = TRUE;
+
+ if (!JThead)
+ return NULL;
+ jtp = JThead;
+ while (jtp && jtp->key && jtp->key != key)
+ jtp = jtp->next;
+ if (!jtp) {
+ char msg[40];
+ sprintf(msg, KEY_NOT_MAPPED_TO_JUMP_FILE, key);
+ HTAlert(msg);
+ return NULL;
+ }
+ if (!jtp->table)
+ jtp->nel = LYRead_Jumpfile(jtp);
+ if (jtp->nel == 0)
+ return NULL;
+
+ if (!jump_buffer || !(jtp->shortcut && *jtp->shortcut))
+ *buf = '\0';
+ else if (jtp->shortcut && *jtp->shortcut) {
+ if (strlen(jtp->shortcut) > 119)
+ jtp->shortcut[119] = '\0';
+ strcpy(buf, jtp->shortcut);
+ }
+
+ ShortcutTotal = (jtp->history ? HTList_count(jtp->history) : 0);
+ if (jump_buffer && *buf) {
+ recall = ((ShortcutTotal > 1) ? RECALL : NORECALL);
+ ShortcutNum = 0;
+ FirstShortcutRecall = FALSE;
+ } else {
+ recall = ((ShortcutTotal >= 1) ? RECALL : NORECALL);
+ ShortcutNum = ShortcutTotal;
+ FirstShortcutRecall = TRUE;
+ }
+
+ statusline(jtp->msg);
+ if ((ch=LYgetstr(buf, VISIBLE, (sizeof(buf) - 4), recall)) < 0) {
+ /*
+ * User cancelled the Jump via ^G. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return NULL;
+ }
+
+check_recall:
+ bp = buf;
+ if (toupper(key) == 'G' && strncmp(buf, "o ", 2) == 0)
+ bp++;
+ while (isspace(*bp))
+ bp++;
+ if (*bp == '\0' &&
+ !(recall && (ch == UPARROW || ch == DNARROW))) {
+ /*
+ * User cancelled the Jump via a zero-length string. - FM
+ */
+ *buf = '\0';
+ StrAllocCopy(jtp->shortcut, buf);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return NULL;
+ }
+#ifdef PERMIT_GOTO_FROM_JUMP
+ if (strchr(bp, ':') || strchr(bp, '/')) {
+ char *temp=NULL;
+
+ LYJumpFileURL = FALSE;
+ if (no_goto) {
+ *buf = '\0';
+ StrAllocCopy(jtp->shortcut, buf);
+ _statusline(RANDOM_URL_DISALLOWED);
+ sleep(MessageSecs);
+ return NULL;
+ }
+ StrAllocCopy(temp, "Go ");
+ StrAllocCat(temp, bp);
+ strcpy(buf, temp);
+ FREE(temp);
+ return(bp=buf);
+ }
+#endif /* PERMIT_GOTO_FROM_JUMP */
+
+ if (recall && ch == UPARROW) {
+ if (FirstShortcutRecall) {
+ /*
+ * Use last Shortcut in the list. - FM
+ */
+ FirstShortcutRecall = FALSE;
+ ShortcutNum = 0;
+ } else {
+ /*
+ * Go back to the previous Shortcut in the list. - FM
+ */
+ ShortcutNum++;
+ }
+ if (ShortcutNum >= ShortcutTotal)
+ /*
+ * Roll around to the last Shortcut in the list. - FM
+ */
+ ShortcutNum = 0;
+ if ((cp=(char *)HTList_objectAt(jtp->history,
+ ShortcutNum)) != NULL) {
+ strcpy(buf, cp);
+ if (jump_buffer && jtp->shortcut &&
+ !strcmp(buf, jtp->shortcut)) {
+ _statusline(EDIT_CURRENT_SHORTCUT);
+ } else if ((jump_buffer && ShortcutTotal == 2) ||
+ (!jump_buffer && ShortcutTotal == 1)) {
+ _statusline(EDIT_THE_PREV_SHORTCUT);
+ } else {
+ _statusline(EDIT_A_PREV_SHORTCUT);
+ }
+ if ((ch=LYgetstr(buf, VISIBLE,
+ sizeof(buf), recall)) < 0) {
+ /*
+ * User cancelled the jump via ^G.
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return NULL;
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstShortcutRecall) {
+ /*
+ * Use the first Shortcut in the list. - FM
+ */
+ FirstShortcutRecall = FALSE;
+ ShortcutNum = ShortcutTotal - 1;
+ } else {
+ /*
+ * Advance to the next Shortcut in the list. - FM
+ */
+ ShortcutNum--;
+ }
+ if (ShortcutNum < 0)
+ /*
+ * Roll around to the first Shortcut in the list. - FM
+ */
+ ShortcutNum = ShortcutTotal - 1;
+ if ((cp=(char *)HTList_objectAt(jtp->history,
+ ShortcutNum)) != NULL) {
+ strcpy(buf, cp);
+ if (jump_buffer && jtp->shortcut &&
+ !strcmp(buf, jtp->shortcut)) {
+ _statusline(EDIT_CURRENT_SHORTCUT);
+ } else if ((jump_buffer && ShortcutTotal == 2) ||
+ (!jump_buffer && ShortcutTotal == 1)) {
+ _statusline(EDIT_THE_PREV_SHORTCUT);
+ } else {
+ _statusline(EDIT_THE_PREV_SHORTCUT);
+ }
+ if ((ch=LYgetstr(buf, VISIBLE,
+ sizeof(buf), recall)) < 0) {
+ /*
+ * User cancelled the jump via ^G.
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return NULL;
+ }
+ goto check_recall;
+ }
+ }
+
+ seeking.key = bp;
+ found = (JumpDatum *)bsearch((char *)&seeking, (char *)jtp->table,
+ jtp->nel, sizeof(JumpDatum), LYCompare);
+ if (!found) {
+ user_message("Unknown target '%s'", buf);
+ sleep(AlertSecs);
+ }
+
+ StrAllocCopy(jtp->shortcut, bp);
+ LYAddJumpShortcut(jtp->history, jtp->shortcut);
+ return found ? found->url : NULL;
+}
+
+PRIVATE unsigned LYRead_Jumpfile ARGS1(struct JumpTable *,jtp)
+{
+ struct stat st;
+ unsigned int nel;
+ char *mp;
+ int fd;
+#ifdef VMS
+ FILE *fp;
+ BOOL IsStream_LF = TRUE;
+#endif /* VMS */
+ char *cp;
+ unsigned i;
+
+ if (jtp->file == NULL || *(jtp->file) == '\0')
+ return 0;
+ if (stat(jtp->file, &st) < 0) {
+ HTAlert(CANNOT_LOCATE_JUMP_FILE);
+ return 0;
+ }
+
+ /* allocate storage to read entire file */
+ if ((mp=(char *)calloc(1, st.st_size + 1)) == NULL) {
+ HTAlert(OUTOF_MEM_FOR_JUMP_FILE);
+ return 0;
+ }
+
+#ifdef VMS
+ if (st.st_fab_rfm != (char)FAB$C_STMLF) {
+ /** It's a record-oriented file. **/
+ IsStream_LF = FALSE;
+ if ((fp = fopen(jtp->file, "r", "mbc=32")) == NULL) {
+ HTAlert(CANNOT_OPEN_JUMP_FILE);
+ FREE(mp);
+ return 0;
+ }
+ } else
+ if ((fd=open(jtp->file, O_RDONLY, "mbc=32")) < 0) {
+#else
+ if ((fd=open(jtp->file, O_RDONLY)) < 0) {
+#endif /* VMS */
+ HTAlert(CANNOT_OPEN_JUMP_FILE);
+ FREE(mp);
+ return 0;
+ }
+
+#ifdef VMS
+ if (IsStream_LF) {
+ /** Handle as a stream. **/
+#endif /* VMS */
+ if (read(fd, mp, st.st_size) < st.st_size) {
+ HTAlert(ERROR_READING_JUMP_FILE);
+ FREE(mp);
+ return 0;
+ }
+ mp[st.st_size] = '\0';
+ close(fd);
+#ifdef VMS
+ } else {
+ /** Handle as a series of records. **/
+ if(fgets(mp, 1024, fp) == NULL) {
+ HTAlert(ERROR_READING_JUMP_FILE);
+ FREE(mp);
+ return 0;
+ } else
+ while(fgets(mp+strlen(mp), 1024, fp) != NULL) ;
+ fclose(fp);
+ }
+#endif /* VMS */
+
+ /* quick scan for approximate number of entries */
+ nel = 0;
+ cp = mp;
+ while((cp = strchr(cp, '\n')) != NULL) {
+ nel++;
+ cp++;
+ }
+
+ jtp->table = (JumpDatum *)malloc(nel * sizeof(JumpDatum));
+ if (jtp->table == NULL) {
+ HTAlert(OUTOF_MEM_FOR_JUMP_TABLE);
+ FREE(mp);
+ return 0;
+ }
+
+ cp = jtp->mp = mp;
+ for (i = 0; i < nel; ) {
+ if (strncmp(cp, "<!--", 4) == 0 || strncmp(cp, "<dl>", 4) == 0) {
+ cp = strchr(cp, '\n');
+ if (cp == NULL)
+ break;
+ cp++;
+ continue;
+ }
+ cp = LYstrstr(cp, "<dt>");
+ if (cp == NULL)
+ break;
+ cp += 4;
+ jtp->table[i].key = cp;
+ cp = LYstrstr(cp, "<dd>");
+ if (cp == NULL)
+ break;
+ *cp = '\0';
+ cp += 4;
+ cp = LYstrstr(cp, "href=\"");
+ if (cp == NULL)
+ break;
+ cp += 6;
+ jtp->table[i].url = cp;
+ cp = strchr(cp, '"');
+ if (cp == NULL)
+ break;
+ *cp = '\0';
+ cp++;
+ cp = strchr(cp, '\n');
+ if (cp == NULL)
+ break;
+ cp++;
+ i++;
+ if (!cp)
+ break;
+ }
+
+ return i;
+}
+
+PRIVATE int LYCompare ARGS2 (CONST void *, e1, CONST void *, e2)
+{
+ return strcasecomp(((CONST JumpDatum *)e1)->key, ((CONST JumpDatum *)e2)->key);
+}
diff --git a/gnu/usr.bin/lynx/src/LYJump.h b/gnu/usr.bin/lynx/src/LYJump.h
new file mode 100644
index 00000000000..5da8f885be6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYJump.h
@@ -0,0 +1,29 @@
+
+#ifndef LYJUMP_H
+#define LYJUMP_H
+
+typedef struct _JumpDatum {
+ char *key;
+ char *url;
+} JumpDatum;
+
+struct JumpTable {
+ int key;
+ int nel;
+ char *msg;
+ char *file;
+ char *shortcut;
+ HTList *history;
+ JumpDatum *table;
+ struct JumpTable *next;
+ char *mp;
+};
+
+extern struct JumpTable *JThead;
+extern void LYJumpTable_free NOPARAMS;
+extern void LYAddJumpShortcut PARAMS((HTList *the_history, char *shortcut));
+extern BOOL LYJumpInit PARAMS((char *config));
+extern char *LYJump PARAMS((int key));
+
+#endif /* LYJUMP_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYKeymap.c b/gnu/usr.bin/lynx/src/LYKeymap.c
new file mode 100644
index 00000000000..bd70042bf4e
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYKeymap.c
@@ -0,0 +1,817 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYUtils.h"
+#include "LYKeymap.h"
+#include "LYGlobalDefs.h"
+#include "HTAccess.h"
+#include "HTFormat.h"
+#include "HTAlert.h"
+
+#include "LYLeaks.h"
+
+PRIVATE CONST DocAddress keymap_anchor = {"LYNXKEYMAP", NULL, NULL};
+
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+/* the character gets 1 added to it before lookup,
+ * so that EOF maps to 0
+ */
+char keymap[] = {
+
+0,
+/* EOF */
+
+0, LYK_HOME, LYK_PREV_PAGE, 0,
+/* nul */ /* ^A */ /* ^B */ /* ^C */
+
+LYK_ABORT, LYK_END, LYK_NEXT_PAGE, 0,
+/* ^D */ /* ^E */ /* ^F */ /* ^G */
+
+LYK_HISTORY, LYK_NEXT_LINK, LYK_ACTIVATE, LYK_COOKIE_JAR,
+/* bs */ /* ht */ /* nl */ /* ^K */
+
+LYK_REFRESH, LYK_ACTIVATE, LYK_DOWN_TWO, 0,
+/* ^L */ /* cr */ /* ^N */ /* ^O */
+
+LYK_UP_TWO, 0, LYK_RELOAD, 0,
+/* ^P */ /* XON */ /* ^R */ /* XOFF */
+
+#ifdef NOT_USED
+LYK_TRACE_TOGGLE, 0, LYK_VERSION, LYK_REFRESH,
+/* ^T */ /* ^U */ /* ^V */ /* ^W */
+#endif /* NOT_USED */
+LYK_TRACE_TOGGLE, 0, LYK_SWITCH_DTD, LYK_REFRESH,
+/* ^T */ /* ^U */ /* ^V */ /* ^W */
+
+0, 0, 0, 0,
+/* ^X */ /* ^Y */ /* ^Z */ /* ESC */
+
+0, 0, 0, 0,
+/* ^\ */ /* ^] */ /* ^^ */ /* ^_ */
+
+LYK_NEXT_PAGE, LYK_SHELL, LYK_SOFT_DQUOTES, LYK_TOOLBAR,
+/* sp */ /* ! */ /* " */ /* # */
+
+0, 0, 0, LYK_HISTORICAL,
+/* $ */ /* % */ /* & */ /* ' */
+
+LYK_UP_HALF, LYK_DOWN_HALF, LYK_IMAGE_TOGGLE, LYK_NEXT_PAGE,
+/* ( */ /* ) */ /* * */ /* + */
+
+#ifndef USE_EXTERNALS
+LYK_NEXT_PAGE, LYK_PREV_PAGE, 0, LYK_WHEREIS,
+/* , */ /* - */ /* . */ /* / */
+#else
+LYK_NEXT_PAGE, LYK_PREV_PAGE, LYK_EXTERN, LYK_WHEREIS,
+/* , */ /* - */ /* . */ /* / */
+#endif
+
+LYK_F_LINK_NUM, LYK_1, LYK_2, LYK_3,
+/* 0 */ /* 1 */ /* 2 */ /* 3 */
+
+LYK_4, LYK_5, LYK_6, LYK_7,
+/* 4 */ /* 5 */ /* 6 */ /* 7 */
+
+LYK_8, LYK_9, 0, LYK_TRACE_LOG,
+/* 8 */ /* 9 */ /* : */ /* ; */
+
+LYK_UP_LINK, LYK_INFO, LYK_DOWN_LINK, LYK_HELP,
+/* < */ /* = */ /* > */ /* ? */
+
+LYK_RAW_TOGGLE, LYK_ADD_BOOKMARK, LYK_PREV_PAGE, LYK_COMMENT,
+/* @ */ /* A */ /* B */ /* C */
+
+LYK_DOWNLOAD, LYK_ELGOTO,
+/* D */ /* E */
+
+#if defined(DIRED_SUPPORT) || defined(VMS)
+LYK_DIRED_MENU,
+#else
+0,
+#endif /* DIRED_SUPPORT || VMS */
+/* F */
+
+LYK_ECGOTO,
+/* G */
+
+LYK_HELP, LYK_INDEX, LYK_JUMP, LYK_KEYMAP,
+/* H */ /* I */ /* J */ /* K */
+
+LYK_LIST, LYK_MAIN_MENU, LYK_NEXT, LYK_OPTIONS,
+/* L */ /* M */ /* N */ /* O */
+
+LYK_PRINT, LYK_ABORT, LYK_DEL_BOOKMARK, LYK_INDEX_SEARCH,
+/* P */ /* Q */ /* R */ /* S */
+
+#ifdef DIRED_SUPPORT
+LYK_TAG_LINK,
+#else
+0,
+#endif /* DIRED_SUPPORT */
+/* T */
+
+ LYK_PREV_DOC, LYK_VLINKS, 0,
+ /* U */ /* V */ /* W */
+
+#ifdef NOT_USED
+LYK_FORM_UP, 0, LYK_FORM_DOWN, LYK_INLINE_TOGGLE,
+/* X */ /* Y */ /* Z */ /* [ */
+#endif /* NOT_USED */
+LYK_NOCACHE, 0, LYK_INTERRUPT, LYK_INLINE_TOGGLE,
+/* X */ /* Y */ /* Z */ /* [ */
+
+LYK_SOURCE, LYK_HEAD, 0, LYK_CLEAR_AUTH,
+/* \ */ /* ] */ /* ^ */ /* _ */
+
+LYK_MINIMAL, LYK_ADD_BOOKMARK, LYK_PREV_PAGE, LYK_COMMENT,
+/* ` */ /* a */ /* b */ /* c */
+
+LYK_DOWNLOAD, LYK_EDIT,
+/* d */ /* e */
+
+#if defined(DIRED_SUPPORT) || defined(VMS)
+LYK_DIRED_MENU,
+#else
+0,
+#endif /* DIRED_SUPPORT || VMS */
+/* f */
+
+LYK_GOTO,
+/* g */
+
+LYK_HELP, LYK_INDEX, LYK_JUMP, LYK_KEYMAP,
+/* h */ /* i */ /* j */ /* k */
+
+LYK_LIST, LYK_MAIN_MENU, LYK_NEXT, LYK_OPTIONS,
+/* l */ /* m */ /* n */ /* o */
+
+LYK_PRINT, LYK_QUIT, LYK_DEL_BOOKMARK, LYK_INDEX_SEARCH,
+/* p */ /* q */ /* r */ /* s */
+
+#ifdef DIRED_SUPPORT
+LYK_TAG_LINK,
+#else
+0,
+#endif /* DIRED_SUPPORT */
+/* t */
+
+ LYK_PREV_DOC, LYK_VIEW_BOOKMARK, 0,
+ /* u */ /* v */ /* w */
+
+#ifdef NOT_USED
+LYK_FORM_UP, 0, LYK_FORM_DOWN, 0,
+/* x */ /* y */ /* z */ /* { */
+#endif /* NOT_USED */
+LYK_NOCACHE, 0, LYK_INTERRUPT, 0,
+/* x */ /* y */ /* z */ /* { */
+
+LYK_PIPE, 0, 0, LYK_HISTORY,
+/* | */ /* } */ /* ~ */ /* del */
+
+/* 80..9F (illegal ISO-8859-1) 8-bit characters. */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+
+/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+
+/* 100..10E function key definitions in LYStrings.h */
+LYK_PREV_LINK, LYK_NEXT_LINK, LYK_ACTIVATE, LYK_PREV_DOC,
+/* UPARROW */ /* DNARROW */ /* RTARROW */ /* LTARROW */
+
+LYK_NEXT_PAGE, LYK_PREV_PAGE, LYK_HOME, LYK_END,
+/* PGDOWN */ /* PGUP */ /* HOME */ /* END */
+
+LYK_HELP, LYK_ACTIVATE, LYK_HOME, LYK_END,
+/* F1*/ /* Do key */ /* Find key */ /* Select key */
+
+LYK_UP_TWO, LYK_DOWN_TWO,
+/* Insert key */ /* Remove key */
+
+LYK_DO_NOTHING,
+/* DO_NOTHING*/
+};
+
+#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
+/*
+ * This table is used to override the standard keyboard assignments
+ * when lynx_edit_mode is in effect and keyboard overrides have been
+ * allowed at compile time.
+ */
+
+char override[] = {
+
+ 0,
+/* EOF */
+
+ 0, 0, 0, 0,
+/* nul */ /* ^A */ /* ^B */ /* ^C */
+
+ 0, 0, 0, 0,
+/* ^D */ /* ^E */ /* ^F */ /* ^G */
+
+ 0, 0, 0, 0,
+/* bs */ /* ht */ /* nl */ /* ^K */
+
+ 0, 0, 0, 0,
+/* ^L */ /* cr */ /* ^N */ /* ^O */
+
+ 0, 0, 0, 0,
+/* ^P */ /* XON */ /* ^R */ /* XOFF */
+
+ 0, LYK_PREV_DOC, 0, 0,
+/* ^T */ /* ^U */ /* ^V */ /* ^W */
+
+ 0, 0, 0, 0,
+/* ^X */ /* ^Y */ /* ^Z */ /* ESC */
+
+ 0, 0, 0, 0,
+/* ^\ */ /* ^] */ /* ^^ */ /* ^_ */
+
+ 0, 0, 0, 0,
+/* sp */ /* ! */ /* " */ /* # */
+
+ 0, 0, 0, 0,
+/* $ */ /* % */ /* & */ /* ' */
+
+ 0, 0, 0, 0,
+/* ( */ /* ) */ /* * */ /* + */
+
+ 0, 0, LYK_TAG_LINK, 0,
+/* , */ /* - */ /* . */ /* / */
+
+ 0, 0, 0, 0,
+/* 0 */ /* 1 */ /* 2 */ /* 3 */
+
+ 0, 0, 0, 0,
+/* 4 */ /* 5 */ /* 6 */ /* 7 */
+
+ 0, 0, 0, 0,
+/* 8 */ /* 9 */ /* : */ /* ; */
+
+ 0, 0, 0, 0,
+/* < */ /* = */ /* > */ /* ? */
+
+ 0, 0, 0, LYK_CREATE,
+/* @ */ /* A */ /* B */ /* C */
+
+ 0, 0, LYK_DIRED_MENU, 0,
+/* D */ /* E */ /* F */ /* G */
+
+ 0, 0, 0, 0,
+/* H */ /* I */ /* J */ /* K */
+
+ 0, LYK_MODIFY, 0, 0,
+/* L */ /* M */ /* N */ /* O */
+
+ 0, 0, LYK_REMOVE, 0,
+/* P */ /* Q */ /* R */ /* S */
+
+LYK_TAG_LINK, LYK_UPLOAD, 0, 0,
+/* T */ /* U */ /* V */ /* W */
+
+ 0, 0, 0, 0,
+/* X */ /* Y */ /* Z */ /* [ */
+
+ 0, 0, 0, 0,
+/* \ */ /* ] */ /* ^ */ /* _ */
+
+0, 0, 0, LYK_CREATE,
+/* ` */ /* a */ /* b */ /* c */
+
+ 0, 0, LYK_DIRED_MENU, 0,
+/* d */ /* e */ /* f */ /* g */
+
+ 0, 0, 0, 0,
+/* h */ /* i */ /* j */ /* k */
+
+0, LYK_MODIFY, 0, 0,
+/* l */ /* m */ /* n */ /* o */
+
+ 0, 0, LYK_REMOVE, 0,
+/* p */ /* q */ /* r */ /* s */
+
+LYK_TAG_LINK, LYK_UPLOAD, 0, 0,
+/* t */ /* u */ /* v */ /* w */
+
+ 0, 0, 0, 0,
+/* x */ /* y */ /* z */ /* { */
+
+ 0, 0, 0, 0,
+/* | */ /* } */ /* ~ */ /* del */
+
+/* 80..9F (illegal ISO-8859-1) 8-bit characters. */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+
+/* A0..FF (permissible ISO-8859-1) 8-bit characters. */
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+
+/* 100..10E function key definitions in LYStrings.h */
+ 0, 0, 0, 0,
+/* UPARROW */ /* DNARROW */ /* RTARROW */ /* LTARROW */
+
+ 0, 0, 0, 0,
+/* PGDOWN */ /* PGUP */ /* HOME */ /* END */
+
+ 0, 0, 0, 0,
+/* F1*/ /* Do key */ /* Find key */ /* Select key */
+
+ 0, 0,
+/* Insert key */ /* Remove key */
+
+LYK_DO_NOTHING,
+/* DO_NOTHING*/
+};
+#endif /* DIRED_SUPPORT && OK_OVERRIDE */
+
+struct rmap {
+ char *name;
+ char *doc;
+};
+PRIVATE struct rmap revmap[] = {
+{ "UNMAPPED", NULL },
+{ "1", NULL },
+{ "2", NULL },
+{ "3", NULL },
+{ "4", NULL },
+{ "5", NULL },
+{ "6", NULL },
+{ "7", NULL },
+{ "8", NULL },
+{ "9", NULL },
+{ "SOURCE", "toggle source/presentation for current document" },
+{ "RELOAD", "reload the current document" },
+{ "PIPE", "pipe the current document to an external command" },
+{ "QUIT", "quit the browser" },
+{ "ABORT", "quit the browser unconditionally" },
+{ "NEXT_PAGE", "view the next page of the document" },
+{ "PREV_PAGE", "view the previous page of the document" },
+{ "UP_TWO", "go back two lines in the document" },
+{ "DOWN_TWO", "go forward two lines in the document" },
+{ "UP_HALF", "go back half a page in the document" },
+{ "DOWN_HALF", "go forward half a page in the document" },
+{ "REFRESH", "refresh the screen to clear garbled text" },
+{ "HOME", "go to the beginning of the current document" },
+{ "END", "go to the end of the current document" },
+{ "PREV_LINK", "make the previous link current" },
+{ "NEXT_LINK", "make the next link current" },
+{ "UP_LINK", "move up the page to a previous link" },
+{ "DOWN_LINK", "move down the page to another link" },
+{ "RIGHT_LINK", "move right to another link" },
+{ "LEFT_LINK", "move left to a previous link" },
+{ "HISTORY", "display stack of currently-suspended documents" },
+{ "PREV_DOC", "go back to the previous document" },
+{ "ACTIVATE", "go to the document given by the current link" },
+{ "GOTO", "go to a document given as a URL" },
+{ "ECGOTO", "edit the current document's URL and go to it" },
+{ "HELP", "display help on using the browser" },
+{ "INDEX", "display an index of potentially useful documents" },
+{ "NOCACHE", "force submission of form or link with no-cache" },
+{ "INTERRUPT", "interrupt network transmission" },
+{ "MAIN_MENU", "return to the first screen (home page)" },
+{ "OPTIONS", "display and change option settings" },
+{ "INDEX_SEARCH", "allow searching of an index" },
+{ "WHEREIS", "search within the current document" },
+{ "NEXT", "search for the next occurence" },
+{ "COMMENT", "send a comment to the author of the current document" },
+{ "EDIT", "edit the current document" },
+{ "INFO", "display information on the current document and link" },
+{ "PRINT", "display choices for printing the current document" },
+{ "ADD_BOOKMARK", "add to your personal bookmark list" },
+{ "DEL_BOOKMARK", "delete from your personal bookmark list" },
+{ "VIEW_BOOKMARK", "view your personal bookmark list" },
+{ "VLINKS", "list links visited during the current Lynx session" },
+{ "SHELL", "escape from the browser to the system" },
+{ "DOWNLOAD", "download the current link to your computer" },
+{ "TRACE_TOGGLE", "toggle tracing of browser operations" },
+{ "TRACE_LOG", "view trace log if started in the current session" },
+{ "IMAGE_TOGGLE", "toggle handling of all images as links" },
+{ "INLINE_TOGGLE", "toggle pseudo-ALTs for inlines with no ALT string" },
+{ "HEAD", "send a HEAD request for the current document or link" },
+{ "DO_NOTHING", NULL },
+{ "TOGGLE_HELP", "show other commands in the novice help menu" },
+{ "JUMP", "go directly to a target document or action" },
+{ "KEYMAP", "display the current key map" },
+{ "LIST", "list the references (links) in the current document" },
+{ "TOOLBAR", "go to Toolbar or Banner in the current document" },
+{ "HISTORICAL", "toggle historical vs. valid/minimal comment parsing" },
+{ "MINIMAL", "toggle minimal vs. valid comment parsing" },
+{ "SOFT_DQUOTES", "toggle valid vs. soft double-quote parsing" },
+{ "RAW_TOGGLE", "toggle raw 8-bit translations or CJK mode ON or OFF" },
+{ "COOKIE_JAR", "examine the Cookie Jar" },
+{ "F_LINK_NUM", "invoke the 'Follow link (or page) number:' prompt" },
+{ "CLEAR_AUTH", "clear all authorization info for this session" },
+{ "SWITCH_DTD", "switch between two ways of parsing HTML" },
+{ "ELGOTO", "edit the current link's URL or ACTION and go to it" },
+#ifdef USE_EXTERNALS
+{ "EXTERN", "run external program with url" },
+#endif
+#ifdef VMS
+{ "DIRED_MENU", "invoke File/Directory Manager, if available" },
+#else
+#ifdef DIRED_SUPPORT
+{ "DIRED_MENU", "display a full menu of file operations" },
+{ "CREATE", "create a new file or directory" },
+{ "REMOVE", "remove a file or directory" },
+{ "MODIFY", "modify the name or location of a file or directory" },
+{ "TAG_LINK", "tag a file or directory for later action" },
+{ "UPLOAD", "upload from your computer to the current directory" },
+{ "INSTALL", "install file or tagged files into a system area" },
+#endif /* DIRED_SUPPORT */
+#endif /* VMS */
+#ifdef NOT_USED
+{ "VERSION", "report version of lynx"},
+{ "FORM_UP", "toggle a checkbox" },
+{ "FORM_DOWN", "toggle a checkbox" },
+#endif /* NOT_USED */
+{ NULL, "" }
+};
+
+PRIVATE char *funckey[] = {
+ "Up Arrow",
+ "Down Arrow",
+ "Right Arrow",
+ "Left Arrow",
+ "Page Down",
+ "Page Up",
+ "Home",
+ "End",
+ "F1",
+ "Do key",
+ "Find key",
+ "Select key",
+ "Insert key",
+ "Remove key"
+};
+
+PRIVATE char *pretty ARGS1 (int, c)
+{
+ static char buf[30];
+
+ if (c == '\t')
+ sprintf(buf, "&lt;tab&gt; ");
+ else if (c == '\r')
+ sprintf(buf, "&lt;return&gt; ");
+ else if (c == ' ')
+ sprintf(buf, "&lt;space&gt; ");
+ else if (c == '<')
+ sprintf(buf, "&lt; ");
+ else if (c == '>')
+ sprintf(buf, "&gt; ");
+ else if (c == 0177)
+ sprintf(buf, "&lt;delete&gt; ");
+ else if (c > ' ' && c <= 0377)
+ sprintf(buf, "%c", c);
+ else if (c < ' ')
+ sprintf(buf, "^%c", c|0100);
+ else
+ sprintf(buf, "%s", funckey[c-0400]);
+
+ return buf;
+}
+
+PRIVATE void print_binding ARGS3(HTStream *, target, char *, buf, int, i)
+{
+#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
+ if (prev_lynx_edit_mode && !no_dired_support &&
+ override[i] && revmap[(unsigned char)override[i]].doc) {
+ sprintf(buf, "%-12s%-14s%s\n", pretty(i-1),
+ revmap[(unsigned char)override[i]].name,
+ revmap[(unsigned char)override[i]].doc);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ } else
+#endif /* DIRED_SUPPORT && OK_OVERRIDE */
+ if (keymap[i] && revmap[(unsigned char)keymap[i]].doc) {
+ sprintf(buf, "%-12s%-14s%s\n", pretty(i-1),
+ revmap[(unsigned char)keymap[i]].name,
+ revmap[(unsigned char)keymap[i]].doc);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ }
+}
+
+PRIVATE int LYLoadKeymap ARGS4 (
+ CONST char *, arg GCC_UNUSED,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ HTFormat format_in = WWW_HTML;
+ HTStream *target;
+ char buf[256];
+ int i;
+
+ /*
+ * Set up the stream. - FM
+ */
+ target = HTStreamStack(format_in, format_out, sink, anAnchor);
+ if (!target || target == NULL) {
+ sprintf(buf, CANNOT_CONVERT_I_TO_O,
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ HTAlert(buf);
+ return(HT_NOT_LOADED);
+ }
+ anAnchor->no_cache = TRUE;
+
+ sprintf(buf, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+ CURRENT_KEYMAP_TITLE);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "<h1>%s (%s Version %s)</h1>\n<pre>",
+ CURRENT_KEYMAP_TITLE, LYNX_NAME, LYNX_VERSION);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ for (i = 'a'+1; i <= 'z'+1; i++) {
+ print_binding(target, buf, i);
+ if (keymap[i - ' '] != keymap[i]) {
+ print_binding(target, buf,
+ i-' '); /* uppercase mapping is different */
+ }
+ }
+ for (i = 1; i < (int) sizeof(keymap); i++) {
+ /*
+ * LYK_PIPE not implemented yet.
+ */
+ if ((i > 127 || i <= ' ' || !isalpha(i-1)) &&
+ strcmp(revmap[(unsigned char)keymap[i]].name, "PIPE")) {
+ print_binding(target, buf, i);
+ }
+ }
+
+ sprintf(buf,"</pre>\n</body>\n");
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ (*target->isa->_free)(target);
+ return(HT_LOADED);
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _LYKEYMAP_C_GLOBALDEF_1_INIT { "LYNXKEYMAP", LYLoadKeymap, 0}
+GLOBALDEF (HTProtocol,LYLynxKeymap,_LYKEYMAP_C_GLOBALDEF_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol LYLynxKeymap = {"LYNXKEYMAP", LYLoadKeymap, 0};
+#endif /* GLOBALDEF_IS_MACRO */
+
+/*
+ * install func as the mapping for key.
+ * func must be present in the revmap table.
+ * returns TRUE if the mapping was made, FALSE if not.
+ */
+PUBLIC int remap ARGS2(char *,key, char *,func)
+ {
+ int i;
+ struct rmap *mp;
+ int c = 0;
+
+ if (func == NULL)
+ return 0;
+ if (strlen(key) == 1)
+ c = *key;
+ else if (strlen(key) == 2 && *key == '^')
+ c = key[1] & 037;
+ else if (strlen(key) >= 2 && isdigit(*key))
+ if (sscanf(key, "%i", &c) != 1)
+ return 0;
+ for (i = 0, mp = revmap; (*mp).name != NULL; mp++, i++) {
+ if (strcmp((*mp).name, func) == 0) {
+ keymap[c+1] = i;
+ return c;
+ }
+ }
+ return 0;
+}
+
+
+PUBLIC void set_vms_keys NOARGS
+{
+ keymap[26+1] = LYK_ABORT; /* control-Z */
+ keymap['$'+1] = LYK_SHELL;
+}
+
+static char saved_vi_keys[4];
+static BOOLEAN did_vi_keys;
+
+PUBLIC void set_vi_keys NOARGS
+{
+ saved_vi_keys[0] = keymap['h'+1];
+ keymap['h'+1] = LYK_PREV_DOC;
+ saved_vi_keys[1] = keymap['j'+1];
+ keymap['j'+1] = LYK_NEXT_LINK;
+ saved_vi_keys[2] = keymap['k'+1];
+ keymap['k'+1] = LYK_PREV_LINK;
+ saved_vi_keys[3] = keymap['l'+1];
+ keymap['l'+1] = LYK_ACTIVATE;
+
+ did_vi_keys = TRUE;
+}
+
+PUBLIC void reset_vi_keys NOARGS
+{
+ if (!did_vi_keys)
+ return;
+
+ keymap['h'+1] = saved_vi_keys[0];
+ keymap['j'+1] = saved_vi_keys[1];
+ keymap['k'+1] = saved_vi_keys[2];
+ keymap['l'+1] = saved_vi_keys[3];
+
+ did_vi_keys = FALSE;
+}
+
+static char saved_emacs_keys[4];
+static BOOLEAN did_emacs_keys;
+
+PUBLIC void set_emacs_keys NOARGS
+{
+ saved_emacs_keys[0] = keymap[2+1];
+ keymap[2+1] = LYK_PREV_DOC; /* ^B */
+ saved_emacs_keys[1] = keymap[14+1];
+ keymap[14+1] = LYK_NEXT_LINK; /* ^N */
+ saved_emacs_keys[2] = keymap[16+1];
+ keymap[16+1] = LYK_PREV_LINK; /* ^P */
+ saved_emacs_keys[3] = keymap[6+1];
+ keymap[6+1] = LYK_ACTIVATE; /* ^F */
+
+ did_emacs_keys = TRUE;
+}
+
+PUBLIC void reset_emacs_keys NOARGS
+{
+ if (!did_emacs_keys)
+ return;
+
+ keymap[2+1] = saved_emacs_keys[0];
+ keymap[14+1] = saved_emacs_keys[1];
+ keymap[16+1] = saved_emacs_keys[2];
+ keymap[6+1] = saved_emacs_keys[3];
+
+ did_emacs_keys = FALSE;
+}
+
+static char saved_number_keys[9];
+static BOOLEAN did_number_keys;
+
+PUBLIC void set_numbers_as_arrows NOARGS
+{
+ /*
+ * Map numbers to functions as labeled on the
+ * IBM Enhanced keypad, and save their original
+ * mapping for reset_numbers_as_arrows(). - FM
+ */
+ saved_number_keys[0] = keymap['4'+1];
+ keymap['4'+1] = LYK_PREV_DOC;
+ saved_number_keys[1] = keymap['2'+1];
+ keymap['2'+1] = LYK_NEXT_LINK;
+ saved_number_keys[2] = keymap['8'+1];
+ keymap['8'+1] = LYK_PREV_LINK;
+ saved_number_keys[3] = keymap['6'+1];
+ keymap['6'+1] = LYK_ACTIVATE;
+ saved_number_keys[4] = keymap['7'+1];
+ keymap['7'+1] = LYK_HOME;
+ saved_number_keys[5] = keymap['1'+1];
+ keymap['1'+1] = LYK_END;
+ saved_number_keys[6] = keymap['9'+1];
+ keymap['9'+1] = LYK_PREV_PAGE;
+ saved_number_keys[7] = keymap['3'+1];
+ keymap['3'+1] = LYK_NEXT_PAGE;
+
+ /*
+ * Disable the 5.
+ */
+ saved_number_keys[8] = keymap['5'+1];
+ keymap['5'+1] = LYK_DO_NOTHING;
+
+ did_number_keys = TRUE;
+}
+
+PUBLIC void reset_numbers_as_arrows NOARGS
+{
+ if (!did_number_keys)
+ return;
+
+ keymap['4'+1] = saved_number_keys[0];
+ keymap['2'+1] = saved_number_keys[1];
+ keymap['8'+1] = saved_number_keys[2];
+ keymap['6'+1] = saved_number_keys[3];
+ keymap['7'+1] = saved_number_keys[4];
+ keymap['1'+1] = saved_number_keys[5];
+ keymap['9'+1] = saved_number_keys[6];
+ keymap['3'+1] = saved_number_keys[7];
+ keymap['5'+1] = saved_number_keys[8];
+
+ did_number_keys = FALSE;
+}
+
+PUBLIC char *key_for_func ARGS1 (
+ int, func)
+{
+ static char buf[512];
+ size_t i;
+
+ buf[0] = '\0';
+ for (i = 1; i < sizeof(keymap); i++) {
+ if (keymap[i] == func) {
+ if (*buf)
+ strcat(buf, " or ");
+ strcat(buf, pretty(i-1));
+ }
+ }
+ return buf;
+}
+
+/*
+ * This function returns TRUE if the ch is non-alphanumeric
+ * and maps to key_name (LYK_foo in the keymap[] array). - FM
+ */
+PUBLIC BOOL LYisNonAlnumKeyname ARGS2(
+ int, ch,
+ int, key_name)
+{
+ if ((ch >= '0' && ch <= '9') ||
+ (ch >= 'A' && ch <= 'z') ||
+ ch < 0 || ch > 269)
+ return (FALSE);
+
+ return(keymap[ch+1] == key_name);
+}
+
+#ifdef NOTUSED_FOTEMODS
+/*
+ * This function returns the (int)ch mapped to the
+ * LYK_foo value passed to it as an argument. - FM
+ */
+PUBLIC int LYReverseKeymap ARGS1(
+ int, key_name)
+{
+ int i;
+
+ for (i = 1; i < sizeof(keymap); i++) {
+ if (keymap[i] == key_name) {
+ return(i - 1);
+ }
+ }
+
+ return(0);
+}
+#endif
diff --git a/gnu/usr.bin/lynx/src/LYKeymap.h b/gnu/usr.bin/lynx/src/LYKeymap.h
new file mode 100644
index 00000000000..77feb48fd7b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYKeymap.h
@@ -0,0 +1,125 @@
+#ifndef LYKEYMAP_H
+#define LYKEYMAP_H
+
+extern int remap PARAMS((char *key, char *func));
+extern void set_vms_keys NOPARAMS;
+extern void set_vi_keys NOPARAMS;
+extern void reset_vi_keys NOPARAMS;
+extern void set_emacs_keys NOPARAMS;
+extern void reset_emacs_keys NOPARAMS;
+extern void set_numbers_as_arrows NOPARAMS;
+extern void reset_numbers_as_arrows NOPARAMS;
+extern void print_keymap PARAMS((char **newfile));
+extern char *key_for_func PARAMS((int func));
+extern BOOLEAN LYisNonAlnumKeyname PARAMS((int ch, int key_name));
+extern int LYReverseKeymap PARAMS((int key_name));
+
+extern char keymap[]; /* main keymap matrix */
+
+#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
+extern char override[];
+#endif
+
+#define CURRENT_KEYMAP_TITLE "Current Key Map"
+
+#define LYK_1 1
+#define LYK_2 2
+#define LYK_3 3
+#define LYK_4 4
+#define LYK_5 5
+#define LYK_6 6
+#define LYK_7 7
+#define LYK_8 8
+#define LYK_9 9
+#define LYK_SOURCE 10
+#define LYK_RELOAD 11
+#define LYK_PIPE 12
+#define LYK_QUIT 13
+#define LYK_ABORT 14
+#define LYK_NEXT_PAGE 15
+#define LYK_PREV_PAGE 16
+#define LYK_UP_TWO 17
+#define LYK_DOWN_TWO 18
+#define LYK_UP_HALF 19
+#define LYK_DOWN_HALF 20
+#define LYK_REFRESH 21
+#define LYK_HOME 22
+#define LYK_END 23
+#define LYK_PREV_LINK 24
+#define LYK_NEXT_LINK 25
+#define LYK_UP_LINK 26
+#define LYK_DOWN_LINK 27
+#define LYK_RIGHT_LINK 28
+#define LYK_LEFT_LINK 29
+#define LYK_HISTORY 30
+#define LYK_PREV_DOC 31
+#define LYK_ACTIVATE 32
+#define LYK_GOTO 33
+#define LYK_ECGOTO 34
+#define LYK_HELP 35
+#define LYK_INDEX 36
+#define LYK_NOCACHE 37
+#define LYK_INTERRUPT 38
+#define LYK_MAIN_MENU 39
+#define LYK_OPTIONS 40
+#define LYK_INDEX_SEARCH 41
+#define LYK_WHEREIS 42
+#define LYK_NEXT 43
+#define LYK_COMMENT 44
+#define LYK_EDIT 45
+#define LYK_INFO 46
+#define LYK_PRINT 47
+#define LYK_ADD_BOOKMARK 48
+#define LYK_DEL_BOOKMARK 49
+#define LYK_VIEW_BOOKMARK 50
+#define LYK_VLINKS 51
+#define LYK_SHELL 52
+#define LYK_DOWNLOAD 53
+#define LYK_TRACE_TOGGLE 54
+#define LYK_TRACE_LOG 55
+#define LYK_IMAGE_TOGGLE 56
+#define LYK_INLINE_TOGGLE 57
+#define LYK_HEAD 58
+#define LYK_DO_NOTHING 59
+#define LYK_TOGGLE_HELP 60
+#define LYK_JUMP 61
+#define LYK_KEYMAP 62
+#define LYK_LIST 63
+#define LYK_TOOLBAR 64
+#define LYK_HISTORICAL 65
+#define LYK_MINIMAL 66
+#define LYK_SOFT_DQUOTES 67
+#define LYK_RAW_TOGGLE 68
+#define LYK_COOKIE_JAR 69
+#define LYK_F_LINK_NUM 70
+#define LYK_CLEAR_AUTH 71
+#define LYK_SWITCH_DTD 72
+#define LYK_ELGOTO 73
+
+#ifdef USE_EXTERNALS
+#define LYK_EXTERN 74
+#if defined(VMS) || defined(DIRED_SUPPORT)
+#define LYK_DIRED_MENU 75
+#endif /* VMS || DIRED_SUPPORT */
+#else /* USE_EXTERNALS */
+#if defined(VMS) || defined(DIRED_SUPPORT)
+#define LYK_DIRED_MENU 74
+#endif /* VMS || DIRED_SUPPORT */
+#endif /* !defined(USE_EXTERNALS) */
+
+#ifdef DIRED_SUPPORT
+#define LYK_CREATE (LYK_DIRED_MENU+1)
+#define LYK_REMOVE (LYK_DIRED_MENU+2)
+#define LYK_MODIFY (LYK_DIRED_MENU+3)
+#define LYK_TAG_LINK (LYK_DIRED_MENU+4)
+#define LYK_UPLOAD (LYK_DIRED_MENU+5)
+#define LYK_INSTALL (LYK_DIRED_MENU+6)
+#endif /* DIRED_SUPPORT */
+
+#ifdef NOT_USED
+#define LYK_VERSION 81
+#define LYK_FORM_UP 82
+#define LYK_FORM_DOWN 83
+#endif /* NOT_USED */
+
+#endif /* LYKEYMAP_H */
diff --git a/gnu/usr.bin/lynx/src/LYLeaks.c b/gnu/usr.bin/lynx/src/LYLeaks.c
new file mode 100644
index 00000000000..79ebf838825
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYLeaks.c
@@ -0,0 +1,607 @@
+/*
+** Copyright (c) 1994, University of Kansas, All Rights Reserved
+**
+** This code will be used only if LY_FIND_LEAKS is defined.
+*/
+
+/*
+** Disable the overriding of the memory routines for this file.
+*/
+#define NO_MEMORY_TRACKING
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYexit.h"
+#include "LYLeaks.h"
+#include "LYUtils.h"
+#include <ctype.h>
+/*#include <stdio.h> included by HTUtils.h -- FM */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PRIVATE AllocationList *ALp_RunTimeAllocations = NULL;
+
+PRIVATE void AddToList PARAMS((
+ AllocationList * ALp_new));
+PRIVATE AllocationList *FindInList PARAMS((
+ void * vp_find));
+PRIVATE void RemoveFromList PARAMS((
+ AllocationList * ALp_del));
+
+/*
+** Purpose: Print a report of all memory left unallocated by
+** Lynx code or attempted unallocations on
+** pointers that are not valid and then free
+** all unfreed memory.
+** Arguments: void
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** This function should be registered for execution with the
+** atexit (stdlib.h) function as the first statement
+** in main.
+** All output of this function is sent to the file defined in
+** the header LYLeaks.h (LEAKAGE_SINK).
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+** 10-30-97 modified to handle StrAllocCopy() and
+** StrAllocCat(). - KW & FM
+*/
+PUBLIC void LYLeaks NOARGS
+{
+ AllocationList *ALp_head;
+ size_t st_total = (size_t)0;
+ FILE *Fp_leakagesink;
+
+ /*
+ * Open the leakage sink to take all the output.
+ * Recreate the file each time.
+ * Do nothing if unable to open the file.
+ */
+ Fp_leakagesink = LYNewTxtFile(LEAKAGE_SINK);
+ if (Fp_leakagesink == NULL) {
+ return;
+ }
+
+ while (ALp_RunTimeAllocations != NULL) {
+ /*
+ * Take the head off of the run time allocation list.
+ */
+ ALp_head = ALp_RunTimeAllocations;
+ ALp_RunTimeAllocations = ALp_head->ALp_Next;
+
+ /*
+ * Print the type of leak/error.
+ * Free off memory when we no longer need it.
+ */
+ if (ALp_head->vp_Alloced == NULL) {
+ /*
+ * If there is realloc information on the
+ * bad request, then it was a bad pointer
+ * value in a realloc statement.
+ */
+ fprintf(Fp_leakagesink,
+ "Invalid pointer detected.\n");
+ fprintf(Fp_leakagesink,
+ "Pointer:\t%p\n", ALp_head->vp_BadRequest);
+
+ /*
+ * Don't free the bad request, it is an invalid pointer.
+ * If the free source information is empty, we
+ * should check the realloc information
+ * too since it can get passed bad pointer
+ * values also.
+ */
+ if (ALp_head->SL_memory.cp_FileName == NULL) {
+ fprintf(Fp_leakagesink, "FileName:\t%s\n",
+ ALp_head->SL_realloc.cp_FileName);
+ fprintf(Fp_leakagesink, "LineCount:\t%d\n",
+ ALp_head->SL_realloc.ssi_LineNumber);
+ } else {
+ fprintf(Fp_leakagesink, "FileName:\t%s\n",
+ ALp_head->SL_memory.cp_FileName);
+ fprintf(Fp_leakagesink, "LineCount:\t%d\n",
+ ALp_head->SL_memory.ssi_LineNumber);
+ }
+ } else {
+ size_t i_counter;
+
+ /*
+ * Increment the count of total memory lost and
+ * then print the information.
+ */
+ st_total += ALp_head->st_Bytes;
+
+ fprintf(Fp_leakagesink, "Memory leak detected.\n");
+ fprintf(Fp_leakagesink, "Pointer:\t%p\n", ALp_head->vp_Alloced);
+ fprintf(Fp_leakagesink, "Contains:\t");
+ for (i_counter = 0;
+ i_counter < ALp_head->st_Bytes &&
+ i_counter < MAX_CONTENT_LENGTH;
+ i_counter++) {
+ if (isprint(((char *)(ALp_head->vp_Alloced))[i_counter])) {
+ fprintf(Fp_leakagesink, "%c",
+ ((char *)(ALp_head->vp_Alloced))[i_counter]);
+ } else {
+ fprintf(Fp_leakagesink, "|");
+ }
+ }
+ fprintf(Fp_leakagesink, "\n");
+ FREE(ALp_head->vp_Alloced);
+ fprintf(Fp_leakagesink, "ByteSize:\t%d\n",
+ (int)(ALp_head->st_Bytes));
+ fprintf(Fp_leakagesink, "FileName:\t%s\n",
+ ALp_head->SL_memory.cp_FileName);
+ fprintf(Fp_leakagesink, "LineCount:\t%d\n",
+ ALp_head->SL_memory.ssi_LineNumber);
+ /*
+ * Give the last time the pointer was realloced
+ * if it happened also.
+ */
+ if (ALp_head->SL_realloc.cp_FileName != NULL) {
+ fprintf(Fp_leakagesink, "realloced:\t%s\n",
+ ALp_head->SL_realloc.cp_FileName);
+ fprintf(Fp_leakagesink, "LineCount:\t%d\n",
+ ALp_head->SL_realloc.ssi_LineNumber);
+ }
+ }
+
+ /*
+ * Create a blank line and release the memory held
+ * by the item.
+ */
+ fprintf(Fp_leakagesink, "\n");
+ FREE(ALp_head);
+ }
+
+ /*
+ * Give a grand total of the leakage.
+ * Close the output file.
+ */
+ fprintf(Fp_leakagesink, "\nTotal memory leakage this run:\t%u\n",
+ (unsigned)st_total);
+ fclose(Fp_leakagesink);
+#ifdef VMS
+ {
+ char VMSfilename[256];
+ /*
+ * Purge lower versions of the file.
+ */
+ sprintf(VMSfilename, "%s;-1", LEAKAGE_SINK);
+ while (remove(VMSfilename) == 0)
+ ;
+ /*
+ * Reset version number.
+ */
+ sprintf(VMSfilename, "%s;1", LEAKAGE_SINK);
+ rename(LEAKAGE_SINK, VMSfilename);
+ }
+#endif /* VMS */
+}
+
+/*
+** Purpose: Capture allocations using malloc (stdlib.h) and track
+** the information in a list.
+** Arguments: st_bytes The size of the allocation requested
+** in bytes.
+** cp_File The file from which the request for
+** allocation came from.
+** ssi_Line The line number in cp_File where the
+** allocation request came from.
+** Return Value: void * A pointer to the allocated memory or NULL on
+** failure as per malloc (stdlib.h)
+** Remarks/Portability/Dependencies/Restrictions:
+** If no memory is allocated, then no entry is added to the
+** allocation list.
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PUBLIC void *LYLeakMalloc ARGS3(
+ size_t, st_bytes,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ /*
+ * Do the actual allocation.
+ */
+ void *vp_malloc = (void *)malloc(st_bytes);
+
+ /*
+ * Only on successful allocation do we track any information.
+ */
+ if (vp_malloc != NULL) {
+ /*
+ * Further allocate memory to store the information.
+ * Just return on failure to allocate more.
+ */
+ AllocationList *ALp_new =
+ (AllocationList *)calloc(1, sizeof(AllocationList));
+
+ if (ALp_new == NULL) {
+ return(vp_malloc);
+ }
+ /*
+ * Copy over the relevant information.
+ * There is no need to allocate more memory for the
+ * file name as it is a static string anyhow.
+ */
+ ALp_new->vp_Alloced = vp_malloc;
+ ALp_new->st_Bytes = st_bytes;
+ ALp_new->SL_memory.cp_FileName = cp_File;
+ ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
+
+ /*
+ * Add the new item to the allocation list.
+ */
+ AddToList(ALp_new);
+ }
+
+ return(vp_malloc);
+}
+
+/*
+** Purpose: Capture allocations by calloc (stdlib.h) and
+** save relevant information in a list.
+** Arguments: st_number The number of items to allocate.
+** st_bytes The size of each item.
+** cp_File The file which wants to allocation.
+** ssi_Line The line number in cp_File requesting
+** the allocation.
+** Return Value: void * The allocated memory, or NULL on failure as
+** per calloc (stdlib.h)
+** Remarks/Portability/Dependencies/Restrictions:
+** If no memory can be allocated, then no entry will be added
+** to the list.
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PUBLIC void *LYLeakCalloc ARGS4(
+ size_t, st_number,
+ size_t, st_bytes,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ /*
+ * Allocate the requested memory.
+ */
+ void *vp_calloc = (void *)calloc(st_number, st_bytes);
+
+ /*
+ * Only if the allocation was a success do we track information.
+ */
+ if (vp_calloc != NULL) {
+ /*
+ * Allocate memory for the item to be in the list.
+ * If unable, just return.
+ */
+ AllocationList *ALp_new =
+ (AllocationList *)calloc(1, sizeof(AllocationList));
+
+ if (ALp_new == NULL) {
+ return(vp_calloc);
+ }
+
+ /*
+ * Copy over the relevant information.
+ * There is no need to allocate memory for the file
+ * name as it is a static string anyway.
+ */
+ ALp_new->vp_Alloced = vp_calloc;
+ ALp_new->st_Bytes = (st_number * st_bytes);
+ ALp_new->SL_memory.cp_FileName = cp_File;
+ ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
+
+ /*
+ * Add the item to the allocation list.
+ */
+ AddToList(ALp_new);
+ }
+
+ return(vp_calloc);
+}
+
+/*
+** Purpose: Capture any realloc (stdlib.h) calls in order to
+** properly keep track of our run time allocation
+** table.
+** Arguments: vp_Alloced The previously allocated block of
+** memory to resize. If NULL,
+** realloc works just like
+** malloc.
+** st_newBytes The new size of the chunk of memory.
+** cp_File The file containing the realloc.
+** ssi_Line The line containing the realloc in cp_File.
+** Return Value: void * The new pointer value (could be the same) or
+** NULL if unable to resize (old block
+** still exists).
+** Remarks/Portability/Dependencies/Restrictions:
+** If unable to resize vp_Alloced, then no change in the
+** allocation list will be made.
+** If vp_Alloced is an invalid pointer value, the program will
+** exit after one last entry is added to the allocation list.
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PUBLIC void *LYLeakRealloc ARGS4(
+ void *, vp_Alloced,
+ size_t, st_newBytes,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ void *vp_realloc;
+ AllocationList *ALp_renew;
+
+ /*
+ * If we are asked to resize a NULL pointer, this is just a
+ * malloc call.
+ */
+ if (vp_Alloced == NULL) {
+ return(LYLeakMalloc(st_newBytes, cp_File, ssi_Line));
+ }
+
+ /*
+ * Find the current vp_Alloced block in the list.
+ * If NULL, this is an invalid pointer value.
+ */
+ ALp_renew = FindInList(vp_Alloced);
+ if (ALp_renew == NULL) {
+ /*
+ * Track the invalid pointer value and then exit.
+ * If unable to allocate, just exit.
+ */
+ auto AllocationList *ALp_new =
+ (AllocationList *)calloc(1,
+ sizeof(AllocationList));
+
+ if (ALp_new == NULL) {
+ exit(-1);
+ }
+
+ /*
+ * Set the information up; no need to allocate file name
+ * since it is a static string.
+ */
+ ALp_new->vp_Alloced = NULL;
+ ALp_new->vp_BadRequest = vp_Alloced;
+ ALp_new->SL_realloc.cp_FileName = cp_File;
+ ALp_new->SL_realloc.ssi_LineNumber = ssi_Line;
+
+ /*
+ * Add the item to the list.
+ * Exit.
+ */
+ AddToList(ALp_new);
+ exit(-1);
+ }
+
+ /*
+ * Perform the resize.
+ * If not NULL, record the information.
+ */
+ vp_realloc = (void *)realloc(vp_Alloced, st_newBytes);
+ if (vp_realloc != NULL) {
+ ALp_renew->vp_Alloced = vp_realloc;
+ ALp_renew->st_Bytes = st_newBytes;
+
+ /*
+ * Update the realloc information, too.
+ * No need to allocate file name, static string.
+ */
+ ALp_renew->SL_realloc.cp_FileName = cp_File;
+ ALp_renew->SL_realloc.ssi_LineNumber = ssi_Line;
+ }
+
+ return(vp_realloc);
+}
+
+/*
+** Purpose: Capture all requests to free information and also
+** remove items from the allocation list.
+** Arguments: vp_Alloced The memory to free.
+** cp_File The file calling free.
+** ssi_Line The line of cp_File calling free.
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** If the pointer value is invalid, then an item will be added
+** to the list and nothing else is done.
+** I really like the name of this function and one day hope
+** that Lynx is Leak Free.
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PUBLIC void LYLeakFree ARGS3(
+ void *, vp_Alloced,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ AllocationList *ALp_free;
+
+ /*
+ * Find the pointer in the allocated list.
+ * If not found, bad pointer.
+ * If found, free list item and vp_Allloced.
+ */
+ ALp_free = FindInList(vp_Alloced);
+ if (ALp_free == NULL) {
+ /*
+ * Create the final entry before exiting marking this error.
+ * If unable to allocate more memory just exit.
+ */
+ AllocationList *ALp_new =
+ (AllocationList *)calloc(1,
+ sizeof(AllocationList));
+
+ if (ALp_new == NULL) {
+ exit(-1);
+ }
+
+ /*
+ * Set up the information, no memory need be allocated
+ * for the file name since it is a static string.
+ */
+ ALp_new->vp_Alloced = NULL;
+ ALp_new->vp_BadRequest = vp_Alloced;
+ ALp_new->SL_memory.cp_FileName = cp_File;
+ ALp_new->SL_memory.ssi_LineNumber = ssi_Line;
+
+ /*
+ * Add the entry to the list and then return.
+ */
+ AddToList(ALp_new);
+ return;
+ } else {
+ /*
+ * Free off the memory.
+ * Take entry out of allocation list.
+ */
+ RemoveFromList(ALp_free);
+ FREE(ALp_free);
+ FREE(vp_Alloced);
+ }
+}
+
+/*
+** Allocates a new copy of a string, and returns it.
+** Tracks allocations by using other LYLeakFoo functions.
+** Equivalent to HTSACopy in HTUtils.c - KW
+*/
+PUBLIC char * LYLeakSACopy ARGS4(
+ char **, dest,
+ CONST char *, src,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ if (*dest) {
+ LYLeakFree(*dest, cp_File, ssi_Line);
+ *dest = NULL;
+ }
+ if (src) {
+ *dest = (char *)LYLeakMalloc(strlen(src) + 1, cp_File, ssi_Line);
+ if (*dest == NULL)
+ outofmem(__FILE__, "LYLeakSACopy");
+ strcpy (*dest, src);
+ }
+ return *dest;
+}
+
+/*
+** String Allocate and Concatenate.
+** Tracks allocations by using other LYLeakFoo functions.
+** Equivalent to HTSACat in HTUtils.c - KW
+*/
+PUBLIC char * LYLeakSACat ARGS4(
+ char **, dest,
+ CONST char *, src,
+ CONST char *, cp_File,
+ CONST short, ssi_Line)
+{
+ if (src && *src) {
+ if (*dest) {
+ int length = strlen(*dest);
+ *dest = (char *)LYLeakRealloc(*dest,
+ (length + strlen(src) + 1),
+ cp_File,
+ ssi_Line);
+ if (*dest == NULL)
+ outofmem(__FILE__, "LYLeakSACat");
+ strcpy (*dest + length, src);
+ } else {
+ *dest = (char *)LYLeakMalloc((strlen(src) + 1),
+ cp_File,
+ ssi_Line);
+ if (*dest == NULL)
+ outofmem(__FILE__, "LYLeakSACat");
+ strcpy (*dest, src);
+ }
+ }
+ return *dest;
+}
+
+/*
+** Purpose: Add a new allocation item to the list.
+** Arguments: ALp_new The new item to add.
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** Static function made to make code reusable in projects beyond
+** Lynx (some might ask why not use HTList).
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void AddToList ARGS1(
+ AllocationList *, ALp_new)
+{
+ /*
+ * Just make this the first item in the list.
+ */
+ ALp_new->ALp_Next = ALp_RunTimeAllocations;
+ ALp_RunTimeAllocations = ALp_new;
+}
+
+/*
+** Purpose: Find the place in the list where vp_find is currently
+** tracked.
+** Arguments: vp_find A pointer to look for in the list.
+** Return Value: AllocationList * Either vp_find's place in the
+** list or NULL if not found.
+** Remarks/Portability/Dependencies/Restrictions:
+** Static function made to make code reusable in projects outside
+** of Lynx (some might ask why not use HTList).
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE AllocationList *FindInList ARGS1(
+ void *, vp_find)
+{
+ AllocationList *ALp_find = ALp_RunTimeAllocations;
+
+ /*
+ * Go through the list of allocated pointers until end of list
+ * or vp_find is found.
+ */
+ while (ALp_find != NULL) {
+ if (ALp_find->vp_Alloced == vp_find) {
+ break;
+ }
+ ALp_find = ALp_find->ALp_Next;
+ }
+
+ return(ALp_find);
+}
+
+/*
+** Purpose: Remove the specified item from the list.
+** Arguments: ALp_del The item to remove from the list.
+** Return Value: void
+** Remarks/Portability/Dependencies/Restrictions:
+** Static function made to make code reusable in projects outside
+** of Lynx (some might ask why not use HTList).
+** Revision History:
+** 05-26-94 created Lynx 2-3-1 Garrett Arch Blythe
+*/
+PRIVATE void RemoveFromList ARGS1(
+ AllocationList *, ALp_del)
+{
+ AllocationList *ALp_findbefore = ALp_RunTimeAllocations;
+
+ /*
+ * There is one special case, where the item to remove is the
+ * first in the list.
+ */
+ if (ALp_del == ALp_findbefore) {
+ ALp_RunTimeAllocations = ALp_del->ALp_Next;
+ return;
+ }
+
+ /*
+ * Loop through checking all of the next values, if a match
+ * don't continue. Always assume the item will be found.
+ */
+ while (ALp_findbefore->ALp_Next != ALp_del) {
+ ALp_findbefore = ALp_findbefore->ALp_Next;
+ }
+
+ /*
+ * We are one item before the one to get rid of.
+ * Get rid of it.
+ */
+ ALp_findbefore->ALp_Next = ALp_del->ALp_Next;
+}
diff --git a/gnu/usr.bin/lynx/src/LYList.c b/gnu/usr.bin/lynx/src/LYList.c
new file mode 100644
index 00000000000..b283ed3bf12
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYList.c
@@ -0,0 +1,360 @@
+/* Lynx Document Reference List Support LYList.c
+** ====================================
+**
+** Author: FM Foteos Macrides (macrides@sci.wfbr.edu)
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYUtils.h"
+#include "GridText.h"
+#include "LYList.h"
+#include "LYSignal.h"
+#include "LYGlobalDefs.h"
+#include "LYCharUtils.h"
+
+#ifdef DIRED_SUPPORT
+#include "LYUpload.h"
+#include "LYLocal.h"
+#endif /* DIRED_SUPPORT */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* showlist - F.Macrides (macrides@sci.wfeb.edu)
+** --------
+** Create a temporary text/html file with a list of links to
+** HyperText References in the current document.
+**
+** On entry
+** titles Set: if we want titles where available
+** Clear: we only get addresses.
+*/
+
+static char list_filename[256] = "\0";
+
+/*
+ * Returns the name of the file used for the List Page, if one has
+ * been created, as a full URL; otherwise, returns an empty string.
+ * - kw
+ */
+PUBLIC char * LYlist_temp_url NOARGS
+{
+ return list_filename;
+}
+
+PUBLIC int showlist ARGS2(
+ document *, newdoc,
+ BOOLEAN, titles)
+{
+ int cnt;
+ int refs, hidden_links;
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ FILE *fp0;
+ char *Address = NULL, *Title = NULL, *cp = NULL;
+ BOOLEAN intern_w_post = FALSE;
+ char *desc = "unknown field or link";
+
+ refs = HText_sourceAnchors(HTMainText);
+ hidden_links = HText_HiddenLinkCount(HTMainText);
+ if (refs <= 0 && hidden_links > 0 &&
+ LYHiddenLinks != HIDDENLINKS_SEPARATE) {
+ _statusline(NO_VISIBLE_REFS_FROM_DOC);
+ sleep(MessageSecs);
+ return(-1);
+ }
+ if (refs <= 0 && hidden_links <= 0) {
+ _statusline(NO_REFS_FROM_DOC);
+ sleep(MessageSecs);
+ return(-1);
+ }
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ /*
+ * Make the file a URL now.
+ */
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(list_filename, "file://localhost/%s", tempfile);
+#else
+ sprintf(list_filename, "file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ _statusline(CANNOT_OPEN_TEMP);
+ sleep(MessageSecs);
+ return(-1);
+ }
+
+ StrAllocCopy(newdoc->address, list_filename);
+ LYforce_HTML_mode = TRUE; /* force this file to be HTML */
+ LYforce_no_cache = TRUE; /* force this file to be new */
+
+
+ fprintf(fp0, "<head>\n");
+ LYAddMETAcharsetToFD(fp0, -1);
+ if (strchr(HTLoadedDocumentURL(), '"') == NULL) {
+ /*
+ * Insert a BASE tag so there is some way to relate the List Page
+ * file to its underlying document after we are done. It won't
+ * be actually used for resolving relative URLs. - kw
+ */
+ StrAllocCopy(Address, HTLoadedDocumentURL());
+ LYEntify(&Address, FALSE);
+ fprintf(fp0, "<base href=\"%s\">\n", Address);
+ FREE(Address);
+ }
+ fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
+ LIST_PAGE_TITLE);
+ fprintf(fp0, "<h1>You have reached the List Page</h1>\n");
+ fprintf(fp0, "<h2>%s Version %s</h2>\n", LYNX_NAME, LYNX_VERSION);
+ StrAllocCopy(Address, HTLoadedDocumentURL());
+ LYEntify(&Address, FALSE);
+ fprintf(fp0,
+ " References in %s<p>\n",
+ ((Address != NULL && *Address != '\0') ?
+ Address : "this document:"));
+ FREE(Address);
+ if (refs > 0) {
+ fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol" : "ul"));
+ if (hidden_links > 0)
+ fprintf(fp0, "<lh><em>Visible links:</em>\n");
+ }
+ if (hidden_links > 0) {
+ if (LYHiddenLinks == HIDDENLINKS_IGNORE)
+ hidden_links = 0;
+ }
+ for (cnt = 1; cnt <= refs; cnt++) {
+ HTChildAnchor *child = HText_childNumber(cnt);
+ HTAnchor *dest_intl = NULL;
+ HTAnchor *dest;
+ HTParentAnchor *parent;
+ char *address;
+ CONST char *title;
+
+ if (child == 0) {
+ /*
+ * child should not be 0 unless form field numbering is on
+ * and cnt is the number of a form input field.
+ * HText_FormDescNumber() will set desc to a description
+ * of what type of input field this is. We'll list it to
+ * ensure that the link numbers on the list page match the
+ * numbering in the original document, but won't create a
+ * forward link to the form. - FM && LE
+ *
+ * Changed to create a fake hidden link, to get the numbering
+ * right in connection with always treating this file as
+ * HIDDENLINKS_MERGE in GridText.c - kw
+ */
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+ HText_FormDescNumber(cnt, (char **)&desc);
+ fprintf(fp0,
+ "<li><a id=%d href=\"#%d\">form field</a> = <em>%s</em>\n",
+ cnt, cnt, desc);
+ }
+ continue;
+ }
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ dest_intl = HTAnchor_followTypedLink((HTAnchor *)child,
+ LINK_INTERNAL);
+#endif
+ dest = dest_intl ?
+ dest_intl : HTAnchor_followMainLink((HTAnchor *)child);
+ parent = HTAnchor_parent(dest);
+ if (!intern_w_post && dest_intl &&
+ HTMainAnchor && HTMainAnchor->post_data &&
+ parent->post_data &&
+ !strcmp(HTMainAnchor->post_data, parent->post_data)) {
+ /*
+ * Set flag to note that we had at least one internal link,
+ * if the document from which we are generating the list
+ * has assosiated POST data; after an extra check that the
+ * link destination really has hthe same POST data so that
+ * we can believe it is an internal link.
+ */
+ intern_w_post = TRUE;
+ }
+ address = HTAnchor_address(dest);
+ title = titles ? HTAnchor_title(parent) : NULL;
+ StrAllocCopy(Address, address);
+ FREE(address);
+ LYEntify(&Address, TRUE);
+ if (title && *title) {
+ StrAllocCopy(Title, title);
+ LYEntify(&Title, TRUE);
+ if (*Title) {
+ cp = strchr(Address, '#');
+ } else {
+ FREE(Title);
+ }
+ }
+
+ fprintf(fp0, "<li><a href=\"%s\"%s>%s%s%s%s%s</a>\n", Address,
+ dest_intl ? " TYPE=\"internal link\"" : "",
+ dest_intl ? "(internal) " : "",
+ ((HTAnchor*)parent != dest) && Title ? "in " : "",
+ (char *)(Title ? Title : Address),
+ (Title && cp) ? " - " : "",
+ (Title && cp) ? (cp+1) : "");
+
+ FREE(Address);
+ FREE(Title);
+ }
+
+ if (hidden_links > 0) {
+ if (refs > 0)
+ fprintf(fp0, "\n</%s>\n\n<p>\n",
+ ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol" : "ul"));
+ fprintf(fp0, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol continue" : "ul"));
+ fprintf(fp0, "<lh><em>Hidden links:</em>\n");
+ }
+
+ for (cnt = 0; cnt < hidden_links; cnt++) {
+ StrAllocCopy(Address, HText_HiddenLinkAt(HTMainText, cnt));
+ LYEntify(&Address, FALSE);
+ if (!(Address && *Address)) {
+ FREE(Address);
+ continue;
+ }
+ fprintf(fp0, "<li><a href=\"%s\">%s</a>\n", Address, Address);
+
+ FREE(Address);
+ }
+
+ fprintf(fp0,"\n</%s>\n</body>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol" : "ul"));
+
+ /*
+ * Make necessary changes to newdoc before returning to caller.
+ * If the intern_w_post flag is set, we keep the POST data in
+ * newdoc that have been passed in. They should be the same as
+ * in the loaded locument for which we generated the list.
+ * In that case the file we have written will be associated with
+ * the same POST data when it is loaded after we are done here,
+ * so that following one of the links we have marked as "internal
+ * link" can lead back to the underlying document with the right
+ * address+post_data combination. - kw
+ */
+ if (intern_w_post) {
+ newdoc->internal_link = TRUE;
+ } else {
+ FREE(newdoc->post_data);
+ FREE(newdoc->post_content_type);
+ newdoc->internal_link = FALSE;
+ }
+ newdoc->isHEAD = FALSE;
+ newdoc->safe = FALSE;
+ fclose(fp0);
+ return(0);
+}
+
+/* printlist - F.Macrides (macrides@sci.wfeb.edu)
+** ---------
+** Print a text/plain list of HyperText References
+** in the current document.
+**
+** On entry
+** titles Set: if we want titles where available
+** Clear: we only get addresses.
+*/
+PUBLIC void printlist ARGS2(
+ FILE *, fp,
+ BOOLEAN, titles)
+{
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+ int cnt;
+ int refs, hidden_links;
+ char *address = NULL;
+ char *desc = "unknown field or link";
+
+ refs = HText_sourceAnchors(HTMainText);
+ if (refs <= 0 && LYHiddenLinks != HIDDENLINKS_SEPARATE)
+ return;
+ hidden_links = HText_HiddenLinkCount(HTMainText);
+ if (refs <= 0 && hidden_links <= 0) {
+ return;
+ } else {
+ fprintf(fp, "\n%s\n\n", "References");
+ if (hidden_links > 0) {
+ fprintf(fp, " Visible links:\n");
+ if (LYHiddenLinks == HIDDENLINKS_IGNORE)
+ hidden_links = 0;
+ }
+ for (cnt = 1; cnt <= refs; cnt++) {
+ HTChildAnchor *child = HText_childNumber(cnt);
+ HTAnchor *dest;
+ HTParentAnchor *parent;
+ CONST char *title;
+
+ if (child == 0) {
+ /*
+ * child should not be 0 unless form field numbering is on
+ * and cnt is the number of a form intput field.
+ * HText_FormDescNumber() will set desc to a description
+ * of what type of input field this is. We'll create a
+ * within-document link to ensure that the link numbers on
+ * the list page match the numbering in the original document,
+ * but won't create a forward link to the form. - FM && LE
+ */
+ if (keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED) {
+ HText_FormDescNumber(cnt, (char **)&desc);
+ fprintf(fp, "%4d. form field = %s\n", cnt, desc);
+ }
+ continue;
+ }
+ dest = HTAnchor_followMainLink((HTAnchor *)child);
+ /*
+ * Ignore if child anchor points to itself, i.e. we had
+ * something like <A NAME=xyz HREF="#xyz"> and it is not
+ * treated as a hidden link. Useful if someone 'P'rints
+ * the List Page (which isn't a very useful action to do,
+ * but anyway...) - kw
+ */
+ if (dest == (HTAnchor *)child)
+ continue;
+ parent = HTAnchor_parent(dest);
+ title = titles ? HTAnchor_title(parent) : NULL;
+ address = HTAnchor_address(dest);
+ fprintf(fp, "%4d. %s%s\n", cnt,
+ ((HTAnchor*)parent != dest) && title ? "in " : "",
+ (title ? title : address));
+ FREE(address);
+#ifdef VMS
+ if (HadVMSInterrupt)
+ break;
+#endif /* VMS */
+ }
+
+ if (hidden_links > 0)
+ fprintf(fp, "%s Hidden links:\n", ((refs > 0) ? "\n" : ""));
+ for (cnt = 0; cnt < hidden_links; cnt++) {
+ StrAllocCopy(address, HText_HiddenLinkAt(HTMainText, cnt));
+ if (!(address && *address)) {
+ FREE(address);
+ continue;
+ }
+ fprintf(fp, "%4d. %s\n", ((cnt + 1) + refs), address);
+ FREE(address);
+#ifdef VMS
+ if (HadVMSInterrupt)
+ break;
+#endif /* VMS */
+ }
+ }
+ return;
+}
diff --git a/gnu/usr.bin/lynx/src/LYList.h b/gnu/usr.bin/lynx/src/LYList.h
new file mode 100644
index 00000000000..4a717284744
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYList.h
@@ -0,0 +1,11 @@
+
+#ifndef LYLIST_H
+#define LYLIST_H
+
+extern char * LYlist_temp_url NOPARAMS;
+extern int showlist PARAMS((document *newdoc, BOOLEAN titles));
+extern void printlist PARAMS((FILE *fp, BOOLEAN titles));
+
+#define LIST_PAGE_TITLE "Lynx List Page"
+
+#endif /* LYLIST_H */
diff --git a/gnu/usr.bin/lynx/src/LYLocal.c b/gnu/usr.bin/lynx/src/LYLocal.c
new file mode 100644
index 00000000000..871395612b8
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYLocal.c
@@ -0,0 +1,2287 @@
+/*
+** Routines to manipulate the local filesystem.
+** Written by: Rick Mallett, Carleton University
+** Report problems to rmallett@ccs.carleton.ca
+** Modified 18-Dec-95 David Trueman (david@cs.dal.ca):
+** Added OK_PERMIT compilation option.
+** Support replacement of compiled-in f)ull menu configuration via
+** DIRED_MENU definitions in lynx.cfg, so that more than one menu
+** can be driven by the same executable.
+** Modified Oct-96 Klaus Weide (kweide@tezcat.com):
+** Changed to use the library's HTList_* functions and macros for
+** managing the list of tagged file URLs.
+** Keep track of proper level of URL escaping, so that unusual filenames
+** which contain #% etc. are handled properly (some HTUnEscapeSome()'s
+** left in to be conservative, and to document where superfluous
+** unescaping took place before).
+** Dynamic memory instead of fixed length buffers in a few cases.
+** Other minor changes to make things work as intended.
+** Modified Jun-97 Klaus Weide (kweide@tezcat.com) & FM:
+** Modified the code handling DIRED_MENU to do more careful
+** checking of the selected file. In addition to "TAG", "FILE", and
+** "DIR", DIRED_MENU definitions in lynx.cfg now also recognize LINK as
+** a type. DIRED_MENU definitions with a type field of "LINK" are only
+** used if the current selection is a symbolic link ("FILE" and "DIR"
+** definitions are not used in that case). The default menu
+** definitions have been updated to reflect this change, and to avoid
+** the showing of menu items whose action would always fail - KW
+** Cast all code into the Lynx programming style. - FM
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAlert.h"
+#include "HTParse.h"
+#include "LYCurses.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYCharUtils.h"
+#include "LYStructs.h"
+#include "LYGetFile.h"
+#include "LYHistory.h"
+#include "LYUpload.h"
+#include "LYLocal.h"
+#include "LYSystem.h"
+
+#ifndef VMS
+#ifndef _WINDOWS
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#include <errno.h>
+#include <grp.h>
+#endif /*_WINDOWS */
+#endif /* VMS */
+
+#ifndef WEXITSTATUS
+# if HAVE_TYPE_UNIONWAIT
+# define WEXITSTATUS(status) (status.w_retcode)
+# else
+# define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
+# endif
+#endif
+
+#ifndef WTERMSIG
+# if HAVE_TYPE_UNIONWAIT
+# define WTERMSIG(status) (status.w_termsig)
+# else
+# define WTERMSIG(status) ((status) & 0x7f)
+# endif
+#endif
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+
+PRIVATE int LYExecv PARAMS((
+ char * path,
+ char ** argv,
+ char * msg));
+
+#ifdef DIRED_SUPPORT
+PUBLIC char LYPermitFileURL[256] = "\0";
+PUBLIC char LYDiredFileURL[256] = "\0";
+
+PRIVATE char *filename PARAMS((
+ char * prompt,
+ char * buf,
+ size_t bufsize));
+
+#ifdef OK_PERMIT
+PRIVATE BOOLEAN permit_location PARAMS((
+ char * destpath,
+ char * srcpath,
+ char ** newpath));
+#endif /* OK_PERMIT */
+
+PRIVATE char *render_item PARAMS((
+ char * s,
+ char * path,
+ char * dir,
+ char * buf,
+ int bufsize,
+ BOOLEAN url_syntax));
+
+PRIVATE struct dired_menu *menu_head = NULL;
+struct dired_menu {
+ int cond;
+#define DE_TAG 1
+#define DE_DIR 2
+#define DE_FILE 3
+#define DE_SYMLINK 4
+ char *sfx;
+ char *link;
+ char *rest;
+ char *href;
+ struct dired_menu *next;
+} defmenu[] = {
+/*
+ * The following initializations determine the contents of the f)ull menu
+ * selection when in dired mode. If any menu entries are defined in the
+ * configuration file via DIRED_MENU lines, then these default entries
+ * are discarded entirely.
+ */
+{ 0, "", "New File",
+"(in current directory)", "LYNXDIRED://NEW_FILE%d", NULL },
+
+{ 0, "", "New Directory",
+"(in current directory)", "LYNXDIRED://NEW_FOLDER%d", NULL },
+
+{ DE_FILE, "", "Install",
+"(of current selection)", "LYNXDIRED://INSTALL_SRC%p", NULL },
+{ DE_DIR, "", "Install",
+"(of current selection)", "LYNXDIRED://INSTALL_SRC%p", NULL },
+
+{ DE_FILE, "", "Modify File Name",
+"(of current selection)", "LYNXDIRED://MODIFY_NAME%p", NULL },
+{ DE_DIR, "", "Modify Directory Name",
+"(of current selection)", "LYNXDIRED://MODIFY_NAME%p", NULL },
+{ DE_SYMLINK, "", "Modify Name",
+"(of selected symbolic link)", "LYNXDIRED://MODIFY_NAME%p", NULL },
+
+#ifdef OK_PERMIT
+{ DE_FILE, "", "Modify File Permissions",
+"(of current selection)", "LYNXDIRED://PERMIT_SRC%p", NULL },
+{ DE_DIR, "", "Modify Directory Permissions",
+"(of current selection)", "LYNXDIRED://PERMIT_SRC%p", NULL },
+#endif /* OK_PERMIT */
+
+{ DE_FILE, "", "Change Location",
+"(of selected file)" , "LYNXDIRED://MODIFY_LOCATION%p", NULL },
+{ DE_DIR, "", "Change Location",
+"(of selected directory)", "LYNXDIRED://MODIFY_LOCATION%p", NULL },
+{ DE_SYMLINK, "", "Change Location",
+"(of selected symbolic link)", "LYNXDIRED://MODIFY_LOCATION%p", NULL },
+
+{ DE_FILE, "", "Remove File",
+ "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL },
+{ DE_DIR, "", "Remove Directory",
+ "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL },
+{ DE_SYMLINK, "", "Remove Symbolic Link",
+ "(current selection)", "LYNXDIRED://REMOVE_SINGLE%p", NULL },
+
+#if defined(OK_UUDECODE) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, "", "UUDecode",
+ "(current selection)", "LYNXDIRED://UUDECODE%p", NULL },
+#endif /* OK_UUDECODE && !ARCHIVE_ONLY */
+
+#if defined(OK_TAR) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, ".tar.Z", "Expand",
+ "(current selection)", "LYNXDIRED://UNTAR_Z%p", NULL },
+#endif /* OK_TAR && !ARCHIVE_ONLY */
+
+#if defined(OK_TAR) && defined(OK_GZIP) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, ".tar.gz", "Expand",
+ "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL },
+
+{ DE_FILE, ".tgz", "Expand",
+ "(current selection)", "LYNXDIRED://UNTAR_GZ%p", NULL },
+#endif /* OK_TAR && OK_GZIP && !ARCHIVE_ONLY */
+
+#ifndef ARCHIVE_ONLY
+{ DE_FILE, ".Z", "Uncompress",
+ "(current selection)", "LYNXDIRED://DECOMPRESS%p", NULL },
+#endif /* ARCHIVE_ONLY */
+
+#if defined(OK_GZIP) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, ".gz", "Uncompress",
+ "(current selection)", "LYNXDIRED://UNGZIP%p", NULL },
+#endif /* OK_GZIP && !ARCHIVE_ONLY */
+
+#if defined(OK_ZIP) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, ".zip", "Uncompress",
+ "(current selection)", "LYNXDIRED://UNZIP%p", NULL },
+#endif /* OK_ZIP && !ARCHIVE_ONLY */
+
+#if defined(OK_TAR) && !defined(ARCHIVE_ONLY)
+{ DE_FILE, ".tar", "UnTar",
+ "(current selection)", "LYNXDIRED://UNTAR%p", NULL },
+#endif /* OK_TAR && !ARCHIVE_ONLY */
+
+#ifdef OK_TAR
+{ DE_DIR, "", "Tar",
+ "(current selection)", "LYNXDIRED://TAR%p", NULL },
+#endif /* OK_TAR */
+
+#if defined(OK_TAR) && defined(OK_GZIP)
+{ DE_DIR, "", "Tar and compress",
+ "(using GNU gzip)", "LYNXDIRED://TAR_GZ%p", NULL },
+#endif /* OK_TAR && OK_GZIP */
+
+#ifdef OK_ZIP
+{ DE_DIR, "", "Package and compress",
+ "(using zip)", "LYNXDIRED://ZIP%p", NULL },
+#endif /* OK_ZIP */
+
+{ DE_FILE, "", "Compress",
+ "(using Unix compress)", "LYNXDIRED://COMPRESS%p", NULL },
+
+#ifdef OK_GZIP
+{ DE_FILE, "", "Compress",
+ "(using gzip)", "LYNXDIRED://GZIP%p", NULL },
+#endif /* OK_GZIP */
+
+#ifdef OK_ZIP
+{ DE_FILE, "", "Compress",
+ "(using zip)", "LYNXDIRED://ZIP%p", NULL },
+#endif /* OK_ZIP */
+
+{ DE_TAG, "", "Move all tagged items to another location.",
+ "", "LYNXDIRED://MOVE_TAGGED%d", NULL },
+
+{ DE_TAG, "", "Remove all tagged files and directories.",
+ "", "LYNXDIRED://REMOVE_TAGGED", NULL },
+
+{ DE_TAG, "", "Untag all tagged files and directories.",
+ "", "LYNXDIRED://CLEAR_TAGGED", NULL },
+
+{ 0, NULL, NULL,
+ NULL, NULL, NULL }
+};
+
+/*
+ * Remove all tagged files and directories.
+ */
+PRIVATE BOOLEAN remove_tagged NOARGS
+{
+ int c, ans;
+ char *cp, *tp;
+ char tmpbuf[1024];
+ char *testpath = NULL;
+ struct stat dir_info;
+ int count, i;
+ HTList *tag;
+ char *args[5];
+
+ if (HTList_isEmpty(tagged)) /* should never happen */
+ return 0;
+
+ _statusline("Remove all tagged files and directories (y or n): ");
+ c = LYgetch();
+ ans = TOUPPER(c);
+
+ count = 0;
+ tag = tagged;
+ while (ans == 'Y' && (cp = (char *)HTList_nextObject(tag)) != NULL) {
+ if (is_url(cp) == FILE_URL_TYPE) { /* unecessary check */
+ tp = cp;
+ if (!strncmp(tp, "file://localhost", 16)) {
+ tp += 16;
+ } else if (!strncmp(tp, "file:", 5)) {
+ tp += 5;
+ }
+ StrAllocCopy(testpath, tp);
+ HTUnEscape(testpath);
+ if ((i = strlen(testpath)) && testpath[i-1] == '/')
+ testpath[(i - 1)] = '\0';
+
+ /*
+ * Check the current status of the path to be deleted.
+ */
+ if (stat(testpath,&dir_info) == -1) {
+ sprintf(tmpbuf,
+ "System error - failed to get status of '%s'.",
+ testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return count;
+ } else {
+ args[0] = "rm";
+ args[1] = "-rf";
+ args[2] = testpath;
+ args[3] = (char *) 0;
+ sprintf(tmpbuf, "remove %s", testpath);
+ if (LYExecv(RM_PATH, args, tmpbuf) <= 0) {
+ FREE(testpath);
+ return ((count == 0) ? -1 : count);
+ }
+ ++count;
+ }
+ }
+ }
+ FREE(testpath);
+ clear_tags();
+ return count;
+}
+
+/*
+ * Move all tagged files and directories to a new location.
+ * Input is current directory.
+ * The tests in this function can, at best, prevent some user mistakes -
+ * anybody who relies on them for security is seriously misguided.
+ * If a user has enough permissions to move a file somewhere, the same
+ * uid with Lynx & dired can do the same thing.
+ */
+PRIVATE BOOLEAN modify_tagged ARGS1(
+ char *, testpath)
+{
+ char *cp;
+ dev_t dev;
+ ino_t inode;
+ uid_t owner;
+ char tmpbuf[1024];
+ char *savepath = NULL;
+ char *srcpath = NULL;
+ struct stat dir_info;
+ char *args[5];
+ int count = 0;
+ HTList *tag;
+
+ if (HTList_isEmpty(tagged)) /* should never happen */
+ return 0;
+
+ _statusline("Enter new location for tagged items: ");
+
+ tmpbuf[0] = '\0';
+ LYgetstr(tmpbuf, VISIBLE, sizeof(tmpbuf), NORECALL);
+ if (strlen(tmpbuf)) {
+ /*
+ * Determine the ownership of the current location.
+ */
+ /*
+ * This test used to always fail from the dired menu...
+ * changed to something that hopefully makes more sense - KW
+ */
+ if (testpath && *testpath && 0!=strcmp(testpath,"/")) {
+ /*
+ * testpath passed in and is not empty and not a single "/"
+ * (which would probably be bogus) - use it.
+ */
+ cp = testpath;
+ } else {
+ /*
+ * Prepare to get directory path from one of the tagged files.
+ */
+ cp = HTList_lastObject(tagged);
+ testpath = NULL; /* Won't be needed any more in this function,
+ set to NULL as a flag. */
+ if (!cp) /* Last resort, should never happen. */
+ cp = "/";
+ }
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ if (testpath == NULL) {
+ /*
+ * Get the directory containing the file or subdir.
+ */
+ cp = strip_trailing_slash(cp);
+ savepath = HTParse(".", cp, PARSE_PATH+PARSE_PUNCTUATION);
+ } else {
+ StrAllocCopy(savepath, cp);
+ }
+ HTUnEscape(savepath);
+ if (stat(savepath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", savepath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ FREE(savepath);
+ return 0;
+ }
+
+ /*
+ * Save the owner of the current location for later use.
+ * Also save the device and inode for location checking/
+ */
+ dev = dir_info.st_dev;
+ inode = dir_info.st_ino;
+ owner = dir_info.st_uid;
+
+ /*
+ * Replace ~/ references to the home directory.
+ */
+ if (!strncmp(tmpbuf, "~/", 2)) {
+ char *cp1 = NULL;
+ StrAllocCopy(cp1, Home_Dir());
+ StrAllocCat(cp1, (tmpbuf + 1));
+ if (strlen(cp1) > (sizeof(tmpbuf) - 1)) {
+ sprintf(tmpbuf, "%s", "Path too long");
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ FREE(savepath);
+ FREE(cp1);
+ return 0;
+ }
+ strcpy(tmpbuf, cp1);
+ FREE(cp1);
+ }
+
+ /*
+ * If path is relative, prefix it with current location.
+ */
+ if (tmpbuf[0] != '/') {
+ if (savepath[(strlen(savepath) - 1)] != '/')
+ StrAllocCat(savepath,"/");
+ StrAllocCat(savepath,tmpbuf);
+ } else {
+ StrAllocCopy(savepath,tmpbuf);
+ }
+
+ /*
+ * stat() the target location to determine type and ownership.
+ */
+ if (stat(savepath, &dir_info) == -1) {
+ sprintf(tmpbuf,"Unable to get status of '%s'.",savepath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ FREE(savepath);
+ return 0;
+ }
+
+ /*
+ * Make sure the source and target locations are not the same place.
+ */
+ if (dev == dir_info.st_dev && inode == dir_info.st_ino) {
+ _statusline(
+ "Source and destination are the same location - request ignored!");
+ sleep(AlertSecs);
+ FREE(savepath);
+ return 0;
+ }
+
+ /*
+ * Make sure the target location is a directory which is owned
+ * by the same uid as the owner of the current location.
+ */
+ if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ if (dir_info.st_uid == owner) {
+ count = 0;
+ tag = tagged;
+
+ /*
+ * Move all tagged items to the target location.
+ */
+ while ((cp = (char *)HTList_nextObject(tag)) != NULL) {
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ StrAllocCopy(srcpath, cp);
+ HTUnEscape(srcpath);
+
+ sprintf(tmpbuf, "move %s to %s", srcpath, savepath);
+ args[0] = "mv";
+ args[1] = srcpath;
+ args[2] = savepath;
+ args[3] = (char *) 0;
+ if (LYExecv(MV_PATH, args, tmpbuf) <= 0) {
+ if (count == 0)
+ count = -1;
+ break;
+ }
+ ++count;
+ }
+ FREE(srcpath);
+ FREE(savepath);
+ clear_tags();
+ return count;
+ } else {
+ _statusline(
+ "Destination has different owner! Request denied.");
+ sleep(AlertSecs);
+ FREE(srcpath);
+ FREE(savepath);
+ return 0;
+ }
+ } else {
+ _statusline(
+ "Destination is not a valid directory! Request denied.");
+ sleep(AlertSecs);
+ FREE(savepath);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Modify the name of the specified item.
+ */
+PRIVATE BOOLEAN modify_name ARGS1(
+ char *, testpath)
+{
+ char *cp;
+ char tmpbuf[512];
+ char newpath[512];
+ char savepath[512];
+ struct stat dir_info;
+ char *args[5];
+
+ /*
+ * Determine the status of the selected item.
+ */
+ testpath = strip_trailing_slash(testpath);
+
+ if (stat(testpath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ } else {
+ /*
+ * Change the name of the file or directory.
+ */
+ if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ cp = "Enter new name for directory: ";
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ cp = "Enter new name for file: ";
+ } else {
+ _statusline(
+ "The selected item is not a file or a directory! Request ignored.");
+ sleep(AlertSecs);
+ return 0;
+ }
+ if (filename(cp, tmpbuf, sizeof(tmpbuf)) == NULL)
+ return 0;
+
+ /*
+ * Do not allow the user to also change the location at this time.
+ */
+ if (strchr(tmpbuf, '/') != NULL) {
+ _statusline("Illegal character \"/\" found! Request ignored.");
+ sleep(AlertSecs);
+ } else if (strlen(tmpbuf) &&
+ (cp = strrchr(testpath, '/')) != NULL) {
+ strcpy(savepath,testpath);
+ *(++cp) = '\0';
+ strcpy(newpath,testpath);
+ strcat(newpath,tmpbuf);
+
+ /*
+ * Make sure the destination does not already exist.
+ */
+ if (stat(newpath, &dir_info) == -1) {
+ if (errno != ENOENT) {
+ sprintf(tmpbuf,
+ "Unable to determine status of '%s'.", newpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ } else {
+ sprintf(tmpbuf, "move %s to %s", savepath, newpath);
+ args[0] = "mv";
+ args[1] = savepath;
+ args[2] = newpath;
+ args[3] = (char *) 0;
+ if (LYExecv(MV_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ return 1;
+ }
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ _statusline(
+ "There is already a directory with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ _statusline(
+ "There is already a file with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else {
+ _statusline(
+ "The specified name is already in use! Request ignored.");
+ sleep(AlertSecs);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Change the location of a file or directory.
+ */
+PRIVATE BOOLEAN modify_location ARGS1(
+ char *, testpath)
+{
+ int mode;
+ char *cp;
+ dev_t dev;
+ ino_t inode;
+ uid_t owner;
+ char tmpbuf[1024];
+ char newpath[512];
+ char savepath[512];
+ struct stat dir_info;
+ char *args[5];
+
+ /*
+ * Determine the status of the selected item.
+ */
+ testpath = strip_trailing_slash(testpath);
+
+ if (stat(testpath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ /*
+ * Change the location of the file or directory.
+ */
+ if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ cp = "Enter new location for directory: ";
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ cp = "Enter new location for file: ";
+ } else {
+ _statusline(
+ "The specified item is not a file or a directory - request ignored.");
+ sleep(AlertSecs);
+ return 0;
+ }
+ if (filename(cp, tmpbuf, sizeof(tmpbuf)) == NULL)
+ return 0;
+ if (strlen(tmpbuf)) {
+ strcpy(savepath, testpath);
+ strcpy(newpath, testpath);
+
+ /*
+ * Allow ~/ references to the home directory.
+ */
+ if (!strncmp(tmpbuf,"~/",2)) {
+ strcpy(newpath, Home_Dir());
+ strcat(newpath, (tmpbuf + 1));
+ strcpy(tmpbuf, newpath);
+ }
+ if (tmpbuf[0] != '/') {
+ if ((cp = strrchr(newpath,'/')) != NULL) {
+ *++cp = '\0';
+ strcat(newpath,tmpbuf);
+ } else {
+ _statusline("Unexpected failure - unable to find trailing \"/\"");
+ sleep(AlertSecs);
+ return 0;
+ }
+ } else {
+ strcpy(newpath,tmpbuf);
+ }
+
+ /*
+ * Make sure the source and target have the same owner (uid).
+ */
+ dev = dir_info.st_dev;
+ mode = dir_info.st_mode;
+ inode = dir_info.st_ino;
+ owner = dir_info.st_uid;
+ if (stat(newpath, &dir_info) == -1) {
+ sprintf(tmpbuf,"Unable to get status of '%s'.",newpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+ if ((dir_info.st_mode & S_IFMT) != S_IFDIR) {
+ _statusline(
+ "Destination is not a valid directory! Request denied.");
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ /*
+ * Make sure the source and target are not the same location.
+ */
+ if (dev == dir_info.st_dev && inode == dir_info.st_ino) {
+ _statusline(
+ "Source and destination are the same location! Request ignored!");
+ sleep(AlertSecs);
+ return 0;
+ }
+ if (dir_info.st_uid == owner) {
+ sprintf(tmpbuf,"move %s to %s",savepath,newpath);
+ args[0] = "mv";
+ args[1] = savepath;
+ args[2] = newpath;
+ args[3] = (char *) 0;
+ if (LYExecv(MV_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ return 1;
+ } else {
+ _statusline("Destination has different owner! Request denied.");
+ sleep(AlertSecs);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Modify name or location of a file or directory on localhost.
+ */
+PUBLIC BOOLEAN local_modify ARGS2(
+ document *, doc,
+ char **, newpath)
+{
+ int c, ans;
+ char *cp;
+ char testpath[512]; /* a bit ridiculous */
+ int count;
+
+ if (!HTList_isEmpty(tagged)) {
+ cp = doc->address;
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ strcpy(testpath, cp);
+ HTUnEscapeSome(testpath, "/");
+ count = modify_tagged(testpath);
+
+ if (doc->link > (nlinks-count - 1))
+ doc->link = (nlinks-count - 1);
+ doc->link = (doc->link < 0) ?
+ 0 : doc->link;
+
+ return count;
+ } else if (doc->link < 0 || doc->link > nlinks) {
+ /*
+ * Added protection.
+ */
+ return 0;
+ }
+
+ /*
+ * Do not allow simultaneous change of name and location as in Unix.
+ * This reduces functionality but reduces difficulty for the novice.
+ */
+#ifdef OK_PERMIT
+ _statusline("Modify name, location, or permission (n, l, or p): ");
+#else
+ _statusline("Modify name, or location (n or l): ");
+#endif /* OK_PERMIT */
+ c = LYgetch();
+ ans = TOUPPER(c);
+
+ if (strchr("NLP", ans) != NULL) {
+ cp = links[doc->link].lname;
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if(!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ strcpy(testpath, cp);
+ HTUnEscape(testpath);
+
+ if (ans == 'N') {
+ return(modify_name(testpath));
+ } else if (ans == 'L') {
+ if (modify_location(testpath)) {
+ if (doc->link == (nlinks-1))
+ --doc->link;
+ return 1;
+ }
+#ifdef OK_PERMIT
+ } else if (ans == 'P') {
+ return(permit_location(NULL, testpath, newpath));
+#endif /* OK_PERMIT */
+ } else {
+ /*
+ * Code for changing ownership needed here.
+ */
+ _statusline("This feature not yet implemented!");
+ sleep(AlertSecs);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Create a new empty file in the current directory.
+ */
+PRIVATE BOOLEAN create_file ARGS1(
+ char *, current_location)
+{
+ char tmpbuf[512];
+ char testpath[512];
+ struct stat dir_info;
+ char *args[5];
+ char *bad_chars = ".~/";
+
+ if (filename("Enter name of file to create: ",
+ tmpbuf, sizeof(tmpbuf)) == NULL) {
+ return 0;
+ }
+
+ if (!no_dotfiles && show_dotfiles) {
+ bad_chars = "~/";
+ }
+
+ if (strstr(tmpbuf, "//") != NULL) {
+ _statusline("Illegal redirection \"//\" found! Request ignored.");
+ sleep(AlertSecs);
+ } else if (strlen(tmpbuf) && strchr(bad_chars, tmpbuf[0]) == NULL) {
+ strcpy(testpath,current_location);
+ if (testpath[(strlen(testpath) - 1)] != '/') {
+ strcat(testpath,"/");
+ }
+
+ /*
+ * Append the target filename to the current location.
+ */
+ strcat(testpath, tmpbuf);
+
+ /*
+ * Make sure the target does not already exist
+ */
+ if (stat(testpath, &dir_info) == -1) {
+ if (errno != ENOENT) {
+ sprintf(tmpbuf,
+ "Unable to determine status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+ sprintf(tmpbuf,"create %s",testpath);
+ args[0] = "touch";
+ args[1] = testpath;
+ args[2] = (char *) 0;
+ if (LYExecv(TOUCH_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ return 1;
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ _statusline(
+ "There is already a directory with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ _statusline(
+ "There is already a file with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else {
+ _statusline(
+ "The specified name is already in use! Request ignored.");
+ sleep(AlertSecs);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Create a new directory in the current directory.
+ */
+PRIVATE BOOLEAN create_directory ARGS1(
+ char *, current_location)
+{
+ char tmpbuf[512];
+ char testpath[512];
+ struct stat dir_info;
+ char *args[5];
+ char *bad_chars = ".~/";
+
+ if (filename("Enter name for new directory: ",
+ tmpbuf, sizeof(tmpbuf)) == NULL) {
+ return 0;
+ }
+
+ if (!no_dotfiles && show_dotfiles) {
+ bad_chars = "~/";
+ }
+
+ if (strstr(tmpbuf, "//") != NULL) {
+ _statusline("Illegal redirection \"//\" found! Request ignored.");
+ sleep(AlertSecs);
+ } else if (strlen(tmpbuf) && strchr(bad_chars, tmpbuf[0]) == NULL) {
+ strcpy(testpath,current_location);
+ if (testpath[(strlen(testpath) - 1)] != '/') {
+ strcat(testpath,"/");
+ }
+ strcat(testpath, tmpbuf);
+
+ /*
+ * Make sure the target does not already exist.
+ */
+ if (stat(testpath, &dir_info) == -1) {
+ if (errno != ENOENT) {
+ sprintf(tmpbuf,
+ "Unable to determine status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+ sprintf(tmpbuf,"make directory %s",testpath);
+ args[0] = "mkdir";
+ args[1] = testpath;
+ args[2] = (char *) 0;
+ if (LYExecv(MKDIR_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ return 1;
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ _statusline(
+ "There is already a directory with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ _statusline(
+ "There is already a file with that name! Request ignored.");
+ sleep(AlertSecs);
+ } else {
+ _statusline(
+ "The specified name is already in use! Request ignored.");
+ sleep(AlertSecs);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Create a file or a directory at the current location.
+ */
+PUBLIC BOOLEAN local_create ARGS1(
+ document *, doc)
+{
+ int c, ans;
+ char *cp;
+ char testpath[512];
+
+ _statusline("Create file or directory (f or d): ");
+ c = LYgetch();
+ ans = TOUPPER(c);
+
+ cp = doc->address;
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ strcpy(testpath,cp);
+ HTUnEscape(testpath);
+
+ if (ans == 'F') {
+ return(create_file(testpath));
+ } else if (ans == 'D') {
+ return(create_directory(testpath));
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Remove a single file or directory.
+ */
+PRIVATE BOOLEAN remove_single ARGS1(
+ char *, testpath)
+{
+ int c;
+ char *cp;
+ char tmpbuf[1024];
+ struct stat dir_info;
+ char *args[5];
+
+ /*
+ * lstat() first in case its a symbolic link.
+ */
+ if (lstat(testpath, &dir_info) == -1 &&
+ stat(testpath, &dir_info) == -1) {
+ sprintf(tmpbuf,
+ "System error - failed to get status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ /*
+ * Locate the filename portion of the path.
+ */
+ if ((cp = strrchr(testpath, '/')) != NULL) {
+ ++cp;
+ } else {
+ cp = testpath;
+ }
+ if ((dir_info.st_mode & S_IFMT) == S_IFDIR) {
+ if (strlen(cp) < 37) {
+ sprintf(tmpbuf,
+ "Remove '%s' and all of its contents (y or n): ", cp);
+ } else {
+ sprintf(tmpbuf,
+ "Remove directory and all of its contents (y or n): ");
+ }
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFREG) {
+ if (strlen(cp) < 60) {
+ sprintf(tmpbuf, "Remove file '%s' (y or n): ", cp);
+ } else {
+ sprintf(tmpbuf, "Remove file (y or n): ");
+ }
+#ifdef S_IFLNK
+ } else if ((dir_info.st_mode & S_IFMT) == S_IFLNK) {
+ if (strlen(cp) < 50) {
+ sprintf(tmpbuf, "Remove symbolic link '%s' (y or n): ", cp);
+ } else {
+ sprintf(tmpbuf, "Remove symbolic link (y or n): ");
+ }
+#endif
+ } else {
+ sprintf(tmpbuf, "Unable to determine status of '%s'.", testpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ }
+ _statusline(tmpbuf);
+
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ sprintf(tmpbuf,"remove %s",testpath);
+ args[0] = "rm";
+ args[1] = "-rf";
+ args[2] = testpath;
+ args[3] = (char *) 0;
+ if (LYExecv(RM_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Remove a file or a directory.
+ */
+PUBLIC BOOLEAN local_remove ARGS1(
+ document *, doc)
+{
+ char *cp, *tp;
+ char testpath[512];
+ int count, i;
+
+ if (!HTList_isEmpty(tagged)) {
+ count = remove_tagged();
+ if (doc->link > (nlinks-count - 1))
+ doc->link = (nlinks-count - 1);
+ doc->link = (doc->link < 0) ?
+ 0 : doc->link;
+ return count;
+ } else if (doc->link < 0 || doc->link > nlinks) {
+ return 0;
+ }
+ cp = links[doc->link].lname;
+ if (is_url(cp) == FILE_URL_TYPE) {
+ tp = cp;
+ if (!strncmp(tp, "file://localhost", 16)) {
+ tp += 16;
+ } else if (!strncmp(tp, "file:", 5)) {
+ tp += 5;
+ }
+ strcpy(testpath, tp);
+ HTUnEscape(testpath);
+ if ((i = strlen(testpath)) && testpath[i - 1] == '/')
+ testpath[(i - 1)] = '\0';
+ if (remove_single(testpath)) {
+ if (doc->link == (nlinks - 1))
+ --doc->link;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef OK_PERMIT
+/*
+ * Table of permission strings and chmod values.
+ * Makes the code a bit cleaner.
+ */
+static struct {
+ char *string_mode; /* Key for value below */
+ long permit_bits; /* Value for chmod/whatever */
+} permissions[] = {
+ {"IRUSR", S_IRUSR},
+ {"IWUSR", S_IWUSR},
+ {"IXUSR", S_IXUSR},
+ {"IRGRP", S_IRGRP},
+ {"IWGRP", S_IWGRP},
+ {"IXGRP", S_IXGRP},
+ {"IROTH", S_IROTH},
+ {"IWOTH", S_IWOTH},
+ {"IXOTH", S_IXOTH},
+ {NULL, 0} /* Don't include setuid and friends;
+ use shell access for that. */
+};
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode&0xF000) == 0x4000)
+#endif /* !S_ISDIR */
+
+PRIVATE char LYValidPermitFile[256] = "\0";
+
+/*
+ * Handle DIRED permissions.
+ */
+PRIVATE BOOLEAN permit_location ARGS3(
+ char *, destpath,
+ char *, srcpath,
+ char **, newpath)
+{
+#ifndef UNIX
+ _statusline("Sorry, don't know how to permit non-UNIX files yet.");
+ sleep(AlertSecs);
+ return(0);
+#else
+ static char tempfile[256] = "\0";
+ static BOOLEAN first = TRUE;
+ char *cp;
+ char tmpbuf[LINESIZE];
+ struct stat dir_info;
+
+ if (srcpath) {
+ /*
+ * Create form.
+ */
+ FILE *fp0;
+ char * user_filename;
+ struct group * grp;
+ char * group_name;
+
+ /*
+ * A couple of sanity tests.
+ */
+ srcpath = strip_trailing_slash(srcpath);
+ if (strncmp(srcpath, "file://localhost", 16) == 0)
+ srcpath += 16;
+ if (lstat(srcpath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", srcpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ } else if ((dir_info.st_mode & S_IFMT) != S_IFDIR &&
+ (dir_info.st_mode & S_IFMT) != S_IFREG) {
+ _statusline(
+ "The specified item is not a file nor a directory - request ignored.");
+ sleep(AlertSecs);
+ return(0);
+ }
+
+ user_filename = srcpath;
+ cp = strrchr(srcpath, '/');
+ if (cp != NULL) {
+ user_filename = (cp + 1);
+ }
+
+ if (first) {
+ /*
+ * Get an unused tempfile name. - FM
+ */
+ tempname(tempfile, NEW_FILE);
+ }
+
+ /*
+ * Open the tempfile for writing and set its
+ * protection in case this wasn't done via an
+ * external umask. - FM
+ */
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ _statusline("Unable to open permit options file");
+ sleep(AlertSecs);
+ return(0);
+ }
+
+ if (first) {
+ /*
+ * Make the tempfile a URL.
+ */
+ strcpy(LYPermitFileURL, "file://localhost");
+ strcat(LYPermitFileURL, tempfile);
+ first = FALSE;
+ }
+ StrAllocCopy(*newpath, LYPermitFileURL);
+
+ grp = getgrgid(dir_info.st_gid);
+ if (grp == NULL) {
+ group_name = "";
+ } else {
+ group_name = grp->gr_name;
+ }
+
+ LYstrncpy(LYValidPermitFile,
+ srcpath,
+ (sizeof(LYValidPermitFile) - 1));
+
+ fprintf(fp0, "<Html><Head>\n<Title>%s</Title>\n</Head>\n<Body>\n",
+ PERMIT_OPTIONS_TITLE);
+ fprintf(fp0,"<H1>Permissions for %s</H1>\n", user_filename);
+ { /*
+ * Prevent filenames which include '#' or '?' from messing it up.
+ */
+ char * srcpath_url = HTEscape(srcpath, URL_PATH);
+ fprintf(fp0, "<Form Action=\"LYNXDIRED://PERMIT_LOCATION%s\">\n",
+ srcpath_url);
+ FREE(srcpath_url);
+ }
+
+ fprintf(fp0, "<Ol><Li>Specify permissions below:<Br><Br>\n");
+ fprintf(fp0, "Owner:<Br>\n");
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IRUSR\" %s> Read<Br>\n",
+ (dir_info.st_mode & S_IRUSR) ? "checked" : "");
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IWUSR\" %s> Write<Br>\n",
+ (dir_info.st_mode & S_IWUSR) ? "checked" : "");
+ /*
+ * If restricted, only change eXecute permissions on directories.
+ */
+ if (!no_change_exec_perms || S_ISDIR(dir_info.st_mode))
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IXUSR\" %s> %s<Br>\n",
+ (dir_info.st_mode & S_IXUSR) ? "checked" : "",
+ S_ISDIR(dir_info.st_mode) ? "Search" : "Execute");
+
+ fprintf(fp0, "Group %s:<Br>\n", group_name);
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IRGRP\" %s> Read<Br>\n",
+ (dir_info.st_mode & S_IRGRP) ? "checked" : "");
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IWGRP\" %s> Write<Br>\n",
+ (dir_info.st_mode & S_IWGRP) ? "checked" : "");
+ /*
+ * If restricted, only change eXecute permissions on directories.
+ */
+ if (!no_change_exec_perms || S_ISDIR(dir_info.st_mode))
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IXGRP\" %s> %s<Br>\n",
+ (dir_info.st_mode & S_IXGRP) ? "checked" : "",
+ S_ISDIR(dir_info.st_mode) ? "Search" : "Execute");
+
+ fprintf(fp0, "Others:<Br>\n");
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IROTH\" %s> Read<Br>\n",
+ (dir_info.st_mode & S_IROTH) ? "checked" : "");
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IWOTH\" %s> Write<Br>\n",
+ (dir_info.st_mode & S_IWOTH) ? "checked" : "");
+ /*
+ * If restricted, only change eXecute permissions on directories.
+ */
+ if (!no_change_exec_perms || S_ISDIR(dir_info.st_mode))
+ fprintf(fp0,
+ "<Input Type=\"checkbox\" Name=\"mode\" Value=\"IXOTH\" %s> %s<Br>\n",
+ (dir_info.st_mode & S_IXOTH) ? "checked" : "",
+ S_ISDIR(dir_info.st_mode) ? "Search" : "Execute");
+
+ fprintf(fp0,
+"<Br>\n<Li><Input Type=\"submit\" Value=\"Submit\"> \
+form to permit %s %s.\n</Ol>\n</Form>\n",
+ (dir_info.st_mode & S_IFMT) == S_IFDIR ? "directory" : "file",
+ user_filename);
+ fprintf(fp0, "</Body></Html>");
+ fclose(fp0);
+
+ LYforce_no_cache = TRUE;
+ return(PERMIT_FORM_RESULT); /* Special flag for LYMainLoop */
+
+ } else { /* The form being activated. */
+ mode_t new_mode = 0;
+ char *args[5];
+ char amode[10];
+
+ /*
+ * Make sure we have a valid set-permission
+ * file comparison string loaded via a previous
+ * call with srcpath != NULL. - KW
+ */
+ if (LYValidPermitFile[0] == '\0') {
+ if (LYCursesON)
+ HTAlert(INVALID_PERMIT_URL);
+ else
+ fprintf(stderr, "%s\n", INVALID_PERMIT_URL);
+ if (TRACE)
+ fprintf(stderr, "permit_location: called for <%s>.\n",
+ (destpath ?
+ destpath : "NULL URL pointer"));
+ return 0;
+ }
+ cp = destpath;
+ while (*cp != '\0' && *cp != '?') { /* Find filename */
+ cp++;
+ }
+ if (*cp == '\0') {
+ return(0); /* Nothing to permit. */
+ }
+ *cp++ = '\0'; /* Null terminate file name and
+ start working on the masks. */
+
+ HTUnEscape(destpath); /* Will now operate only on filename part. */
+
+ /*
+ * Make sure that the file string is the one from
+ * the last displayed File Permissions menu. - KW
+ */
+ if (strcmp(destpath, LYValidPermitFile)) {
+ if (LYCursesON)
+ HTAlert(INVALID_PERMIT_URL);
+ else
+ fprintf(stderr, "%s\n", INVALID_PERMIT_URL);
+ if (TRACE)
+ fprintf(stderr, "permit_location: called for file '%s'.\n",
+ destpath);
+ return 0;
+ }
+
+ /*
+ * A couple of sanity tests.
+ */
+ destpath = strip_trailing_slash(destpath);
+ if (stat(destpath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", destpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ } else if ((dir_info.st_mode & S_IFMT) != S_IFDIR &&
+ (dir_info.st_mode & S_IFMT) != S_IFREG) {
+ _statusline(
+ "The specified item is not a file nor a directory - request ignored.");
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ /*
+ * Cycle over permission strings.
+ */
+ while(*cp != '\0') {
+ char *cr = cp;
+
+ while(*cr != '\0' && *cr != '&') { /* GET data split by '&'. */
+ cr++;
+ }
+ if (*cr != '\0') {
+ *cr++ = '\0';
+ }
+ if (strncmp(cp, "mode=", 5) == 0) { /* Magic string. */
+ int i;
+
+ for(i = 0; permissions[i].string_mode != NULL; i++) {
+ if (strcmp(permissions[i].string_mode, cp+5) == 0) {
+ /*
+ * If restricted, only change eXecute
+ * permissions on directories.
+ */
+ if (!no_change_exec_perms ||
+ strchr(cp+5,'X') == NULL ||
+ S_ISDIR(dir_info.st_mode))
+ new_mode |= permissions[i].permit_bits;
+ break;
+ }
+ }
+ if (permissions[i].string_mode == NULL) {
+ _statusline("Invalid mode format.");
+ sleep(AlertSecs);
+ return 0;
+ }
+ } else {
+ _statusline("Invalid syntax format.");
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ cp = cr;
+ }
+
+#ifdef UNIX
+ /*
+ * Call chmod().
+ */
+ sprintf(tmpbuf, "chmod %.4o %s", (unsigned int)new_mode, destpath);
+ sprintf(amode, "%.4o", (unsigned int)new_mode);
+ args[0] = "chmod";
+ args[1] = amode;
+ args[2] = destpath;
+ args[3] = (char *) 0;
+ if (LYExecv(CHMOD_PATH, args, tmpbuf) <= 0) {
+ return (-1);
+ }
+#endif /* UNIX */
+ LYforce_no_cache = TRUE; /* Force update of dired listing. */
+ return 1;
+ }
+#endif /* !UNIX */
+}
+#endif /* OK_PERMIT */
+
+/*
+ * Display or remove a tag from a given link.
+ */
+PUBLIC void tagflag ARGS2(
+ int, flag,
+ int, cur)
+{
+ if (nlinks > 0) {
+ move(links[cur].ly, 2);
+ stop_reverse();
+ if (flag == ON) {
+ addch('+');
+ } else {
+ addch(' ');
+ }
+
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ if (!LYShowCursor)
+ move((LYlines - 1), (LYcols - 1)); /* get cursor out of the way */
+ else
+#endif /* FANCY CURSES || USE_SLANG */
+ /*
+ * Never hide the cursor if there's no FANCY CURSES.
+ */
+ move(links[cur].ly, links[cur].lx);
+
+ refresh();
+ }
+}
+
+/*
+ * Handle DIRED tags.
+ */
+PUBLIC void showtags ARGS1(
+ HTList *, t)
+{
+ int i;
+ HTList *s;
+ char *name;
+
+ for (i = 0; i < nlinks; i++) {
+ s = t;
+ while ((name = HTList_nextObject(s)) != NULL) {
+ if (!strcmp(links[i].lname, name)) {
+ tagflag(ON, i);
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Perform file management operations for LYNXDIRED URL's.
+ * Attempt to be consistent. These are (pseudo) URLs - i.e. they should
+ * be in URL syntax: some bytes will be URL-escaped with '%'. This is
+ * necessary because these (pseudo) URLs will go through some of the same
+ * kinds of interpretations and mutilations as real ones: HTParse, stripping
+ * off #fragments etc. (Some access schemes currently have special rules
+ * about not escaping parsing '#' "the URL way" built into HTParse, but that
+ * doesn't look like a clean way.)
+ */
+PUBLIC int local_dired ARGS1(
+ document *, doc)
+{
+ char *line_url; /* will point to doc's address, which is a URL */
+ char *line = NULL; /* same as line_url, but HTUnEscaped, will be alloced */
+ char *cp, *tp, *bp;
+ char tmpbuf[256];
+ char buffer[512];
+
+ line_url = doc->address;
+ if (TRACE)
+ fprintf(stderr, "local_dired: called for <%s>.\n",
+ (line_url ?
+ line_url : "NULL URL pointer"));
+ HTUnEscapeSome(line_url, "/"); /* don't mess too much with *doc */
+
+ StrAllocCopy(line, line_url);
+ HTUnEscape(line); /* _file_ (not URL) syntax, for those functions
+ that need it. Don't forget to FREE it. */
+
+ tp = NULL;
+ if (!strncmp(line, "LYNXDIRED://NEW_FILE", 20)) {
+ if (create_file(&line[20]) > 0)
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://NEW_FOLDER", 22)) {
+ if (create_directory(&line[22]) > 0)
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://INSTALL_SRC", 23)) {
+ local_install(NULL, &line[23], &tp);
+ StrAllocCopy(doc->address, tp);
+ FREE(line);
+ return 0;
+ } else if (!strncmp(line, "LYNXDIRED://INSTALL_DEST", 24)) {
+ local_install(&line[24], NULL, &tp);
+ LYpop(doc);
+ } else if (!strncmp(line, "LYNXDIRED://MODIFY_NAME", 23)) {
+ if (modify_name(&line[23]) > 0)
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://MODIFY_LOCATION", 27)) {
+ if (modify_location(&line[27]) > 0)
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://MOVE_TAGGED", 23)) {
+ if (modify_tagged(&line_url[23]) > 0)
+ LYforce_no_cache = TRUE;
+#ifdef OK_PERMIT
+ } else if (!strncmp(line, "LYNXDIRED://PERMIT_SRC", 22)) {
+ permit_location(NULL, &line[22], &tp);
+ if (tp)
+ /*
+ * One of the checks may have failed.
+ */
+ StrAllocCopy(doc->address, tp);
+ FREE(line);
+ return 0;
+ } else if (!strncmp(line, "LYNXDIRED://PERMIT_LOCATION", 27)) {
+ permit_location(&line_url[27], NULL, &tp);
+#endif /* OK_PERMIT */
+ } else if (!strncmp(line, "LYNXDIRED://REMOVE_SINGLE", 25)) {
+ if (remove_single(&line[25]) > 0)
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://REMOVE_TAGGED", 25)) {
+ if (remove_tagged())
+ LYforce_no_cache = TRUE;
+ } else if (!strncmp(line, "LYNXDIRED://CLEAR_TAGGED", 24)) {
+ clear_tags();
+ } else if (!strncmp(line, "LYNXDIRED://UPLOAD", 18)) {
+ /*
+ * They're written by LYUpload_options() HTUnEscaped;
+ * don't want to change that for now... so pass through
+ * without more unescaping. Directory names containing
+ * '#' will probably fail.
+ */
+ if (LYUpload(line_url))
+ LYforce_no_cache = TRUE;
+ } else {
+ if (line[(strlen(line) - 1)] == '/')
+ line[strlen(line)-1] = '\0';
+ if ((cp = strrchr(line, '/')) == NULL) {
+ FREE(line);
+ return 0;
+ }
+
+ /*
+ * Construct the appropriate system command taking care to
+ * escape all path references to avoid spoofing the shell.
+ */
+ *buffer = '\0';
+ if (!strncmp(line, "LYNXDIRED://DECOMPRESS", 22)) {
+ tp = quote_pathname(line + 22);
+ sprintf(buffer,"%s %s", UNCOMPRESS_PATH, tp);
+ FREE(tp);
+
+#if defined(OK_UUDECODE) && !defined(ARCHIVE_ONLY)
+ } else if (!strncmp(line, "LYNXDIRED://UUDECODE", 20)) {
+ tp = quote_pathname(line + 20);
+ sprintf(buffer,"%s %s", UUDECODE_PATH, tp);
+ _statusline(
+ "Warning! UUDecoded file will exist in the directory you started Lynx.");
+ sleep(AlertSecs);
+ FREE(tp);
+#endif /* OK_UUDECODE && !ARCHIVE_ONLY */
+
+#ifdef OK_TAR
+# ifndef ARCHIVE_ONLY
+# ifdef OK_GZIP
+ } else if (!strncmp(line, "LYNXDIRED://UNTAR_GZ", 20)) {
+ tp = quote_pathname(line+20);
+ *cp++ = '\0';
+ cp = quote_pathname(line + 20);
+ sprintf(buffer, "%s -qdc %s | (cd %s; %s -xf -)",
+ GZIP_PATH, tp, cp, TAR_PATH);
+ FREE(cp);
+ FREE(tp);
+# endif /* OK_GZIP */
+
+ } else if (!strncmp(line, "LYNXDIRED://UNTAR_Z", 19)) {
+ tp = quote_pathname(line + 19);
+ *cp++ = '\0';
+ cp = quote_pathname(line + 19);
+ sprintf(buffer, "%s %s | (cd %s; %s -xf -)",
+ ZCAT_PATH, tp, cp, TAR_PATH);
+ FREE(cp);
+ FREE(tp);
+
+ } else if (!strncmp(line, "LYNXDIRED://UNTAR", 17)) {
+ tp = quote_pathname(line + 17);
+ *cp++ = '\0';
+ cp = quote_pathname(line + 17);
+ sprintf(buffer, "cd %s; %s -xf %s", cp, TAR_PATH, tp);
+ FREE(cp);
+ FREE(tp);
+# endif /* !ARCHIVE_ONLY */
+
+# ifdef OK_GZIP
+ } else if (!strncmp(line, "LYNXDIRED://TAR_GZ", 18)) {
+ *cp++ = '\0';
+ cp = quote_pathname(cp);
+ tp = quote_pathname(line + 18);
+ sprintf(buffer, "(cd %s; %s -cf - %s) | %s -qc >%s/%s.tar.gz",
+ tp, TAR_PATH, cp, GZIP_PATH, tp, cp);
+ FREE(cp);
+ FREE(tp);
+# endif /* OK_GZIP */
+
+ } else if (!strncmp(line, "LYNXDIRED://TAR_Z", 17)) {
+ *cp++ = '\0';
+ cp = quote_pathname(cp);
+ tp = quote_pathname(line + 17);
+ sprintf(buffer, "(cd %s; %s -cf - %s) | %s >%s/%s.tar.Z",
+ tp, TAR_PATH, cp, COMPRESS_PATH, tp, cp);
+ FREE(cp);
+ FREE(tp);
+
+ } else if (!strncmp(line, "LYNXDIRED://TAR", 15)) {
+ *cp++ = '\0';
+ cp = quote_pathname(cp);
+ tp = quote_pathname(line + 15);
+ sprintf(buffer, "(cd %s; %s -cf %s.tar %s)",
+ tp, TAR_PATH, cp, cp);
+ FREE(cp);
+ FREE(tp);
+#endif /* OK_TAR */
+
+#ifdef OK_GZIP
+ } else if (!strncmp(line, "LYNXDIRED://GZIP", 16)) {
+ tp = quote_pathname(line + 16);
+ sprintf(buffer, "%s -q %s", GZIP_PATH, tp);
+ FREE(tp);
+#ifndef ARCHIVE_ONLY
+ } else if (!strncmp(line, "LYNXDIRED://UNGZIP", 18)) {
+ tp = quote_pathname(line + 18);
+ sprintf(buffer, "%s -d %s", GZIP_PATH, tp);
+ FREE(tp);
+#endif /* !ARCHIVE_ONLY */
+#endif /* OK_GZIP */
+
+#ifdef OK_ZIP
+ } else if (!strncmp(line, "LYNXDIRED://ZIP", 15)) {
+ tp = quote_pathname(line + 15);
+ *cp++ = '\0';
+ bp = quote_pathname(cp);
+ cp = quote_pathname(line + 15);
+ sprintf(buffer, "cd %s; %s -rq %s.zip %s", cp, ZIP_PATH, tp, bp);
+ FREE(cp);
+ FREE(bp);
+ FREE(tp);
+#ifndef ARCHIVE_ONLY
+ } else if (!strncmp(line, "LYNXDIRED://UNZIP", 17)) {
+ tp = quote_pathname(line + 17);
+ *cp = '\0';
+ cp = quote_pathname(line + 17);
+ sprintf(buffer, "cd %s; %s -q %s", cp, UNZIP_PATH, tp);
+ FREE(cp);
+ FREE(tp);
+# endif /* !ARCHIVE_ONLY */
+#endif /* OK_ZIP */
+
+ } else if (!strncmp(line, "LYNXDIRED://COMPRESS", 20)) {
+ tp = quote_pathname(line + 20);
+ sprintf(buffer, "%s %s", COMPRESS_PATH, tp);
+ FREE(tp);
+ }
+
+ if (strlen(buffer)) {
+ if (strlen(buffer) < 60) {
+ sprintf(tmpbuf, "Executing %s ", buffer);
+ } else {
+ sprintf(tmpbuf,
+ "Executing system command. This might take a while.");
+ }
+ _statusline(tmpbuf);
+ stop_curses();
+ printf("%s\n", tmpbuf);
+ fflush(stdout);
+ system(buffer);
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt
+ HadVMSInterrupt = FALSE;
+#endif /* VMS */
+ start_curses();
+ LYforce_no_cache = TRUE;
+ }
+ }
+
+ FREE(line);
+ LYpop(doc);
+ return 0;
+}
+
+/*
+ * Provide a menu of file management options.
+ */
+PUBLIC int dired_options ARGS2(
+ document *, doc,
+ char **, newfile)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ char path[512], dir[512]; /* much too large */
+ char tmpbuf[LINESIZE];
+ lynx_html_item_type *nxt;
+ struct stat dir_info;
+ FILE *fp0;
+ char *cp = NULL;
+ char *dir_url = NULL; /* Will hold URL-escaped path of
+ directory from where DIRED_MENU was
+ invoked (NOT its full URL). */
+ char *path_url = NULL; /* Will hold URL-escaped path of file
+ (or directory) which was selected
+ when DIRED_MENU was invoked (NOT
+ its full URL). */
+ BOOLEAN nothing_tagged;
+ int count;
+ struct dired_menu *mp;
+ char buf[2048];
+
+
+ if (first) {
+ /*
+ * Get an unused tempfile name. - FM
+ */
+ tempname(tempfile, NEW_FILE);
+ }
+
+ /*
+ * Open the tempfile for writing and set its
+ * protection in case this wasn't done via an
+ * external umask. - FM
+ */
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ _statusline("Unable to open file management menu file.");
+ sleep(AlertSecs);
+ return(0);
+ }
+
+ if (first) {
+ /*
+ * Make the tempfile a URL.
+ */
+ strcpy(LYDiredFileURL, "file://localhost");
+ strcat(LYDiredFileURL, tempfile);
+ first = FALSE;
+ }
+ StrAllocCopy(*newfile, LYDiredFileURL);
+
+ cp = doc->address;
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ strcpy(dir, cp);
+ StrAllocCopy(dir_url, cp);
+ if (dir_url[(strlen(dir_url) - 1)] == '/')
+ dir_url[(strlen(dir_url) - 1)] = '\0';
+ HTUnEscape(dir);
+ if (dir[(strlen(dir) - 1)] == '/')
+ dir[(strlen(dir) - 1)] = '\0';
+
+ if (doc->link > -1 && doc->link < (nlinks+1)) {
+ cp = links[doc->link].lname;
+ if (!strncmp(cp, "file://localhost", 16)) {
+ cp += 16;
+ } else if (!strncmp(cp, "file:", 5)) {
+ cp += 5;
+ }
+ strcpy(path, cp);
+ StrAllocCopy(path_url, cp);
+ if (*path_url && path_url[1] && path_url[(strlen(path_url) - 1)] == '/')
+ path_url[(strlen(path_url) - 1)] = '\0';
+ HTUnEscape(path);
+ if (*path && path[1] && path[(strlen(path) - 1)] == '/')
+ path[(strlen(path) - 1)] = '\0';
+
+ if (lstat(path, &dir_info) == -1 && stat(path, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", path);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ FREE(dir_url);
+ FREE(path_url);
+ return 0;
+ }
+
+ } else {
+ path[0] = '\0';
+ StrAllocCopy(path_url, path);
+ }
+
+ nothing_tagged = (HTList_isEmpty(tagged));
+
+ fprintf(fp0,
+ "<head>\n<title>%s</title></head>\n<body>\n", DIRED_MENU_TITLE);
+
+ fprintf(fp0,
+ "\n<h1>File Management Options (%s Version %s)</h1>",
+ LYNX_NAME, LYNX_VERSION);
+
+ fprintf(fp0, "Current directory is %s<br>\n", dir);
+
+ if (nothing_tagged) {
+ if (strlen(path)) {
+ fprintf(fp0, "Current selection is %s<p>\n", path);
+ } else {
+ fprintf(fp0, "Nothing currently selected.<p>\n");
+ }
+ } else {
+ /*
+ * Write out number of tagged items, and names of first
+ * few of them relative to current (in the DIRED sense)
+ * directory.
+ */
+ int n = HTList_count(tagged);
+ char *cp1 = NULL;
+ char *cd = NULL;
+ int i, m;
+#define NUM_TAGS_TO_WRITE 10
+ fprintf(fp0, "Current selection is %d tagged item%s",
+ n, ((n == 1) ? ":" : "s:"));
+ StrAllocCopy(cd, doc->address);
+ HTUnEscapeSome(cd, "/");
+ if (*cd && cd[(strlen(cd) - 1)] != '/')
+ StrAllocCat(cd, "/");
+ m = (n < NUM_TAGS_TO_WRITE) ? n : NUM_TAGS_TO_WRITE;
+ for (i = 1; i <= m; i++) {
+ cp1 = HTRelative(HTList_objectAt(tagged, i-1),
+ (*cd ? cd : "file://localhost"));
+ HTUnEscape(cp1);
+ LYEntify(&cp1, TRUE); /* _should_ do this everywhere... */
+ fprintf(fp0, "%s <br>\n &nbsp;&nbsp;&nbsp;%s",
+ (i == 1 ? "" : " ,"), cp1);
+ FREE(cp1);
+ }
+ if (n > m) {
+ fprintf(fp0," , ...");
+ }
+ fprintf(fp0, "<p>\n");
+ FREE(cd);
+ }
+
+ /*
+ * If menu_head is NULL then use defaults and link them together now.
+ */
+ if (menu_head == NULL) {
+ for (mp = defmenu; mp->href != NULL; mp++)
+ mp->next = (mp + 1);
+ (--mp)->next = NULL;
+ menu_head = defmenu;
+ }
+
+ for (mp = menu_head; mp != NULL; mp = mp->next) {
+ if (mp->cond != DE_TAG && !nothing_tagged)
+ continue;
+ if (mp->cond == DE_TAG && nothing_tagged)
+ continue;
+ if (mp->cond == DE_DIR &&
+ (!*path || (dir_info.st_mode & S_IFMT) != S_IFDIR))
+ continue;
+ if (mp->cond == DE_FILE &&
+ (!*path || (dir_info.st_mode & S_IFMT) != S_IFREG))
+ continue;
+#ifdef S_IFLNK
+ if (mp->cond == DE_SYMLINK &&
+ (!*path || (dir_info.st_mode & S_IFMT) != S_IFLNK))
+ continue;
+#endif
+ if (*mp->sfx &&
+ (strlen(path) < strlen(mp->sfx) ||
+ strcmp(mp->sfx, &path[(strlen(path) - strlen(mp->sfx))]) != 0))
+ continue;
+ fprintf(fp0, "<a href=\"%s",
+ render_item(mp->href, path_url, dir_url, buf,2048, YES));
+ fprintf(fp0, "\">%s</a> ",
+ render_item(mp->link, path, dir, buf,2048, NO));
+ fprintf(fp0, "%s<br>\n",
+ render_item(mp->rest, path, dir, buf,2048, NO));
+ }
+
+ if (uploaders != NULL) {
+ fprintf(fp0, "<p>Upload to current directory:<p>\n");
+ for (count = 0, nxt = uploaders;
+ nxt != NULL;
+ nxt = nxt->next, count++) {
+ fprintf(fp0,
+ "<a href=\"LYNXDIRED://UPLOAD=%d/TO=%s\"> %s </a><br>\n",
+ count, dir, nxt->name);
+ }
+ }
+
+ fprintf(fp0, "</body>\n");
+ fclose(fp0);
+
+ FREE(dir_url);
+ FREE(path_url);
+
+ LYforce_no_cache = TRUE;
+
+ return(0);
+}
+
+/*
+ * Check DIRED filename.
+ */
+PRIVATE char *filename ARGS3(
+ char *, prompt,
+ char *, buf,
+ size_t, bufsize)
+{
+ char *cp;
+
+ _statusline(prompt);
+
+ *buf = '\0';
+ LYgetstr(buf, VISIBLE, bufsize, NORECALL);
+ if (strstr(buf, "../") != NULL) {
+ _statusline("Illegal filename; request ignored.");
+ sleep(AlertSecs);
+ return NULL;
+ }
+
+ if (no_dotfiles || !show_dotfiles) {
+ cp = strrchr(buf, '/'); /* find last slash */
+ if (cp)
+ cp += 1;
+ else
+ cp = buf;
+ if (*cp == '.') {
+ _statusline("Illegal filename; request ignored.");
+ sleep(AlertSecs);
+ return NULL;
+ }
+ }
+ return buf;
+}
+
+/*
+ * Install the specified file or directory.
+ */
+PUBLIC BOOLEAN local_install ARGS3(
+ char *, destpath,
+ char *, srcpath,
+ char **, newpath)
+{
+ char tmpbuf[512];
+ static char savepath[512]; /* This will be the link that
+ is to be installed. */
+ struct stat dir_info;
+ char *args[6];
+ HTList *tag;
+ int count = 0;
+ int n = 0, src; /* indices into 'args[]' */
+
+ /*
+ * Determine the status of the selected item.
+ */
+ if (srcpath) {
+ srcpath = strip_trailing_slash(srcpath);
+ if (strncmp(srcpath, "file://localhost", 16) == 0)
+ srcpath += 16;
+ if (stat(srcpath, &dir_info) == -1) {
+ sprintf(tmpbuf, "Unable to get status of '%s'.", srcpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ } else if ((dir_info.st_mode & S_IFMT) != S_IFDIR &&
+ (dir_info.st_mode & S_IFMT) != S_IFREG) {
+ _statusline(
+ "The selected item is not a file or a directory! Request ignored.");
+ sleep(AlertSecs);
+ return 0;
+ }
+ strcpy(savepath, srcpath);
+ LYforce_no_cache = TRUE;
+ strcpy(tmpbuf, "file://localhost");
+ strcat(tmpbuf, Home_Dir());
+ strcat(tmpbuf, "/.installdirs.html");
+ StrAllocCopy(*newpath, tmpbuf);
+ return 0;
+ }
+
+ destpath = strip_trailing_slash(destpath);
+
+ if (stat(destpath,&dir_info) == -1) {
+ sprintf(tmpbuf,"Unable to get status of '%s'.",destpath);
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ return 0;
+ } else if ((dir_info.st_mode & S_IFMT) != S_IFDIR) {
+ _statusline(
+ "The selected item is not a directory! Request ignored.");
+ sleep(AlertSecs);
+ return 0;
+ } else if (0 /*directory not writeable*/) {
+ _statusline("Install in the selected directory not permitted.");
+ sleep(AlertSecs);
+ return 0;
+ }
+
+ statusline("Just a moment, ...");
+ args[n++] = "install";
+#ifdef INSTALL_ARGS
+ args[n++] = INSTALL_ARGS;
+#endif /* INSTALL_ARGS */
+ src = n++;
+ args[n++] = destpath;
+ args[n] = (char *)0;
+ sprintf(tmpbuf, "install %s", destpath);
+ tag = tagged;
+
+ if (HTList_isEmpty(tagged)) {
+ args[src] = savepath;
+ if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0)
+ return (-1);
+ count++;
+ } else {
+ char *name;
+ while ((name = (char *)HTList_nextObject(tag))) {
+ args[src] = name;
+ if (strncmp("file://localhost", args[src], 16) == 0)
+ args[src] = (name + 16);
+
+ if (LYExecv(INSTALL_PATH, args, tmpbuf) <= 0)
+ return ((count == 0) ? -1 : count);
+ count++;
+ }
+ clear_tags();
+ }
+ statusline("Installation complete");
+ sleep(InfoSecs);
+ return count;
+}
+
+/*
+ * Clear DIRED tags.
+ */
+PUBLIC void clear_tags NOARGS
+{
+ char *cp = NULL;
+
+ while ((cp = HTList_removeLastObject(tagged)) != NULL) {
+ FREE(cp);
+ }
+ if (HTList_isEmpty(tagged))
+ FREE(tagged);
+}
+
+/*
+ * Handle DIRED menu item.
+ */
+PUBLIC void add_menu_item ARGS1(
+ char *, str)
+{
+ struct dired_menu *new, *mp;
+ char *cp;
+
+ /*
+ * First custom menu definition causes entire default menu to be
+ * discarded.
+ */
+ if (menu_head == defmenu)
+ menu_head = NULL;
+
+ new = (struct dired_menu *)calloc(1, sizeof(*new));
+
+ /*
+ * Conditional on tagged != NULL ?
+ */
+ cp = strchr(str, ':');
+ *cp++ = '\0';
+ if (strcasecomp(str, "tag") == 0) {
+ new->cond = DE_TAG;
+ } else if (strcasecomp(str, "dir") == 0) {
+ new->cond = DE_DIR;
+ } else if (strcasecomp(str, "file") == 0) {
+ new->cond = DE_FILE;
+ } else if (strcasecomp(str, "link") == 0) {
+ new->cond = DE_SYMLINK;
+ }
+
+ /*
+ * Conditional on matching suffix.
+ */
+ str = cp;
+ cp = strchr(str, ':');
+ *cp++ = '\0';
+ StrAllocCopy(new->sfx, str);
+
+ str = cp;
+ cp = strchr(str, ':');
+ *cp++ = '\0';
+ StrAllocCopy(new->link, str);
+
+ str = cp;
+ cp = strchr(str, ':');
+ *cp++ = '\0';
+ StrAllocCopy(new->rest, str);
+
+ StrAllocCopy(new->href, cp);
+
+ if (menu_head) {
+ for (mp = menu_head; mp && mp->next != NULL; mp = mp->next)
+ ;
+ mp->next = new;
+ } else
+ menu_head = new;
+}
+
+/*
+ * Create URL for DIRED HREF value.
+ */
+PRIVATE char * render_item ARGS6(
+ char *, s,
+ char *, path,
+ char *, dir,
+ char *, buf,
+ int, bufsize,
+ BOOLEAN, url_syntax)
+{
+ char *cp;
+ char *bp;
+ char overrun = '\0';
+ char *taglist = NULL;
+#define BP_INC (bp>buf+bufsize-2 ? &overrun : bp++)
+ /* Buffer overrun could happen for very long
+ tag list, if %l or %t are used */
+ bp = buf;
+ while (*s && !overrun) {
+ if (*s == '%') {
+ s++;
+ switch (*s) {
+ case '%':
+ *BP_INC = '%';
+#ifdef NOTDEFINED
+ /*
+ * These chars come from lynx.cfg or the default, let's
+ * just assume there won't be any improper %'s there that
+ * would need escaping.
+ */
+ if(url_syntax) {
+ *BP_INC = '2';
+ *BP_INC = '5';
+ }
+#endif /* NOTDEFINED */
+ break;
+ case 'p':
+ cp = path;
+ while (*cp)
+ *BP_INC = *cp++;
+ break;
+ case 'd':
+ cp = dir;
+ while (*cp)
+ *BP_INC = *cp++;
+ break;
+ case 'f':
+ cp = strrchr(path, '/');
+ if (cp)
+ cp++;
+ else
+ cp = path;
+ while (*cp)
+ *BP_INC = *cp++;
+ break;
+ case 'l':
+ case 't':
+ if (!HTList_isEmpty(tagged)) {
+ HTList *cur = tagged;
+ char *name;
+
+ while (!overrun &&
+ (name = (char *)HTList_nextObject(cur))!=NULL) {
+ if (*s == 'l' && (cp = strrchr(name, '/')))
+ cp++;
+ else
+ cp = name;
+ StrAllocCat(taglist, cp);
+ StrAllocCat(taglist, " "); /* should this be %20?*/
+ }
+ }
+ if (taglist) {
+ /* could HTUnescape here... */
+ cp = taglist;
+ while (*cp)
+ *BP_INC = *cp++;
+ FREE(taglist);
+ }
+ break;
+ default:
+ *BP_INC = '%';
+#ifdef NOTDEFINED
+ if (url_syntax) {
+ *BP_INC = '2';
+ *BP_INC = '5';
+ }
+#endif /* NOTDEFINED */
+ *BP_INC =*s;
+ break;
+ }
+ } else {
+ /*
+ * Other chars come from the lynx.cfg or
+ * the default. Let's assume there isn't
+ * anything weird there that needs escaping.
+ */
+ *BP_INC =*s;
+ }
+ s++;
+ }
+ if (overrun & url_syntax) {
+ sprintf(buf,"Temporary URL or list would be too long.");
+ _statusline(buf);
+ sleep(AlertSecs);
+ bp = buf; /* set to start, will return empty string as URL */
+ }
+ *bp = '\0';
+ return buf;
+}
+#endif /* DIRED_SUPPORT */
+
+/*
+ * Execute DIRED command.
+ */
+PRIVATE int LYExecv ARGS3(
+ char *, path,
+ char **, argv,
+ char *, msg)
+{
+#if defined(VMS) || defined(_WINDOWS)
+ if (TRACE) {
+ fprintf(stderr, "LYExecv: Called inappropriately!\n");
+ }
+ return(0);
+#else
+ int rc;
+ char tmpbuf[512];
+ pid_t pid;
+#if HAVE_TYPE_UNIONWAIT
+ union wait wstatus;
+#else
+ int wstatus;
+#endif
+
+ rc = 1; /* It will work */
+ tmpbuf[0] = '\0'; /* empty buffer for alert messages */
+ stop_curses();
+ pid = fork(); /* fork and execute rm */
+ switch (pid) {
+ case -1:
+ sprintf(tmpbuf, "Unable to %s due to system error!", msg);
+ rc = 0;
+ break; /* don't fall thru! - KW */
+ case 0: /* child */
+ execv(path, argv);
+ exit(-1); /* execv failed, give wait() something to look at */
+ default: /* parent */
+#if !HAVE_WAITPID
+ while (wait(&wstatus) != pid)
+ ; /* do nothing */
+#else
+ while (-1 == waitpid(pid, &wstatus, 0)) { /* wait for child */
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif /* EINTR */
+#ifdef ERESTARTSYS
+ if (errno == ERESTARTSYS)
+ continue;
+#endif /* ERESTARTSYS */
+ break;
+ }
+#endif /* !HAVE_WAITPID */
+ if (WEXITSTATUS(wstatus) != 0 ||
+ WTERMSIG(wstatus) > 0) { /* error return */
+ sprintf(tmpbuf, "Probable failure to %s due to system error!",
+ msg);
+ rc = 0;
+ }
+ }
+
+ if (rc == 0) {
+ /*
+ * Screen may have message from the failed execv'd command.
+ * Give user time to look at it before screen refresh.
+ */
+ sleep(AlertSecs);
+ }
+ start_curses();
+ if (tmpbuf[0]) {
+ _statusline(tmpbuf);
+ sleep(AlertSecs);
+ }
+
+ return(rc);
+#endif /* VMS */
+}
diff --git a/gnu/usr.bin/lynx/src/LYLocal.h b/gnu/usr.bin/lynx/src/LYLocal.h
new file mode 100644
index 00000000000..47fff5c01cf
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYLocal.h
@@ -0,0 +1,75 @@
+#ifndef LYLOCAL_H
+#define LYLOCAL_H
+
+#ifdef DIRED_SUPPORT
+
+#ifdef VMS
+#include <types.h>
+#include <stat.h>
+#else
+#if 0 /* already included in tcp.h */
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+#endif /* VMS */
+
+#ifndef S_IRWXU
+#define S_IRWXU 0000700 /* rwx, owner */
+#define S_IRUSR 0000400 /* read permission, owner */
+#define S_IWUSR 0000200 /* write permission, owner */
+#define S_IXUSR 0000100 /* execute/search permission, owner */
+#define S_IRWXG 0000070 /* rwx, group */
+#define S_IRGRP 0000040 /* read permission, group */
+#define S_IWGRP 0000020 /* write permission, grougroup */
+#define S_IXGRP 0000010 /* execute/search permission, group */
+#define S_IRWXO 0000007 /* rwx, other */
+#define S_IROTH 0000004 /* read permission, other */
+#define S_IWOTH 0000002 /* write permission, other */
+#define S_IXOTH 0000001 /* execute/search permission, other */
+#endif /* !S_IRWXU */
+
+#ifndef S_ISUID /* Unusual modes */
+#define S_ISUID 0x800 /* set user id on execution */
+#define S_ISGID 0x400 /* set group id on execution */
+#define S_ISVTX 0x200 /* save swapped text even after use */
+#endif /* !S_ISUID */
+
+/* Special return code for LYMainLoop.c */
+#define PERMIT_FORM_RESULT (-99)
+
+extern char LYPermitFileURL[];
+extern char LYDiredFileURL[];
+extern char LYUploadFileURL[];
+
+extern BOOLEAN local_create PARAMS((document *doc));
+extern BOOLEAN local_modify PARAMS((document *doc, char **newpath));
+extern BOOLEAN local_remove PARAMS((document *doc));
+extern BOOLEAN local_install PARAMS((char *destpath, char *srcpath, char **newpath));
+
+/* MainLoop needs to know about this one for atexit cleanup */
+extern void clear_tags NOPARAMS;
+
+/* Define the PRIVATE routines in case they ever go PUBLIC
+
+extern BOOLEAN modify_name PARAMS((char *testpath));
+extern BOOLEAN modify_location PARAMS((char *testpath));
+extern BOOLEAN create_file PARAMS((char *testpath));
+extern BOOLEAN create_directory PARAMS((char *testpath));
+extern BOOLEAN modify_tagged PARAMS((char *testpath));
+extern BOOLEAN remove_tagged NOPARAMS;
+extern BOOLEAN remove_single PARAMS ((char *testpath));
+extern BOOLEAN is_a_file PARAMS((char *testname));
+*/
+extern void tagflag PARAMS((int flag, int cur));
+extern void showtags PARAMS((HTList *tag));
+extern int local_dired PARAMS((document *doc));
+extern int dired_options PARAMS ((document *doc, char ** newfile));
+
+#define DIRED_MENU_TITLE "File Management Options"
+#define PERMIT_OPTIONS_TITLE "File Permission Options"
+
+extern void add_menu_item PARAMS((char *str));
+
+#endif /* DIRED_SUPPORT */
+
+#endif /* LYLOCAL_H */
diff --git a/gnu/usr.bin/lynx/src/LYMail.c b/gnu/usr.bin/lynx/src/LYMail.c
new file mode 100644
index 00000000000..b7acce45f39
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMail.c
@@ -0,0 +1,1914 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "LYGlobalDefs.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYSignal.h"
+#include "LYUtils.h"
+#include "LYClean.h"
+#include "LYStrings.h"
+#include "GridText.h"
+#include "LYSystem.h"
+#include "LYMail.h"
+#include "LYCharSets.h" /* to get current charset for mail header */
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+BOOLEAN term_letter; /* Global variable for async i/o. */
+PRIVATE void terminate_letter PARAMS((int sig));
+PRIVATE void remove_tildes PARAMS((char *string));
+
+/*
+** mailform() sends form content to the mailto address(es). - FM
+*/
+PUBLIC void mailform ARGS4(
+ char *, mailto_address,
+ char *, mailto_subject,
+ char *, mailto_content,
+ char *, mailto_type)
+{
+ FILE *fd;
+ char *address = NULL;
+ char *ccaddr = NULL;
+ char *keywords = NULL;
+ char *searchpart = NULL;
+ char *cp = NULL, *cp0 = NULL, *cp1 = NULL;
+ char subject[80];
+ char self[80];
+ char cmd[512];
+ int len, i, ch;
+#if defined(VMS) || defined(DOSPATH)
+ char my_tmpfile[256];
+ char *address_ptr1, *address_ptr2;
+ char *command = NULL;
+ BOOLEAN first = TRUE;
+ BOOLEAN isPMDF = FALSE;
+ char hdrfile[256];
+ FILE *hfd;
+
+ if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
+ isPMDF = TRUE;
+ }
+#endif /* VMS */
+
+ if (!mailto_address || !mailto_content) {
+ HTAlert(BAD_FORM_MAILTO);
+ return;
+ }
+ subject[0] = '\0';
+ self[0] = '\0';
+
+ if ((cp = (char *)strchr(mailto_address,'\n')) != NULL)
+ *cp = '\0';
+ StrAllocCopy(address, mailto_address);
+
+ /*
+ * Check for a ?searchpart. - FM
+ */
+ if ((cp = strchr(address, '?')) != NULL) {
+ StrAllocCopy(searchpart, cp);
+ *cp = '\0';
+ cp = (searchpart + 1);
+ if (*cp != '\0') {
+ /*
+ * Seek and handle a subject=foo. - FM
+ */
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "subject=", 8))
+ break;
+ cp++;
+ }
+ if (*cp) {
+ cp += 8;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ if (*cp) {
+ HTUnEscape(subject);
+ LYstrncpy(subject, cp, 70);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp1 = NULL;
+ }
+ }
+
+ /*
+ * Seek and handle to=address(es) fields.
+ * Appends to address. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "to=", 3)) {
+ cp += 3;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (*address) {
+ StrAllocCat(address, ",");
+ }
+ StrAllocCat(address, cp);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+
+ /*
+ * Seek and handle cc=address(es) fields. Excludes
+ * Bcc=address(es) as unsafe. We may append our own
+ * cc (below) as a list for the actual mailing. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "cc=", 3)) {
+ cp += 3;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (ccaddr == NULL) {
+ StrAllocCopy(ccaddr, cp);
+ } else {
+ StrAllocCat(ccaddr, ",");
+ StrAllocCat(ccaddr, cp);
+ }
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+
+ /*
+ * Seek and handle keywords=term(s) fields. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "keywords=", 9)) {
+ cp += 9;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (keywords == NULL) {
+ StrAllocCopy(keywords, cp);
+ } else {
+ StrAllocCat(keywords, cp);
+ StrAllocCat(keywords, ", ");
+ }
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+ if (keywords != NULL) {
+ if (*keywords != '\0') {
+ HTUnEscape(keywords);
+ } else {
+ FREE(keywords);
+ }
+ }
+
+ FREE(searchpart);
+ }
+ }
+
+ /*
+ * Convert any Explorer semi-colon Internet address
+ * separators to commas. - FM
+ */
+ cp = address;
+ while ((cp1 = strchr(cp, '@')) != NULL) {
+ cp1++;
+ if ((cp0 = strchr(cp1, ';')) != NULL) {
+ *cp0 = ',';
+ cp1 = cp0 + 1;
+ }
+ cp = cp1;
+ }
+ if (address[(strlen(address) - 1)] == ',')
+ address[(strlen(address) - 1)] = '\0';
+ if (*address == '\0') {
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ HTAlert(BAD_FORM_MAILTO);
+ return;
+ }
+ if (ccaddr != NULL) {
+ cp = ccaddr;
+ while ((cp1 = strchr(cp, '@')) != NULL) {
+ cp1++;
+ if ((cp0 = strchr(cp1, ';')) != NULL) {
+ *cp0 = ',';
+ cp1 = cp0 + 1;
+ }
+ cp = cp1;
+ }
+ if (ccaddr[(strlen(ccaddr) - 1)] == ',') {
+ ccaddr[(strlen(ccaddr) - 1)] = '\0';
+ }
+ if (*ccaddr == '\0') {
+ FREE(ccaddr);
+ }
+ }
+
+ /*
+ * Unescape the address and ccaddr fields. - FM
+ */
+ HTUnEscape(address);
+ if (ccaddr != NULL) {
+ HTUnEscape(ccaddr);
+ }
+
+ /*
+ * Allow user to edit the default Subject - FM
+ */
+ if (subject[0] == '\0') {
+ if (mailto_subject && *mailto_subject) {
+ LYstrncpy(subject, mailto_subject, 70);
+ } else {
+ strcpy(subject, "mailto:");
+ LYstrncpy((char*)&subject[7], address, 63);
+ }
+ }
+ _statusline(SUBJECT_PROMPT);
+ if ((ch = LYgetstr(subject, VISIBLE, 71, NORECALL)) < 0) {
+ /*
+ * User cancelled via ^G. - FM
+ */
+ _statusline(FORM_MAILTO_CANCELLED);
+ sleep(InfoSecs);
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+ }
+
+ /*
+ * Allow user to specify a self copy via a CC:
+ * entry, if permitted. - FM
+ */
+ if (!LYNoCc) {
+ sprintf(self, "%.79s", (personal_mail_address ?
+ personal_mail_address : ""));
+ self[79] = '\0';
+ _statusline("Cc: ");
+ if ((ch = LYgetstr(self, VISIBLE, sizeof(self), NORECALL)) < 0) {
+ /*
+ * User cancelled via ^G. - FM
+ */
+ _statusline(FORM_MAILTO_CANCELLED);
+ sleep(InfoSecs);
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+ }
+ remove_tildes(self);
+ if (ccaddr == NULL) {
+ StrAllocCopy(ccaddr, self);
+ } else {
+ StrAllocCat(ccaddr, ",");
+ StrAllocCat(ccaddr, self);
+ }
+ }
+
+#if defined(VMS) || defined(DOSPATH)
+ tempname(my_tmpfile, NEW_FILE);
+ if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
+ NULL == strchr(cp, ']') &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(my_tmpfile, ".txt");
+ }
+ if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
+ HTAlert(FORM_MAILTO_FAILED);
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+ }
+ if (isPMDF) {
+ tempname(hdrfile, NEW_FILE);
+ if (((cp = strrchr(hdrfile, '.')) != NULL) &&
+ NULL == strchr(cp, ']') &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(hdrfile, ".txt");
+ }
+ if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
+ HTAlert(FORM_MAILTO_FAILED);
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+ }
+ }
+#ifdef VMS
+ if (isPMDF) {
+ if (mailto_type && *mailto_type) {
+ fprintf(hfd, "Mime-Version: 1.0\n");
+ fprintf(hfd, "Content-Type: %s\n", mailto_type);
+ if (personal_mail_address && *personal_mail_address)
+ fprintf(hfd, "From: %s\n", personal_mail_address);
+ }
+ } else if (mailto_type &&
+ !strncasecomp(mailto_type, "multipart/form-data", 19)) {
+ /*
+ * Ugh! There's no good way to include headers while
+ * we're still using "generic" VMS MAIL, so we'll put
+ * this in the body of the message. - FM
+ */
+ fprintf(fd, "X-Content-Type: %s\n\n", mailto_type);
+ }
+#else
+ if (mailto_type && *mailto_type) {
+ fprintf(fd, "Mime-Version: 1.0\n");
+ fprintf(fd, "Content-Type: %s\n", mailto_type);
+ }
+ fprintf(fd,"To: %s\n", address);
+ if (personal_mail_address && *personal_mail_address)
+ fprintf(fd,"From: %s\n", personal_mail_address);
+ remove_tildes(self);
+ fprintf(fd,"Subject: %.70s\n\n", subject);
+#endif
+
+#else
+ sprintf(cmd, "%s %s", system_mail, system_mail_flags);
+ if ((fd = popen(cmd, "w")) == NULL) {
+ HTAlert(FORM_MAILTO_FAILED);
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+ }
+
+ if (mailto_type && *mailto_type) {
+ fprintf(fd, "Mime-Version: 1.0\n");
+ fprintf(fd, "Content-Type: %s\n", mailto_type);
+ }
+ fprintf(fd, "To: %s\n", address);
+ if (personal_mail_address && *personal_mail_address)
+ fprintf(fd, "From: %s\n", personal_mail_address);
+ if (ccaddr != NULL && *ccaddr != '\0')
+ fprintf(fd, "Cc: %s\n", ccaddr);
+ fprintf(fd, "Subject: %s\n\n", subject);
+ if (keywords != NULL && *keywords != '\0')
+ fprintf(fd, "Keywords: %s\n", keywords);
+ _statusline(SENDING_FORM_CONTENT);
+#endif /* VMS */
+
+ /*
+ * Break up the content into lines with a maximum length of 78.
+ * If the ENCTYPE was text/plain, we have physical newlines and
+ * should take them into account. Otherwise, the actual newline
+ * characters in the content are hex escaped. - FM
+ */
+ while((cp = strchr(mailto_content, '\n')) != NULL) {
+ *cp = '\0';
+ i = 0;
+ len = strlen(mailto_content);
+ while (len > 78) {
+ strncpy(cmd, (char *)&mailto_content[i], 78);
+ cmd[78] = '\0';
+ fprintf(fd, "%s\n", cmd);
+ i += 78;
+ len = strlen((char *)&mailto_content[i]);
+ }
+ fprintf(fd, "%s\n", (char *)&mailto_content[i]);
+ mailto_content = (cp+1);
+ }
+ i = 0;
+ len = strlen(mailto_content);
+ while (len > 78) {
+ strncpy(cmd, (char *)&mailto_content[i], 78);
+ cmd[78] = '\0';
+ fprintf(fd, "%s\n", cmd);
+ i += 78;
+ len = strlen((char *)&mailto_content[i]);
+ }
+ if (len)
+ fprintf(fd, "%s\n", (char *)&mailto_content[i]);
+
+#ifdef UNIX
+ pclose(fd);
+ sleep(MessageSecs);
+#endif /* UNIX */
+#if defined(VMS) || defined(DOSPATH)
+ fclose(fd);
+#ifdef VMS
+ /*
+ * Set the mail command. - FM
+ */
+ if (isPMDF) {
+ /*
+ * For PMDF, put any keywords and the subject
+ * in the header file and close it. - FM
+ */
+ if (keywords != NULL && *keywords != '\0') {
+ fprintf(hfd, "Keywords: %s\n", keywords);
+ }
+ fprintf(hfd, "Subject: %s\n\n", subject);
+ fclose(hfd);
+ /*
+ * Now set up the command. - FM
+ */
+ sprintf(cmd,
+ "%s %s %s,%s ",
+ system_mail,
+ system_mail_flags,
+ hdrfile,
+ my_tmpfile);
+ } else {
+ /*
+ * For "generic" VMS MAIL, include the subject in the
+ * command, and ignore any keywords to minimize risk
+ * of them making the line too long or having problem
+ * characters. - FM
+ */
+ sprintf(cmd,
+ "%s %s%s/subject=\"%s\" %s ",
+ system_mail,
+ system_mail_flags,
+ (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"),
+ subject,
+ my_tmpfile);
+ }
+ StrAllocCopy(command, cmd);
+
+ /*
+ * Now add all the people in the address field. - FM
+ */
+ address_ptr1 = address;
+ do {
+ if ((cp = strchr(address_ptr1, ',')) != NULL) {
+ address_ptr2 = (cp+1);
+ *cp = '\0';
+ } else {
+ address_ptr2 = NULL;
+ }
+
+ /*
+ * 4 letters is arbitrarily the smallest possible mail
+ * address, at least for lynx. That way extra spaces
+ * won't confuse the mailer and give a blank address.
+ */
+ if (strlen(address_ptr1) > 3) {
+ if (!first) {
+ StrAllocCat(command, ",");
+ }
+ sprintf(cmd, mail_adrs, address_ptr1);
+ StrAllocCat(command, cmd);
+ first = FALSE;
+ }
+ address_ptr1 = address_ptr2;
+ } while (address_ptr1 != NULL);
+
+ /*
+ * Now add all the people in the CC field. - FM
+ */
+ if (ccaddr != NULL && *ccaddr != '\0') {
+ address_ptr1 = ccaddr;
+ do {
+ if ((cp = strchr(address_ptr1, ',')) != NULL) {
+ address_ptr2 = (cp+1);
+ *cp = '\0';
+ } else {
+ address_ptr2 = NULL;
+ }
+
+ /*
+ * 4 letters is arbitrarily the smallest possible mail
+ * address, at least for lynx. That way extra spaces
+ * won't confuse the mailer and give a blank address.
+ */
+ if (strlen(address_ptr1) > 3) {
+ StrAllocCat(command, ",");
+ sprintf(cmd, mail_adrs, address_ptr1);
+ if (isPMDF) {
+ strcat(cmd, "/CC");
+ }
+ StrAllocCat(command, cmd);
+ }
+ address_ptr1 = address_ptr2;
+ } while (address_ptr1 != NULL);
+ }
+
+ stop_curses();
+ printf("Sending form content:\n\n$ %s\n\nPlease wait...", command);
+ system(command);
+ FREE(command);
+ sleep(AlertSecs);
+ start_curses();
+ remove(my_tmpfile);
+ remove(hdrfile);
+#else /* DOSPATH */
+ sprintf(cmd, "%s -t \"%s\" -F %s", system_mail, address, my_tmpfile);
+ stop_curses();
+ printf("Sending form content:\n\n$ %s\n\nPlease wait...", cmd);
+ system(cmd);
+ sleep(MessageSecs);
+ start_curses();
+ remove(my_tmpfile);
+#endif
+#endif /* VMS */
+
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ return;
+}
+
+/*
+** mailmsg() sends a message to the owner of the file, if one is defined,
+** telling of errors (i.e., link not available).
+*/
+PUBLIC void mailmsg ARGS4(
+ int, cur,
+ char *, owner_address,
+ char *, filename,
+ char *, linkname)
+{
+ FILE *fd, *fp;
+ char *address = NULL;
+ char *searchpart = NULL;
+ char cmd[512], *cp, *cp0, *cp1;
+#if defined(VMS) || defined(DOSPATH)
+ char my_tmpfile[256];
+ char *address_ptr1, *address_ptr2;
+ char *command = NULL;
+ BOOLEAN first = TRUE;
+ BOOLEAN isPMDF = FALSE;
+ char hdrfile[256];
+ FILE *hfd;
+
+ if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
+ isPMDF = TRUE;
+ }
+#endif /* VMS */
+
+ if (owner_address == NULL || *owner_address == '\0') {
+ return;
+ }
+ if ((cp = (char *)strchr(owner_address,'\n')) != NULL)
+ *cp = '\0';
+ StrAllocCopy(address, owner_address);
+
+ /*
+ * Check for a ?searchpart. - FM
+ */
+ if ((cp = strchr(address, '?')) != NULL) {
+ StrAllocCopy(searchpart, cp);
+ *cp = '\0';
+ cp = (searchpart + 1);
+ if (*cp != '\0') {
+ /*
+ * Seek and handle to=address(es) fields.
+ * Appends to address. We ignore any other
+ * headers in the ?searchpart. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "to=", 3)) {
+ cp += 3;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (*address) {
+ StrAllocCat(address, ",");
+ }
+ StrAllocCat(address, cp);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+ }
+ }
+
+ /*
+ * Convert any Explorer semi-colon Internet address
+ * separators to commas. - FM
+ */
+ cp = address;
+ while ((cp1 = strchr(cp, '@')) != NULL) {
+ cp1++;
+ if ((cp0 = strchr(cp1, ';')) != NULL) {
+ *cp0 = ',';
+ cp1 = cp0 + 1;
+ }
+ cp = cp1;
+ }
+
+ /*
+ * Unescape the address field. - FM
+ */
+ HTUnEscape(address);
+ if (address[(strlen(address) - 1)] == ',')
+ address[(strlen(address) - 1)] = '\0';
+ if (*address == '\0') {
+ FREE(address);
+ if (TRACE) {
+ fprintf(stderr,
+ "mailmsg: No address in '%s'.\n",
+ owner_address);
+ }
+ return;
+ }
+
+#ifdef UNIX
+ sprintf(cmd, "%s %s", system_mail, system_mail_flags);
+ if ((fd = popen(cmd, "w")) == NULL) {
+ FREE(address);
+ if (TRACE) {
+ fprintf(stderr,
+ "mailmsg: '%s' failed.\n",
+ cmd);
+ }
+ return;
+ }
+
+ fprintf(fd, "To: %s\n", address);
+ fprintf(fd, "Subject: Lynx Error in %s\n", filename);
+ if (personal_mail_address != NULL && *personal_mail_address != '\0') {
+ fprintf(fd, "Cc: %s\n", personal_mail_address);
+ }
+ fprintf(fd, "X-URL: %s\n", filename);
+ fprintf(fd, "X-Mailer: Lynx, Version %s\n\n", LYNX_VERSION);
+#endif /* UNIX */
+#if defined(VMS) || defined(DOSPATH)
+ tempname(my_tmpfile, NEW_FILE);
+ if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
+ NULL == strchr(cp, ']') &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(my_tmpfile, ".txt");
+ }
+ if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "mailmsg: Could not fopen '%s'.\n",
+ my_tmpfile);
+ }
+ FREE(address);
+ return;
+ }
+ if (isPMDF) {
+ tempname(hdrfile, NEW_FILE);
+ if (((cp = strrchr(hdrfile, '.')) != NULL) &&
+ NULL == strchr(cp, ']') &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(hdrfile, ".txt");
+ }
+ if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
+ if (TRACE) {
+ fprintf(stderr,
+ "mailmsg: Could not fopen '%s'.\n",
+ hdrfile);
+ }
+ FREE(address);
+ return;
+ }
+
+ if (personal_mail_address != NULL && *personal_mail_address != '\0') {
+ fprintf(fd, "Cc: %s\n", personal_mail_address);
+ }
+ fprintf(fd, "X-URL: %s\n", filename);
+ fprintf(fd, "X-Mailer: Lynx, Version %s\n\n", LYNX_VERSION);
+ }
+#endif /* VMS */
+
+ fprintf(fd, "The link %s :?: %s \n",
+ links[cur].lname, links[cur].target);
+ fprintf(fd, "called \"%s\"\n", links[cur].hightext);
+ fprintf(fd, "in the file \"%s\" called \"%s\"", filename, linkname);
+
+ fputs("\nwas requested but was not available.", fd);
+ fputs("\n\nThought you might want to know.", fd);
+
+ fputs("\n\nThis message was automatically generated by\n", fd);
+ fprintf(fd, "Lynx ver. %s", LYNX_VERSION);
+ if ((LynxSigFile != NULL) &&
+ (fp = fopen(LynxSigFile, "r")) != NULL) {
+ fputs("-- \n", fd);
+ while (fgets(cmd, sizeof(cmd), fp) != NULL)
+ fputs(cmd, fd);
+ fclose(fp);
+ }
+#ifdef UNIX
+ pclose(fd);
+#endif /* UNIX */
+#if defined(VMS) || defined(DOSPATH)
+ fclose(fd);
+#ifdef VMS
+ if (isPMDF) {
+ /*
+ * For PMDF, put the subject in the
+ * header file and close it. - FM
+ */
+ fprintf(hfd, "Subject: Lynx Error in %.56s\n\n", filename);
+ fclose(hfd);
+ /*
+ * Now set up the command. - FM
+ */
+ sprintf(cmd,
+ "%s %s %s,%s ",
+ system_mail,
+ system_mail_flags,
+ hdrfile,
+ my_tmpfile);
+ } else {
+ /*
+ * For "generic" VMS MAIL, include the
+ * subject in the command. - FM
+ */
+ sprintf(cmd,
+ "%s %s/self/subject=\"Lynx Error in %.56s\" %s ",
+ system_mail,
+ system_mail_flags,
+ filename,
+ my_tmpfile);
+ }
+ StrAllocCopy(command, cmd);
+ address_ptr1 = address;
+ do {
+ if ((cp = strchr(address_ptr1, ',')) != NULL) {
+ address_ptr2 = (cp+1);
+ *cp = '\0';
+ } else
+ address_ptr2 = NULL;
+
+ if (strlen(address) > 3) {
+ if (!first) {
+ StrAllocCat(command, ",");
+ }
+ sprintf(cmd, mail_adrs, address_ptr1);
+ StrAllocCat(command, cmd);
+ first = FALSE;
+ }
+ address_ptr1 = address_ptr2;
+ } while (address_ptr1 != NULL);
+
+ system(command);
+ FREE(command);
+ remove(my_tmpfile);
+ if (isPMDF) {
+ remove(hdrfile);
+ }
+#else /* DOSPATH */
+ sprintf(cmd, "%s -t \"%s\" -F %s", system_mail, address, my_tmpfile);
+ system(cmd);
+ remove(my_tmpfile);
+#endif
+#endif /* VMS */
+
+ if (traversal) {
+ FILE *ofp;
+
+ if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
+ if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
+ perror(NOOPEN_TRAV_ERR_FILE);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ }
+
+ fprintf(ofp, "%s\t%s \tin %s\n",
+ links[cur].lname, links[cur].target, filename);
+ fclose(ofp);
+ }
+
+ FREE(address);
+ return;
+}
+
+/*
+** reply_by_mail() invokes sendmail on Unix or mail on VMS to send
+** a comment from the users to the owner
+*/
+PUBLIC void reply_by_mail ARGS3(
+ char *, mail_address,
+ char *, filename,
+ CONST char *, title)
+{
+ char user_input[1000];
+ FILE *fd, *fp;
+ char *address = NULL;
+ char *ccaddr = NULL;
+ char *keywords = NULL;
+ char *searchpart = NULL;
+ char *body = NULL;
+ char *cp = NULL, *cp0 = NULL, *cp1 = NULL;
+ char *temp = NULL;
+ int i, len;
+ int c = 0; /* user input */
+ char my_tmpfile[256], cmd[512];
+#ifdef DOSPATH
+ char tmpfile2[256];
+#endif
+ static char *personal_name = NULL;
+ char subject[80];
+#ifdef VMS
+ char *address_ptr1 = NULL, *address_ptr2 = NULL;
+ char *command = NULL;
+ BOOLEAN first = TRUE;
+ BOOLEAN isPMDF = FALSE;
+ char hdrfile[256];
+ FILE *hfd;
+
+ if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
+ isPMDF = TRUE;
+ }
+#else
+ char buf[512];
+ char *header = NULL;
+ int n;
+#endif /* VMS */
+
+ term_letter = FALSE;
+
+ if (mail_address && *mail_address) {
+ StrAllocCopy(address, mail_address);
+ } else {
+ HTAlert(NO_ADDRESS_IN_MAILTO_URL);
+ return;
+ }
+
+ tempname(my_tmpfile, NEW_FILE);
+ if (((cp = strrchr(my_tmpfile, '.')) != NULL) &&
+#ifdef VMS
+ NULL == strchr(cp, ']') &&
+#endif /* VMS */
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(my_tmpfile, ".txt");
+ }
+ if ((fd = LYNewTxtFile(my_tmpfile)) == NULL) {
+ HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
+ return;
+ }
+#ifdef VMS
+ if (isPMDF) {
+ tempname(hdrfile, NEW_FILE);
+ if (((cp = strrchr(hdrfile, '.')) != NULL) &&
+ NULL == strchr(cp, ']') &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(hdrfile, ".txt");
+ }
+ if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
+ HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
+ return;
+ }
+ }
+#endif /* VMS */
+ subject[0] = '\0';
+
+ /*
+ * Check for a ?searchpart. - FM
+ */
+ if ((cp = strchr(address, '?')) != NULL) {
+ StrAllocCopy(searchpart, cp);
+ *cp = '\0';
+ cp = (searchpart + 1);
+ if (*cp != '\0') {
+ /*
+ * Seek and handle a subject=foo. - FM
+ */
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "subject=", 8))
+ break;
+ cp++;
+ }
+ if (*cp) {
+ cp += 8;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ if (*cp) {
+ strncpy(subject, cp, 70);
+ subject[70] = '\0';
+ HTUnEscape(subject);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp1 = NULL;
+ }
+ }
+
+ /*
+ * Seek and handle to=address(es) fields.
+ * Appends to address. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "to=", 3)) {
+ cp += 3;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (*address) {
+ StrAllocCat(address, ",");
+ }
+ StrAllocCat(address, cp);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+
+ /*
+ * Seek and handle cc=address(es) fields. Excludes
+ * Bcc=address(es) as unsafe. We may append our own
+ * cc (below) as a list for the actual mailing. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "cc=", 3)) {
+ cp += 3;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (ccaddr == NULL) {
+ StrAllocCopy(ccaddr, cp);
+ } else {
+ StrAllocCat(ccaddr, ",");
+ StrAllocCat(ccaddr, cp);
+ }
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+
+ /*
+ * Seek and handle keywords=term(s) fields. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "keywords=", 9)) {
+ cp += 9;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (keywords == NULL) {
+ StrAllocCopy(keywords, cp);
+ } else {
+ StrAllocCat(keywords, cp);
+ StrAllocCat(keywords, ", ");
+ }
+ StrAllocCat(keywords, cp);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+ if (keywords != NULL) {
+ if (*keywords != '\0') {
+ HTUnEscape(keywords);
+ } else {
+ FREE(keywords);
+ }
+ }
+
+ /*
+ * Seek and handle body=foo fields. - FM
+ */
+ cp = (searchpart + 1);
+ while (*cp != '\0') {
+ if ((*(cp - 1) == '?' || *(cp - 1) == '&') &&
+ !strncasecomp(cp, "body=", 5)) {
+ cp += 5;
+ if ((cp1 = strchr(cp, '&')) != NULL) {
+ *cp1 = '\0';
+ }
+ if (*cp) {
+ /*
+ * Break up the value into lines with
+ * a maximum length of 78. - FM
+ */
+ StrAllocCopy(temp, cp);
+ HTUnEscape(temp);
+ cp0 = temp;
+ while((cp = strchr(cp0, '\n')) != NULL) {
+ *cp = '\0';
+ if (cp > cp0) {
+ if (*(cp - 1) == '\r') {
+ *(cp - 1) = '\0';
+ }
+ }
+ i = 0;
+ len = strlen(cp0);
+ while (len > 78) {
+ strncpy(cmd, (char *)&cp0[i], 78);
+ cmd[78] = '\0';
+ strcat(cmd, "\n");
+ StrAllocCat(body, cmd);
+ i += 78;
+ len = strlen((char *)&cp0[i]);
+ }
+ sprintf(cmd, "%s\n", (char *)&cp0[i]);
+ StrAllocCat(body, cmd);
+ cp0 = (cp + 1);
+ }
+ i = 0;
+ len = strlen(cp0);
+ while (len > 78) {
+ strncpy(cmd, (char *)&cp0[i], 78);
+ cmd[78] = '\0';
+ strcat(cmd, "\n");
+ StrAllocCat(body, cmd);
+ i += 78;
+ len = strlen((char *)&cp0[i]);
+ }
+ if (len) {
+ sprintf(cmd, "%s\n", (char *)&cp0[i]);
+ StrAllocCat(body, cmd);
+ }
+ FREE(temp);
+ }
+ if (cp1) {
+ *cp1 = '&';
+ cp = cp1;
+ cp1 = NULL;
+ } else {
+ break;
+ }
+ }
+ cp++;
+ }
+
+ FREE(searchpart);
+ }
+ }
+
+ /*
+ * Convert any Explorer semi-colon Internet address
+ * separators to commas. - FM
+ */
+ cp = address;
+ while ((cp1 = strchr(cp, '@')) != NULL) {
+ cp1++;
+ if ((cp0 = strchr(cp1, ';')) != NULL) {
+ *cp0 = ',';
+ cp1 = cp0 + 1;
+ }
+ cp = cp1;
+ }
+ if (address[(strlen(address) - 1)] == ',')
+ address[(strlen(address) - 1)] = '\0';
+ if (*address == '\0') {
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ FREE(body);
+ fclose(fd); /* Close the tmpfile. */
+ remove(my_tmpfile); /* Delete the tmpfile. */
+ HTAlert(NO_ADDRESS_IN_MAILTO_URL);
+ return;
+ }
+ if (ccaddr != NULL) {
+ cp = ccaddr;
+ while ((cp1 = strchr(cp, '@')) != NULL) {
+ cp1++;
+ if ((cp0 = strchr(cp1, ';')) != NULL) {
+ *cp0 = ',';
+ cp1 = cp0 + 1;
+ }
+ cp = cp1;
+ }
+ if (ccaddr[(strlen(ccaddr) - 1)] == ',') {
+ ccaddr[(strlen(ccaddr) - 1)] = '\0';
+ }
+ if (*ccaddr == '\0') {
+ FREE(ccaddr);
+ }
+ }
+
+ /*
+ * Unescape the address and ccaddr fields. - FM
+ */
+ HTUnEscape(address);
+ if (ccaddr != NULL) {
+ HTUnEscape(ccaddr);
+ }
+
+ /*
+ * Set the default subject. - FM
+ */
+ if (subject[0] == '\0' && title && *title) {
+ strncpy(subject, title, 70);
+ subject[70] = '\0';
+ }
+
+ /*
+ * Use ^G to cancel mailing of comment
+ * and don't let SIGINTs exit lynx.
+ */
+ signal(SIGINT, terminate_letter);
+
+
+#ifdef VMS
+ if (isPMDF || !body) {
+ /*
+ * Put the X-URL and X-Mailer lines in the hdrfile
+ * for PMDF or my_tmpfile for VMS MAIL. - FM
+ */
+ fprintf((isPMDF ? hfd : fd),
+ "X-URL: %s%s\n",
+ (filename && *filename) ? filename : "mailto:",
+ (filename && *filename) ? "" : address);
+ fprintf((isPMDF ? hfd : fd),
+ "X-Mailer: Lynx, Version %s\n",LYNX_VERSION);
+#ifdef NO_ANONYMOUS_MAIL
+ if (!isPMDF) {
+ fprintf(fd, "\n");
+ }
+#endif /* NO_ANONYMOUS_MAIL */
+ }
+#else /* Unix: */
+ /*
+ * Put the To: line in the header.
+ */
+#ifndef DOSPATH
+ sprintf(buf, "To: %s\n", address);
+ StrAllocCopy(header, buf);
+#endif
+
+ /*
+ * Put the Mime-Version, Content-Type and
+ * Content-Transfer-Encoding in the header.
+ * This assumes that the same character set is used
+ * for composing the mail which is currently selected
+ * as display character set...
+ * Don't send a charset if we have a CJK character set
+ * selected, since it may not be appropriate for mail...
+ * Also don't use an unofficial "x-" charset.
+ * Also if the charset would be "us-ascii" (7-bit replacements
+ * selected, don't send any MIME headers. - kw
+ */
+ if (strncasecomp(LYCharSet_UC[current_char_set].MIMEname,
+ "us-ascii", 8) != 0) {
+ StrAllocCat(header, "Mime-Version: 1.0\n");
+ if (!LYHaveCJKCharacterSet &&
+ strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "x-", 2)
+ != 0) {
+ sprintf(buf,"Content-Type: text/plain; charset=%s\n",
+ LYCharSet_UC[current_char_set].MIMEname);
+ StrAllocCat(header, buf);
+ }
+ StrAllocCat(header, "Content-Transfer-Encoding: 8bit\n");
+ }
+ /*
+ * Put the X-URL and X-Mailer lines in the header.
+ */
+ sprintf(buf,
+ "X-URL: %s%s\n",
+ (filename && *filename) ? filename : "mailto:",
+ (filename && *filename) ? "" : address);
+ StrAllocCat(header, buf);
+ sprintf(buf, "X-Mailer: Lynx, Version %s\n", LYNX_VERSION);
+ StrAllocCat(header, buf);
+#endif /* VMS */
+
+ /*
+ * Clear the screen and inform the user.
+ */
+ clear();
+ move(2,0);
+ scrollok(stdscr, TRUE); /* Enable scrolling. */
+ if (body)
+ addstr(SENDING_MESSAGE_WITH_BODY_TO);
+ else
+ addstr(SENDING_COMMENT_TO);
+ cp = address;
+ while ((cp1 = strchr(cp, ',')) != NULL) {
+ *cp1 = '\0';
+ while (*cp == ' ')
+ cp++;
+ if (*cp) {
+ addstr(cp);
+ addstr(",\n ");
+ }
+ *cp1 = ',';
+ cp = (cp1 + 1);
+ }
+ if (*cp) {
+ addstr(cp);
+ }
+#ifdef VMS
+ if ((isPMDF == TRUE) &&
+ (cp = ccaddr) != NULL)
+#else
+ if ((cp = ccaddr) != NULL)
+#endif /* VMS */
+ {
+ if (strchr(cp, ',') != NULL) {
+ addstr(WITH_COPIES_TO);
+ } else {
+ addstr(WITH_COPY_TO);
+ }
+ while ((cp1 = strchr(cp, ',')) != NULL) {
+ *cp1 = '\0';
+ while (*cp == ' ')
+ cp++;
+ if (*cp) {
+ addstr(cp);
+ addstr(",\n ");
+ }
+ *cp1 = ',';
+ cp = (cp1 + 1);
+ }
+ if (*cp) {
+ addstr(cp);
+ }
+ }
+ addstr(CTRL_G_TO_CANCEL_SEND);
+
+#ifdef VMS
+ if (isPMDF || !body) {
+#endif /* VMS */
+#ifndef NO_ANONYMOUS_EMAIL
+ /*
+ * Get the user's personal name.
+ */
+ addstr(ENTER_NAME_OR_BLANK);
+ if (personal_name == NULL)
+ *user_input = '\0';
+ else {
+ addstr(CTRL_U_TO_ERASE);
+ strcpy(user_input, personal_name);
+ }
+#ifdef VMS
+ if (isPMDF) {
+ addstr("Personal_name: ");
+ } else {
+ addstr("X_Personal_name: ");
+ }
+#else
+ addstr("Personal Name: ");
+#endif /* VMS */
+ if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
+ term_letter) {
+ addstr("\n");
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ addstr("\n");
+ remove_tildes(user_input);
+ StrAllocCopy(personal_name, user_input);
+ term_letter = FALSE;
+ if (*user_input) {
+#ifdef VMS
+ fprintf((isPMDF ? hfd : fd),
+ "X-Personal_name: %s\n",user_input);
+#else
+ sprintf(buf, "X-Personal_name: %s\n", user_input);
+ StrAllocCat(header, buf);
+#endif /* VMS */
+ }
+
+ /*
+ * Get the user's return address.
+ */
+ addstr(ENTER_MAIL_ADDRESS_OR_OTHER);
+ addstr(MEANS_TO_CONTACT_FOR_RESPONSE);
+ if (personal_mail_address)
+ addstr(CTRL_U_TO_ERASE);
+#ifdef VMS
+ if (isPMDF) {
+ addstr("From: ");
+ } else {
+ addstr("X-From: ");
+ }
+#else
+ addstr("From: ");
+#endif /* VMS */
+ /* Add the personal mail address if there is one. */
+ sprintf(user_input, "%s", (personal_mail_address ?
+ personal_mail_address : ""));
+ if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
+ term_letter) {
+ addstr("\n");
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ addstr("\n");
+ remove_tildes(user_input);
+#ifdef VMS
+ if (*user_input) {
+ if (isPMDF) {
+ fprintf(hfd, "From: %s\n", user_input);
+ } else {
+ fprintf(fd, "X-From: %s\n\n", user_input);
+ }
+ } else if (!isPMDF) {
+ fprintf(fd, "\n");
+ }
+#else
+ sprintf(buf, "From: %s\n", user_input);
+ StrAllocCat(header, buf);
+#endif /* VMS */
+#endif /* !NO_ANONYMOUS_EMAIL */
+#ifdef VMS
+ }
+#endif /* VMS */
+
+ /*
+ * Get the subject line.
+ */
+ addstr(ENTER_SUBJECT_LINE);
+ addstr(CTRL_U_TO_ERASE);
+ addstr("Subject: ");
+ /* Add the default subject. */
+ sprintf(user_input, "%.70s%.63s",
+ (subject[0] != '\0') ?
+ subject :
+ ((filename && *filename) ?
+ filename : "mailto:"),
+ (subject[0] != '\0') ?
+ "" :
+ ((filename && *filename) ?
+ "" : address));
+ if (LYgetstr(user_input, VISIBLE, 71, NORECALL) < 0 ||
+ term_letter) {
+ addstr("\n");
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ addstr("\n");
+ remove_tildes(user_input);
+#ifdef VMS
+ sprintf(subject, "%.70s", user_input);
+#else
+ sprintf(buf, "Subject: %s\n", user_input);
+ StrAllocCat(header, buf);
+#endif /* VMS */
+
+ /*
+ * Offer a CC line, if permitted. - FM
+ */
+ user_input[0] = '\0';
+ if (!LYNoCc) {
+ addstr(ENTER_ADDRESS_FOR_CC);
+ if (personal_mail_address)
+ addstr(CTRL_U_TO_ERASE);
+ addstr(BLANK_FOR_NO_COPY);
+ addstr("Cc: ");
+ /*
+ * Add the mail address if there is one.
+ */
+ sprintf(user_input, "%s", (personal_mail_address ?
+ personal_mail_address : ""));
+ if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
+ term_letter) {
+ addstr("\n");
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ addstr("\n");
+ }
+ remove_tildes(user_input);
+#if defined (VMS) || defined (DOSPATH)
+ if (*user_input) {
+ cp = user_input;
+ while (*cp == ',' || isspace((unsigned char)*cp))
+ cp++;
+ if (*cp) {
+ if (ccaddr == NULL) {
+ StrAllocCopy(ccaddr, cp);
+ } else {
+ StrAllocCat(ccaddr, ",");
+ StrAllocCat(ccaddr, cp);
+ }
+ }
+ }
+#endif
+#ifdef DOSPATH
+ if (*address) {
+ sprintf(buf, "To: %s\n", address);
+ StrAllocCat(header, buf);
+ }
+#endif
+
+#ifndef VMS
+ /*
+ ** Add the Cc: header. - FM
+ */
+ if (ccaddr != NULL && *ccaddr != '\0') {
+ StrAllocCat(header, "Cc: ");
+ StrAllocCat(header, ccaddr);
+ StrAllocCat(header, "\n");
+ }
+
+ /*
+ ** Add the Keywords: header. - FM
+ */
+ if (keywords != NULL && *keywords != '\0') {
+ StrAllocCat(header, "Keywords: ");
+ StrAllocCat(header, keywords);
+ StrAllocCat(header, "\n");
+ }
+
+ /*
+ * Terminate the header.
+ */
+ sprintf(buf, "\n");
+ StrAllocCat(header, buf);
+#endif /* !VMS */
+
+ if (!no_editor && editor && *editor != '\0') {
+ /*
+ * Use an external editor for the message.
+ */
+ char *editor_arg = "";
+
+ if (body) {
+ cp1 = body;
+ while((cp = strchr(cp1, '\n')) != NULL) {
+ *cp++ = '\0';
+ fprintf(fd, "%s\n", cp1);
+ cp1 = cp;
+ }
+ } else if (strcmp(HTLoadedDocumentURL(), "")) {
+ /*
+ * Ask if the user wants to include the original message.
+ */
+ BOOLEAN is_preparsed = (LYPreparsedSource &&
+ HTisDocumentSource());
+ if (is_preparsed)
+ _statusline(INC_PREPARSED_MSG_PROMPT);
+ else
+ _statusline(INC_ORIG_MSG_PROMPT);
+ c = 0;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_letter && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ /*
+ * The 1 will add the reply "> " in front of every line.
+ */
+ if (is_preparsed)
+ print_wwwfile_to_fd(fd, 0);
+ else
+ print_wwwfile_to_fd(fd, 1);
+ }
+ }
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+
+ if (term_letter || c == 7 || c == 3)
+ goto cleanup;
+
+ /*
+ * Spawn the users editor on the mail file
+ */
+ if (strstr(editor, "pico")) {
+ editor_arg = " -t"; /* No prompt for filename to use */
+ }
+ sprintf(user_input, "%s%s %s", editor, editor_arg, my_tmpfile);
+ _statusline(SPAWNING_EDITOR_FOR_MAIL);
+ stop_curses();
+ if (system(user_input)) {
+ start_curses();
+ _statusline(ERROR_SPAWNING_EDITOR);
+ sleep(AlertSecs);
+ } else {
+ start_curses();
+ }
+
+ } else if (body) {
+ /*
+ * Let user review the body. - FM
+ */
+ clear();
+ move(0,0);
+ addstr(REVIEW_MESSAGE_BODY);
+ refresh();
+ cp1 = body;
+ i = (LYlines - 5);
+ while((cp = strchr(cp1, '\n')) != NULL) {
+ if (i <= 0) {
+ addstr(RETURN_TO_CONTINUE);
+ refresh();
+ c = LYgetch();
+ addstr("\n");
+ if (term_letter || c == 7 || c == 3) {
+ addstr(CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ i = (LYlines - 2);
+ }
+ *cp++ = '\0';
+ sprintf(cmd, "%s\n", cp1);
+ fprintf(fd, cmd);
+ addstr(cmd);
+ cp1 = cp;
+ i--;
+ }
+ while (i >= 0) {
+ addstr("\n");
+ i--;
+ }
+ refresh();
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+
+ } else {
+ /*
+ * Use the internal line editor for the message.
+ */
+ addstr(ENTER_MESSAGE_BELOW);
+ addstr(ENTER_PERIOD_WHEN_DONE_A);
+ addstr(ENTER_PERIOD_WHEN_DONE_B);
+ addstr("\n\n");
+ refresh();
+ *user_input = '\0';
+ if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 ||
+ term_letter || STREQ(user_input, ".")) {
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+
+ while (!STREQ(user_input, ".") && !term_letter) {
+ addstr("\n");
+ remove_tildes(user_input);
+ fprintf(fd, "%s\n", user_input);
+ *user_input = '\0';
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0) {
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ }
+
+ fprintf(fd, "\n"); /* Terminate the message. */
+ fclose(fd); /* Close the tmpfile. */
+ scrollok(stdscr,FALSE); /* Stop scrolling. */
+ }
+
+#ifndef VMS
+ /*
+ * Ignore CTRL-C on this last question.
+ */
+ signal(SIGINT, SIG_IGN);
+#endif /* !VMS */
+ LYStatusLine = (LYlines - 1);
+ if (body)
+ _statusline(SEND_MESSAGE_PROMPT);
+ else
+ _statusline(SEND_COMMENT_PROMPT);
+ LYStatusLine = -1;
+ c = 0;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_letter && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) != 'Y') {
+ clear(); /* clear the screen */
+ goto cleanup;
+ }
+ if ((body == NULL && LynxSigFile != NULL) &&
+ (fp = fopen(LynxSigFile, "r")) != NULL) {
+ LYStatusLine = (LYlines - 1);
+ _user_message(APPEND_SIG_FILE, LynxSigFile);
+ c = 0;
+ LYStatusLine = -1;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_letter && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ if ((fd = fopen(my_tmpfile, "a")) != NULL) {
+ fputs("-- \n", fd);
+ while (fgets(user_input, sizeof(user_input), fp) != NULL) {
+ fputs(user_input, fd);
+ }
+ fclose(fd);
+ }
+ }
+ fclose(fp);
+ }
+ clear(); /* Clear the screen. */
+
+ /*
+ * Send the message.
+ */
+#ifdef VMS
+ /*
+ * Set the mail command. - FM
+ */
+ if (isPMDF) {
+ /*
+ * For PMDF, put any keywords and the subject
+ * in the header file and close it. - FM
+ */
+ if (keywords != NULL && *keywords != '\0') {
+ fprintf(hfd, "Keywords: %s\n", keywords);
+ }
+ fprintf(hfd, "Subject: %s\n\n", subject);
+ fclose(hfd);
+ /*
+ * Now set up the command. - FM
+ */
+ sprintf(cmd,
+ "%s %s %s,%s ",
+ system_mail,
+ system_mail_flags,
+ hdrfile,
+ my_tmpfile);
+ } else {
+ /*
+ * For "generic" VMS MAIL, include the subject in the
+ * command, and ignore any keywords to minimize risk
+ * of them making the line too long or having problem
+ * characters. - FM
+ */
+ sprintf(cmd,
+ "%s %s%s/subject=\"%s\" %s ",
+ system_mail,
+ system_mail_flags,
+ (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"),
+ subject,
+ my_tmpfile);
+ }
+ StrAllocCopy(command, cmd);
+
+ /*
+ * Now add all the people in the address field. - FM
+ */
+ address_ptr1 = address;
+ do {
+ if ((cp = strchr(address_ptr1, ',')) != NULL) {
+ address_ptr2 = (cp+1);
+ *cp = '\0';
+ } else {
+ address_ptr2 = NULL;
+ }
+
+ /*
+ * 4 letters is arbitrarily the smallest possible mail
+ * address, at least for lynx. That way extra spaces
+ * won't confuse the mailer and give a blank address.
+ */
+ if (strlen(address_ptr1) > 3) {
+ if (!first) {
+ StrAllocCat(command, ",");
+ }
+ sprintf(cmd, mail_adrs, address_ptr1);
+ StrAllocCat(command, cmd);
+ first = FALSE;
+ }
+ address_ptr1 = address_ptr2;
+ } while (address_ptr1 != NULL);
+
+ /*
+ * Now add all the people in the CC field. - FM
+ */
+ if (ccaddr != NULL && *ccaddr != '\0') {
+ address_ptr1 = ccaddr;
+ do {
+ if ((cp = strchr(address_ptr1, ',')) != NULL) {
+ address_ptr2 = (cp+1);
+ *cp = '\0';
+ } else {
+ address_ptr2 = NULL;
+ }
+
+ /*
+ * 4 letters is arbitrarily the smallest possible mail
+ * address, at least for lynx. That way extra spaces
+ * won't confuse the mailer and give a blank address.
+ */
+ if (strlen(address_ptr1) > 3) {
+ StrAllocCat(command, ",");
+ sprintf(cmd, mail_adrs, address_ptr1);
+ if (isPMDF) {
+ strcat(cmd, "/CC");
+ }
+ StrAllocCat(command, cmd);
+ }
+ address_ptr1 = address_ptr2;
+ } while (address_ptr1 != NULL);
+ }
+
+ stop_curses();
+ printf("Sending your comment:\n\n$ %s\n\nPlease wait...", command);
+ system(command);
+ FREE(command);
+ sleep(AlertSecs);
+ start_curses();
+ goto cleandown;
+#else /* Unix: */
+ /*
+ * Send the tmpfile into sendmail.
+ */
+ _statusline(SENDING_YOUR_MSG);
+ sprintf(cmd, "%s %s", system_mail, system_mail_flags);
+#ifdef DOSPATH
+ tempname(tmpfile2, NEW_FILE);
+ if (((cp = strrchr(tmpfile2, '.')) != NULL) &&
+ NULL == strchr(cp, '/')) {
+ *cp = '\0';
+ strcat(tmpfile2, ".txt");
+ }
+ if ((fp = LYNewTxtFile(tmpfile2)) == NULL) {
+ HTAlert(MAILTO_URL_TEMPOPEN_FAILED);
+ return;
+ }
+#else
+ signal(SIGINT, SIG_IGN);
+ fp = popen(cmd, "w");
+ if (fp == NULL) {
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ goto cleanup;
+ }
+#endif /* DOSPATH */
+ fd = fopen(my_tmpfile, "r");
+ if (fd == NULL) {
+ _statusline(COMMENT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ pclose(fp);
+ goto cleanup;
+ }
+ fputs(header, fp);
+ while ((n = fread(buf, 1, sizeof(buf), fd)) != 0)
+ fwrite(buf, 1, n, fp);
+#ifdef DOSPATH
+ sprintf(cmd, "%s -t \"%s\" -F %s", system_mail, address, tmpfile2);
+ fclose(fp); /* Close the tmpfile. */
+ stop_curses();
+ printf("Sending your comment:\n\n$ %s\n\nPlease wait...", cmd);
+ system(cmd);
+ sleep(MessageSecs);
+ start_curses();
+ remove(tmpfile2); /* Delete the tmpfile. */
+#else
+ pclose(fp);
+#endif
+ fclose(fd); /* Close the tmpfile. */
+
+ if (TRACE)
+ printf("%s\n", cmd);
+#endif /* VMS */
+
+ /*
+ * Come here to cleanup and exit.
+ */
+cleanup:
+ signal(SIGINT, cleanup_sig);
+#if !defined(VMS) && !defined(DOSPATH)
+ FREE(header);
+#endif /* !VMS */
+
+#if defined(VMS) || defined(DOSPATH)
+cleandown:
+#endif /* VMS */
+ term_letter = FALSE;
+#ifdef VMS
+ FREE(command);
+ while (remove(my_tmpfile) == 0)
+ ; /* Delete the tmpfile(s). */
+ if (isPMDF) {
+ remove(hdrfile); /* Delete the hdrfile. */
+ }
+#else
+ remove(my_tmpfile); /* Delete the tmpfile. */
+#endif /* VMS */
+ FREE(address);
+ FREE(ccaddr);
+ FREE(keywords);
+ FREE(body);
+ return;
+}
+
+PRIVATE void terminate_letter ARGS1(int,sig GCC_UNUSED)
+{
+ term_letter = TRUE;
+ /* Reassert the AST */
+ signal(SIGINT, terminate_letter);
+#if defined(VMS) || defined(DOSPATH)
+ /*
+ * Refresh the screen to get rid of the "interrupt" message.
+ */
+ if (!dump_output_immediately) {
+ lynx_force_repaint();
+ refresh();
+ }
+#endif /* VMS */
+}
+
+PRIVATE void remove_tildes ARGS1(char *,string)
+{
+ /*
+ * Change the first character to
+ * a space if it is a '~'.
+ */
+ if (*string == '~')
+ *string = ' ';
+}
diff --git a/gnu/usr.bin/lynx/src/LYMail.h b/gnu/usr.bin/lynx/src/LYMail.h
new file mode 100644
index 00000000000..22ce906337b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMail.h
@@ -0,0 +1,26 @@
+
+#ifndef LYMAIL_H
+#define LYMAIL_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern BOOLEAN term_letter;
+
+extern void mailform PARAMS((
+ char * mailto_address,
+ char * mailto_subject,
+ char * mailto_content,
+ char * mailto_type));
+extern void mailmsg PARAMS((
+ int cur,
+ char * owner_address,
+ char * filename,
+ char * linkname));
+extern void reply_by_mail PARAMS((
+ char * mail_address,
+ char * filename,
+ CONST char * title));
+
+#endif /* LYMAIL_H */
diff --git a/gnu/usr.bin/lynx/src/LYMain.c b/gnu/usr.bin/lynx/src/LYMain.c
new file mode 100644
index 00000000000..2e600b1e325
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMain.c
@@ -0,0 +1,2908 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTP.h"
+#include "HTParse.h"
+#include "HTAccess.h"
+#include "HTList.h"
+#include "HTFile.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#include "HTInit.h"
+#include "LYCurses.h"
+#include "LYStyle.h"
+#include "HTML.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYGetFile.h"
+#include "LYStrings.h"
+#include "LYClean.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h"
+#include "UCMap.h"
+#include "LYReadCFG.h"
+#include "LYrcFile.h"
+#include "LYKeymap.h"
+#include "LYList.h"
+#include "LYJump.h"
+#include "LYMainLoop.h"
+#include "LYBookmark.h"
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+#include <syslog.h>
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#ifdef LOCALE
+#include<locale.h>
+#endif /* LOCALE */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+/* ahhhhhhhhhh!! Global variables :-< */
+#ifdef SOCKS
+PUBLIC BOOLEAN socks_flag=TRUE;
+#endif /* SOCKS */
+
+#ifdef IGNORE_CTRL_C
+PUBLIC BOOLEAN sigint = FALSE;
+#endif /* IGNORE_CTRL_C */
+
+#ifdef __DJGPP__
+char init_ctrl_break[1];
+#endif /* __DJGPP__ */
+
+#ifdef VMS
+PUBLIC char *mail_adrs = NULL; /* the mask for a VMS mail transport */
+ /* create FIXED 512 binaries */
+PUBLIC BOOLEAN UseFixedRecords = USE_FIXED_RECORDS;
+#endif /* VMS */
+
+#ifndef VMS
+PUBLIC char *lynx_version_putenv_command = NULL;
+PUBLIC char *NNTPSERVER_putenv_cmd = NULL; /* lynx.cfg defined NNTPSERVER */
+PUBLIC char *http_proxy_putenv_cmd = NULL; /* lynx.cfg defined http_proxy */
+PUBLIC char *https_proxy_putenv_cmd = NULL; /* lynx.cfg defined https_proxy */
+PUBLIC char *ftp_proxy_putenv_cmd = NULL; /* lynx.cfg defined ftp_proxy */
+PUBLIC char *gopher_proxy_putenv_cmd = NULL; /* lynx.cfg defined gopher_proxy */
+PUBLIC char *cso_proxy_putenv_cmd = NULL; /* lynx.cfg defined cso_proxy */
+PUBLIC char *news_proxy_putenv_cmd = NULL; /* lynx.cfg defined news_proxy */
+PUBLIC char *newspost_proxy_putenv_cmd = NULL;
+PUBLIC char *newsreply_proxy_putenv_cmd = NULL;
+PUBLIC char *snews_proxy_putenv_cmd = NULL; /* lynx.cfg defined snews_proxy */
+PUBLIC char *snewspost_proxy_putenv_cmd = NULL;
+PUBLIC char *snewsreply_proxy_putenv_cmd = NULL;
+PUBLIC char *nntp_proxy_putenv_cmd = NULL; /* lynx.cfg defined nntp_proxy */
+PUBLIC char *wais_proxy_putenv_cmd = NULL; /* lynx.cfg defined wais_proxy */
+PUBLIC char *finger_proxy_putenv_cmd = NULL; /* lynx.cfg defined finger_proxy */
+PUBLIC char *no_proxy_putenv_cmd = NULL; /* lynx.cfg defined no_proxy */
+PUBLIC char *list_format=NULL; /* LONG_LIST formatting mask */
+#ifdef SYSLOG_REQUESTED_URLS
+PUBLIC char *syslog_txt = NULL; /* syslog arb text for session */
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#ifdef VMS
+PUBLIC char *LYCSwingPath = NULL;
+#endif /* VMS */
+
+#ifdef DIRED_SUPPORT
+PUBLIC BOOLEAN lynx_edit_mode = FALSE;
+PUBLIC BOOLEAN no_dired_support = FALSE;
+PUBLIC BOOLEAN dir_list_style = MIXED_STYLE;
+PUBLIC HTList *tagged = NULL;
+#ifdef OK_OVERRIDE
+PUBLIC BOOLEAN prev_lynx_edit_mode = FALSE;
+#endif /* OK_OVERRIDE */
+#ifdef OK_PERMIT
+#ifdef NO_CHANGE_EXECUTE_PERMS
+PUBLIC BOOLEAN no_change_exec_perms = TRUE;
+#else
+PUBLIC BOOLEAN no_change_exec_perms = FALSE;
+#endif /* NO_CHANGE_EXECUTE_PERMS */
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
+
+ /* Number of docs cached in memory */
+PUBLIC int HTCacheSize = DEFAULT_CACHE_SIZE;
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+ /* Don't dump doc cache unless this size is exceeded */
+PUBLIC int HTVirtualMemorySize = DEFAULT_VIRTUAL_MEMORY_SIZE;
+#endif /* VMS && VAXC && !_DECC */
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+PUBLIC BOOLEAN local_exec = LOCAL_EXECUTION_LINKS_ALWAYS_ON;
+#else
+PUBLIC BOOLEAN local_exec = FALSE;
+#endif /* NEVER_ALLOW_REMOTE_EXEC */
+PUBLIC BOOLEAN local_exec_on_local_files =
+ LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE;
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+#if defined(LYNXCGI_LINKS) && !defined(VMS) /* WebSter Mods -jkt */
+PUBLIC char *LYCgiDocumentRoot = NULL; /* DOCUMENT_ROOT in the lynxcgi env */
+#endif /* LYNXCGI_LINKS */
+
+#ifdef REVERSE_CLEAR_SCREEN_PROBLEM
+PUBLIC BOOLEAN enable_scrollback=TRUE;
+#else
+PUBLIC BOOLEAN enable_scrollback=FALSE;
+#endif /* REVERSE_CLEAR_SCREEN_PROBLEM */
+
+PUBLIC char *empty_string = "\0";
+PUBLIC int display_lines; /* number of lines in display */
+PUBLIC int www_search_result= -1;
+ /* linked list of printers */
+PUBLIC lynx_printer_item_type *printers = NULL;
+ /* linked list of download options */
+PUBLIC lynx_html_item_type *downloaders = NULL;
+ /* linked list of upload options */
+#ifdef USE_EXTERNALS
+PUBLIC lynx_html_item_type *externals = NULL;
+ /* linked list of external options */
+#endif
+PUBLIC lynx_html_item_type *uploaders = NULL;
+PUBLIC int port_syntax = 1;
+PUBLIC int LYShowColor = SHOW_COLOR_UNKNOWN; /* to show or not to show */
+PUBLIC int LYChosenShowColor = SHOW_COLOR_UNKNOWN; /* whether to show and save */
+PUBLIC int LYrcShowColor = SHOW_COLOR_UNKNOWN; /* ... as last read or written */
+PUBLIC BOOLEAN LYShowCursor = SHOW_CURSOR; /* to show or not to show */
+PUBLIC BOOLEAN LYUseDefShoCur = TRUE; /* Command line -show_cursor toggle */
+PUBLIC BOOLEAN LYforce_no_cache = FALSE;
+PUBLIC BOOLEAN LYoverride_no_cache = FALSE;/*override no-cache b/c history etc*/
+PUBLIC BOOLEAN LYinternal_flag = FALSE; /* override no-cache b/c internal link*/
+PUBLIC BOOLEAN LYresubmit_posts = ALWAYS_RESUBMIT_POSTS;
+PUBLIC BOOLEAN LYUserSpecifiedURL = TRUE;/* always TRUE the first time */
+PUBLIC BOOLEAN LYJumpFileURL = FALSE; /* always FALSE the first time */
+PUBLIC BOOLEAN jump_buffer = JUMPBUFFER; /* TRUE if offering default shortcut */
+PUBLIC BOOLEAN goto_buffer = GOTOBUFFER; /* TRUE if offering default goto URL */
+PUBLIC BOOLEAN recent_sizechange = FALSE;/* the window size changed recently? */
+PUBLIC BOOLEAN user_mode = NOVICE_MODE;
+PUBLIC BOOLEAN dump_output_immediately = FALSE;
+PUBLIC BOOLEAN is_www_index = FALSE;
+PUBLIC BOOLEAN lynx_mode = NORMAL_LYNX_MODE;
+PUBLIC BOOLEAN bold_headers = FALSE;
+PUBLIC BOOLEAN bold_H1 = FALSE;
+PUBLIC BOOLEAN bold_name_anchors = FALSE;
+PUBLIC BOOLEAN use_underscore = SUBSTITUTE_UNDERSCORES;
+PUBLIC BOOLEAN nolist = FALSE;
+PUBLIC BOOLEAN historical_comments = FALSE;
+PUBLIC BOOLEAN minimal_comments = FALSE;
+PUBLIC BOOLEAN soft_dquotes = FALSE;
+PUBLIC BOOLEAN LYValidate = FALSE;
+PUBLIC BOOLEAN LYPermitURL = FALSE;
+PUBLIC BOOLEAN child_lynx = FALSE;
+PUBLIC BOOLEAN error_logging = MAIL_SYSTEM_ERROR_LOGGING;
+PUBLIC BOOLEAN check_mail = CHECKMAIL;
+PUBLIC BOOLEAN vi_keys = VI_KEYS_ALWAYS_ON;
+PUBLIC BOOLEAN emacs_keys = EMACS_KEYS_ALWAYS_ON;
+PUBLIC BOOLEAN keypad_mode = DEFAULT_KEYPAD_MODE;
+PUBLIC BOOLEAN case_sensitive = CASE_SENSITIVE_ALWAYS_ON;
+PUBLIC BOOLEAN telnet_ok = TRUE;
+PUBLIC BOOLEAN news_ok = TRUE;
+PUBLIC BOOLEAN rlogin_ok = TRUE;
+PUBLIC BOOLEAN ftp_ok = TRUE;
+PUBLIC BOOLEAN system_editor = FALSE;
+#ifdef USE_EXTERNALS
+PUBLIC BOOLEAN no_externals = FALSE;
+#endif
+#ifdef RAWDOSKEYHACK
+PUBLIC BOOLEAN raw_dos_key_hack = TRUE;
+#endif /* RAWDOSKEYHACK */
+PUBLIC BOOLEAN no_inside_telnet = FALSE;
+PUBLIC BOOLEAN no_outside_telnet = FALSE;
+PUBLIC BOOLEAN no_telnet_port = FALSE;
+PUBLIC BOOLEAN no_inside_news = FALSE;
+PUBLIC BOOLEAN no_outside_news = FALSE;
+PUBLIC BOOLEAN no_inside_ftp = FALSE;
+PUBLIC BOOLEAN no_outside_ftp = FALSE;
+PUBLIC BOOLEAN no_inside_rlogin = FALSE;
+PUBLIC BOOLEAN no_outside_rlogin = FALSE;
+PUBLIC BOOLEAN no_suspend = FALSE;
+PUBLIC BOOLEAN no_editor = FALSE;
+PUBLIC BOOLEAN no_shell = FALSE;
+PUBLIC BOOLEAN no_bookmark = FALSE;
+PUBLIC BOOLEAN no_multibook = FALSE;
+PUBLIC BOOLEAN no_bookmark_exec = FALSE;
+PUBLIC BOOLEAN no_option_save = FALSE;
+PUBLIC BOOLEAN no_print = FALSE;
+PUBLIC BOOLEAN no_download = FALSE;
+PUBLIC BOOLEAN no_disk_save = FALSE;
+PUBLIC BOOLEAN no_exec = FALSE;
+PUBLIC BOOLEAN no_lynxcgi = FALSE;
+PUBLIC BOOLEAN exec_frozen = FALSE;
+PUBLIC BOOLEAN no_goto = FALSE;
+PUBLIC BOOLEAN no_goto_cso = FALSE;
+PUBLIC BOOLEAN no_goto_file = FALSE;
+PUBLIC BOOLEAN no_goto_finger = FALSE;
+PUBLIC BOOLEAN no_goto_ftp = FALSE;
+PUBLIC BOOLEAN no_goto_gopher = FALSE;
+PUBLIC BOOLEAN no_goto_http = FALSE;
+PUBLIC BOOLEAN no_goto_https = FALSE;
+PUBLIC BOOLEAN no_goto_lynxcgi = FALSE;
+PUBLIC BOOLEAN no_goto_lynxexec = FALSE;
+PUBLIC BOOLEAN no_goto_lynxprog = FALSE;
+PUBLIC BOOLEAN no_goto_mailto = FALSE;
+PUBLIC BOOLEAN no_goto_news = FALSE;
+PUBLIC BOOLEAN no_goto_nntp = FALSE;
+PUBLIC BOOLEAN no_goto_rlogin = FALSE;
+PUBLIC BOOLEAN no_goto_snews = FALSE;
+PUBLIC BOOLEAN no_goto_telnet = FALSE;
+PUBLIC BOOLEAN no_goto_tn3270 = FALSE;
+PUBLIC BOOLEAN no_goto_wais = FALSE;
+PUBLIC BOOLEAN no_jump = FALSE;
+PUBLIC BOOLEAN no_file_url = FALSE;
+PUBLIC BOOLEAN no_newspost = FALSE;
+PUBLIC BOOLEAN no_mail = FALSE;
+PUBLIC BOOLEAN no_dotfiles = NO_DOT_FILES;
+PUBLIC BOOLEAN no_useragent = FALSE;
+PUBLIC BOOLEAN no_statusline = FALSE;
+PUBLIC BOOLEAN no_filereferer = FALSE;
+PUBLIC BOOLEAN local_host_only = FALSE;
+PUBLIC BOOLEAN override_no_download = FALSE;
+PUBLIC BOOLEAN show_dotfiles = FALSE; /* From rcfile if no_dotfiles is false */
+PUBLIC BOOLEAN LYforce_HTML_mode = FALSE;
+PUBLIC char *homepage = NULL; /* home page or main screen */
+PUBLIC char *editor = NULL; /* the name of the current editor */
+PUBLIC char *jumpfile = NULL; /* the name of the default jumps file */
+PUBLIC char *jumpprompt = NULL; /* the default jumps prompt */
+PUBLIC char *bookmark_page = NULL; /* the name of the default bookmark page */
+PUBLIC char *BookmarkPage = NULL; /* the name of the current bookmark page */
+PUBLIC char *LynxHome = NULL; /* the default Home HREF. */
+PUBLIC char *startfile = NULL; /* the first file */
+PUBLIC char *helpfile = NULL; /* the main help file */
+PUBLIC char *helpfilepath = NULL; /* the path to the help file set */
+PUBLIC char *lynxjumpfile = NULL; /* the current jump file URL */
+PUBLIC char *lynxlistfile = NULL; /* the current list file URL */
+PUBLIC char *lynxlinksfile = NULL; /* the current visited links file URL */
+PUBLIC char *startrealm = NULL; /* the startfile realm */
+PUBLIC char *indexfile = NULL; /* an index file if there is one */
+PUBLIC char *personal_mail_address = NULL; /* the users mail address */
+PUBLIC char *display = NULL; /* display environment variable */
+PUBLIC char *personal_type_map = NULL; /* .mailcap */
+PUBLIC char *global_type_map = NULL; /* global mailcap */
+PUBLIC char *global_extension_map = NULL; /* global mime.types */
+PUBLIC char *personal_extension_map = NULL;/* .mime.types */
+PUBLIC char *language = NULL; /* preferred language */
+PUBLIC char *pref_charset = NULL; /* preferred character set */
+PUBLIC BOOLEAN LYNewsPosting = NEWS_POSTING; /* News posting supported? */
+PUBLIC char *LynxSigFile = NULL; /* Signature file, in or off home */
+PUBLIC char *system_mail = NULL; /* The path for sending mail */
+PUBLIC char *system_mail_flags = NULL; /* Flags for sending mail */
+PUBLIC char *lynx_temp_space = NULL; /* The prefix for temporary file paths */
+PUBLIC char *lynx_save_space = NULL; /* The prefix for save to disk paths */
+PUBLIC char *LYHostName = NULL; /* treat as a local host name */
+PUBLIC char *LYLocalDomain = NULL; /* treat as a local domain tail */
+PUBLIC BOOLEAN clickable_images = MAKE_LINKS_FOR_ALL_IMAGES;
+PUBLIC BOOLEAN pseudo_inline_alts = MAKE_PSEUDO_ALTS_FOR_INLINES;
+PUBLIC BOOLEAN crawl = FALSE; /* Do crawl? */
+PUBLIC BOOLEAN traversal = FALSE; /* Do traversals? */
+PUBLIC BOOLEAN check_realm = FALSE; /* Restrict to the starting realm? */
+ /* Links beyond a displayed page with no links? */
+PUBLIC BOOLEAN more_links = FALSE;
+PUBLIC int ccount = 0; /* Starting number for lnk#.dat files in crawls */
+PUBLIC BOOLEAN LYCancelledFetch = FALSE; /* TRUE if cancelled binary fetch */
+ /* Include mime headers with source dump */
+PUBLIC BOOLEAN keep_mime_headers = FALSE;
+PUBLIC BOOLEAN no_url_redirection = FALSE; /* Don't follow URL redirections */
+PUBLIC char *form_post_data = NULL; /* User data for post form */
+PUBLIC char *form_get_data = NULL; /* User data for get form */
+PUBLIC char *http_error_file = NULL; /* Place HTTP status code in this file */
+ /* Id:Password for protected documents */
+PUBLIC char *authentication_info[2] = {NULL, NULL};
+ /* Id:Password for protected proxy servers */
+PUBLIC char *proxyauth_info[2] = {NULL, NULL};
+PUBLIC BOOLEAN HEAD_request = FALSE;
+PUBLIC BOOLEAN scan_for_buried_news_references = TRUE;
+PUBLIC BOOLEAN LYRawMode;
+PUBLIC BOOLEAN LYDefaultRawMode;
+PUBLIC BOOLEAN LYUseDefaultRawMode = TRUE;
+PUBLIC char *UCAssume_MIMEcharset = NULL;
+PUBLIC char *UCAssume_localMIMEcharset = NULL;
+PUBLIC char *UCAssume_unrecMIMEcharset = NULL;
+PUBLIC int LYlines = 24;
+PUBLIC int LYcols = 80;
+PUBLIC int dump_output_width = 0;
+PUBLIC linkstruct links[MAXLINKS];
+PUBLIC histstruct history[MAXHIST];
+PUBLIC int nlinks = 0; /* number of links in memory */
+PUBLIC int nhist = 0; /* number of history entries */
+PUBLIC int more = FALSE; /* is there more text to display? */
+PUBLIC int InfoSecs; /* Seconds to sleep() for Information messages */
+PUBLIC int MessageSecs; /* Seconds to sleep() for important Messages */
+PUBLIC int AlertSecs; /* Seconds to sleep() for HTAlert() messages */
+PUBLIC BOOLEAN bookmark_start = FALSE;
+PUBLIC char *LYUserAgent = NULL; /* Lynx User-Agent header */
+PUBLIC char *LYUserAgentDefault = NULL; /* Lynx default User-Agent header */
+PUBLIC BOOLEAN LYUseMouse = FALSE;
+PUBLIC BOOLEAN LYNoRefererHeader=FALSE; /* Never send Referer header? */
+PUBLIC BOOLEAN LYNoRefererForThis=FALSE;/* No Referer header for this URL? */
+PUBLIC BOOLEAN LYNoFromHeader = TRUE; /* Never send From header? */
+PUBLIC BOOLEAN LYListNewsNumbers = LIST_NEWS_NUMBERS;
+PUBLIC BOOLEAN LYListNewsDates = LIST_NEWS_DATES;
+PUBLIC BOOLEAN LYisConfiguredForX = FALSE;
+PUBLIC char *URLDomainPrefixes = NULL;
+PUBLIC char *URLDomainSuffixes = NULL;
+PUBLIC BOOLEAN startfile_ok = FALSE;
+PUBLIC BOOLEAN LYSelectPopups = USE_SELECT_POPUPS;
+PUBLIC BOOLEAN LYUseDefSelPop = TRUE; /* Command line -popup toggle */
+PUBLIC int LYMultiBookmarks = MULTI_BOOKMARK_SUPPORT;
+PUBLIC BOOLEAN LYMBMBlocked = BLOCK_MULTI_BOOKMARKS;
+PUBLIC BOOLEAN LYMBMAdvanced = TRUE;
+PUBLIC int LYStatusLine = -1; /* Line for statusline() if > -1 */
+PUBLIC BOOLEAN LYCollapseBRs = COLLAPSE_BR_TAGS; /* Collapse serial BRs? */
+PUBLIC BOOLEAN LYSetCookies = SET_COOKIES; /* Process Set-Cookie headers? */
+PUBLIC char *XLoadImageCommand = NULL; /* Default image viewer for X */
+PUBLIC BOOLEAN LYNoISMAPifUSEMAP = FALSE; /* Omit ISMAP link if MAP present? */
+PUBLIC int LYHiddenLinks = HIDDENLINKS_SEPARATE; /* Show hidden links? */
+
+PUBLIC BOOL New_DTD = YES;
+PUBLIC FILE *LYTraceLogFP = NULL; /* Pointer for TRACE log */
+PUBLIC char *LYTraceLogPath = NULL; /* Path for TRACE log */
+PUBLIC BOOLEAN LYUseTraceLog = USE_TRACE_LOG; /* Use a TRACE log? */
+PUBLIC FILE LYOrigStderr; /* Original stderr pointer */
+PUBLIC BOOLEAN LYSeekFragMAPinCur = TRUE;
+PUBLIC BOOLEAN LYSeekFragAREAinCur = TRUE;
+
+PUBLIC BOOLEAN LYStripDotDotURLs = TRUE; /* Try to fix ../ in some URLs? */
+PUBLIC BOOLEAN LYForceSSLCookiesSecure = FALSE;
+PUBLIC BOOLEAN LYNoCc = FALSE;
+PUBLIC BOOLEAN LYPreparsedSource = FALSE; /* Show source as preparsed? */
+PUBLIC BOOLEAN LYPrependBaseToSource = TRUE;
+PUBLIC BOOLEAN LYPrependCharsetToSource = FALSE;
+PUBLIC BOOLEAN LYQuitDefaultYes = QUIT_DEFAULT_YES;
+
+/* These are declared in cutil.h for current freeWAIS libraries. - FM */
+#ifdef DECLARE_WAIS_LOGFILES
+PUBLIC char *log_file_name = NULL; /* for WAIS log file name in libWWW */
+PUBLIC FILE *logfile = NULL; /* for WAIS log file output in libWWW */
+#endif /* DECLARE_WAIS_LOGFILES */
+
+extern int HTNewsChunkSize; /* Number of news articles per chunk (HTNews.c) */
+extern int HTNewsMaxChunk; /* Max news articles before chunking (HTNews.c) */
+
+PRIVATE BOOLEAN anon_restrictions_set = FALSE;
+PRIVATE BOOLEAN stack_dump = FALSE;
+PRIVATE char *terminal = NULL;
+PRIVATE char *pgm;
+PRIVATE BOOLEAN number_links = FALSE;
+PRIVATE BOOLEAN LYPrependBase = FALSE;
+PRIVATE HTList *LYStdinArgs = NULL;
+
+PRIVATE void parse_arg PARAMS((char **arg, int *i, int argc));
+#ifndef VMS
+PUBLIC BOOLEAN LYNoCore = NO_FORCED_CORE_DUMP;
+PRIVATE void FatalProblem PARAMS((int sig));
+#endif /* !VMS */
+
+#if defined(USE_HASH)
+ char *lynx_lss_file=NULL;
+#endif
+
+#ifdef __DJGPP__
+void reset_break()
+{
+ PDC_set_ctrl_break(init_ctrl_break[0]);
+}
+#endif /* __DJGPP__ */
+
+PRIVATE void free_lynx_globals NOARGS
+{
+ int i;
+
+#ifndef VMS
+ FREE(list_format);
+#ifdef SYSLOG_REQUESTED_URLS
+ FREE(syslog_txt);
+#endif /* SYSLOG_REQUESTED_URLS */
+#ifdef LYNXCGI_LINKS /* WebSter Mods -jkt */
+ FREE(LYCgiDocumentRoot);
+#endif /* LYNXCGI_LINKS */
+ FREE(lynx_version_putenv_command);
+ FREE(NNTPSERVER_putenv_cmd);
+ FREE(http_proxy_putenv_cmd);
+ FREE(https_proxy_putenv_cmd);
+ FREE(ftp_proxy_putenv_cmd);
+ FREE(gopher_proxy_putenv_cmd);
+ FREE(cso_proxy_putenv_cmd);
+ FREE(news_proxy_putenv_cmd);
+ FREE(newspost_proxy_putenv_cmd);
+ FREE(newsreply_proxy_putenv_cmd);
+ FREE(snews_proxy_putenv_cmd);
+ FREE(snewspost_proxy_putenv_cmd);
+ FREE(snewsreply_proxy_putenv_cmd);
+ FREE(nntp_proxy_putenv_cmd);
+ FREE(wais_proxy_putenv_cmd);
+ FREE(finger_proxy_putenv_cmd);
+ FREE(no_proxy_putenv_cmd);
+#endif /* !VMS */
+
+#ifdef VMS
+ Define_VMSLogical("LYNX_VERSION", "");
+ FREE(mail_adrs);
+ FREE(LYCSwingPath);
+#endif /* VMS */
+
+ FREE(LynxHome);
+ FREE(startfile);
+ FREE(helpfile);
+ FREE(jumpprompt);
+#ifdef JUMPFILE
+ FREE(jumpfile);
+#endif /* JUMPFILE */
+ FREE(indexfile);
+ FREE(display);
+ FREE(global_type_map);
+ FREE(personal_type_map);
+ FREE(global_extension_map);
+ FREE(personal_extension_map);
+ FREE(language);
+ FREE(pref_charset);
+ FREE(LynxSigFile);
+ FREE(system_mail);
+ FREE(system_mail_flags);
+ FREE(LYUserAgent);
+ FREE(LYUserAgentDefault);
+ FREE(LYHostName);
+ FREE(LYLocalDomain);
+ FREE(lynx_save_space);
+ FREE(homepage);
+ FREE(helpfilepath);
+ FREE(bookmark_page);
+ FREE(BookmarkPage);
+ for (i = 0; i <= MBM_V_MAXFILES; i++) {
+ FREE(MBM_A_subbookmark[i]);
+ FREE(MBM_A_subdescript[i]);
+ }
+ FREE(editor);
+ FREE(authentication_info[0]);
+ FREE(authentication_info[1]);
+ FREE(proxyauth_info[0]);
+ FREE(proxyauth_info[1]);
+ FREE(lynxjumpfile);
+ FREE(startrealm);
+ FREE(personal_mail_address);
+ FREE(URLDomainPrefixes);
+ FREE(URLDomainSuffixes);
+ FREE(XLoadImageCommand);
+ FREE(LYTraceLogPath);
+#if defined(USE_HASH)
+ FREE(lynx_lss_file);
+#endif
+ FREE(UCAssume_MIMEcharset);
+ FREE(UCAssume_unrecMIMEcharset);
+ FREE(UCAssume_localMIMEcharset);
+ for (i = 0; i < nlinks; i++) {
+ FREE(links[i].lname);
+ }
+ nlinks = 0;
+
+ return;
+}
+
+/*
+ * This function frees the LYStdinArgs list. - FM
+ */
+PRIVATE void LYStdinArgs_free NOARGS
+{
+ char *argument;
+ HTList *cur = LYStdinArgs;
+
+ if (cur == NULL)
+ return;
+
+ while (NULL != (argument = (char *)HTList_nextObject(cur))) {
+ FREE(argument);
+ }
+ HTList_delete(LYStdinArgs);
+ LYStdinArgs = NULL;
+ return;
+}
+
+/*
+ * Wow! Someone wants to start up Lynx.
+ */
+PUBLIC int main ARGS2(
+ int, argc,
+ char **, argv)
+{
+ int i; /* indexing variable */
+ int status = 0; /* exit status */
+ int len;
+ char *lynx_cfg_file = NULL;
+ char *temp = NULL;
+ char *cp;
+ FILE *fp;
+ char filename[256];
+ BOOL LYGetStdinArgs = FALSE;
+
+#ifdef _WINDOWS
+ WSADATA WSAData;
+ {
+ int err;
+ WORD wVerReq;
+
+ wVerReq = MAKEWORD(1,1);
+
+ err = WSAStartup(wVerReq, &WSAData);
+ if (err != 0)
+ {
+ printf("No Winsock found, sorry.");
+ sleep(5);
+ return;
+ }
+ }
+#endif /* _WINDOWS */
+
+#ifdef __DJGPP__
+if (PDC_get_ctrl_break() == 0) {
+ PDC_set_ctrl_break(TRUE);
+ init_ctrl_break[0] = 0;}
+else {init_ctrl_break[0] = 1;}
+ atexit(reset_break);
+ sock_init();
+#endif
+
+#if defined(_WINDOWS) || defined(DJGPP)
+ /*
+ * To prevent corrupting binary data with _WINDOWS and DJGPP
+ * we open files and stdout in BINARY mode by default.
+ * Where necessary we should open and (close!) TEXT mode.
+ */
+ _fmode = O_BINARY;
+ setmode( fileno( stdout ), O_BINARY );
+#endif
+
+#ifdef DOSPATH
+ terminal = "vt100";
+#endif
+
+ LYShowColor = (SHOW_COLOR ? SHOW_COLOR_ON : SHOW_COLOR_OFF);
+ /*
+ * Set up the argument list.
+ */
+ pgm = argv[0];
+ if ((cp = strrchr(pgm, '/')) != NULL) {
+ pgm = cp + 1;
+ }
+
+ /*
+ * Act on -help NOW, so we only output the help and exit. - FM
+ */
+ for (i = 1; i < argc; i++) {
+ if (strncmp(argv[i], "-help", 5) == 0) {
+ parse_arg(&argv[i], &i, argc);
+ }
+ }
+
+#ifdef LY_FIND_LEAKS
+ /*
+ * Register the final function to be executed when being exited.
+ * Will display memory leaks if LY_FIND_LEAKS is defined.
+ */
+ atexit(LYLeaks);
+#endif /* LY_FIND_LEAKS */
+ /*
+ * Register the function which will free our allocated globals.
+ */
+ atexit(free_lynx_globals);
+
+#ifdef LOCALE
+ /*
+ * LOCALE support for international characters.
+ */
+ setlocale(LC_ALL, "");
+#endif /* LOCALE */
+
+ /*
+ * Initialize our startup and global variables.
+ */
+#ifdef ULTRIX
+ /*
+ * Need this for Ultrix.
+ */
+ terminal = getenv("TERM");
+ if ((terminal == NULL) || !strncasecomp(terminal, "xterm", 5))
+ terminal = "vt100";
+#endif /* ULTRIX */
+ /*
+ * Zero the links and history struct arrays.
+ */
+ memset((void *)links, 0, sizeof(linkstruct)*MAXLINKS);
+ memset((void *)history, 0, sizeof(histstruct)*MAXHIST);
+ /*
+ * Zero the MultiBookmark arrays.
+ */
+ memset((void *)MBM_A_subbookmark, 0, sizeof(char)*(MBM_V_MAXFILES+1));
+ memset((void *)MBM_A_subdescript, 0, sizeof(char)*(MBM_V_MAXFILES+1));
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ openlog("lynx", LOG_PID, LOG_LOCAL5);
+#endif /* SYSLOG_REQUESTED_URLS */
+ StrAllocCopy(list_format, LIST_FORMAT);
+#endif /* !VMS */
+ InfoSecs = (int)INFOSECS;
+ MessageSecs = (int)MESSAGESECS;
+ AlertSecs = (int)ALERTSECS;
+ StrAllocCopy(helpfile, HELPFILE);
+ StrAllocCopy(startfile, STARTFILE);
+ LYTrimHead(startfile);
+ if (!strncasecomp(startfile, "lynxexec:", 9) ||
+ !strncasecomp(startfile, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(startfile, " \r\n\t");
+ convert_to_spaces(startfile, TRUE);
+ }
+ StrAllocCopy(indexfile, DEFAULT_INDEX_FILE);
+ StrAllocCopy(global_type_map, GLOBAL_MAILCAP);
+ StrAllocCopy(personal_type_map, PERSONAL_MAILCAP);
+ StrAllocCopy(global_extension_map, GLOBAL_EXTENSION_MAP);
+ StrAllocCopy(personal_extension_map, PERSONAL_EXTENSION_MAP);
+ StrAllocCopy(language, PREFERRED_LANGUAGE);
+ StrAllocCopy(pref_charset, PREFERRED_CHARSET);
+ StrAllocCopy(system_mail, SYSTEM_MAIL);
+ StrAllocCopy(system_mail_flags, SYSTEM_MAIL_FLAGS);
+ StrAllocCopy(LYUserAgent, LYNX_NAME);
+ StrAllocCat(LYUserAgent, "/");
+ StrAllocCat(LYUserAgent, LYNX_VERSION);
+ if (HTLibraryVersion) {
+ StrAllocCat(LYUserAgent, " libwww-FM/");
+ StrAllocCat(LYUserAgent, HTLibraryVersion);
+ }
+ StrAllocCopy(LYUserAgentDefault, LYUserAgent);
+#ifdef VMS
+ Define_VMSLogical("LYNX_VERSION", LYNX_VERSION);
+#else
+ StrAllocCopy(lynx_version_putenv_command, "LYNX_VERSION=");
+ StrAllocCat(lynx_version_putenv_command, LYNX_VERSION);
+ putenv(lynx_version_putenv_command);
+#endif /* VMS */
+ if ((cp = getenv("LYNX_TEMP_SPACE")) != NULL)
+ StrAllocCopy(lynx_temp_space, cp);
+ else
+#ifdef DOSPATH
+ if ((cp = getenv("TEMP")) != NULL)
+ StrAllocCopy(lynx_temp_space, cp);
+ else if ((cp = getenv("TMP")) != NULL)
+ StrAllocCopy(lynx_temp_space, cp);
+ else
+#endif
+ StrAllocCopy(lynx_temp_space, TEMP_SPACE);
+ if ((cp = strchr(lynx_temp_space, '~'))) {
+ *(cp++) = '\0';
+ StrAllocCopy(temp, lynx_temp_space);
+ if (((len = strlen(temp)) > 0) && temp[len-1] == '/')
+ temp[len-1] = '\0';
+#ifdef DOSPATH
+ StrAllocCat(temp, HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(temp, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ StrAllocCat(temp, cp);
+ StrAllocCopy(lynx_temp_space, temp);
+ FREE(temp);
+ }
+ if ((cp = strstr(lynx_temp_space, "$USER")) != NULL) {
+ char *cp1;
+
+ if ((cp1 = (char *)getenv("USER")) != NULL) {
+ *cp = '\0';
+ StrAllocCopy(temp, lynx_temp_space);
+ *cp = '$';
+ StrAllocCat(temp, cp1);
+ cp += 5;
+ StrAllocCat(temp, cp);
+ StrAllocCopy(lynx_temp_space, temp);
+ FREE(temp);
+ }
+ }
+#ifdef VMS
+ for (i = 0; lynx_temp_space[i]; i++)
+ lynx_temp_space[i] = TOLOWER(lynx_temp_space[i]);
+ if (strchr(lynx_temp_space, '/') != NULL) {
+ if ((len = strlen(lynx_temp_space)) == 1) {
+ StrAllocCopy(lynx_temp_space, "sys$scratch:");
+ } else {
+ if (lynx_temp_space[len-1] != '/')
+ StrAllocCat(lynx_temp_space, "/");
+ StrAllocCopy(temp, HTVMS_name("", lynx_temp_space));
+ StrAllocCopy(lynx_temp_space, temp);
+ FREE(temp);
+ }
+ }
+ if (strchr(lynx_temp_space, ':') == NULL &&
+ strchr(lynx_temp_space, ']') == NULL) {
+ StrAllocCat(lynx_temp_space, ":");
+ }
+#else
+#ifndef __DJGPP__
+ if (((len = strlen(lynx_temp_space)) > 1) &&
+ lynx_temp_space[len-1] != '/') {
+ StrAllocCat(lynx_temp_space, "/");
+ }
+#else
+ if (((len = strlen(lynx_temp_space)) > 1) &&
+ lynx_temp_space[len-1] != '\\') {
+ StrAllocCat(lynx_temp_space, "\\");
+ }
+#endif /* __DJGPP__ */
+#endif /* VMS */
+#ifdef VMS
+ StrAllocCopy(mail_adrs, MAIL_ADRS);
+#ifdef CSWING_PATH
+ StrAllocCopy(LYCSwingPath, CSWING_PATH);
+#endif /* CSWING_PATH */
+#endif /* VMS */
+#ifdef LYNX_HOST_NAME
+ StrAllocCopy(LYHostName, LYNX_HOST_NAME);
+#else
+ StrAllocCopy(LYHostName, HTHostName());
+#endif /* LYNX_HOST_NAME */
+ StrAllocCopy(LYLocalDomain, LOCAL_DOMAIN);
+ StrAllocCopy(URLDomainPrefixes, URL_DOMAIN_PREFIXES);
+ StrAllocCopy(URLDomainSuffixes, URL_DOMAIN_SUFFIXES);
+ StrAllocCopy(XLoadImageCommand, XLOADIMAGE_COMMAND);
+ /*
+ * Set up the compilation default character set. - FM
+ */
+ for (i = 0; LYchar_set_names[i]; i++) {
+ if (!strncmp(CHARACTER_SET, LYchar_set_names[i],
+ strlen(CHARACTER_SET))) {
+ current_char_set=i;
+ break;
+ }
+ }
+ if (!LYchar_set_names[i])
+ current_char_set = i = 0;
+ HTMLSetRawModeDefault(i);
+
+ /*
+ * Disable news posting if the compilation-based
+ * LYNewsPosting value is FALSE. This may be changed
+ * further down via lynx.cfg or the -restriction
+ * command line switch. - FM
+ */
+ no_newspost = (LYNewsPosting == FALSE);
+
+ /*
+ * Set up trace, the anonymous account defaults,
+ * validate restrictions, and/or the nosocks flag,
+ * if requested, and an alternate configuration
+ * file, if specified, NOW. Also, if we only want
+ * the help menu, output that and exit. - FM
+ */
+ for (i = 1; i < argc; i++) {
+ if (strncmp(argv[i], "-trace", 6) == 0) {
+ WWW_TraceFlag = TRUE;
+ } else if (strncmp(argv[i], "-tlog", 5) == 0) {
+ if (LYUseTraceLog) {
+ LYUseTraceLog = FALSE;
+ } else {
+ LYUseTraceLog = TRUE;
+ }
+ } else if (strncmp(argv[i], "-anonymous", 10) == 0) {
+ if (!LYValidate)
+ parse_restrictions("default");
+ anon_restrictions_set = TRUE;
+ } else if (strcmp(argv[i], "-validate") == 0) {
+ /*
+ * Follow only http URLs.
+ */
+ LYValidate = TRUE;
+#ifdef SOCKS
+ } else if (strncmp(argv[i], "-nosocks", 8) == 0) {
+ socks_flag = FALSE;
+#endif /* SOCKS */
+ } else if (strncmp(argv[i], "-cfg", 4) == 0) {
+ if ((cp=strchr(argv[i],'=')) != NULL)
+ StrAllocCopy(lynx_cfg_file, cp+1);
+ else {
+ StrAllocCopy(lynx_cfg_file, argv[i+1]);
+ i++;
+ }
+
+#if defined(USE_HASH)
+ } else if (strncmp(argv[i], "-lss", 4) == 0) {
+ if ((cp=strchr(argv[i],'=')) != NULL)
+ StrAllocCopy(lynx_lss_file, cp+1);
+ else {
+ StrAllocCopy(lynx_lss_file, argv[i+1]);
+ i++;
+ }
+ if (TRACE)
+ fprintf(stderr, "LYMain found -lss flag, lss file is %s\n",
+ lynx_lss_file ? lynx_lss_file : "<NONE>");
+#endif
+ }
+ }
+
+ /*
+ * If we have a lone "-" switch for getting arguments from stdin,
+ * get them NOW, and act on the relevant ones, saving the others
+ * into an HTList for handling after the other initializations.
+ * The primary purpose of this feature is to allow for the
+ * potentially very long command line that can be associated with
+ * post or get data. The original implementation required that
+ * the lone "-" be the only command line argument, but that
+ * precluded its use when the lynx command is aliased with other
+ * arguments. When interactive, the stdin input is terminated by
+ * by Control-D on Unix or Control-Z on VMS, and each argument
+ * is terminated by a RETURN. When the argument is -get_data or
+ * -post_data, the data are terminate by a "___" string, alone
+ * on the line (also terminated by RETURN). - FM
+ */
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-") == 0) {
+ LYGetStdinArgs = TRUE;
+ }
+ }
+ if (LYGetStdinArgs == TRUE) {
+ char buf[1025];
+
+ while (fgets(buf, sizeof(buf) - 1, stdin)) {
+ int j;
+
+ for (j = strlen(buf) - 1; j > 0 &&
+ (buf[j] == CR || buf[j] == LF); j--) {
+ buf[j] = '\0';
+ }
+
+ if (strncmp(buf, "-trace", 6) == 0) {
+ WWW_TraceFlag = TRUE;
+ } else if (strncmp(buf, "-tlog", 5) == 0) {
+ if (LYUseTraceLog) {
+ LYUseTraceLog = FALSE;
+ } else {
+ LYUseTraceLog = TRUE;
+ }
+ } else if (strncmp(buf, "-anonymous", 10) == 0) {
+ if (!LYValidate && !anon_restrictions_set)
+ parse_restrictions("default");
+ anon_restrictions_set = TRUE;
+ } else if (strcmp(buf, "-validate") == 0) {
+ /*
+ * Follow only http URLs.
+ */
+ LYValidate = TRUE;
+#ifdef SOCKS
+ } else if (strncmp(buf, "-nosocks", 8) == 0) {
+ socks_flag = FALSE;
+#endif /* SOCKS */
+ } else if (strncmp(buf, "-cfg", 4) == 0) {
+ if ((cp = strchr(buf,'=')) != NULL) {
+ StrAllocCopy(lynx_cfg_file, cp+1);
+ } else {
+ cp = buf;
+ while (*cp && !isspace((unsigned char)*cp))
+ cp++;
+ while (*cp && isspace((unsigned char)*cp))
+ cp++;
+ if (*cp)
+ StrAllocCopy(lynx_cfg_file, cp);
+ }
+#if defined(USE_HASH)
+ } else if (strncmp(buf, "-lss", 4) == 0) {
+ if ((cp = strchr(buf,'=')) != NULL) {
+ StrAllocCopy(lynx_lss_file, cp+1);
+ } else {
+ cp = buf;
+ while (*cp && !isspace((unsigned char)*cp))
+ cp++;
+ while (*cp && isspace((unsigned char)*cp))
+ cp++;
+ if (*cp)
+ StrAllocCopy(lynx_cfg_file, cp);
+ }
+ if (TRACE)
+ fprintf(stderr, "LYMain found -lss flag, lss file is %s\n",
+ lynx_lss_file ? lynx_lss_file : "<NONE>");
+#endif
+ } else if (strcmp(buf, "-get_data") == 0) {
+ /*
+ * User data for GET form.
+ */
+ char **get_data;
+
+ /*
+ * On Unix, conflicts with curses when interactive
+ * so let's force a dump. - CL
+ *
+ * On VMS, mods have been made in LYCurses.c to deal
+ * with potential conflicts, so don't force the dump
+ * here. - FM
+ */
+#ifndef VMS
+ dump_output_immediately = TRUE;
+ LYcols = 80;
+#endif /* VMS */
+
+ StrAllocCopy(form_get_data, "?"); /* Prime the pump */
+ get_data = &form_get_data;
+
+ /*
+ * Build GET data for later. Stop reading when we see
+ * a line with "---" as its first three characters.
+ */
+ while (fgets(buf, sizeof(buf), stdin) &&
+ strncmp(buf, "---", 3) != 0) {
+ int j2;
+
+ /*
+ * Strip line terminators.
+ */
+ for (j2 = strlen(buf) - 1; j2 >= 0 &&
+ (buf[j2] == CR || buf[j2] == LF); j2--) {
+ buf[j2] = '\0';
+ }
+ StrAllocCat(*get_data, buf);
+ }
+ } else if (strcmp(buf, "-post_data") == 0) {
+ /*
+ * User data for POST form.
+ */
+ char **post_data;
+
+ /*
+ * On Unix, conflicts with curses when interactive
+ * so let's force a dump. - CL
+ *
+ * On VMS, mods have been made in LYCurses.c to deal
+ * with potential conflicts, so don't force a dump
+ * here. - FM
+ */
+#ifndef VMS
+ dump_output_immediately = TRUE;
+ LYcols = 80;
+#endif /* VMS */
+
+ post_data = &form_post_data;
+
+ /*
+ * Build post data for later. Stop reading when we see
+ * a line with "---" as its first three characters.
+ */
+ while (fgets(buf, sizeof(buf), stdin) &&
+ strncmp(buf, "---", 3) != 0) {
+ int j2;
+
+ /*
+ * Strip line terminators.
+ */
+ for (j2 = strlen(buf) - 1; j2 >= 0 &&
+ (buf[j2] == CR || buf[j2] == LF); j2--) {
+ buf[j2] = '\0';
+ }
+ StrAllocCat(*post_data, buf);
+ }
+ } else if (buf[0] != '\0') {
+ char *argument = NULL;
+
+ if (LYStdinArgs == NULL) {
+ LYStdinArgs = HTList_new();
+ atexit(LYStdinArgs_free);
+ }
+ StrAllocCopy(argument, buf);
+ HTList_appendObject(LYStdinArgs, argument);
+ }
+ }
+ }
+
+#ifdef SOCKS
+ if (socks_flag)
+ SOCKSinit(argv[0]);
+#endif /* SOCKS */
+
+ /*
+ * If we had -validate set all of the restrictions
+ * and disallow a TRACE log NOW. - FM
+ */
+ if (LYValidate == TRUE) {
+ parse_restrictions("all");
+ LYUseTraceLog = FALSE;
+ }
+
+ /*
+ * If we didn't get and act on a -validate or -anonymous
+ * switch, but can verify that this is the anonymous account,
+ * set the default restrictions for that account and disallow
+ * a TRACE log NOW. - FM
+ */
+ if (!LYValidate && !anon_restrictions_set &&
+ strlen((char *)ANONYMOUS_USER) > 0 &&
+#if defined (VMS) || defined (NOUSERS)
+ !strcasecomp(((char *)getenv("USER")==NULL ? " " : getenv("USER")),
+ ANONYMOUS_USER)) {
+#else
+#if HAVE_CUSERID
+ STREQ((char *)cuserid((char *) NULL), ANONYMOUS_USER)) {
+#else
+ STREQ(((char *)getlogin()==NULL ? " " : getlogin()), ANONYMOUS_USER)) {
+#endif /* HAVE_CUSERID */
+#endif /* VMS */
+ parse_restrictions("default");
+ anon_restrictions_set = TRUE;
+ LYUseTraceLog = FALSE;
+ }
+
+ /*
+ * Set up the TRACE log path, and logging if appropriate. - FM
+ */
+#ifdef VMS
+ StrAllocCopy(LYTraceLogPath, "sys$login:Lynx.trace");
+#else
+ StrAllocCopy(LYTraceLogPath, (Home_Dir() ? Home_Dir() : ""));
+ StrAllocCat(LYTraceLogPath, "/Lynx.trace");
+#endif /* VMS */
+ LYOrigStderr = *stderr;
+ if (TRACE && LYUseTraceLog) {
+ /*
+ * If we can't open it for writing, give up.
+ * Otherwise, on VMS close it, delete it and any
+ * versions from previous sessions so they don't
+ * accumulate, and open it again. - FM
+ */
+ if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag = FALSE;
+ fprintf(stderr, "%s\n", TRACELOG_OPEN_FAILED);
+ exit(-1);
+ }
+#ifdef VMS
+ fclose(LYTraceLogFP);
+ while (remove(LYTraceLogPath) == 0)
+ ;
+ if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag = FALSE;
+ printf("%s\n", TRACELOG_OPEN_FAILED);
+ exit(-1);
+ }
+#endif /* VMS */
+ fflush(stdout);
+ fflush(stderr);
+ *stderr = *LYTraceLogFP;
+ fprintf(stderr, "\t\t%s\n\n", LYNX_TRACELOG_TITLE);
+ }
+
+ /*
+ * If TRACE is on, indicate whether the
+ * anonymous restrictions are set. - FM
+ */
+ if (TRACE && anon_restrictions_set) {
+ fprintf(stderr, "LYMain: Anonymous restrictions set.\n");
+ }
+
+ /*
+ * Set up the default jump file stuff. - FM
+ */
+ StrAllocCopy(jumpprompt, JUMP_PROMPT);
+#ifdef JUMPFILE
+ StrAllocCopy(jumpfile, JUMPFILE);
+ {
+ temp = (char *)malloc(strlen(jumpfile) + 10);
+ if (!temp) {
+ outofmem(__FILE__, "main");
+ } else {
+ sprintf(temp, "JUMPFILE:%s", jumpfile);
+ if (!LYJumpInit(temp)) {
+ if (TRACE)
+ fprintf(stderr, "Failed to register %s\n", temp);
+ }
+ FREE(temp);
+ }
+ }
+#endif /* JUMPFILE */
+
+ /*
+ * If no alternate configuration file was specified on
+ * the command line, see if it's in the environment.
+ */
+ if (!lynx_cfg_file) {
+ if (((cp=getenv("LYNX_CFG")) != NULL) ||
+ (cp=getenv("lynx_cfg")) != NULL)
+ StrAllocCopy(lynx_cfg_file, cp);
+ }
+
+ /*
+ * If we still don't have a configuration file,
+ * use the userdefs.h definition.
+ */
+ if (!lynx_cfg_file)
+ StrAllocCopy(lynx_cfg_file, LYNX_CFG_FILE);
+
+ /*
+ * Convert a '~' in the configuration file path to $HOME.
+ */
+#ifndef _WINDOWS /* avoid the whole ~ thing for now */
+ /* I think this should only be performed if lynx_cfg_file starts with ~/ */
+ if ((lynx_cfg_file[0] == '~') && (lynx_cfg_file[1] == '/'))
+ {
+#ifdef VMS
+ StrAllocCopy(temp, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCopy(temp, Home_Dir());
+#endif /* VMS */
+ StrAllocCat(temp, lynx_cfg_file + 1);
+ StrAllocCopy(lynx_cfg_file, temp);
+ FREE(temp);
+ }
+#endif
+
+ /*
+ * If the configuration file is not available,
+ * inform the user and exit.
+ */
+ if ((fp = fopen(lynx_cfg_file, "r")) == NULL) {
+ fprintf(stderr, "\nConfiguration file %s is not available.\n\n",
+ lynx_cfg_file);
+ exit(-1);
+ }
+ fclose(fp);
+
+ /*
+ * Make sure we have the character sets declared.
+ * This will initialize the CHARTRANS handling. - KW
+ */
+ if (!LYCharSetsDeclared()) {
+ fprintf(stderr, "\nLynx character sets not declared.\n\n");
+ exit(-1);
+ }
+
+#if defined(USE_HASH)
+ /*
+ * If no alternate lynx-style file was specified on
+ * the command line, see if it's in the environment.
+ */
+ if (!lynx_lss_file) {
+ if (((cp=getenv("LYNX_LSS")) != NULL) ||
+ (cp=getenv("lynx_lss")) != NULL)
+ StrAllocCopy(lynx_lss_file, cp);
+ }
+
+ /*
+ * If we still don't have a lynx-style file,
+ * use the userdefs.h definition.
+ */
+ if (!lynx_lss_file)
+ StrAllocCopy(lynx_lss_file, LYNX_LSS_FILE);
+
+ /*
+ * Convert a '~' in the lynx-style file path to $HOME.
+ */
+ if ((cp = strchr(lynx_lss_file, '~'))) {
+ *(cp++) = '\0';
+ StrAllocCopy(temp, lynx_lss_file);
+ if ((len=strlen(temp)) > 0 && temp[len-1] == '/')
+ temp[len-1] = '\0';
+#ifdef VMS
+ StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(temp, Home_Dir());
+#endif /* VMS */
+ StrAllocCat(temp, cp);
+ StrAllocCopy(lynx_lss_file, temp);
+ FREE(temp);
+ }
+ /*
+ * If the lynx-style file is not available,
+ * inform the user and exit.
+ */
+ if ((fp = fopen(lynx_lss_file, "r")) == NULL) {
+ fprintf(stderr, "\nLynxile file %s is not available.\n\n",
+ lynx_lss_file);
+ }
+ else
+ {
+ fclose(fp);
+ style_readFromFile(lynx_lss_file);
+ }
+#endif
+
+ /*
+ * Make sure we have the edit map declared. - FM
+ */
+ if (!LYEditmapDeclared()) {
+ fprintf(stderr, "\nLynx edit map not declared.\n\n");
+ exit(-1);
+ }
+
+#if USE_COLOR_TABLE
+ /*
+ * Set up default foreground and background colors.
+ */
+ lynx_setup_colors();
+#endif /* USE_SLANG */
+
+ /*
+ * Set the compilation default signature file. - FM
+ */
+ strcpy(filename, LYNX_SIG_FILE);
+ if (LYPathOffHomeOK(filename, sizeof(filename))) {
+ StrAllocCopy(LynxSigFile, filename);
+ LYAddPathToHome(filename, sizeof(filename), LynxSigFile);
+ StrAllocCopy(LynxSigFile, filename);
+ if (TRACE)
+ fprintf(stderr, "LYNX_SIG_FILE set to '%s'\n", LynxSigFile);
+ } else {
+ if (TRACE)
+ fprintf(stderr, "LYNX_SIG_FILE '%s' is bad. Ignoring.\n",
+ LYNX_SIG_FILE);
+ }
+
+ /*
+ * Process the configuration file.
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "Loading cfg file '%s'.\n", lynx_cfg_file);
+ }
+ read_cfg(lynx_cfg_file);
+ FREE(lynx_cfg_file);
+
+ HTSwitchDTD(New_DTD);
+
+ /*
+ * Check for a save space path in the environment.
+ * If one was set in the configuration file, that
+ * one will be overridden. - FM
+ */
+ if ((cp=getenv("LYNX_SAVE_SPACE")) != NULL)
+ StrAllocCopy(lynx_save_space, cp);
+
+ /*
+ * We have a save space path, make sure it's valid. - FM
+ */
+ if (lynx_save_space && *lynx_save_space == '\0') {
+ FREE(lynx_save_space);
+ }
+ if (lynx_save_space) {
+ if ((cp = strchr(lynx_save_space, '~')) != NULL) {
+ *(cp++) = '\0';
+ StrAllocCopy(temp, lynx_save_space);
+ if (((len = strlen(temp)) > 0) && temp[len-1] == '/')
+ temp[len-1] = '\0';
+#ifdef DOSPATH
+ StrAllocCat(temp, HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ StrAllocCat(temp, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(temp, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ StrAllocCat(temp, cp);
+ StrAllocCopy(lynx_save_space, temp);
+ FREE(temp);
+ }
+#ifdef VMS
+ for (i = 0; lynx_save_space[i]; i++)
+ lynx_save_space[i] = TOLOWER(lynx_save_space[i]);
+ if (strchr(lynx_save_space, '/') != NULL) {
+ if ((len = strlen(lynx_save_space)) == 1) {
+ StrAllocCopy(lynx_save_space, "sys$login:");
+ } else {
+ if (lynx_save_space[len-1] != '/')
+ StrAllocCat(lynx_save_space, "/");
+ StrAllocCopy(temp, HTVMS_name("", lynx_save_space));
+ StrAllocCopy(lynx_save_space, temp);
+ FREE(temp);
+ }
+ }
+ if (strchr(lynx_save_space, ':') == NULL &&
+ strchr(lynx_save_space, ']') == NULL) {
+ StrAllocCat(lynx_save_space, ":");
+ }
+#else
+ {
+ if (((len = strlen(lynx_save_space)) > 1) &&
+ lynx_save_space[len-1] != '/') {
+ StrAllocCat(lynx_save_space, "/");
+ }
+ }
+#endif /* VMS */
+ }
+
+ /*
+ * Set up the file extension and mime type maps from
+ * src/HTInit.c and the global and personal mime.types
+ * and mailcap files. These will override any SUFFIX
+ * or VIEWER maps in userdefs.h or the configuration
+ * file, if they overlap.
+ */
+ HTFormatInit();
+ HTFileInit();
+
+ /*
+ * Get WWW_HOME environment variable if it exists.
+ */
+ if ((cp = getenv("WWW_HOME")) != NULL) {
+ StrAllocCopy(startfile, cp);
+ LYTrimHead(startfile);
+ if (!strncasecomp(startfile, "lynxexec:", 9) ||
+ !strncasecomp(startfile, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(startfile, " \r\n\t");
+ convert_to_spaces(startfile, TRUE);
+ }
+ }
+
+ /*
+ * Set the LynxHome URL. If it's a file URL and the
+ * host is defaulted, force in "//localhost", and if
+ * it's not an absolute URL, make it one. - FM
+ */
+ StrAllocCopy(LynxHome, startfile);
+ LYFillLocalFileURL((char **)&LynxHome, "file://localhost");
+ LYEnsureAbsoluteURL((char **)&LynxHome, "LynxHome");
+
+ /*
+ * Process any command line arguments not already handled. - FM
+ */
+ for (i = 1; i < argc; i++) {
+ parse_arg(&argv[i], &i, argc);
+ }
+
+ /*
+ * Process any stdin-derived arguments for a lone "-" which we've
+ * loaded into LYStdinArgs. - FM
+ */
+ if (LYStdinArgs != NULL) {
+ char *my_args[2];
+ HTList *cur = LYStdinArgs;
+
+ my_args[1] = NULL;
+ while (NULL != (my_args[0] = (char *)HTList_nextObject(cur))) {
+ parse_arg(my_args, NULL, -1);
+ }
+ LYStdinArgs_free();
+ }
+
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ if (syslog_txt) {
+ syslog(LOG_INFO, "Session start:%s", syslog_txt);
+ } else {
+ syslog(LOG_INFO, "Session start");
+ }
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+ /*
+ * Process the RC file.
+ */
+ read_rc();
+
+#ifdef USE_SLANG
+ if (LYShowColor >= SHOW_COLOR_ON &&
+ !(Lynx_Color_Flags & SL_LYNX_USE_COLOR)) {
+ Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
+ } else if ((Lynx_Color_Flags & SL_LYNX_USE_COLOR) ||
+ getenv("COLORTERM") != NULL) {
+ if (LYShowColor != SHOW_COLOR_NEVER &&
+ LYShowColor != SHOW_COLOR_ALWAYS) {
+ LYShowColor = SHOW_COLOR_ON;
+ }
+ }
+#endif /* USE_SLANG */
+
+ if (LYPreparsedSource) {
+ HTPreparsedFormatInit();
+ }
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+#ifdef NEVER_ALLOW_REMOTE_EXEC
+ if (local_exec) {
+ local_exec = FALSE;
+ local_exec_on_local_files = TRUE;
+ }
+#endif /* NEVER_ALLOW_REMOTE_EXEC */
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+ if (emacs_keys)
+ set_emacs_keys();
+
+ if (vi_keys)
+ set_vi_keys();
+
+ if (number_links && keypad_mode == NUMBERS_AS_ARROWS)
+ keypad_mode = LINKS_ARE_NUMBERED;
+ if (keypad_mode == NUMBERS_AS_ARROWS)
+ set_numbers_as_arrows();
+
+ /*
+ * Check the -popup command line toggle. - FM
+ */
+ if (LYUseDefSelPop == FALSE) {
+ if (LYSelectPopups == TRUE)
+ LYSelectPopups = FALSE;
+ else
+ LYSelectPopups = TRUE;
+ }
+
+ /*
+ * Check the -show_cursor command line toggle. - FM
+ */
+ if (LYUseDefShoCur == FALSE) {
+ if (LYShowCursor == TRUE)
+ LYShowCursor = FALSE;
+ else
+ LYShowCursor = TRUE;
+ }
+
+ /*
+ * Check the -base command line switch with -source. - FM
+ */
+ if (LYPrependBase && HTOutputFormat == HTAtom_for("www/download")) {
+ LYPrependBaseToSource = TRUE;
+ }
+
+ /*
+ * Disable multiple bookmark support if not interactive,
+ * so it doesn't crash on curses functions, or if the
+ * support was blocked via userdefs.h and/or lynx.cfg,
+ * or via command line restrictions. - FM
+ */
+ if (no_multibook)
+ LYMBMBlocked = TRUE;
+ if (dump_output_immediately || LYMBMBlocked || no_multibook) {
+ LYMultiBookmarks = FALSE;
+ LYMBMBlocked = TRUE;
+ no_multibook = TRUE;
+ }
+
+#ifdef VMS
+ set_vms_keys();
+#endif /* VMS */
+
+ /* trap interrupts */
+ if (!dump_output_immediately)
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, cleanup_sig);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, cleanup_sig);
+#ifdef SIGWINCH
+ (void) signal(SIGWINCH, size_change);
+#endif /* SIGWINCH */
+#ifndef VMS
+ if (!TRACE && !dump_output_immediately && !stack_dump) {
+ (void) signal(SIGINT, cleanup_sig);
+#ifndef __linux__
+#ifndef DOSPATH
+ (void) signal(SIGBUS, FatalProblem);
+#endif /* DOSPATH */
+#endif /* !__linux__ */
+ (void) signal(SIGSEGV, FatalProblem);
+ (void) signal(SIGILL, FatalProblem);
+ /*
+ * Since we're doing lots of TCP, just ignore SIGPIPE altogether.
+ *
+ * HTTCP.c should deal with a broken pipe for servers.
+ * Rick Mallet's check after c = GetChar() in LYStrings.c should
+ * deal with a disconnected terminal.
+ * So the runaway CPU time problem on Unix should not occur any
+ * more.
+ */
+#ifndef DOSPATH
+ (void) signal(SIGPIPE, SIG_IGN);
+#endif /* DOSPATH */
+ }
+#endif /* !VMS */
+
+ /*
+ * Set up the proper character set with the desired
+ * startup raw 8-bit or CJK mode handling. - FM
+ */
+ HTMLUseCharacterSet(current_char_set);
+
+ /*
+ * If startfile is a file URL and the host is defaulted,
+ * force in "//localhost", and if it's not an absolute URL,
+ * make it one. - FM
+ */
+ LYFillLocalFileURL((char **)&startfile, "file://localhost");
+ LYEnsureAbsoluteURL((char **)&startfile, "STARTFILE");
+
+ /*
+ * If homepage was specified and is a file URL with the
+ * host defaulted, force in "//localhost", and if it's
+ * not an absolute URL, make it one. - FM
+ */
+ if (homepage) {
+ LYFillLocalFileURL((char **)&homepage, "file://localhost");
+ LYEnsureAbsoluteURL((char **)&homepage, "HOMEPAGE");
+ }
+
+ /*
+ * If we don't have a homepage specified,
+ * set it to startfile. Otherwise, reset
+ * LynxHome. - FM
+ */
+ if (!(homepage && *homepage)) {
+ StrAllocCopy(homepage, startfile);
+ } else {
+ StrAllocCopy(LynxHome, homepage);
+ }
+
+ /*
+ * Set up the inside/outside domain restriction flags. - FM
+ */
+ if (inlocaldomain()) {
+#if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
+ telnet_ok = !no_inside_telnet && !no_outside_telnet && telnet_ok;
+ news_ok = !no_inside_news && !no_outside_news && news_ok;
+ ftp_ok = !no_inside_ftp && !no_outside_ftp && ftp_ok;
+ rlogin_ok = !no_inside_rlogin && !no_outside_rlogin && rlogin_ok;
+#else
+ if (TRACE)
+ fprintf(stderr,"LYMain.c: User in Local domain\n");
+ telnet_ok = !no_inside_telnet && telnet_ok;
+ news_ok = !no_inside_news && news_ok;
+ ftp_ok = !no_inside_ftp && ftp_ok;
+ rlogin_ok = !no_inside_rlogin && rlogin_ok;
+#endif /* !HAVE_UTMP || VMS */
+ } else {
+ if (TRACE)
+ fprintf(stderr,"LYMain.c: User in REMOTE domain\n");
+ telnet_ok = !no_outside_telnet && telnet_ok;
+ news_ok = !no_outside_news && news_ok;
+ ftp_ok = !no_outside_ftp && ftp_ok;
+ rlogin_ok = !no_outside_rlogin && rlogin_ok;
+ }
+
+#ifdef SIGTSTP
+ /*
+ * Block Control-Z suspending if requested. - FM
+ */
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_IGN);
+#endif /* SIGTSTP */
+
+ /*
+ * Check for a valid HEAD request. - FM
+ */
+ if (HEAD_request && LYCanDoHEAD(startfile) != TRUE) {
+ fprintf(stderr,
+ "The '-head' switch is for http HEAD requests and cannot be used for\n'%s'.\n",
+ startfile);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ /*
+ * Check for a valid MIME headers request. - FM
+ */
+ if (keep_mime_headers && LYCanDoHEAD(startfile) != TRUE) {
+ fprintf(stderr,
+ "The '-mime_header' switch is for http URLs and cannot be used for\n'%s'.\n",
+ startfile);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ /*
+ * Check for a valid traversal request. - FM
+ */
+ if (traversal && strncmp(startfile, "http", 4)) {
+ fprintf(stderr,
+ "The '-traversal' switch is for http URLs and cannot be used for\n'%s'.\n",
+ startfile);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ /*
+ * Set up our help and about file base paths. - FM
+ */
+ StrAllocCopy(helpfilepath, helpfile);
+ if ((cp=strrchr(helpfilepath, '/')) != NULL)
+ *cp = '\0';
+ /*
+ * Remove code to merge the historical about_lynx
+ * directory into lynx_help. - HN
+ */
+ StrAllocCat(helpfilepath, "/");
+
+
+ /*
+ * Make sure our bookmark default strings
+ * are all allocated and synchronized. - FM
+ */
+ if (!bookmark_page || *bookmark_page == '\0') {
+ StrAllocCopy(bookmark_page, "lynx_bookmarks");
+ StrAllocCat(bookmark_page, HTML_SUFFIX);
+ StrAllocCopy(BookmarkPage, bookmark_page);
+ StrAllocCopy(MBM_A_subbookmark[0], bookmark_page);
+ StrAllocCopy(MBM_A_subdescript[0], "Default");
+ }
+ if (!BookmarkPage || *BookmarkPage == '\0') {
+ StrAllocCopy(BookmarkPage, bookmark_page);
+ StrAllocCopy(MBM_A_subbookmark[0], bookmark_page);
+ StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT);
+ }
+
+ /*
+ * Here's where we do all the work.
+ */
+ if (dump_output_immediately) {
+ /*
+ * Finish setting up and start a
+ * NON-INTERACTIVE session. - FM
+ */
+ if (crawl && !number_links) {
+ keypad_mode = NUMBERS_AS_ARROWS;
+ } else if (!nolist) {
+ if (keypad_mode == NUMBERS_AS_ARROWS) {
+ keypad_mode = LINKS_ARE_NUMBERED;
+ }
+ }
+ if (display != NULL && *display != '\0') {
+ LYisConfiguredForX = TRUE;
+ }
+ if (dump_output_width > 0) {
+ LYcols = dump_output_width;
+ }
+ status = mainloop();
+ if (!nolist &&
+ (keypad_mode == LINKS_ARE_NUMBERED ||
+ keypad_mode == LINKS_AND_FORM_FIELDS_ARE_NUMBERED))
+ printlist(stdout,FALSE);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ } else {
+ /*
+ * Finish setting up and start an
+ * INTERACTIVE session. - FM
+ */
+ if (setup(terminal)) {
+ if (display != NULL && *display != '\0') {
+ LYisConfiguredForX = TRUE;
+ }
+ ena_csi((LYlowest_eightbit[current_char_set] > 155));
+ status = mainloop();
+ cleanup();
+ }
+ }
+
+ exit(status);
+}
+
+/*
+ * Called by HTAccessInit to register any protocols supported by lynx.
+ * Protocols added by lynx:
+ * LYNXKEYMAP, lynxcgi, LYNXIMGMAP, LYNXCOOKIE
+ */
+#ifdef GLOBALREF_IS_MACRO
+extern GLOBALREF (HTProtocol, LYLynxKeymap);
+extern GLOBALREF (HTProtocol, LYLynxCGI);
+extern GLOBALREF (HTProtocol, LYLynxIMGmap);
+extern GLOBALREF (HTProtocol, LYLynxCookies);
+#else
+GLOBALREF HTProtocol LYLynxKeymap;
+GLOBALREF HTProtocol LYLynxCGI;
+GLOBALREF HTProtocol LYLynxIMGmap;
+GLOBALREF HTProtocol LYLynxCookies;
+#endif /* GLOBALREF_IS_MACRO */
+
+PUBLIC void LYRegisterLynxProtocols NOARGS
+{
+ HTRegisterProtocol(&LYLynxKeymap);
+ HTRegisterProtocol(&LYLynxCGI);
+ HTRegisterProtocol(&LYLynxIMGmap);
+ HTRegisterProtocol(&LYLynxCookies);
+}
+
+/*
+ * Parse one argument, optionally picking up the next entry in argv (if
+ * appropriate).
+ */
+
+PRIVATE char * scan3D ARGS2(
+ char **, argv,
+ int *, i)
+{
+ char *result;
+
+ if ((result=strchr(argv[0],'=')) != NULL)
+ return result+1;
+ if (argv[1] && i)
+ (*i)++; /* Let master know we've stolen an argument */
+ return argv[1];
+}
+
+PRIVATE void parse_arg ARGS3(
+ char **, argv,
+ int *, i,
+ int, argc)
+{
+ char *cp;
+#ifndef VMS
+ static char display_putenv_command[142];
+#endif /* !VMS */
+#define nextarg ((cp=scan3D(&argv[0], i))!=NULL)
+
+ /*
+ * Check for a command line startfile. - FM
+ */
+ if (argv[0][0] != '-') {
+ StrAllocCopy(startfile, argv[0]);
+ LYTrimHead(startfile);
+ if (!strncasecomp(startfile, "lynxexec:", 9) ||
+ !strncasecomp(startfile, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(startfile, " \r\n\t");
+ convert_to_spaces(startfile, TRUE);
+ }
+ return;
+ }
+
+ /*
+ * Skip any lone "-" arguments, because we've loaded
+ * the stdin input into an HTList structure for
+ * special handling. - FM
+ */
+ if (strcmp(argv[0], "-") == 0) {
+ return;
+ }
+
+ switch (TOLOWER(argv[0][1])) {
+
+ case 'a':
+ if (strncmp(argv[0], "-anonymous", 10) == 0) {
+ /*
+ * Should already have been set, so we don't
+ * override or replace any additional
+ * restrictions from the command line. - FM
+ */
+ if (!anon_restrictions_set)
+ parse_restrictions("default");
+ anon_restrictions_set = TRUE;
+
+ } else if ((strncmp(argv[0], "-assume_charset", 15) == 0) ||
+ (strncmp(argv[0], "-assume_local_charset", 21) == 0) ||
+ (strncmp(argv[0], "-assume_unrec_charset", 21) == 0)) {
+ BOOL local_flag = (argv[0][8] == 'l');
+ BOOL unrec_flag = (argv[0][8] == 'u');
+
+ if (nextarg) {
+ int j;
+
+ for (j = 0; cp[j]; j++)
+ cp[j] = TOLOWER(cp[j]);
+ if (local_flag) {
+ StrAllocCopy(UCAssume_localMIMEcharset, cp);
+ if (UCAssume_localMIMEcharset && *UCAssume_localMIMEcharset)
+ UCLYhndl_HTFile_for_unspec =
+ UCGetLYhndl_byMIME(UCAssume_localMIMEcharset);
+ } else if (unrec_flag) {
+ StrAllocCopy(UCAssume_unrecMIMEcharset, cp);
+ if (UCAssume_unrecMIMEcharset && *UCAssume_unrecMIMEcharset)
+ UCLYhndl_for_unrec =
+ UCGetLYhndl_byMIME(UCAssume_unrecMIMEcharset);
+ } else {
+ StrAllocCopy(UCAssume_MIMEcharset, cp);
+ if (UCAssume_MIMEcharset && *UCAssume_MIMEcharset)
+ UCLYhndl_for_unspec =
+ UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ }
+ } else {
+ if (local_flag)
+ UCLYhndl_HTFile_for_unspec = 0;
+ else if (unrec_flag)
+ UCLYhndl_for_unrec = 0;
+ else
+ UCLYhndl_for_unspec = 0;
+ }
+
+ } else if (strncmp(argv[0], "-auth", 5) == 0) {
+ /*
+ * Authentication information for protected documents.
+ */
+ char *auth_info = NULL;
+
+ if (nextarg) {
+ StrAllocCopy(auth_info, cp);
+ memset(cp, ' ', strlen(cp)); /* Let's not show too much */
+ }
+ if (auth_info != NULL) {
+ if ((cp = strchr(auth_info, ':')) != NULL) { /* Pw */
+ *cp++ = '\0'; /* Terminate ID */
+ if (*cp) {
+ HTUnEscape(cp);
+ StrAllocCopy(authentication_info[1], cp);
+ }
+ }
+ if (*auth_info) { /* Id */
+ HTUnEscape(auth_info);
+ StrAllocCopy(authentication_info[0], auth_info);
+ }
+ FREE(auth_info);
+ }
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'b':
+ if (strcmp(argv[0], "-base") == 0) {
+ /*
+ * Treat -source equivalently to an interactive
+ * download with LYPrefixBaseToSource configured
+ * to TRUE, so that a BASE tag is prepended for
+ * text/html content types. We normally treat
+ * the module-wide global LYPrefixBaseToSource
+ * flag as FALSE with -source, but force it TRUE,
+ * later, if LYPrependBase is set TRUE here. - FM
+ */
+ LYPrependBase = TRUE;
+ if (HTOutputFormat == HTAtom_for("www/dump")) {
+ HTOutputFormat = HTAtom_for("www/download");
+ }
+
+ } else if (strcmp(argv[0], "-book") == 0) {
+ /*
+ * Use bookmarks as startfile.
+ */
+ bookmark_start = TRUE;
+
+ } else if (strcmp(argv[0], "-buried_news") == 0) {
+ /*
+ * Toggle scans for buried news references.
+ */
+ if (scan_for_buried_news_references)
+ scan_for_buried_news_references = FALSE;
+ else
+ scan_for_buried_news_references = TRUE;
+
+#ifdef USE_SLANG
+ } else if (strncmp(argv[0], "-blink", 6) == 0) {
+ Lynx_Color_Flags |= SL_LYNX_USE_BLINK;
+#endif /* USE_SLANG */
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'c':
+ if (strncmp(argv[0], "-cache", 6) == 0) {
+ if (nextarg)
+ HTCacheSize = atoi(cp);
+ /*
+ * Limit size.
+ */
+ if (HTCacheSize < 2) HTCacheSize = 2;
+
+ } else if (strncmp(argv[0], "-case", 5) == 0) {
+ case_sensitive = TRUE;
+
+ } else if (strncmp(argv[0], "-cfg", 4) == 0) {
+ /*
+ * Already read the alternate configuration file
+ * so just check whether we need to increment i
+ */
+ if (nextarg)
+ ; /* do nothing */
+
+ } else if (strncmp(argv[0], "-child", 6) == 0) {
+ child_lynx = TRUE;
+ no_disk_save = TRUE;
+
+#ifdef USE_SLANG
+ } else if (strncmp(argv[0], "-color", 6) == 0) {
+ Lynx_Color_Flags |= SL_LYNX_USE_COLOR;
+ if (LYShowColor != SHOW_COLOR_ALWAYS) {
+ LYShowColor = SHOW_COLOR_ON;
+ }
+#endif /* USE_SLANG */
+
+ } else if (strncmp(argv[0], "-crawl", 6) == 0) {
+ crawl = TRUE;
+ LYcols = 80;
+
+ } else if (strncmp(argv[0], "-cookies", 8) == 0) {
+ if (LYSetCookies)
+ LYSetCookies = FALSE;
+ else
+ LYSetCookies = TRUE;
+
+#ifndef VMS
+ } else if (strncmp(argv[0], "-core", 5) == 0) {
+ if (LYNoCore)
+ LYNoCore = FALSE;
+ else
+ LYNoCore = TRUE;
+#endif /* !VMS */
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'd':
+ if (strncmp(argv[0], "-display", 8) == 0) {
+ if (nextarg) {
+#ifdef VMS
+ int j;
+ for (j = 0; cp[j]; j++)
+ cp[j] = TOUPPER(cp[j]);
+ Define_VMSLogical(DISPLAY, cp ? cp : "");
+#else
+ sprintf(display_putenv_command, "DISPLAY=%s", cp ? cp : "");
+ putenv(display_putenv_command);
+#endif /* VMS */
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
+ StrAllocCopy(display, cp);
+ }
+ }
+
+ } else if (strncmp(argv[0], "-dump", 5) == 0) {
+ dump_output_immediately = TRUE;
+ LYcols=80;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'e':
+ if (strncmp(argv[0], "-editor", 7) == 0) {
+ if (nextarg)
+ StrAllocCopy(editor,cp);
+ system_editor = TRUE;
+
+ } else if (strncmp(argv[0], "-emacskeys", 10) == 0) {
+ emacs_keys = TRUE;
+
+ } else if (strncmp(argv[0], "-enable_scrollback", 18) == 0) {
+ if (enable_scrollback)
+ enable_scrollback = FALSE;
+ else
+ enable_scrollback = TRUE;
+
+ } else if (strncmp(argv[0], "-error_file", 11) == 0) {
+ /*
+ * Output return (success/failure) code
+ * of an HTTP transaction.
+ */
+ if (nextarg)
+ http_error_file = cp;
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ } else if (strncmp(argv[0], "-exec", 5) == 0) {
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ local_exec = TRUE;
+#else
+ local_exec_on_local_files = TRUE;
+#endif /* NEVER_ALLOW_REMOTE_EXEC */
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'f':
+ if (strncmp(argv[0], "-force_html", 11) == 0) {
+ LYforce_HTML_mode = TRUE;
+
+ } else if (strncmp(argv[0], "-fileversions", 13) == 0) {
+#ifdef VMS
+ HTVMSFileVersions = TRUE;
+#else
+ break;;
+#endif /* VMS */
+
+ } else if (strncmp(argv[0], "-force_secure", 13) == 0) {
+ if (LYForceSSLCookiesSecure)
+ LYForceSSLCookiesSecure = FALSE;
+ else
+ LYForceSSLCookiesSecure = TRUE;
+
+ } else if (strncmp(argv[0], "-from", 5) == 0) {
+ if (LYNoFromHeader)
+ LYNoFromHeader = FALSE;
+ else
+ LYNoFromHeader = TRUE;
+
+ } else if (strncmp(argv[0], "-ftp", 4) == 0) {
+ ftp_ok = FALSE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'g':
+ if (strcmp(argv[0], "-get_data") == 0) {
+ /*
+ * User data for GET form.
+ */
+ char **get_data;
+ char buf[1024];
+
+ /*
+ * On Unix, conflicts with curses when interactive
+ * so let's force a dump. - CL
+ *
+ * On VMS, mods have been made in LYCurses.c to deal with
+ * potential conflicts, so don't force the dump here. - FM
+ */
+#ifndef VMS
+ dump_output_immediately = TRUE;
+ LYcols = 80;
+#endif /* VMS */
+
+ StrAllocCopy(form_get_data, "?"); /* Prime the pump */
+ get_data = &form_get_data;
+
+ /*
+ * Build GET data for later. Stop reading when we see a line
+ * with "---" as its first three characters.
+ */
+ while (fgets(buf, sizeof(buf), stdin) &&
+ strncmp(buf, "---", 3) != 0) {
+ int j;
+
+ for (j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */
+ (buf[j] == CR || buf[j] == LF); j--) {
+ buf[j] = '\0';
+ }
+ StrAllocCat(*get_data, buf);
+ }
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'h':
+ if (strcmp(argv[0], "-help") == 0) {
+ goto Output_Help_List;
+
+ } else if (strcmp(argv[0], "-head") == 0) {
+ /*
+ * Return mime headers.
+ */
+ HEAD_request = TRUE;
+
+ } else if (strncmp(argv[0], "-hiddenlinks", 7) == 0) {
+ if (nextarg) {
+ if (strncasecomp(cp, "merge", 1) == 0)
+ LYHiddenLinks = HIDDENLINKS_MERGE;
+ else if (strncasecomp(cp, "listonly", 1) == 0)
+ LYHiddenLinks = HIDDENLINKS_SEPARATE;
+ else if (strncasecomp(cp, "ignore", 1) == 0)
+ LYHiddenLinks = HIDDENLINKS_IGNORE;
+ else
+ goto Output_Error_and_Help_List;
+ } else
+ LYHiddenLinks = HIDDENLINKS_MERGE;
+
+ } else if (strncmp(argv[0], "-historical", 11) == 0) {
+ if (historical_comments)
+ historical_comments = FALSE;
+ else
+ historical_comments = TRUE;
+
+ } else if (strncmp(argv[0], "-homepage", 9) == 0) {
+ if (nextarg) {
+ StrAllocCopy(homepage, cp);
+ LYTrimHead(homepage);
+ if (!strncasecomp(homepage, "lynxexec:", 9) ||
+ !strncasecomp(homepage, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(homepage, " \r\n\t");
+ convert_to_spaces(homepage, TRUE);
+ }
+ }
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'i':
+ if (strncmp(argv[0], "-image_links", 12) == 0) {
+ if (clickable_images)
+ clickable_images = FALSE;
+ else
+ clickable_images = TRUE;
+
+ } else if (strncmp(argv[0], "-index", 6) == 0) {
+ if (nextarg)
+ StrAllocCopy(indexfile, cp);
+
+ } else if (strncmp(argv[0], "-ismap", 6) == 0) {
+ if (LYNoISMAPifUSEMAP)
+ LYNoISMAPifUSEMAP = FALSE;
+ else
+ LYNoISMAPifUSEMAP = TRUE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'l':
+ if (strncmp(argv[0], "-link", 5) == 0) {
+ if (nextarg)
+ ccount = atoi(cp);
+
+ } else if (strncmp(argv[0], "-localhost", 10) == 0) {
+ local_host_only = TRUE;
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ } else if (strncmp(argv[0], "-locexec", 8) == 0) {
+ local_exec_on_local_files = TRUE;
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+#if defined(USE_HASH)
+ } else if (strncmp(argv[0], "-lss", 4) == 0) {
+ /*
+ * Already read the alternate lynx-style file
+ * so just check whether we need to increment i
+ */
+ if (nextarg)
+ ; /* do nothing */
+#endif
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'm':
+ if (strcmp(argv[0], "-mime_header") == 0) {
+ /*
+ * Include mime headers and force source dump.
+ */
+ keep_mime_headers = TRUE;
+ dump_output_immediately = TRUE;
+ HTOutputFormat = (LYPrependBase ?
+ HTAtom_for("www/download") : HTAtom_for("www/dump"));
+ LYcols=999;
+
+ } else if (strncmp(argv[0], "-minimal", 8) == 0) {
+ if (minimal_comments)
+ minimal_comments = FALSE;
+ else
+ minimal_comments = TRUE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'n':
+ if (strncmp(argv[0], "-newschunksize", 14) == 0) {
+ if (nextarg) {
+ HTNewsChunkSize = atoi(cp);
+ /*
+ * If the new HTNewsChunkSize exceeds the maximum,
+ * increase HTNewsMaxChunk to this size. - FM
+ */
+ if (HTNewsChunkSize > HTNewsMaxChunk) {
+ HTNewsMaxChunk = HTNewsChunkSize;
+ }
+ }
+
+ } else if (strncmp(argv[0], "-newsmaxchunk", 13) == 0) {
+ if (nextarg) {
+ HTNewsMaxChunk = atoi(cp);
+ /*
+ * If HTNewsChunkSize exceeds the new maximum,
+ * reduce HTNewsChunkSize to this maximum. - FM
+ */
+ if (HTNewsChunkSize > HTNewsMaxChunk) {
+ HTNewsChunkSize = HTNewsMaxChunk;
+ }
+ }
+
+ } else if (strncmp(argv[0], "-nobrowse", 9) == 0) {
+ HTDirAccess = HT_DIR_FORBID;
+
+ } else if (strncmp(argv[0], "-nocc", 5) == 0) {
+ LYNoCc = TRUE;
+
+ } else if (strncmp(argv[0], "-nocolor", 8) == 0) {
+ LYShowColor = SHOW_COLOR_NEVER;
+#ifdef USE_SLANG
+ Lynx_Color_Flags &= ~SL_LYNX_USE_COLOR;
+ Lynx_Color_Flags |= SL_LYNX_OVERRIDE_COLOR;
+#endif
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ } else if (strncmp(argv[0], "-noexec", 7) == 0) {
+ local_exec = FALSE;
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+
+ } else if (strncmp(argv[0], "-nofilereferer", 14) == 0) {
+ no_filereferer = TRUE;
+
+ } else if (strncmp(argv[0], "-nolist", 7) == 0) {
+ nolist = TRUE;
+
+ } else if (strncmp(argv[0], "-nolog", 6) == 0) {
+ error_logging = FALSE;
+
+ } else if (strcmp(argv[0], "-nopause") == 0) { /* No statusline pauses */
+ InfoSecs = 0;
+ MessageSecs = 0;
+ AlertSecs = 0;
+
+ } else if (strncmp(argv[0], "-noprint", 8) == 0) {
+ no_print = TRUE;
+
+ } else if (strcmp(argv[0], "-noredir") == 0) {
+ /*
+ * Don't follow URL redirections.
+ */
+ no_url_redirection = TRUE;
+
+ } else if (strncmp(argv[0], "-noreferer", 10) == 0) {
+ LYNoRefererHeader = TRUE;
+
+#ifdef SOCKS
+ } else if (strncmp(argv[0], "-nosocks", 8) == 0) {
+ socks_flag = FALSE;
+#endif /* SOCKS */
+
+ } else if (strncmp(argv[0], "-nostatus", 9) == 0) {
+ no_statusline = TRUE;
+
+ } else if (strncmp(argv[0], "-number_links", 13) == 0) {
+ number_links = TRUE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'p':
+ if (strncmp(argv[0], "-pauth", 6) == 0) {
+ /*
+ * Authentication information for protected proxy server. - AJL
+ */
+ char *pauth_info = NULL;
+
+ if (nextarg) {
+ StrAllocCopy(pauth_info, cp);
+ memset(cp, ' ', strlen(cp)); /* Let's not show too much */
+ }
+ if (pauth_info != NULL) {
+ if ((cp = strchr(pauth_info, ':')) != NULL) { /* Pw */
+ *cp++ = '\0'; /* Terminate ID */
+ if (*cp) {
+ HTUnEscape(cp);
+ StrAllocCopy(proxyauth_info[1], cp);
+ }
+ }
+ if (*pauth_info) { /* Id */
+ HTUnEscape(pauth_info);
+ StrAllocCopy(proxyauth_info[0], pauth_info);
+ }
+ FREE(pauth_info);
+ }
+
+ } else if (strncmp(argv[0], "-popup", 6) == 0) {
+ LYUseDefSelPop = FALSE;
+
+ } else if (strcmp(argv[0], "-post_data") == 0) {
+ /*
+ * User data for POST form.
+ */
+ char **post_data;
+ char buf[1024];
+
+ /*
+ * On Unix, conflicts with curses when interactive
+ * so let's force a dump. - CL
+ *
+ * On VMS, mods have been made in LYCurses.c to deal with
+ * potential conflicts, so don't force a dump here. - FM
+ */
+#ifndef VMS
+ dump_output_immediately = TRUE;
+ LYcols = 80;
+#endif /* VMS */
+
+ post_data = &form_post_data;
+
+ /*
+ * Build post data for later. Stop reading when we see a line
+ * with "---" as its first three characters.
+ */
+ while (fgets(buf, sizeof(buf), stdin) &&
+ strncmp(buf, "---", 3) != 0) {
+ int j;
+
+ for (j = strlen(buf) - 1; j >= 0 && /* Strip line terminators */
+ (buf[j] == CR || buf[j] == LF); j--) {
+ buf[j] = '\0';
+ }
+ StrAllocCat(*post_data, buf);
+ }
+
+ } else if (strncmp(argv[0], "-preparsed", 9) == 0) {
+ LYPreparsedSource = TRUE;
+
+ } else if (strncmp(argv[0], "-print", 6) == 0) {
+ no_print=FALSE;
+
+ } else if (strncmp(argv[0], "-pseudo_inlines", 15) == 0) {
+ if (pseudo_inline_alts)
+ pseudo_inline_alts = FALSE;
+ else
+ pseudo_inline_alts = TRUE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'r':
+ if (strncmp(argv[0], "-raw", 4) == 0) {
+ LYUseDefaultRawMode = FALSE;
+
+ } else if (strncmp(argv[0], "-realm", 6) == 0) {
+ check_realm = TRUE;
+
+ } else if (strncmp(argv[0], "-reload", 7) == 0) {
+ reloading = TRUE;
+
+ } else if (strncmp(argv[0], "-restrictions", 13) == 0) {
+ if ((cp=strchr(argv[0],'=')) != NULL)
+ parse_restrictions(cp+1);
+ else {
+ static CONST char *Usage[] = {
+ ""
+," USAGE: lynx -restrictions=[option][,option][,option]"
+," List of Options:"
+," all restricts all options."
+," bookmark disallow changing the location of the bookmark file."
+," bookmark_exec disallow execution links via the bookmark file"
+#if defined(DIRED_SUPPORT) && defined(OK_PERMIT)
+," change_exec_perms disallow changing the eXecute permission on files"
+," (but still allow it for directories) when local file"
+," management is enabled."
+#endif /* DIRED_SUPPORT && OK_PERMIT */
+," default same as commandline option -anonymous. Disables"
+," default services for anonymous users. Currently set to,"
+," all restricted except for: inside_telnet, outside_telnet,"
+," inside_news, inside_ftp, outside_ftp, inside_rlogin,"
+," outside_rlogin, goto, jump and mail. Defaults"
+," are settable within userdefs.h"
+#ifdef DIRED_SUPPORT
+," dired_support disallow local file management"
+#endif /* DIRED_SUPPORT */
+," disk_save disallow saving to disk in the download and print menus"
+," dotfiles disallow access to, or creation of, hidden (dot) files"
+," download disallow downloaders in the download menu"
+," editor disallow editing"
+," exec disable execution scripts"
+," exec_frozen disallow the user from changing the execution link"
+#ifdef USE_EXTERNALS
+," externals disable passing URLs to external programs"
+#endif
+," file_url disallow using G)oto, served links or bookmarks for"
+," file: URL's"
+," goto disable the 'g' (goto) command"
+#if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
+," inside_ftp disallow ftps for people coming from inside your"
+," domain (utmp required for selectivity)"
+," inside_news disallow USENET news posting for people coming from"
+," inside your domain (utmp required for selectivity)"
+," inside_rlogin disallow rlogins for people coming from inside your"
+," domain (utmp required for selectivity)"
+," inside_telnet disallow telnets for people coming from inside your"
+," domain (utmp required for selectivity)"
+#else
+," inside_ftp disallow ftps for people coming from inside your domain"
+," inside_news disallow USENET news posting for people coming from inside"
+," your domain"
+," inside_rlogin disallow rlogins for people coming from inside your domain"
+," inside_telnet disallow telnets for people coming from inside your domain"
+#endif /* HAVE_UTMP || VMS */
+," jump disable the 'j' (jump) command"
+," mail disallow mail"
+," multibook disallow multiple bookmark files"
+," news_post disallow USENET News posting."
+," option_save disallow saving options in .lynxrc"
+#if !defined(HAVE_UTMP) || defined(VMS) /* not selective */
+," outside_ftp disallow ftps for people coming from outside your"
+," domain (utmp required for selectivity)"
+," outside_news disallow USENET news posting for people coming from"
+," outside your domain (utmp required for selectivity)"
+," outside_rlogin disallow rlogins for people coming from outside your"
+," domain (utmp required for selectivity)"
+," outside_telnet disallow telnets for people coming from outside your"
+," domain (utmp required for selectivity)"
+#else
+," outside_ftp disallow ftps for people coming from outside your domain"
+," outside_news disallow USENET news posting for people coming from outside"
+," your domain"
+," outside_rlogin disallow rlogins for people coming from outside your domain"
+," outside_telnet disallow telnets for people coming from outside your domain"
+#endif /* !HAVE_UTMP || VMS */
+," print disallow most print options"
+," shell disallow shell escapes, and lynxexec, lynxprog or lynxcgi"
+," G)oto's"
+," suspend disallow Control-Z suspends with escape to shell"
+," telnet_port disallow specifying a port in telnet G)oto's"
+," useragent disallow modifications of the User-Agent header"
+ };
+ size_t n;
+ for (n = 0; n < sizeof(Usage)/sizeof(Usage[0]); n++)
+ printf("%s\n", Usage[n]);
+ exit(0);
+ }
+
+ } else if (strncmp(argv[0], "-resubmit_posts", 15) == 0) {
+ if (LYresubmit_posts)
+ LYresubmit_posts = FALSE;
+ else
+ LYresubmit_posts = TRUE;
+
+ } else if (strncmp(argv[0], "-rlogin", 7) == 0) {
+ rlogin_ok = FALSE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 's':
+ if (strncmp(argv[0], "-selective", 10) == 0) {
+ HTDirAccess = HT_DIR_SELECTIVE;
+
+ } else if (strncmp(argv[0], "-show_cursor", 12) == 0) {
+ LYUseDefShoCur = FALSE;
+
+ } else if (strncmp(argv[0], "-soft_dquotes", 13) == 0) {
+ if (soft_dquotes)
+ soft_dquotes = FALSE;
+ else
+ soft_dquotes = TRUE;
+
+ } else if (strncmp(argv[0], "-source", 7) == 0) {
+ dump_output_immediately = TRUE;
+ HTOutputFormat = (LYPrependBase ?
+ HTAtom_for("www/download") : HTAtom_for("www/dump"));
+ LYcols=999;
+
+ } else if (strncmp(argv[0], "-stack_dump", 11) == 0) {
+ stack_dump = TRUE;
+
+ } else if (strncmp(argv[0], "-startfile_ok", 13) == 0) {
+ startfile_ok = TRUE;
+
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ } else if (strncmp(argv[0], "-syslog", 7) == 0) {
+ if (nextarg)
+ StrAllocCopy(syslog_txt, cp);
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 't':
+ if (strncmp(argv[0], "-telnet", 7) == 0) {
+ telnet_ok = FALSE;
+
+ } else if (strncmp(argv[0], "-term", 5) == 0) {
+ if (nextarg)
+ terminal = cp;
+
+ } else if (strncmp(argv[0], "-tlog", 5) == 0) {
+ /*
+ * Already handled. - FM
+ */
+ break;
+
+ } else if (strncmp(argv[0], "-trace", 6) == 0) {
+ /*
+ * Already handled. - FM
+ */
+ break;
+
+ } else if (strncmp(argv[0], "-traversal", 10) == 0) {
+ traversal = TRUE;
+#ifdef USE_SLANG
+ LYcols=80;
+#else
+ LYcols=999;
+#endif /* USE_SLANG */
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'u':
+ if (strncmp(argv[0], "-underscore", 11) == 0) {
+ if (use_underscore)
+ use_underscore = FALSE;
+ else
+ use_underscore = TRUE;
+
+ } else if (strncmp(argv[0], "-useragent", 10) == 0) {
+ /*
+ * Set alternate Lynx User-Agent header.
+ */
+ if (nextarg)
+ StrAllocCopy(LYUserAgent, cp);
+
+#if defined(NCURSES_MOUSE_VERSION) || defined(USE_SLANG_MOUSE)
+ } else if (strncmp(argv[0], "-use_mouse", 9) == 0) {
+ LYUseMouse = TRUE;
+#endif
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'v':
+ if (strcmp(argv[0], "-validate") == 0) {
+ /*
+ * Follow only http URLs.
+ * Already handled. - FM
+ */
+ break;
+
+ } else if (strncmp(argv[0], "-version", 8) == 0) {
+ printf("\n%s Version %s (1998)\n", LYNX_NAME, LYNX_VERSION);
+ printf(
+ "Copyrights held by the University of Kansas, CERN, and other contributors.\n"
+ );
+ printf("Distributed under the GNU General Public License.\n");
+ printf(
+ "See http://lynx.browser.org/ and the online help for more information.\n\n"
+ );
+ exit(0);
+
+ } else if (strncmp(argv[0], "-vikeys", 7) == 0) {
+ vi_keys = TRUE;
+
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ case 'w':
+ if (strncmp(argv[0], "-width", 2) == 0) {
+ if (nextarg) {
+ int w = atoi(cp);
+ if (w > 0) {
+ dump_output_width = ((w < 999) ? w : 999);
+ break;
+ }
+ }
+ dump_output_width = 80;
+ } else {
+ goto Output_Error_and_Help_List;
+ }
+ break;
+
+ default:
+Output_Error_and_Help_List:
+#ifdef VMS
+ printf(" LYNX: Invalid Option: %s\n", argv[0]);
+#else
+#ifdef UNIX
+ if (strncmp(argv[0], "-help", 5) != 0)
+ fprintf(stderr, "%s: Invalid Option: %s\n", pgm, argv[0]);
+ else
+#endif /* UNIX */
+ printf("%s: Invalid Option: %s\n", pgm, argv[0]);
+#endif /* VMS */
+Output_Help_List:
+#ifdef VMS
+ printf("USAGE: lynx [options] [file]\n");
+#else
+ printf("USAGE: %s [options] [file]\n",pgm);
+#endif /* VMS */
+ {
+ static CONST char *Options[] = {
+ "Options are:"
+," - receive the arguments from stdin (enclose"
+," in double-quotes (\"-\") on VMS)"
+," -anonymous used to specify the anonymous account"
+," -assume_charset=MIMEname charset for documents that don't specify it"
+," -assume_local_charset=MIMEname charset assumed for local files"
+," -assume_unrec_charset=MIMEname use this instead of unrecognized charsets"
+," -auth=id:pw authentication information for protected documents"
+," -base prepend a request URL comment and BASE tag to text/html"
+," outputs for -source dumps"
+," -book use the bookmark page as the startfile"
+," -buried_news toggles scanning of news articles for buried references"
+," -cache=NUMBER NUMBER of documents cached in memory"
+," -case enable case sensitive user searching"
+," -cfg=FILENAME specifies a lynx.cfg file other than the default"
+," -child exit on left-arrow in startfile, and disable save to disk"
+#ifdef USE_SLANG
+," -color force color mode on with standard bg colors"
+," -blink force high intensity bg colors in color mode"
+#endif /* USE_SLANG */
+," -cookies toggles handling of Set-Cookie headers"
+#ifndef VMS
+," -core toggles forced core dumps on fatal errors"
+#endif /* !VMS */
+," -crawl with -traversal, output each page to a file"
+," with -dump, format output as with -traversal, but to stdout"
+," -display=DISPLAY set the display variable for X execed programs"
+," -dump dump the first file to stdout and exit"
+," -editor=EDITOR enable edit mode with specified editor"
+," -emacskeys enable emacs-like key movement"
+," -enable_scrollback toggles compatibility with comm programs' scrollback"
+," keys (may be incompatible with some curses packages)"
+," -error_file=FILE write the HTTP status code here"
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+," -exec enable local program execution"
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+," -locexec enable local program execution from local files only"
+," -noexec disable local program execution (DEFAULT)"
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+," -fileversions include all versions of files in local VMS directory"
+," listings"
+," -force_html forces the first document to be interpreted as HTML"
+," -force_secure toggles forcing of the secure flag for SSL cookies"
+," -from toggle transmissions of From headers"
+," -ftp disable ftp access"
+," -get_data user data for get forms, read from stdin,"
+," terminated by '---' on a line"
+," -head send a HEAD request"
+," -help print this usage message"
+," -hiddenlinks=[option] hidden links: options are merge, listonly, or ignore"
+," -historical toggles use of '>' or '-->' as a terminator for comments"
+," -homepage=URL set homepage separate from start page"
+," -image_links toggles inclusion of links for all images"
+," -index=URL set the default index file to URL"
+," -ismap toggles inclusion of ISMAP links when client-side"
+," MAPs are present"
+," -link=NUMBER starting count for lnk#.dat files produced by -crawl"
+," -localhost disable URLs that point to remote hosts"
+#if defined(USE_HASH)
+," -lss=FILENAME specifies a lynx.css file other than the default"
+#endif
+," -mime_header include mime headers and force source dump"
+," -minimal toggles minimal versus valid comment parsing"
+," -newschunksize=NUMBER number of articles in chunked news listings"
+," -newsmaxchunk=NUMBER maximum news articles in listings before chunking"
+," -nobrowse disable directory browsing"
+," -nocc disable Cc: prompts for self copies of mailings"
+," -nofilereferer disable transmissions of Referer headers for file URLs"
+," -nolist disable the link list feature in dumps"
+," -nolog disable mailing of error messages to document owners"
+," -nopause disable forced pauses for statusline messages"
+," -noprint disable print functions"
+," -noredir don't follow Location: redirection"
+," -noreferer disable transmissions of Referer headers"
+#ifdef SOCKS
+," -nosocks don't use SOCKS proxy for this session"
+#endif /* SOCKS */
+," -nostatus disable the miscellaneous information messages"
+," -number_links force numbering of links"
+," -pauth=id:pw authentication information for protected proxy server"
+," -popup toggles handling of single-choice SELECT options via"
+," popup windows or as lists of radio buttons"
+," -post_data user data for post forms, read from stdin,"
+," terminated by '---' on a line"
+," -preparsed show parsed text/html with -source and in source view"
+," -print enable print functions (DEFAULT)"
+," -pseudo_inlines toggles pseudo-ALTs for inlines with no ALT string"
+," -raw toggles default setting of 8-bit character translations"
+," or CJK mode for the startup character set"
+," -realm restricts access to URLs in the starting realm"
+," -reload flushes the cache on a proxy server"
+," (only the first document affected)"
+," -restrictions=[options] use -restrictions to see list"
+," -resubmit_posts toggles forced resubmissions (no-cache) of forms with"
+," method POST when the documents they returned are sought"
+," with the PREV_DOC command or from the History List"
+," -rlogin disable rlogins"
+," -selective require .www_browsable files to browse directories"
+," -show_cursor toggles hiding of the cursor in the lower right corner"
+," -soft_dquotes toggles emulation of the old Netscape and Mosaic bug which"
+," treated '>' as a co-terminator for double-quotes and tags"
+," -source dump the source of the first file to stdout and exit"
+," -startfile_ok allow non-http startfile and homepage with -validate"
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+," -syslog=text information for syslog call"
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+," -telnet disable telnets"
+," -term=TERM set terminal type to TERM"
+," -tlog toggles use of a Lynx Trace Log for the current session"
+," -trace turns on Lynx trace mode"
+," -traversal traverse all http links derived from startfile"
+," -underscore toggles use of _underline_ format in dumps"
+," -useragent=Name set alternate Lynx User-Agent header"
+#if defined(NCURSES_MOUSE_VERSION) || defined(USE_SLANG_MOUSE)
+," -use_mouse enable use of the mouse"
+#endif
+," -validate accept only http URLs (for validation)"
+," -version print Lynx version information"
+," -vikeys enable vi-like key movement"
+," -width=NUMBER screen width for formatting of dumps (default is 80)"
+ };
+ size_t n;
+ for (n = 0; n < sizeof(Options)/sizeof(Options[0]); n++)
+ printf("%s\n", Options[n]);
+ }
+ if (strncmp(argv[0], "-help", 5) != 0)
+ exit(-1);
+ exit(0);
+ break;
+
+ } /* end of switch. */
+}
+
+#ifndef VMS
+PRIVATE void FatalProblem ARGS1(
+ int, sig)
+{
+ /*
+ * Ignore further interrupts. - mhc: 11/2/91
+ */
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_IGN);
+#endif /* NOSIGHUP */
+ (void) signal (SIGTERM, SIG_IGN);
+ (void) signal (SIGINT, SIG_IGN);
+#ifndef __linux__
+#ifndef DOSPATH
+ (void) signal(SIGBUS, SIG_IGN);
+#endif /* ! DOSPATH */
+#endif /* !__linux__ */
+ (void) signal(SIGSEGV, SIG_IGN);
+ (void) signal(SIGILL, SIG_IGN);
+
+ /*
+ * Flush all messages. - FM
+ */
+ fflush(stderr);
+ fflush(stdout);
+
+ /*
+ * Deal with curses, if on, and clean up. - FM
+ */
+ if (LYOutOfMemory && LYCursesON) {
+ sleep(AlertSecs);
+ }
+ cleanup_sig(0);
+#ifndef __linux__
+#ifndef DOSPATH
+ signal(SIGBUS, SIG_DFL);
+#endif /* DOSPATH */
+#endif /* !__linux__ */
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
+
+ /*
+ * Issue appropriate messages and abort or exit. - FM
+ */
+ if (LYOutOfMemory == FALSE) {
+ fprintf (stderr, "\r\n\
+A Fatal error has occurred in %s Ver. %s\r\n", LYNX_NAME, LYNX_VERSION);
+
+ fprintf(stderr, "\r\n\
+Please notify your system administrator to confirm a bug, and\r\n\
+if confirmed, to notify the lynx-dev list. Bug reports should\r\n\
+have concise descriptions of the command and/or URL which causes\r\n\
+the problem, the operating system name with version number, the\r\n\
+TCPIP implementation, and any other relevant information.\r\n");
+
+ fprintf(stderr, "\r\n\
+Do NOT mail the core file if one was generated.\r\n");
+
+ fprintf(stderr, "\r\n\
+Lynx now exiting with signal: %d\r\n\r\n", sig);
+
+ /*
+ * Exit and possibly dump core.
+ */
+ if (LYNoCore) {
+ exit(-1);
+ }
+ abort();
+
+ } else {
+ LYOutOfMemory = FALSE;
+ printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
+ fflush(stdout);
+
+ /*
+ * Exit without dumping core.
+ */
+ exit(0);
+ }
+}
+#endif /* !VMS */
diff --git a/gnu/usr.bin/lynx/src/LYMainLoop.c b/gnu/usr.bin/lynx/src/LYMainLoop.c
new file mode 100644
index 00000000000..07faecb7728
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMainLoop.c
@@ -0,0 +1,5807 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAccess.h"
+#include "HTParse.h"
+#include "HTList.h"
+#include "HTML.h"
+#include "HTFTP.h"
+#include "HTFile.h"
+#include "HTTP.h"
+#include "HTAABrow.h"
+#include "HTNews.h"
+#include "LYCurses.h"
+#include "LYStyle.h"
+#include "LYGlobalDefs.h"
+#include "HTAlert.h"
+#include "LYUtils.h"
+#include "GridText.h"
+#include "LYStrings.h"
+#include "LYOptions.h"
+#include "LYSignal.h"
+#include "LYGetFile.h"
+#include "HTForms.h"
+#include "LYSearch.h"
+#include "LYClean.h"
+#include "LYHistory.h"
+#include "LYPrint.h"
+#include "LYMail.h"
+#include "LYEdit.h"
+#include "LYShowInfo.h"
+#include "LYBookmark.h"
+#include "LYSystem.h"
+#include "LYKeymap.h"
+#include "LYJump.h"
+#include "LYDownload.h"
+#include "LYList.h"
+#include "LYMap.h"
+#include "LYTraversal.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h"
+#include "LYCookie.h"
+#include "LYMainLoop.h"
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#ifdef USE_EXTERNALS
+#include "LYExtern.h"
+#endif
+
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+
+#ifdef DIRED_SUPPORT
+#include "LYLocal.h"
+#include "LYUpload.h"
+#endif /* DIRED_SUPPORT */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+PRIVATE BOOL confirm_post_resub PARAMS((
+ CONST char* address,
+ CONST char* title,
+ int if_imgmap,
+ int if_file));
+PRIVATE int are_different PARAMS((document *doc1, document *doc2));
+PUBLIC void HTGotoURLs_free NOPARAMS;
+PUBLIC void HTAddGotoURL PARAMS((char *url));
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+PRIVATE int are_phys_different PARAMS((document *doc1, document *doc2));
+#endif
+
+#define FASTTAB
+#ifdef FASTTAB
+PRIVATE int sametext ARGS2(
+ char *, een,
+ char *, twee)
+{
+ if (een && twee)
+ return (strcmp(een, twee) == 0);
+ return TRUE;
+}
+#endif /* FASTTAB */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC HTList * Goto_URLs = NULL; /* List of Goto URLs */
+
+PUBLIC char * LYRequestTitle = NULL; /* newdoc.title in calls to getfile() */
+
+PRIVATE document newdoc;
+PRIVATE document curdoc;
+PRIVATE char *traversal_host = NULL;
+PRIVATE char *traversal_link_to_add = NULL;
+PRIVATE char *CurrentUserAgent = NULL;
+PRIVATE char *CurrentNegoLanguage = NULL;
+PRIVATE char *CurrentNegoCharset = NULL;
+
+/*
+ * Function for freeing allocated mainloop() variables. - FM
+ */
+PRIVATE void free_mainloop_variables NOARGS
+{
+ FREE(newdoc.title);
+ FREE(newdoc.address);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ FREE(curdoc.title);
+ FREE(curdoc.address);
+ FREE(curdoc.post_data);
+ FREE(curdoc.post_content_type);
+ FREE(curdoc.bookmark);
+#ifdef USE_HASH
+ FREE(curdoc.style);
+ FREE(newdoc.style);
+#endif
+ FREE(traversal_host);
+ FREE(traversal_link_to_add);
+ FREE(CurrentUserAgent);
+ FREE(CurrentNegoLanguage);
+ FREE(CurrentNegoCharset);
+#ifdef DIRED_SUPPORT
+ clear_tags();
+#endif /* DIRED_SUPPORT */
+
+ return;
+}
+
+/*
+ * Here's where we do all the work.
+ * mainloop is basically just a big switch dependent on the users input.
+ * I have tried to offload most of the work done here to procedures to
+ * make it more modular, but this procedure still does a lot of variable
+ * manipulation. This needs some work to make it neater. - Lou Moutilli
+ * (memoir from the original Lynx - FM)
+ */
+
+int mainloop NOARGS
+{
+ int c = 0, real_c = 0, old_c = 0;
+ int cmd = LYK_DO_NOTHING, real_cmd = LYK_DO_NOTHING;
+ int getresult;
+ int arrowup = FALSE, show_help = FALSE;
+ int lines_in_file = -1;
+ int Newline = 0;
+ char prev_target[512];
+ char user_input_buffer[1024];
+ char *owner_address = NULL; /* Holds the responsible owner's address */
+ char *ownerS_address = NULL; /* Holds owner's address during source fetch */
+ BOOLEAN first_file = TRUE;
+ BOOLEAN popped_doc = FALSE;
+ BOOLEAN refresh_screen = FALSE;
+ BOOLEAN force_load = FALSE;
+ BOOLEAN try_internal = FALSE;
+ BOOLEAN crawl_ok = FALSE;
+ BOOLEAN rlink_exists;
+ BOOLEAN rlink_allowed;
+ BOOLEAN vi_keys_flag = vi_keys;
+ BOOLEAN emacs_keys_flag = emacs_keys;
+ BOOLEAN keypad_mode_flag = keypad_mode;
+ BOOLEAN user_mode_flag = user_mode;
+ BOOLEAN HTfileSortMethod_flag = HTfileSortMethod;
+ int CurrentCharSet_flag = current_char_set;
+ BOOLEAN show_dotfiles_flag = show_dotfiles;
+ BOOLEAN LYRawMode_flag = LYRawMode;
+ BOOLEAN LYSelectPopups_flag = LYSelectPopups;
+ BOOLEAN trace_mode_flag = FALSE;
+ BOOLEAN forced_HTML_mode = LYforce_HTML_mode;
+ char cfile[128];
+ FILE *cfp;
+ char *cp, *toolbar;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig */
+#endif /* VMS */
+ int ch, recall;
+ int URLTotal;
+ int URLNum;
+ BOOLEAN FirstURLRecall = TRUE;
+ char *temp = NULL;
+ BOOLEAN ForcePush = FALSE;
+ BOOLEAN override_LYresubmit_posts = FALSE;
+ unsigned int len;
+ int i;
+
+#ifdef DIRED_SUPPORT
+ char *tp = NULL;
+ struct stat dir_info;
+#endif /* DIRED_SUPPORT */
+
+/*
+ * curdoc.address contains the name of the file that is currently open.
+ * newdoc.address contains the name of the file that will soon be
+ * opened if it exits.
+ * prev_target contains the last search string the user searched for.
+ * newdoc.title contains the link name that the user last chose to get
+ * into the current link (file).
+ */
+ /* initialize some variables*/
+ newdoc.address = NULL;
+ newdoc.title = NULL;
+ newdoc.post_data = NULL;
+ newdoc.post_content_type = NULL;
+ newdoc.bookmark = NULL;
+ curdoc.address = NULL;
+ curdoc.title = NULL;
+ curdoc.post_data = NULL;
+ curdoc.post_content_type = NULL;
+ curdoc.bookmark = NULL;
+#ifdef USE_HASH
+ curdoc.style = NULL;
+ newdoc.style = NULL;
+#endif
+ nhist = 0;
+ user_input_buffer[(sizeof(user_input_buffer) - 1)] = '\0';
+ *prev_target = '\0';
+ *user_input_buffer = '\0';
+ StrAllocCopy(CurrentUserAgent, (LYUserAgent ?
+ LYUserAgent : ""));
+ StrAllocCopy(CurrentNegoLanguage, (language ?
+ language : ""));
+ StrAllocCopy(CurrentNegoCharset, (pref_charset ?
+ pref_charset : ""));
+ atexit(free_mainloop_variables);
+initialize:
+ StrAllocCopy(newdoc.address, startfile);
+ StrAllocCopy(startrealm, startfile);
+ StrAllocCopy(newdoc.title, "Entry into main screen");
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ newdoc.line = 1;
+ newdoc.link = 0;
+
+#ifdef USE_SLANG
+ if (TRACE && LYCursesON) {
+ addstr("\n");
+ refresh();
+ }
+#endif /* USE_SLANG */
+ if (TRACE)
+ fprintf(stderr,"Entering mainloop, startfile=%s\n",startfile);
+
+ if (form_post_data) {
+ StrAllocCopy(newdoc.post_data, form_post_data);
+ StrAllocCopy(newdoc.post_content_type,
+ "application/x-www-form-urlencoded");
+ } else if (form_get_data) {
+ StrAllocCat(newdoc.address, form_get_data);
+ }
+
+ if (bookmark_start) {
+ if (LYValidate) {
+ _statusline(BOOKMARKS_DISABLED);
+ sleep(AlertSecs);
+ bookmark_start = FALSE;
+ goto initialize;
+ } else if (traversal) {
+ _statusline(BOOKMARKS_NOT_TRAVERSED);
+ sleep(AlertSecs);
+ traversal = FALSE;
+ crawl = FALSE;
+ bookmark_start = FALSE;
+ goto initialize;
+ } else {
+ /*
+ * See if a bookmark page exists. If it does,
+ * replace newdoc.address with it's name
+ */
+ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL &&
+ *cp != '\0' && strcmp(cp, " ")) {
+ StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
+ StrAllocCopy(newdoc.bookmark, BookmarkPage);
+ StrAllocCopy(startrealm, newdoc.address);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ if (TRACE)
+ fprintf(stderr, "Using bookmarks=%s\n", newdoc.address);
+ } else {
+ _statusline(BOOKMARKS_NOT_OPEN);
+ sleep(MessageSecs);
+ bookmark_start = FALSE;
+ goto initialize;
+ }
+ }
+ }
+
+ FREE(form_post_data);
+ FREE(form_get_data);
+
+ if (user_mode == NOVICE_MODE)
+ display_lines = LYlines-4;
+ else
+ display_lines = LYlines-2;
+
+ while (TRUE) {
+#ifdef USE_HASH
+ if (curdoc.style != NULL) force_load = TRUE;
+#endif
+ /*
+ * If newdoc.address is different then curdoc.address then
+ * we need to go out and find and load newdoc.address.
+ */
+ if (LYforce_no_cache || force_load ||
+ are_different(&curdoc, &newdoc)) {
+
+ force_load = FALSE; /* done */
+ if (TRACE && LYCursesON) {
+ move(LYlines-1, LYcols-1); /* make sure cursor is down */
+#ifdef USE_SLANG
+ addstr("\n");
+#endif /* USE_SLANG */
+ refresh();
+ }
+try_again:
+ /*
+ * Push the old file onto the history stack if we
+ * have a current doc and a new address. - FM
+ */
+ if (curdoc.address && newdoc.address) {
+ /*
+ * Don't actually push if this is a LYNXDOWNLOAD
+ * URL, because that returns NORMAL even if it
+ * fails due to a spoof attempt or file access
+ * problem, and we set the newdoc structure
+ * elements to the curdoc structure elements
+ * under case NORMAL. - FM
+ */
+ if (strncmp(newdoc.address, "LYNXDOWNLOAD:", 13)) {
+ LYpush(&curdoc, ForcePush);
+ }
+ } else if (!newdoc.address) {
+ /*
+ * If newdoc.address is empty then pop a file
+ * and load it. - FM
+ */
+ LYpop(&newdoc);
+ popped_doc = TRUE;
+
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+#define NO_INTERNAL_OR_DIFFERENT(c,n) TRUE
+#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) (!curdoc.internal_link || \
+ are_phys_different(p,n))
+#else /* TRACK_INTERNAL_LINKS */
+#define NO_INTERNAL_OR_DIFFERENT(c,n) are_different(c,n)
+#define NONINTERNAL_OR_PHYS_DIFFERENT(p,n) are_different(p,n)
+#endif /* TRACK_INTERNAL_LINKS */
+
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ /*
+ ** If curdoc had been reached via an internal
+ ** (fragment) link from what we now have just
+ ** popped into newdoc, then override non-caching in
+ ** all cases. - kw
+ */
+ if (curdoc.internal_link &&
+ !are_phys_different(&curdoc, &newdoc)) {
+ LYinternal_flag = TRUE;
+ LYoverride_no_cache = TRUE;
+ LYforce_no_cache = FALSE;
+ try_internal = TRUE;
+ } else
+#endif /* TRACK_INTERNAL_LINKS */
+ /*
+ * Force a no_cache override unless
+ * it's a bookmark file, or it has POST content
+ * and LYresubmit_posts is set without safe also
+ * set, and we are not going to another position
+ * in the current document or restoring the previous
+ * document due to a NOT_FOUND or NULLFILE return
+ * value from getfile(). - FM
+ */
+ if ((newdoc.bookmark != NULL) ||
+ (newdoc.post_data != NULL &&
+ !newdoc.safe &&
+ LYresubmit_posts &&
+ !override_LYresubmit_posts &&
+ NO_INTERNAL_OR_DIFFERENT(&curdoc, &newdoc))) {
+ LYoverride_no_cache = FALSE;
+ } else {
+ LYoverride_no_cache = TRUE;
+ }
+ }
+ override_LYresubmit_posts = FALSE;
+
+ if (HEAD_request) {
+ /*
+ * Make SURE this is an appropriate request. - FM
+ */
+ if (newdoc.address) {
+ if (LYCanDoHEAD(newdoc.address) == TRUE) {
+ newdoc.isHEAD = TRUE;
+ } else if (!strncmp(newdoc.address, "LYNXIMGMAP:", 11)) {
+ if (LYCanDoHEAD(newdoc.address + 11) == TRUE) {
+ StrAllocCopy(temp, newdoc.address + 11);
+ FREE(newdoc.address);
+ newdoc.address = temp;
+ newdoc.isHEAD = TRUE;
+ temp = NULL;
+ }
+ }
+ }
+ try_internal = FALSE;
+ HEAD_request = FALSE;
+ }
+
+ /*
+ * If we're getting the TRACE log and it's not new,
+ * check whether its HText structure has been dumped,
+ * and if so, fflush() and fclose() it to ensure it's
+ * fully updated, and then fopen() it again. - FM
+ */
+ if (LYUseTraceLog == TRUE &&
+ trace_mode_flag == FALSE &&
+ LYTraceLogFP != NULL &&
+ !strcmp((newdoc.title ? newdoc.title : ""),
+ LYNX_TRACELOG_TITLE)) {
+ DocAddress WWWDoc;
+ HTParentAnchor *tmpanchor;
+
+ WWWDoc.address = newdoc.address;
+ WWWDoc.post_data = newdoc.post_data;
+ WWWDoc.post_content_type = newdoc.post_content_type;
+ WWWDoc.bookmark = newdoc.bookmark;
+ WWWDoc.isHEAD = newdoc.isHEAD;
+ WWWDoc.safe = newdoc.safe;
+ tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ if ((HText *)HTAnchor_document(tmpanchor) == NULL) {
+ if (TRACE)
+ fprintf(stderr,
+ "\nTurning off TRACE for fetch of log.\n");
+ fflush(stdout);
+ fflush(stderr);
+ fclose(LYTraceLogFP);
+ *stderr = LYOrigStderr;
+ if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag = FALSE;
+ _statusline(TRACELOG_OPEN_FAILED);
+ sleep(MessageSecs);
+ old_c = 0;
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+ *stderr = *LYTraceLogFP;
+ if (TRACE) {
+ WWW_TraceFlag = FALSE;
+ trace_mode_flag = TRUE;
+ }
+ }
+ }
+
+ LYRequestTitle = newdoc.title;
+ if (newdoc.bookmark)
+ LYforce_HTML_mode = TRUE;
+ if (LYValidate &&
+ startfile_ok &&
+ newdoc.address && startfile && homepage &&
+ (!strcmp(newdoc.address, startfile) ||
+ !strcmp(newdoc.address, homepage))) {
+ LYPermitURL = TRUE;
+ }
+
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (try_internal) {
+ if (newdoc.address &&
+ 0==strncmp(newdoc.address, "LYNXIMGMAP:", 11)) {
+ try_internal = FALSE;
+ } else if (curdoc.address &&
+ 0==strncmp(curdoc.address, "LYNXIMGMAP:", 11)) {
+ try_internal = FALSE;
+ }
+ }
+ if (try_internal) {
+ char *hashp = strchr(newdoc.address,'#');
+ if (hashp) {
+ HTFindPoundSelector(hashp+1);
+ }
+ getresult = (HTMainText != NULL) ? NORMAL : NOT_FOUND;
+ try_internal = FALSE; /* done */
+ /* fix up newdoc.address which may have been fragment-only */
+ if (getresult == NORMAL && (!hashp || hashp == newdoc.address)) {
+ if (!hashp) {
+ StrAllocCopy(newdoc.address, HTLoadedDocumentURL());
+ } else {
+ StrAllocCopy(temp, HTLoadedDocumentURL());
+ StrAllocCat(temp, hashp); /* append fragment */
+ StrAllocCopy(newdoc.address, temp);
+ FREE(temp);
+ }
+ }
+ } else {
+ if (newdoc.internal_link && newdoc.address &&
+ *newdoc.address == '#' && nhist > 0) {
+ char *cp0;
+ if (0==strncmp(history[nhist-1].address, "LYNXIMGMAP:", 11))
+ cp0 = history[nhist-1].address + 11;
+ else
+ cp0 = history[nhist-1].address;
+ StrAllocCopy(temp, cp0);
+ cp0 = strchr(temp, '#');
+ if (cp0)
+ *cp0 = '\0';
+ StrAllocCat(temp, newdoc.address);
+ FREE(newdoc.address);
+ newdoc.address = temp;
+ temp = NULL;
+ }
+ getresult = getfile(&newdoc);
+ }
+#else /* TRACK_INTERNAL_LINKS */
+ getresult = getfile(&newdoc);
+#endif /* TRACK_INTERNAL_LINKS */
+
+ switch(getresult) {
+
+ case NOT_FOUND:
+ /*
+ * OK! can't find the file, so it must not be around now.
+ * Do any error logging, if appropriate.
+ */
+ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
+ popped_doc = FALSE; /* Was TRUE if popped. - FM */
+ LYinternal_flag = FALSE; /* Reset to default. - kw */
+ if (trace_mode_flag == TRUE) {
+ WWW_TraceFlag = TRUE;
+ trace_mode_flag = FALSE;
+ fprintf(stderr, "Turning TRACE back on.\n\n");
+ }
+ if (error_logging &&
+ first_file && owner_address && !LYCancelledFetch) {
+ /*
+ * Email a bad link message to the owner of
+ * the document (but NOT to lynx-dev). - FM
+ */
+ if (strncasecomp(owner_address, "mailto:", 7)) {
+ if (strncasecomp((owner_address + 7),
+ "lynx-dev@", 9)) {
+ mailmsg(curdoc.link,
+ (owner_address+7),
+ history[nhist-1].address,
+ history[nhist-1].title);
+ }
+ }
+ }
+ if (traversal && !first_file && !LYCancelledFetch) {
+ FILE *ofp;
+
+ if ((ofp = LYAppendToTxtFile(TRAVERSE_ERRORS)) == NULL) {
+ if ((ofp = LYNewTxtFile(TRAVERSE_ERRORS)) == NULL) {
+ perror(NOOPEN_TRAV_ERR_FILE);
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ }
+ fprintf(ofp, "%s %s\tin %s\n",
+ links[curdoc.link].lname,
+ links[curdoc.link].target,
+ history[nhist-1].address);
+ fclose(ofp);
+ }
+
+ /*
+ * Fall through to do the NULL stuff and reload the
+ * old file, unless the first file wasn't found or
+ * has gone missing.
+ */
+ if (!nhist) {
+ /*
+ * If nhist = 0 then it must be the first file.
+ */
+ if (!dump_output_immediately)
+ cleanup();
+#ifdef UNIX
+ if (dump_output_immediately)
+ fprintf(stderr,"\nlynx: Can't access startfile %s\n",
+ startfile);
+ else
+#endif /* UNIX */
+ printf("\nlynx: Can't access startfile %s\n",
+ startfile);
+ if (!dump_output_immediately) {
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ return(-1);
+ }
+
+ case NULLFILE:
+ /*
+ * Not supposed to return any file.
+ */
+ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
+ popped_doc = FALSE; /* Was TRUE if popped. - FM */
+ LYinternal_flag = FALSE; /* Reset to default. - kw */
+ if (trace_mode_flag == TRUE) {
+ WWW_TraceFlag = TRUE;
+ trace_mode_flag = FALSE;
+ fprintf(stderr, "Turning TRACE back on.\n\n");
+ }
+ FREE(newdoc.address); /* to pop last doc */
+ FREE(newdoc.bookmark);
+ LYJumpFileURL = FALSE;
+ reloading = FALSE;
+ LYPermitURL = FALSE;
+ LYCancelledFetch = FALSE;
+ ForcePush = FALSE;
+ LYforce_HTML_mode = FALSE;
+ if (traversal) {
+ crawl_ok = FALSE;
+ if (traversal_link_to_add) {
+ /*
+ * It's a binary file, or the fetch attempt
+ * failed. Add it to TRAVERSE_REJECT_FILE
+ * so we don't try again in this run.
+ */
+ if (!lookup_reject(traversal_link_to_add)) {
+ add_to_reject_list(traversal_link_to_add);
+ }
+ FREE(traversal_link_to_add);
+ }
+ }
+ /*
+ * Make sure the first file was found and
+ * has not gone missing.
+ */
+ if (!nhist) {
+ /*
+ * If nhist = 0 then it must be the first file.
+ */
+ if (first_file && homepage &&
+#ifdef VMS
+ strcasecomp(homepage, startfile) != 0
+#else
+ strcmp(homepage, startfile) != 0
+#endif /* VMS */
+ ) {
+ /*
+ * Couldn't return to the first file but there is a
+ * homepage we can use instead. Useful for when the
+ * first URL causes a program to be invoked. - GL
+ *
+ * But first make sure homepage is different from
+ * startfile (above), then make it the same (below)
+ * so we don't enter an infinite getfile() loop on
+ * on failures to find the files. - FM
+ */
+ StrAllocCopy(newdoc.address, homepage);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ StrAllocCopy(startfile, homepage);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ goto try_again;
+ } else {
+ if (!dump_output_immediately)
+ cleanup();
+#ifdef UNIX
+ if (dump_output_immediately) {
+ fprintf(stderr,
+ "\nlynx: Start file could not be found or is not text/html or text/plain\n");
+ fprintf(stderr," Exiting...\n");
+ } else
+#endif /* UNIX */
+ {
+ printf(
+ "\nlynx: Start file could not be found or is not text/html or text/plain\n");
+ printf(" Exiting...\n");
+ }
+ if (!dump_output_immediately) {
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ return(-1);
+ }
+ }
+
+ /*
+ * Retrieval of a newdoc just failed, and just
+ * going to try_again would pop the next doc
+ * from history and try to get it without further
+ * questions. This may not be the right thing to do if
+ * we have POST data, so fake a PREV_DOC key if it seems
+ * that some prompting should be done. Dunno about the
+ * traversal logic, so I leave that case alone.
+ */
+ if (history[nhist - 1].post_data &&
+ !history[nhist - 1].safe) {
+ if (HText_POSTReplyLoaded((document *)&history[(nhist - 1)])) {
+ override_LYresubmit_posts = TRUE;
+ goto try_again;
+ }
+ /* Set newdoc fields, just in case the PREV_DOC
+ * gets cancelled. - kw */
+ if (!curdoc.address) {
+ StrAllocCopy(newdoc.address, HTLoadedDocumentURL());
+ StrAllocCopy(newdoc.title, HTLoadedDocumentTitle());
+ if (HTMainAnchor && HTMainAnchor->post_data) {
+ StrAllocCopy(newdoc.post_data,
+ HTMainAnchor->post_data);
+ StrAllocCopy(newdoc.post_content_type,
+ HTMainAnchor->post_content_type);
+ } else {
+ FREE(newdoc.post_data);
+ }
+ newdoc.isHEAD = HTLoadedDocumentIsHEAD();
+ newdoc.safe = HTLoadedDocumentIsSafe();
+ newdoc.internal_link = FALSE;
+ } else {
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title, curdoc.title);
+ StrAllocCopy(newdoc.post_data, curdoc.post_data);
+ StrAllocCopy(newdoc.post_content_type,
+ curdoc.post_content_type);
+ newdoc.isHEAD = curdoc.isHEAD;
+ newdoc.safe = curdoc.safe;
+ newdoc.internal_link = curdoc.internal_link;
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+ }
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+ override_LYresubmit_posts = TRUE;
+ goto try_again;
+ break;
+
+ case NORMAL:
+ /*
+ * Marvelously, we got the document!
+ */
+ LYoverride_no_cache = FALSE; /* Was TRUE if popped. - FM */
+ LYinternal_flag = FALSE; /* Reset to default. - kw */
+ if (trace_mode_flag == TRUE) {
+ WWW_TraceFlag = TRUE;
+ trace_mode_flag = FALSE;
+ fprintf(stderr, "Turning TRACE back on.\n\n");
+ }
+ *prev_target = '\0'; /* Reset for this document. - FM */
+
+ /*
+ * If it's the first file and we're interactive,
+ * check whether it's a bookmark file which was
+ * not accessed via the -book switch. - FM
+ */
+ if (((first_file == TRUE) &&
+ (dump_output_immediately == FALSE) &&
+ !(newdoc.bookmark && *newdoc.bookmark)) &&
+ ((LYisLocalFile(newdoc.address) == TRUE) &&
+ !(strcmp((HText_getTitle() ? HText_getTitle() : ""),
+ BOOKMARK_TITLE))) &&
+ (temp = HTParse(newdoc.address, "",
+ PARSE_PATH+PARSE_PUNCTUATION)) != NULL) {
+#ifdef DOSPATH
+ cp = HTDOS_wwwName((char *)Home_Dir());
+#else
+#ifdef VMS
+ cp = HTVMS_wwwName((char *)Home_Dir());
+#else
+ cp = (char *)Home_Dir();
+#endif /* VMS */
+#endif /* DOSPATH */
+ len = strlen(cp);
+#ifdef VMS
+ if (!strncasecomp(temp, cp, len) &&
+ strlen(temp) > len)
+#else
+ if (!strncmp(temp, cp, len) &&
+ strlen(temp) > len)
+#endif /* VMS */
+ {
+ /*
+ * We're interactive and this might be a
+ * bookmark file entered as a startfile
+ * rather than invoked via -book. Check
+ * if it's in our bookmark file list, and
+ * if so, reload if with the relevant
+ * bookmark elements set. - FM
+ */
+ if ((cp = (char *)calloc(1,
+ (strlen((char *)&temp[len]) + 2))) == NULL)
+ outofmem(__FILE__, "mainloop");
+ if (temp[len] == '/') {
+ if (strchr((char *)&temp[(len + 1)], '/')) {
+ sprintf(cp, ".%s", (char *)&temp[len]);
+ } else {
+ strcpy(cp, (char *)&temp[(len + 1)]);
+ }
+ } else {
+ strcpy(cp, (char *)&temp[len]);
+ }
+ for (i = 0; i <= MBM_V_MAXFILES; i++) {
+ if (MBM_A_subbookmark[i] &&
+#ifdef VMS
+ !strcasecomp(cp, MBM_A_subbookmark[i])
+#else
+ !strcmp(cp, MBM_A_subbookmark[i])
+#endif /* VMS */
+ ) {
+ StrAllocCopy(BookmarkPage,
+ MBM_A_subbookmark[i]);
+ break;
+ }
+ }
+ FREE(cp);
+ if (i <= MBM_V_MAXFILES) {
+ FREE(temp);
+ if (LYValidate) {
+ _statusline(BOOKMARKS_DISABLED);
+ sleep(AlertSecs);
+ return(-1);
+ }
+ if ((temp = HTParse(newdoc.address, "",
+ PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION))) {
+ StrAllocCopy(newdoc.address, temp);
+ HTuncache_current_document();
+ FREE(curdoc.address);
+#ifdef DOSPATH
+ StrAllocCat(newdoc.address,
+ HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ StrAllocCat(newdoc.address,
+ HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(newdoc.address, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ StrAllocCat(newdoc.address, "/");
+ StrAllocCat(newdoc.address,
+ (strncmp(BookmarkPage, "./", 2) ?
+ BookmarkPage :
+ (BookmarkPage + 2)));
+ StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
+ StrAllocCopy(newdoc.bookmark, BookmarkPage);
+#ifdef USE_HASH
+ if (curdoc.style)
+ StrAllocCopy(newdoc.style, curdoc.style);
+#endif
+ StrAllocCopy(startrealm, newdoc.address);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ FREE(temp);
+ if (!strcmp(homepage, startfile))
+ StrAllocCopy(homepage, newdoc.address);
+ StrAllocCopy(startfile, newdoc.address);
+ if (TRACE)
+ fprintf(stderr,
+ "Reloading as bookmarks=%s\n",
+ newdoc.address);
+ goto try_again;
+ }
+ }
+ }
+ cp = NULL;
+ }
+ FREE(temp);
+
+ if (traversal) {
+ /*
+ * During traversal build up lists of all links
+ * traversed. Traversal mode is a special
+ * feature for traversing http links in the web.
+ */
+ if (traversal_link_to_add) {
+ /*
+ * Add the address we sought to TRAVERSE_FILE.
+ */
+ if (!lookup(traversal_link_to_add))
+ add_to_table(traversal_link_to_add);
+ FREE(traversal_link_to_add);
+ }
+ if (curdoc.address && curdoc.title &&
+ strncmp(curdoc.address, "LYNXIMGMAP:", 11))
+ /*
+ * Add the address we got to TRAVERSE_FOUND_FILE.
+ */
+ add_to_traverse_list(curdoc.address, curdoc.title);
+ }
+
+ /*
+ * If this was a LYNXDOWNLOAD, we still have curdoc,
+ * not a newdoc, so reset the address, title and
+ * positioning elements. - FM
+ */
+ if (newdoc.address && curdoc.address &&
+ !strncmp(newdoc.address, "LYNXDOWNLOAD:", 13)) {
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title, (curdoc.title ?
+ curdoc.title : ""));
+ StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+ newdoc.internal_link = FALSE; /* can't be true. - kw */
+ }
+
+ /*
+ * Set Newline to the saved line. It contains the
+ * line the user was on if s/he has been in the file
+ * before, or it is 1 if this is a new file.
+ */
+ Newline = newdoc.line;
+
+ /*
+ * If we are going to a target line or
+ * the first page of a popped document,
+ * override any www_search line result.
+ */
+ if (Newline > 1 || popped_doc == TRUE)
+ www_search_result = -1;
+
+ /*
+ * Make sure curdoc.line will not be equal
+ * to Newline, so we get a redraw.
+ */
+ curdoc.line = -1;
+
+ break;
+ } /* end switch */
+
+ if (TRACE) {
+ if (!LYTraceLogFP || trace_mode_flag) {
+ sleep(AlertSecs); /* allow me to look at the results */
+ }
+ }
+
+ /*
+ * Set the files the same.
+ */
+ StrAllocCopy(curdoc.address, newdoc.address);
+ StrAllocCopy(curdoc.post_data, newdoc.post_data);
+ StrAllocCopy(curdoc.post_content_type, newdoc.post_content_type);
+ StrAllocCopy(curdoc.bookmark, newdoc.bookmark);
+#ifdef USE_HASH
+ StrAllocCopy(curdoc.style, HText_getStyle());
+ if (curdoc.style != NULL)
+ style_readFromFile (curdoc.style);
+#endif
+ curdoc.isHEAD = newdoc.isHEAD;
+ curdoc.internal_link = newdoc.internal_link;
+
+ /*
+ * Set the remaining document elements and add to
+ * the visitied links list. - FM
+ */
+ if (ownerS_address != NULL) {
+ if (HTOutputFormat == WWW_SOURCE && !HText_getOwner())
+ HText_setMainTextOwner(ownerS_address);
+ FREE(ownerS_address);
+ }
+ if (HText_getTitle()) {
+ StrAllocCopy(curdoc.title, HText_getTitle());
+ } else if (!dump_output_immediately) {
+ StrAllocCopy(curdoc.title, newdoc.title);
+ }
+ owner_address = HText_getOwner();
+ curdoc.safe = HTLoadedDocumentIsSafe();
+ if (!dump_output_immediately) {
+ LYAddVisitedLink(&curdoc);
+ }
+
+
+ /*
+ * Reset WWW present mode so that if we were getting
+ * the source, we get rendered HTML from now on.
+ */
+ HTOutputFormat = WWW_PRESENT;
+
+ /*
+ * Reset all of the other relevant flags. - FM
+ */
+ LYUserSpecifiedURL = FALSE; /* only set for goto's and jumps's */
+ LYJumpFileURL = FALSE; /* only set for jump's */
+ LYNoRefererForThis = FALSE; /* always reset on return here */
+ reloading = FALSE; /* only set for RELOAD and RESUBMIT */
+ HEAD_request = FALSE; /* only set for HEAD requests */
+ LYPermitURL = FALSE; /* only set for LYValidate */
+ ForcePush = FALSE; /* only set for some PRINT requests. */
+ LYforce_HTML_mode = FALSE;
+ popped_doc = FALSE;
+
+ } /* end if (LYforce_no_cache || force_load || are_different(...)) */
+
+ if (dump_output_immediately) {
+ if (crawl) {
+ print_crawl_to_fd(stdout, curdoc.address, curdoc.title);
+ } else {
+ print_wwwfile_to_fd(stdout,0);
+ }
+ return(0);
+ }
+
+ /*
+ * If the recent_sizechange variable is set to TRUE
+ * then the window size changed recently.
+ */
+ if (recent_sizechange) {
+ stop_curses();
+ start_curses();
+ clear();
+ refresh_screen = TRUE; /* to force a redraw */
+ recent_sizechange = FALSE;
+ if (user_mode == NOVICE_MODE) {
+ display_lines = LYlines-4;
+ } else {
+ display_lines = LYlines-2;
+ }
+ }
+
+ if (www_search_result != -1) {
+ /*
+ * This was a WWW search, set the line
+ * to the result of the search.
+ */
+ Newline = www_search_result;
+ www_search_result = -1; /* reset */
+ more = HText_canScrollDown();
+ }
+
+ if (first_file == TRUE) {
+ /*
+ * We can never again have the first file.
+ */
+ first_file = FALSE;
+
+ /*
+ * Set the startrealm, and deal as best we can
+ * with preserving forced HTML mode for a local
+ * startfile. - FM
+ */
+ temp = HTParse(curdoc.address, "",
+ PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
+ if (!temp || *temp == '\0') {
+ StrAllocCopy(startrealm, "None");
+ } else {
+ StrAllocCopy(startrealm, temp);
+ FREE(temp);
+ if (!(temp = HTParse(curdoc.address, "",
+ PARSE_PATH+PARSE_PUNCTUATION))) {
+ if (startrealm[strlen(startrealm)-1] != '/') {
+ StrAllocCat(startrealm, "/");
+ }
+ } else {
+ if (forced_HTML_mode &&
+ !dump_output_immediately &&
+ !curdoc.bookmark &&
+ !strncasecomp(curdoc.address, "file:", 5) &&
+ strlen(temp) > 1) {
+ /*
+ * We forced HTML for a local startfile which
+ * is not a bookmark file and has a path of at
+ * least two letters. If it doesn't have a
+ * suffix mapped to text/html, we'll set the
+ * entire path (including the lead slash) as a
+ * "suffix" mapped to text/html to ensure it is
+ * always treated as an HTML source file. We
+ * are counting on a tail match to this full path
+ * for some other URL fetched during the session
+ * having too low a probability to worry about,
+ * but it could happen. - FM
+ */
+ HTAtom *encoding;
+
+ if (HTFileFormat(temp, &encoding, NULL) != WWW_HTML) {
+ HTSetSuffix(temp, "text/html", "8bit", 1.0);
+ }
+ }
+ if ((cp = strrchr(temp, '/')) != NULL) {
+ *(cp+1) = '\0';
+ StrAllocCat(startrealm, temp);
+ }
+ }
+ }
+ FREE(temp);
+ if (TRACE) {
+ fprintf(stderr, "Starting realm is '%s'\n\n", startrealm);
+ }
+ if (traversal) {
+ /*
+ * Set up the crawl output stuff.
+ */
+ if (curdoc.address && !lookup(curdoc.address)) {
+ if (strncmp(curdoc.address, "LYNXIMGMAP:", 11))
+ crawl_ok = TRUE;
+ add_to_table(curdoc.address);
+ }
+ /*
+ * Set up the traversal_host comparison string.
+ */
+ if (strncmp((curdoc.address ? curdoc.address : "NULL"),
+ "http", 4)) {
+ StrAllocCopy(traversal_host, "None");
+ } else if (check_realm) {
+ StrAllocCopy(traversal_host, startrealm);
+ } else {
+ temp = HTParse(curdoc.address, "",
+ PARSE_ACCESS+PARSE_HOST+PARSE_PUNCTUATION);
+ if (!temp || *temp == '\0') {
+ StrAllocCopy(traversal_host, "None");
+ } else {
+ StrAllocCopy(traversal_host, temp);
+ if (traversal_host[strlen(traversal_host)-1] != '/') {
+ StrAllocCat(traversal_host, "/");
+ }
+ }
+ FREE(temp);
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "Traversal host is '%s'\n\n", traversal_host);
+ }
+ }
+ if (startfile) {
+ /*
+ * If homepage was not equated to startfile,
+ * make the homepage URL the first goto
+ * entry. - FM
+ */
+ if (homepage && strcmp(startfile, homepage))
+ HTAddGotoURL(homepage);
+ /*
+ * If we are not starting up with startfile
+ * (e.g., had -book), or if we are using the
+ * startfile and it has no POST content, make
+ * the startfile URL a goto entry. - FM
+ */
+ if (strcmp(startfile, newdoc.address) ||
+ newdoc.post_data == NULL)
+ HTAddGotoURL(startfile);
+ }
+ if (TRACE) {
+ refresh_screen = TRUE;
+ if (!LYTraceLogFP || trace_mode_flag) {
+ sleep(AlertSecs);
+ }
+ }
+ }
+
+ /*
+ * If the curdoc.line is different than Newline then there must
+ * have been a change since last update. Run HText_pageDisplay()
+ * create a fresh screen of text out.
+ */
+ if (curdoc.line != Newline) {
+
+ refresh_screen = FALSE;
+
+ HText_pageDisplay(Newline, prev_target);
+
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
+ showtags(tagged);
+#endif /* DIRED_SUPPORT */
+ /*
+ * If more equals TRUE, then there is more
+ * info below this page .
+ */
+ more = HText_canScrollDown();
+ curdoc.line = Newline = HText_getTopOfScreen()+1;
+ lines_in_file = HText_getNumOfLines();
+
+ if (curdoc.title == NULL) {
+ /*
+ * If we don't yet have a title, try to get it,
+ * or set to that for newdoc.title. - FM
+ */
+ if (HText_getTitle()) {
+ StrAllocCopy(curdoc.title, HText_getTitle());
+ } else {
+ StrAllocCopy(curdoc.title, newdoc.title);
+ }
+ }
+
+ if (arrowup) {
+ /*
+ * arrowup is set if we just came up from
+ * a page below.
+ */
+ curdoc.link = nlinks - 1;
+ arrowup = FALSE;
+ } else {
+ curdoc.link = newdoc.link;
+ if (curdoc.link >= nlinks) {
+ curdoc.link = nlinks - 1;
+ } else if (curdoc.link < 0 && nlinks > 0) {
+ /*
+ * We may have popped a doc (possibly in local_dired)
+ * which didn't have any links when it was pushed, but
+ * does have links now (e.g. a file was created) - KW
+ */
+ curdoc.link = 0;
+ }
+ }
+
+ show_help = FALSE; /* reset */
+ newdoc.line = 1;
+ newdoc.link = 0;
+ curdoc.line = Newline; /* set */
+ }
+
+ /*
+ * Refresh the screen if necessary.
+ */
+ if (refresh_screen) {
+#if defined(FANCY_CURSES) || defined (USE_SLANG)
+ if (enable_scrollback) {
+ clear();
+ } else {
+ erase();
+ }
+#else
+ clear();
+#endif /* FANCY_CURSES || USE_SLANG */
+ HText_pageDisplay(Newline, prev_target);
+
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode && nlinks > 0 && !HTList_isEmpty(tagged))
+ showtags(tagged);
+#endif /* DIRED_SUPPORT */
+ if (user_mode == NOVICE_MODE)
+ noviceline(more); /* print help message */
+ refresh_screen = FALSE;
+
+ }
+
+ /*
+ * Report unread or new mail, if appropriate.
+ */
+ if (check_mail && !no_mail && LYCheckMail())
+ sleep(MessageSecs);
+
+ /*
+ * If help is not on the screen,
+ * then put a message on the screen
+ * to tell the user other misc info.
+ */
+ if (!show_help) {
+ /*
+ * Make sure form novice lines are replaced.
+ */
+ if (user_mode == NOVICE_MODE) {
+ noviceline(more);
+ }
+
+ /*
+ * If we are in forms mode then explicitly
+ * tell the user what each kind of link is.
+ */
+ if (HTisDocumentSource()) {
+ /*
+ * Currently displaying HTML source.
+ */
+ _statusline(SOURCE_HELP);
+
+#ifdef INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE
+ } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0) {
+#else
+#ifdef NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES
+ } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
+ !(links[curdoc.link].type & WWW_LINK_TYPE)) {
+#else
+ } else if (lynx_mode == FORMS_LYNX_MODE && nlinks > 0 &&
+ !(user_mode == ADVANCED_MODE &&
+ (links[curdoc.link].type & WWW_LINK_TYPE))) {
+#endif /* NORMAL_NON_FORM_LINK_STATUSLINES_FOR_ALL_USER_MODES */
+#endif /* INDICATE_FORMS_MODE_FOR_ALL_LINKS_ON_PAGE */
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE)
+ switch(links[curdoc.link].form->type) {
+ case F_PASSWORD_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_PASSWORD_UNM_MSG);
+ else
+ statusline(FORM_LINK_PASSWORD_MESSAGE);
+ break;
+ case F_OPTION_LIST_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_OPTION_LIST_UNM_MSG);
+ else
+ statusline(FORM_LINK_OPTION_LIST_MESSAGE);
+ break;
+ case F_CHECKBOX_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_CHECKBOX_UNM_MSG);
+ else
+ statusline(FORM_LINK_CHECKBOX_MESSAGE);
+ break;
+ case F_RADIO_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_RADIO_UNM_MSG);
+ else
+ statusline(FORM_LINK_RADIO_MESSAGE);
+ break;
+ case F_TEXT_SUBMIT_TYPE:
+ if (links[curdoc.link].form->disabled == YES) {
+ statusline(FORM_LINK_TEXT_SUBMIT_UNM_MSG);
+ } else if (links[curdoc.link].form->submit_method ==
+ URL_MAIL_METHOD) {
+ if (no_mail)
+ statusline(
+ FORM_LINK_TEXT_SUBMIT_MAILTO_DIS_MSG);
+ else
+ statusline(FORM_LINK_TEXT_SUBMIT_MAILTO_MSG);
+ } else if (links[curdoc.link].form->no_cache) {
+ statusline(FORM_LINK_TEXT_RESUBMIT_MESSAGE);
+ } else {
+ statusline(FORM_LINK_TEXT_SUBMIT_MESSAGE);
+ }
+ break;
+ case F_SUBMIT_TYPE:
+ case F_IMAGE_SUBMIT_TYPE:
+ if (links[curdoc.link].form->disabled == YES) {
+ statusline(FORM_LINK_SUBMIT_DIS_MSG);
+ } else if (links[curdoc.link].form->submit_method ==
+ URL_MAIL_METHOD) {
+ if (no_mail) {
+ statusline(FORM_LINK_SUBMIT_MAILTO_DIS_MSG);
+ } else {
+ statusline(FORM_LINK_SUBMIT_MAILTO_MSG);
+ }
+ } else if (links[curdoc.link].form->no_cache) {
+ statusline(FORM_LINK_RESUBMIT_MESSAGE);
+ } else {
+ statusline(FORM_LINK_SUBMIT_MESSAGE);
+ }
+ break;
+ case F_RESET_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_RESET_DIS_MSG);
+ else
+ statusline(FORM_LINK_RESET_MESSAGE);
+ break;
+ case F_TEXT_TYPE:
+ case F_TEXTAREA_TYPE:
+ if (links[curdoc.link].form->disabled == YES)
+ statusline(FORM_LINK_TEXT_UNM_MSG);
+ else
+ statusline(FORM_LINK_TEXT_MESSAGE);
+ break;
+ }
+ else
+ statusline(NORMAL_LINK_MESSAGE);
+
+ /*
+ * Let them know if it's an index -- very rare.
+ */
+ if (is_www_index) {
+ move(LYlines-1,LYcols-8);
+ start_reverse();
+ addstr("-index-");
+ stop_reverse();
+ }
+
+ } else if (user_mode == ADVANCED_MODE && nlinks > 0) {
+ /*
+ * Show the URL or, for some internal links, the fragment
+ */
+ cp = NULL;
+ if (links[curdoc.link].type == WWW_INTERN_LINK_TYPE &&
+ strncmp(links[curdoc.link].lname, "LYNXIMGMAP:", 11)) {
+ cp = strchr(links[curdoc.link].lname, '#');
+ }
+ if (!cp)
+ cp = links[curdoc.link].lname;
+ if (more)
+ if (is_www_index)
+ _user_message("-more- -index- %s",
+ cp);
+ else
+ _user_message("-more- %s",cp);
+ else
+ if (is_www_index)
+ _user_message("-index- %s",cp);
+ else
+ statusline(cp);
+ } else if (is_www_index && more) {
+ char buf[128];
+
+ sprintf(buf, WWW_INDEX_MORE_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
+ _statusline(buf);
+ } else if (is_www_index) {
+ char buf[128];
+
+ sprintf(buf, WWW_INDEX_MESSAGE, key_for_func(LYK_INDEX_SEARCH));
+ _statusline(buf);
+ } else if (more) {
+ if (user_mode == NOVICE_MODE)
+ _statusline(MORE);
+ else
+ _statusline(MOREHELP);
+ } else {
+ _statusline(HELP);
+ }
+ } else {
+ show_help = FALSE;
+ }
+
+ if (!(nlinks > 0 &&
+ links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ (links[curdoc.link].form->type == F_TEXT_TYPE ||
+ links[curdoc.link].form->type == F_TEXTAREA_TYPE)))
+ /*
+ * Highlight current link.
+ */
+ highlight(ON, curdoc.link, prev_target);
+
+ if (traversal) {
+ /*
+ * Don't go interactively into forms,
+ * or accept keystrokes from the user
+ */
+ if (crawl && crawl_ok) {
+ crawl_ok = FALSE;
+#ifdef FNAMES_8_3
+ sprintf(cfile,"lnk%05d.dat",ccount);
+#else
+ sprintf(cfile,"lnk%08d.dat",ccount);
+#endif /* FNAMES_8_3 */
+ ccount = ccount + 1;
+ if ((cfp = LYNewTxtFile(cfile)) != NULL) {
+ print_crawl_to_fd(cfp,curdoc.address,curdoc.title);
+ fclose(cfp);
+ } else {
+ if (!dump_output_immediately)
+ cleanup();
+#ifdef UNIX
+ if (dump_output_immediately)
+ fprintf(stderr,
+ "Fatal error - could not open output file %s\n",cfile);
+ else
+#endif
+ printf(
+ "Fatal error - could not open output file %s\n",cfile);
+ if (!dump_output_immediately) {
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ return(-1);
+ }
+ }
+ } else {
+ /*
+ * Normal, non-traversal handling.
+ */
+ if (nlinks > 0 &&
+ links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ (links[curdoc.link].form->type == F_TEXT_TYPE ||
+ links[curdoc.link].form->type == F_TEXT_SUBMIT_TYPE ||
+ links[curdoc.link].form->type == F_PASSWORD_TYPE ||
+ links[curdoc.link].form->type == F_TEXTAREA_TYPE)) {
+ /*
+ * Replace novice lines if in NOVICE_MODE.
+ */
+ if (user_mode==NOVICE_MODE) {
+ move(LYlines-2,0); clrtoeol();
+ addstr(FORM_NOVICELINE_ONE);
+ move(LYlines-1,0); clrtoeol();
+ addstr(FORM_NOVICELINE_TWO);
+ }
+ c = change_form_link(&links[curdoc.link],
+ FORM_UP, &newdoc, &refresh_screen,
+ links[curdoc.link].form->name,
+ links[curdoc.link].form->value);
+
+ if (c == '\n' || c == '\r')
+#ifdef FASTTAB
+ /*
+ * Make return act like down-arrow.
+ */
+ c = DNARROW;
+#else
+ /*
+ * Make return act like tab.
+ */
+ c = '\t';
+#endif /* FASTTAB */
+ } else {
+ /*
+ * Get a keystroke from the user.
+ * Save the last keystroke to avoid
+ * redundant error reporting.
+ */
+ real_c = c = LYgetch(); /* get user input */
+
+#ifndef VMS
+ if (c == 3) { /* ^C */
+ /*
+ * This shouldn't happen. We'll try to
+ * deal with whatever bug caused it. - FM
+ */
+ signal(SIGINT, cleanup_sig);
+ old_c = 0;
+ cmd = LYK_QUIT;
+ goto new_cmd;
+ }
+#endif /* !VMS */
+ if (old_c != real_c) {
+ old_c = 0;
+ }
+ }
+ }
+
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ c = DO_NOTHING;
+ }
+#else
+ if (recent_sizechange) {
+ if (c <= 0)
+ c = DO_NOTHING;
+ }
+#endif /* VMS */
+
+new_keyboard_input:
+ /*
+ * A goto point for new input without going
+ * back through the getch() loop.
+ */
+ if (traversal) {
+ /*
+ * This is a special feature to traverse every http link
+ * derived from startfile and check for errors or create
+ * crawl output files. Only URL's that begin with
+ * "traversal_host" are searched - this keeps the search
+ * from crossing to other servers (a feature, not a bug!).
+ */
+ rlink_exists = (nlinks > 0 && links[curdoc.link].lname != NULL);
+ if (rlink_exists) {
+ rlink_allowed =
+ (!lookup_reject(links[curdoc.link].lname) &&
+ traversal_host && links[curdoc.link].lname &&
+ !strncmp(traversal_host,
+ (strncmp(links[curdoc.link].lname,
+ "LYNXIMGMAP:", 11)
+ ?
+ links[curdoc.link].lname : (links[curdoc.link].lname + 11)),
+ strlen(traversal_host)));
+ } else {
+ rlink_allowed = FALSE;
+ }
+ if (rlink_exists && rlink_allowed) {
+ if (lookup(links[curdoc.link].lname)) {
+ if (more_links ||
+ (curdoc.link > -1 && curdoc.link < nlinks -1))
+ c= DNARROW;
+ else {
+ if (STREQ(curdoc.title,"Entry into main screen") ||
+ (nhist <= 0 )) {
+ if (!dump_output_immediately) {
+ cleanup();
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ return(-1);
+ }
+ c = LTARROW;
+ }
+ } else {
+ StrAllocCopy(traversal_link_to_add,
+ links[curdoc.link].lname);
+ if (strncmp(traversal_link_to_add, "LYNXIMGMAP:", 11))
+ crawl_ok = TRUE;
+ c = RTARROW;
+ }
+ } else { /* no good right link, so only down and left arrow ok*/
+ if (rlink_exists)
+ add_to_reject_list(links[curdoc.link].lname);
+ if (more_links ||
+ (curdoc.link > -1 && curdoc.link < nlinks-1))
+ c = DNARROW;
+ else {
+ /*
+ * curdoc.title doesn't always work, so
+ * bail out if the history list is empty.
+ */
+ if (STREQ(curdoc.title,"Entry into main screen") ||
+ (nhist <= 0 )) {
+ if (!dump_output_immediately) {
+ cleanup();
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ return(-1);
+ }
+ c = LTARROW;
+ }
+ } /* right link not NULL or link to another site*/
+ } /* traversal */
+
+ cmd = keymap[c+1]; /* add 1 to map EOF to 0 */
+
+#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
+ if (lynx_edit_mode && override[c+1] && !no_dired_support)
+ cmd = override[c+1];
+#endif /* DIRED_SUPPORT && OK_OVERRIDE */
+
+ real_cmd = cmd;
+
+new_cmd: /*
+ * A goto point for new input without going
+ * back through the getch() loop.
+ */
+
+ switch(cmd) {
+ case 0: /* unmapped character */
+ default:
+ if (more)
+ _statusline(MOREHELP);
+ else
+ _statusline(HELP);
+ show_help = TRUE;
+
+ if (TRACE) {
+ sprintf(cfile, "%d", c);
+ addstr(cfile); /* show the user input */
+ cfile[0] = '\0';
+ }
+ break;
+
+ case LYK_INTERRUPT:
+ /*
+ * No network transmission to interrupt - 'til we multithread.
+ */
+ break;
+
+ case LYK_F_LINK_NUM:
+ c = '\0';
+ case LYK_1:
+ case LYK_2:
+ case LYK_3:
+ case LYK_4:
+ case LYK_5:
+ case LYK_6:
+ case LYK_7:
+ case LYK_8:
+ case LYK_9:
+ {
+ /*
+ * Get a number from the user and follow that link number.
+ */
+ int lindx = ((nlinks > 0) ? curdoc.link : 0);
+ int number;
+
+ switch (follow_link_number(c, lindx, &newdoc, &number)) {
+ case DO_LINK_STUFF:
+ /*
+ * Follow a normal link.
+ */
+ StrAllocCopy(newdoc.address, links[lindx].lname);
+ StrAllocCopy(newdoc.title, links[lindx].hightext);
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ /*
+ * For internal links, retain POST content if present.
+ * If we are on the List Page, prevent pushing it on
+ * the history stack. Otherwise set try_internal to
+ * signal that the top of the loop should attempt to
+ * reposition directly, without calling getfile. - kw
+ */
+ if (links[lindx].type == WWW_INTERN_LINK_TYPE) {
+ LYinternal_flag = TRUE;
+ newdoc.internal_link = TRUE;
+ if (0==strcmp((curdoc.title ? curdoc.title : ""),
+ LIST_PAGE_TITLE) &&
+ 0==strcmp(HTLoadedDocumentURL(), LYlist_temp_url())) {
+ if (!curdoc.post_data ||
+ /*
+ * Normal case - List Page is not associated
+ * with post data. - kw
+ */
+ (!LYresubmit_posts && curdoc.post_data &&
+ history[nhist - 1].post_data &&
+ !strcmp(curdoc.post_data,
+ history[nhist - 1].post_data) &&
+ HText_getContentBase() &&
+ !strncmp(HText_getContentBase(),
+ strncmp(history[nhist - 1].address,
+ "LYNXIMGMAP:", 11) ?
+ history[nhist - 1].address :
+ history[nhist - 1].address + 11,
+ strlen(HText_getContentBase())))) {
+ /*
+ * Normal case - as best as we can check, the
+ * document at the top of the history stack
+ * seems to be the document the List Page is
+ * about (or a LYNXIMGMAP derived from it),
+ * and LYresubmit_posts is not set, so don't
+ * prompt here. If we actually have to repeat
+ * a POST because, against expectations, the
+ * underlying document isn't cached any more,
+ * HTAccess will prompt for confirmation,
+ * unless we had LYK_NOCACHE. - kw
+ */
+ LYinternal_flag = TRUE;
+ } else {
+ HTLastConfirmCancelled(); /* reset flag */
+ if (!confirm_post_resub(newdoc.address,
+ newdoc.title,
+ (LYresubmit_posts &&
+ HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
+ 2)) {
+ if (HTLastConfirmCancelled() ||
+ (LYresubmit_posts &&
+ !HText_POSTReplyLoaded(&newdoc))) {
+ /* cancel the whole thing */
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title, curdoc.title);
+ newdoc.internal_link = curdoc.internal_link;
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ if (nlinks > 0)
+ HText_pageDisplay(curdoc.line, prev_target);
+ break;
+ } else if (LYresubmit_posts) {
+ /* If LYresubmit_posts is set, and the
+ answer was No, and we have a cached
+ copy, then use it. - kw */
+ LYforce_no_cache = FALSE;
+ } else {
+ /* if No, but not ^C or ^G, drop
+ * the post data. Maybe the link
+ * wasn't meant to be internal after
+ * all, here we can recover from that
+ * assumption. - kw */
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ newdoc.internal_link = FALSE;
+ _statusline(DISCARDING_POST_DATA);
+ sleep(AlertSecs);
+ }
+ }
+ }
+ /*
+ * Don't push the List Page if we follow an
+ * internal link given by it. - kw
+ */
+ FREE(curdoc.address);
+ } else
+ try_internal = TRUE;
+ if (!(LYresubmit_posts && newdoc.post_data))
+ LYinternal_flag = TRUE;
+ force_load = TRUE;
+ break;
+ } else {
+ /*
+ * Free POST content if not an internal link. - kw
+ */
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ }
+#endif /* DONT_TRACK_INTERNAL_LINKS */
+ /*
+ * Might be an anchor in the same doc from a POST
+ * form. If so, don't free the content. -- FM
+ */
+ if (are_different(&curdoc, &newdoc)) {
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ }
+ newdoc.internal_link = FALSE;
+ force_load = TRUE; /* force MainLoop to reload */
+ break;
+
+ case DO_GOTOLINK_STUFF:
+ /*
+ * Position on a normal link, don't follow it. - KW
+ */
+ Newline = newdoc.line;
+ newdoc.line = 1;
+ if (Newline == curdoc.line) {
+ /*
+ * It's a link in the current page. - FM
+ */
+ if (nlinks > 0 && curdoc.link > -1) {
+ if (curdoc.link == newdoc.link) {
+ /*
+ * It's the current link, and presumably
+ * reflects a typo in the statusline entry,
+ * so issue a statusline message for the
+ * typo-prone users (like me 8-). - FM
+ */
+ StrAllocCopy(temp, user_input_buffer);
+ sprintf(user_input_buffer,
+ LINK_ALREADY_CURRENT, number);
+ _statusline(user_input_buffer);
+ sleep(MessageSecs);
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ } else {
+ /*
+ * It's a different link on this page,
+ * so turn the highlighting off, set the
+ * current link to the new link value from
+ * follow_link_number(), and re-initialize
+ * the new link value. - FM
+ */
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = newdoc.link;
+ newdoc.link = 0;
+ }
+ }
+ }
+ break; /* nothing more to do */
+
+ case DO_GOTOPAGE_STUFF:
+ /*
+ * Position on a page in this document. - FM
+ */
+ Newline = newdoc.line;
+ newdoc.line = 1;
+ if (Newline == curdoc.line) {
+ /*
+ * It's the current page, so issue a
+ * statusline message for the typo-prone
+ * users (like me 8-). - FM
+ */
+ if (Newline <= 1) {
+ _statusline(ALREADY_AT_BEGIN);
+ } else if (!more) {
+ _statusline(ALREADY_AT_END);
+ } else {
+ StrAllocCopy(temp, user_input_buffer);
+ sprintf(user_input_buffer,
+ ALREADY_AT_PAGE, number);
+ _statusline(user_input_buffer);
+ sleep(MessageSecs);
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ }
+ sleep(MessageSecs);
+ }
+ break;
+
+ case PRINT_ERROR:
+ old_c = real_c;
+ _statusline(BAD_LINK_NUM_ENTERED);
+ sleep(MessageSecs);
+ break;
+ }
+ break;
+ }
+
+ case LYK_SOURCE: /* toggle view source mode */
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation if the safe element is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, curdoc.title,
+ 1, 1) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ if (HTisDocumentSource()) {
+ HTOutputFormat = WWW_PRESENT;
+ } else {
+ if (HText_getOwner())
+ StrAllocCopy(ownerS_address, HText_getOwner());
+ LYUCPushAssumed(HTMainAnchor);
+ HTOutputFormat = WWW_SOURCE;
+ }
+ LYforce_no_cache = TRUE;
+ FREE(curdoc.address); /* so it doesn't get pushed */
+ break;
+
+ case LYK_RELOAD: /* control-R to reload and refresh */
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation if the safe element is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ /*
+ * Check to see if should reload source, or load html
+ */
+ if (HTisDocumentSource()) {
+ HTOutputFormat = WWW_SOURCE;
+ }
+ HEAD_request = HTLoadedDocumentIsHEAD();
+ HTuncache_current_document();
+#ifdef NO_ASSUME_SAME_DOC
+ /*
+ * Don't assume the reloaded document will be the same. - FM
+ */
+ newdoc.line = 1;
+ newdoc.link = 0;
+#else
+ /*
+ * Do assume the reloaded document will be the same. - FM
+ * (I don't remember all the reasons why we couldn't assume
+ * this. As the problems show up, we'll try to fix them,
+ * or add warnings. - FM)
+ */
+ if (lynx_mode == FORMS_LYNX_MODE) {
+ /*
+ * Note that if there are no form links on the current
+ * page, lynx_mode won't have this setting and we won't
+ * know that this warning should be issued. - FM
+ */
+ _statusline(RELOADING_FORM);
+ sleep(AlertSecs);
+ }
+ newdoc.line = ((curdoc.line > 0) ?
+ curdoc.line : 1);
+ newdoc.link = ((curdoc.link > -1) ?
+ curdoc.link : 0);
+#endif /* NO_ASSUME_SAME_DOC */
+ FREE(curdoc.address); /* so it doesn't get pushed */
+#ifdef VMS
+ lynx_force_repaint();
+#endif /* VMS */
+ /*
+ * Reload should force a cache refresh on a proxy.
+ * -- Ari L. <luotonen@dxcern.cern.ch>
+ *
+ * -- but only if this was really a reload requested by
+ * the user, not if we jumped here to handle reloading for
+ * INLINE_TOGGLE, IMAGE_TOGGLE, RAW_TOGGLE, etc. - KW
+ */
+ if (real_cmd == LYK_RELOAD)
+ reloading = TRUE;
+ break;
+
+ case LYK_HISTORICAL:
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation of reload if the safe element
+ * is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, NULL,
+ 0, 0) == FALSE) {
+ _statusline(WILL_NOT_RELOAD_DOC);
+ sleep(InfoSecs);
+ } else {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ }
+ if (historical_comments)
+ historical_comments = FALSE;
+ else
+ historical_comments = TRUE;
+ if (minimal_comments) {
+ _statusline(historical_comments ?
+ HISTORICAL_ON_MINIMAL_OFF : HISTORICAL_OFF_MINIMAL_ON);
+ } else {
+ _statusline(historical_comments ?
+ HISTORICAL_ON_VALID_OFF : HISTORICAL_OFF_VALID_ON);
+ }
+ sleep(AlertSecs);
+ break;
+
+ case LYK_MINIMAL:
+ if (!historical_comments) {
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation of reload if the safe element
+ * is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, NULL,
+ 0, 0) == FALSE) {
+ _statusline(WILL_NOT_RELOAD_DOC);
+ sleep(InfoSecs);
+ } else {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ }
+ }
+ if (minimal_comments)
+ minimal_comments = FALSE;
+ else
+ minimal_comments = TRUE;
+ if (!historical_comments) {
+ _statusline(minimal_comments ?
+ MINIMAL_ON_IN_EFFECT : MINIMAL_OFF_VALID_ON);
+ } else {
+ _statusline(minimal_comments ?
+ MINIMAL_ON_BUT_HISTORICAL : MINIMAL_OFF_HISTORICAL_ON);
+ }
+ sleep(AlertSecs);
+ break;
+
+ case LYK_SOFT_DQUOTES:
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation of reload if the safe element
+ * is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, NULL,
+ 1, 1) == FALSE) {
+ _statusline(WILL_NOT_RELOAD_DOC);
+ sleep(InfoSecs);
+ } else {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ }
+ if (soft_dquotes)
+ soft_dquotes = FALSE;
+ else
+ soft_dquotes = TRUE;
+ _statusline(soft_dquotes ?
+ SOFT_DOUBLE_QUOTE_ON : SOFT_DOUBLE_QUOTE_OFF);
+ sleep(MessageSecs);
+ break;
+
+ case LYK_SWITCH_DTD:
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation of reload if the safe element
+ * is not set. - FM, kw
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, NULL,
+ 1, 1) == FALSE) {
+ _statusline(WILL_NOT_RELOAD_DOC);
+ sleep(InfoSecs);
+ } else {
+ /*
+ * If currently viewing preparsed source, switching
+ * to the other DTD parsing may show source differences,
+ * so stay in source view - kw
+ */
+ if (HTisDocumentSource() && LYPreparsedSource) {
+ HTOutputFormat = WWW_SOURCE;
+ }
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ }
+#ifdef NO_ASSUME_SAME_DOC
+ newdoc.line=1;
+ newdoc.link=0;
+#else
+ newdoc.line = ((curdoc.line > 0) ? curdoc.line : 1);
+ newdoc.link = ((curdoc.link > -1) ? curdoc.link : 0);
+#endif /* NO_ASSUME_SAME_DOC */
+ if (New_DTD)
+ New_DTD = NO;
+ else
+ New_DTD = YES;
+ HTSwitchDTD(New_DTD);
+ _statusline(New_DTD ? USING_DTD_1 : USING_DTD_0);
+ sleep(MessageSecs);
+ break;
+
+#ifdef NOT_DONE_YET
+ case LYK_PIPE:
+ /* ignore for now */
+ break;
+#endif /* NOT_DONE_YET */
+
+ case LYK_QUIT: /* quit */
+ if (LYQuitDefaultYes == TRUE) {
+ _statusline(REALLY_QUIT_Y);
+ } else {
+ _statusline(REALLY_QUIT_N);
+ }
+ c = LYgetch();
+ if (LYQuitDefaultYes == TRUE) {
+ if (TOUPPER(c) != 'N' &&
+ c != 7) {
+ return(0);
+ } else {
+ statusline(NO_CANCEL);
+ sleep(InfoSecs);
+ }
+ } else if (TOUPPER(c) == 'Y') {
+ return(0);
+ } else {
+ statusline(NO_CANCEL);
+ sleep(InfoSecs);
+ }
+ break;
+
+ case LYK_ABORT: /* don't ask the user about quitting */
+ return(0);
+ break;
+
+ case LYK_NEXT_PAGE: /* next page */
+ if (more) {
+ Newline += display_lines;
+ } else if (curdoc.link < nlinks-1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = nlinks-1; /* put on last link */
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_END);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_PREV_PAGE: /* page up */
+ if (Newline > 1) {
+ Newline -= display_lines;
+ } else if (curdoc.link > 0) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0; /* put on first link */
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_BEGIN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_UP_TWO:
+ if (Newline > 1) {
+ int scrollamount = (Newline > 2 ? 2 : 1);
+ Newline -= scrollamount;
+ if (nlinks > 0 && curdoc.link > -1) {
+ if (links[curdoc.link].ly + scrollamount <= display_lines) {
+ newdoc.link = curdoc.link +
+ HText_LinksInLines(HTMainText,
+ Newline, scrollamount);
+ } else {
+ arrowup = TRUE;
+ }
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_BEGIN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_DOWN_TWO:
+ if (more) {
+ Newline += 2;
+ if (nlinks > 0 && curdoc.link > -1 &&
+ links[curdoc.link].ly > 2) {
+ newdoc.link = curdoc.link;
+ for (i = 0; links[i].ly <= 2; i++)
+ --newdoc.link;
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_END);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_UP_HALF:
+ if (Newline > 1) {
+ int scrollamount = display_lines/2;
+ if (Newline - scrollamount < 1)
+ scrollamount = Newline - 1;
+ Newline -= scrollamount;
+ if (nlinks > 0 && curdoc.link > -1) {
+ if (links[curdoc.link].ly + scrollamount <= display_lines) {
+ newdoc.link = curdoc.link +
+ HText_LinksInLines(HTMainText,
+ Newline,
+ scrollamount);
+ } else {
+ arrowup = TRUE;
+ }
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_BEGIN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_DOWN_HALF:
+ if (more) {
+ Newline += (display_lines/2);
+ if (nlinks > 0 && curdoc.link > -1 &&
+ links[curdoc.link].ly > display_lines/2) {
+ newdoc.link = curdoc.link;
+ for (i = 0; links[i].ly <= (display_lines/2); i++)
+ --newdoc.link;
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_END);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_REFRESH:
+ refresh_screen = TRUE;
+ lynx_force_repaint();
+ break;
+
+ case LYK_HOME:
+ if (curdoc.line > 1)
+ Newline = 1;
+ else {
+ cmd = LYK_PREV_PAGE;
+ goto new_cmd;
+ }
+ break;
+
+ case LYK_END:
+ if (more) {
+ Newline = MAXINT; /* go to end of file */
+ arrowup = TRUE; /* position on last link */
+ } else {
+ cmd = LYK_NEXT_PAGE;
+ goto new_cmd;
+ }
+ break;
+
+ case LYK_PREV_LINK:
+ if (curdoc.link > 0) { /* previous link */
+ /*
+ * Unhighlight current link.
+ */
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link--;
+
+ } else if (!more &&
+ curdoc.link==0 && Newline==1) { /* at the top of list */
+ /*
+ * If there is only one page of data and the user
+ * goes off the top, then unhighlight the current
+ * link and just move the cursor to last link on
+ * the page.
+ */
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = nlinks-1; /* the last link */
+
+ } else if (curdoc.line > 1) { /* previous page */
+ /*
+ * Go back to the previous page.
+ */
+ int scrollamount = (Newline > display_lines ?
+ display_lines : Newline - 1);
+ Newline -= scrollamount;
+ if (scrollamount < display_lines &&
+ nlinks > 0 && curdoc.link == 0 &&
+ links[0].ly - 1 + scrollamount <= display_lines) {
+ newdoc.link = HText_LinksInLines(HTMainText,
+ 1,
+ scrollamount) - 1;
+ } else {
+ arrowup = TRUE;
+ }
+
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_BEGIN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_NEXT_LINK:
+ if (curdoc.link < nlinks-1) { /* next link */
+ highlight(OFF, curdoc.link, prev_target);
+#ifdef FASTTAB
+ /*
+ * Move to different textarea if TAB in textarea.
+ */
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->type == F_TEXTAREA_TYPE &&
+ c=='\t') {
+ int thisgroup = links[curdoc.link].form->number;
+ char *thisname = links[curdoc.link].form->name;
+
+ do curdoc.link++;
+ while ((curdoc.link < nlinks-1) &&
+ links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->type == F_TEXTAREA_TYPE &&
+ links[curdoc.link].form->number == thisgroup &&
+ sametext(links[curdoc.link].form->name, thisname));
+ } else {
+ curdoc.link++;
+ }
+#else
+ curdoc.link++;
+#endif /* FASTTAB */
+ /*
+ * At the bottom of list and there is only one page.
+ * Move to the top link on the page.
+ */
+ } else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0;
+
+ } else if (more) { /* next page */
+ Newline += (display_lines);
+
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_END);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_UP_LINK:
+ if (curdoc.link > 0 &&
+ (links[0].ly != links[curdoc.link].ly ||
+ !HText_LinksInLines(HTMainText, 1, Newline - 1))) {
+ /* more links before this on screen, and first of them on
+ a different line or no previous links before this screen? */
+ int newlink = -1;
+ for (i = curdoc.link; i >= 0; i--) {
+ if (links[i].ly < links[curdoc.link].ly) {
+ newlink = i;
+ break;
+ }
+ }
+ if (newlink > -1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = newlink;
+#ifdef NOTDEFINED
+ } else if (!more && Newline == 1 && curdoc.link == 0) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = (nlinks-1);
+ } else if (more) { /* next page */
+ Newline += (display_lines);
+#else
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_LINKS_ABOVE);
+ sleep(MessageSecs);
+#endif /* NOTDEFINED */
+ }
+
+#ifdef NOTDEFINED
+ /*
+ * At the bottom of list and there is only one page.
+ * Move to the top link on the page.
+ */
+ } else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0;
+#endif /* NOTDEFINED */
+
+ } else if (curdoc.line > 1 && Newline > 1) { /* previous page */
+ int scrollamount = (Newline > display_lines ?
+ display_lines : Newline - 1);
+ Newline -= scrollamount;
+ if (scrollamount < display_lines &&
+ nlinks > 0 && curdoc.link > -1 &&
+ links[0].ly -1 + scrollamount <= display_lines) {
+ newdoc.link = HText_LinksInLines(HTMainText,
+ 1,
+ scrollamount) - 1;
+ } else {
+ arrowup = TRUE;
+ }
+
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_BEGIN);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_DOWN_LINK:
+ if (curdoc.link < (nlinks-1)) { /* more links? */
+ int newlink = -1;
+ for (i = curdoc.link; i < nlinks; i++)
+ if (links[i].ly > links[curdoc.link].ly) {
+ newlink = i;
+ break;
+ }
+
+ if (newlink > -1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = newlink;
+#ifdef NOTDEFINED
+ } else if (!more &&
+ Newline == 1 && curdoc.link == (nlinks-1)) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0;
+#endif /* NOTDEFINED */
+ } else if (more) { /* next page */
+ Newline += (display_lines);
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_LINKS_BELOW);
+ sleep(MessageSecs);
+ break;
+ }
+#ifdef NOTDEFINED
+ /*
+ * At the bottom of list and there is only one page.
+ * Move to the top link on the page.
+ */
+ } else if (!more && Newline == 1 && curdoc.link == (nlinks-1)) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0;
+#endif /* NOTDEFINED */
+ } else if (more) { /* next page */
+ Newline += (display_lines);
+
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_END);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_RIGHT_LINK:
+ if (curdoc.link<nlinks-1 &&
+ links[curdoc.link].ly == links[curdoc.link+1].ly) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link++;
+ }
+ break;
+
+ case LYK_LEFT_LINK:
+ if (curdoc.link>0 &&
+ links[curdoc.link].ly == links[curdoc.link-1].ly) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link--;
+ }
+ break;
+
+ case LYK_COOKIE_JAR: /* show the cookie jar */
+ /*
+ * Don't do if already viewing the cookie jar.
+ */
+ if (strcmp((curdoc.title ? curdoc.title : ""),
+ COOKIE_JAR_TITLE)) {
+ StrAllocCopy(newdoc.address, "LYNXCOOKIE:/");
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ LYforce_no_cache = TRUE;
+ if (LYValidate || check_realm) {
+ LYPermitURL = TRUE;
+ }
+ } else {
+ /*
+ * If already in the cookie jar, get out.
+ */
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+ break;
+
+ case LYK_HISTORY: /* show the history page */
+ if (curdoc.title && strcmp(curdoc.title, HISTORY_PAGE_TITLE)) {
+ /*
+ * Don't do this if already viewing history page.
+ *
+ * Push the current file so that the history list
+ * contains the current file for printing purposes.
+ * Pop the file afterwards to prevent multiple copies.
+ */
+ if (TRACE && !LYUseTraceLog && LYCursesON) {
+ move(LYlines-1, LYcols-1); /* make sure cursor is down */
+#ifdef USE_SLANG
+ addstr("\n");
+#endif /* USE_SLANG */
+ refresh();
+ }
+ LYpush(&curdoc, ForcePush);
+
+ /*
+ * Print history options to file.
+ */
+ if (showhistory(&newdoc.address) < 0) {
+ LYpop(&curdoc);
+ break;
+ }
+ StrAllocCopy(newdoc.title, HISTORY_PAGE_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ FREE(curdoc.address); /* so it doesn't get pushed */
+
+ refresh_screen = TRUE;
+ if (LYValidate || check_realm) {
+ LYPermitURL = TRUE;
+ }
+ break;
+ } /* end if strncmp */
+ /*
+ * Don't put break here so that if the backspace key
+ * is pressed in the history page, we fall though,
+ * i.e., it acts like a left arrow.
+ */
+
+ case LYK_PREV_DOC: /* back up a level */
+ if (nhist > 0) { /* if there is anything to go back to */
+ /*
+ * Check if the previous document is a reply from a POST,
+ * and if so, seek confirmation of resubmission if the safe
+ * element is not set and the document is not still in the
+ * cache or LYresubmit_posts is set. If not confirmed and
+ * it is not the startfile, pop it so we go to the yet
+ * previous document, until we're OK or reach the startfile.
+ * If we reach the startfile and its not OK or we don't get
+ * confirmation, cancel. - FM
+ */
+ DocAddress WWWDoc;
+ HTParentAnchor *tmpanchor;
+ HText *text;
+ BOOLEAN conf = FALSE, first = TRUE;
+
+ HTLastConfirmCancelled(); /* reset flag */
+ while (nhist > 0) {
+ conf = FALSE;
+ if (history[(nhist - 1)].post_data == NULL) {
+ break;
+ }
+ WWWDoc.address = history[(nhist - 1)].address;
+ WWWDoc.post_data = history[(nhist - 1)].post_data;
+ WWWDoc.post_content_type =
+ history[(nhist - 1)].post_content_type;
+ WWWDoc.bookmark = history[(nhist - 1)].bookmark;
+ WWWDoc.isHEAD = history[(nhist - 1)].isHEAD;
+ WWWDoc.safe = history[(nhist - 1)].safe;
+ tmpanchor = HTAnchor_parent(HTAnchor_findAddress(&WWWDoc));
+ if (HTAnchor_safe(tmpanchor)) {
+ break;
+ }
+ if (((text =
+ (HText *)HTAnchor_document(tmpanchor)) == NULL &&
+ (!strncmp(WWWDoc.address, "LYNXIMGMAP:", 11) ||
+ (conf = confirm_post_resub(WWWDoc.address,
+ history[(nhist - 1)].title,
+ 0, 0))
+ == FALSE)) ||
+ ((LYresubmit_posts && !conf &&
+ (NONINTERNAL_OR_PHYS_DIFFERENT(
+ (document *)&history[(nhist - 1)],
+ &curdoc) ||
+ NONINTERNAL_OR_PHYS_DIFFERENT(
+ (document *)&history[(nhist - 1)],
+ &newdoc))) &&
+ !confirm_post_resub(WWWDoc.address,
+ history[(nhist - 1)].title,
+ 2, 2))) {
+ if (HTLastConfirmCancelled()) {
+ if (!first && curdoc.internal_link)
+ FREE(curdoc.address);
+ cmd = LYK_DO_NOTHING;
+ goto new_cmd;
+ }
+ if (nhist == 1) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ old_c = 0;
+ cmd = LYK_DO_NOTHING;
+ goto new_cmd;
+ } else {
+ _user_message(WWW_SKIP_MESSAGE, WWWDoc.address);
+ sleep(MessageSecs);
+ do {
+ LYpop(&curdoc);
+ } while (nhist > 1 && !are_different(
+ (document *)&history[(nhist - 1)],
+ &curdoc));
+ first = FALSE; /* have popped at least one */
+ continue;
+ }
+ } else {
+ /*
+ * Break from loop; if user just confirmed to
+ * load again because document wasn't in cache,
+ * set LYforce_no_cache to avoid unnecessary
+ * repeat question down the road. - kw
+ */
+ if (conf)
+ LYforce_no_cache = TRUE;
+ break;
+ }
+ }
+
+ if (!first)
+ curdoc.internal_link = FALSE;
+
+ /*
+ * Set newdoc.address to empty to pop a file.
+ */
+ FREE(newdoc.address);
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode)
+ HTuncache_current_document();
+#endif /* DIRED_SUPPORT */
+ } else if (child_lynx == TRUE) {
+ return(0); /* exit on left arrow in main screen */
+
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(ALREADY_AT_FIRST);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_NOCACHE: /* Force submission of form or link with no-cache */
+ if (nlinks > 0) {
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->type != F_SUBMIT_TYPE &&
+ links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE) {
+ if (old_c == real_c)
+ break;
+ old_c = real_c;
+ _statusline(NOT_ON_SUBMIT_OR_LINK);
+ sleep(MessageSecs);
+ break;
+ } else {
+ LYforce_no_cache = TRUE;
+ reloading = TRUE;
+ }
+ } /* fall through to LYK_ACTIVATE */
+
+ case LYK_ACTIVATE: /* follow a link */
+ {
+ /* Is there a mouse-clicked link waiting? */
+ int mouse_tmp = get_mouse_link();
+ /* If yes, use it as the link */
+ if (mouse_tmp != -1) curdoc.link = mouse_tmp;
+ }
+ if (nlinks > 0) {
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
+ /*
+ * Don't try to submit forms with bad actions. - FM
+ */
+ if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+ links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE ||
+ links[curdoc.link].form->type ==
+ F_TEXT_SUBMIT_TYPE) {
+ /*
+ * Do nothing if it's disabled. - FM
+ */
+ if (links[curdoc.link].form->disabled == YES) {
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ /*
+ * Make sure we have an action. - FM
+ */
+ if (!links[curdoc.link].form->submit_action ||
+ *links[curdoc.link].form->submit_action
+ == '\0') {
+ _statusline(NO_FORM_ACTION);
+ sleep(MessageSecs);
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ /*
+ * Check for no_mail if the form action
+ * is a mailto URL. - FM
+ */
+ if (links[curdoc.link].form->submit_method
+ == URL_MAIL_METHOD && no_mail) {
+ HTAlert(FORM_MAILTO_DISALLOWED);
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ /*
+ * Make sure this isn't a spoof in an account
+ * with restrictions on file URLs. - FM
+ */
+ if (no_file_url &&
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "file:", 5)) {
+ HTAlert(FILE_ACTIONS_DISALLOWED);
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ /*
+ * Make sure this isn't a spoof attempt
+ * via an internal URL. - FM
+ */
+ if (!strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXCOOKIE:", 11) ||
+#ifdef DIRED_SUPPORT
+#ifdef OK_PERMIT
+ (!(strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXDIRED:", 10)) &&
+ (no_dired_support ||
+ strncasecomp(
+ (links[curdoc.link].form->submit_action + 10),
+ "//PERMIT_LOCATION", 17) ||
+ strcmp(curdoc.address, LYPermitFileURL) ||
+ strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE))) ||
+#else
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXDIRED:", 10) ||
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXDOWNLOAD:", 13) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXHIST:", 9) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXKEYMAP:", 11) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXIMGMAP:", 11) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "LYNXPRINT:", 10) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "lynxexec:", 9) ||
+ !strncasecomp(
+ links[curdoc.link].form->submit_action,
+ "lynxprog:", 9)) {
+ HTAlert(SPECIAL_ACTION_DISALLOWED);
+ if (TRACE) {
+ fprintf(stderr,
+ "LYMainLoop: Rejected '%s'\n",
+ links[curdoc.link].form->submit_action);
+ }
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+#ifdef NOTDEFINED /* We're disabling form inputs instead of using this. - FM */
+ /*
+ * Check for enctype and let user know we
+ * don't yet support multipart/form-data - FM
+ */
+ if (links[curdoc.link].form->submit_enctype) {
+ if (!strcmp(
+ links[curdoc.link].form->submit_enctype,
+ "multipart/form-data")) {
+ HTAlert(
+ "Enctype multipart/form-data not yet supported! Cannot submit.");
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ }
+#endif /* NOTDEFINED */
+ if (check_realm) {
+ LYPermitURL = TRUE;
+ }
+ if (no_filereferer == TRUE &&
+ !strncmp(curdoc.address, "file:", 5)) {
+ LYNoRefererForThis = TRUE;
+ }
+ StrAllocCopy(newdoc.title,
+ links[curdoc.link].hightext);
+ }
+ c = change_form_link(&links[curdoc.link],
+ FORM_UP, &newdoc, &refresh_screen,
+ links[curdoc.link].form->name,
+ links[curdoc.link].form->value);
+ if (HTOutputFormat == HTAtom_for("www/download") &&
+ newdoc.post_data != NULL &&
+ newdoc.safe == FALSE) {
+ if ((HText_POSTReplyLoaded(&newdoc) == TRUE) &&
+ HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title, curdoc.title);
+ StrAllocCopy(newdoc.post_data, curdoc.post_data);
+ StrAllocCopy(newdoc.post_content_type,
+ curdoc.post_content_type);
+ StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+ newdoc.isHEAD = curdoc.isHEAD;
+ newdoc.safe = curdoc.safe;
+ newdoc.internal_link = curdoc.internal_link;
+ break;
+ }
+ }
+ if (c == 23) {
+ c = DO_NOTHING;
+ refresh_screen = TRUE;
+ }
+ goto new_keyboard_input;
+ } else {
+ /*
+ * Not a forms link.
+ *
+ * Make sure this isn't a spoof in an account
+ * with restrictions on file URLs. - FM
+ */
+ if (no_file_url &&
+ !strncmp(links[curdoc.link].lname, "file:", 5)) {
+ if (strncmp(curdoc.address, "file:", 5)) {
+ HTAlert(FILE_SERVED_LINKS_DISALLOWED);
+ reloading = FALSE;
+ break;
+ } else if (curdoc.bookmark != NULL) {
+ HTAlert(FILE_BOOKMARKS_DISALLOWED);
+ reloading = FALSE;
+ break;
+ }
+ }
+ /*
+ * Make sure this isn't a spoof attempt
+ * via an internal URL in a non-internal
+ * document. - FM
+ */
+ if ((!strncmp(links[curdoc.link].lname,
+ "LYNXCOOKIE:", 11) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ COOKIE_JAR_TITLE)) ||
+#ifdef DIRED_SUPPORT
+ (!strncmp(links[curdoc.link].lname,
+ "LYNXDIRED:", 10) &&
+ (strcmp(curdoc.address, LYDiredFileURL) ||
+ strcmp((curdoc.title ? curdoc.title : ""),
+ DIRED_MENU_TITLE)) &&
+ (strcmp(curdoc.address, LYPermitFileURL) ||
+ strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE)) &&
+ (strcmp(curdoc.address, LYUploadFileURL) ||
+ strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE))) ||
+#endif /* DIRED_SUPPORT */
+ (!strncmp(links[curdoc.link].lname,
+ "LYNXDOWNLOAD:", 13) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ DOWNLOAD_OPTIONS_TITLE)) ||
+ (!strncmp(links[curdoc.link].lname,
+ "LYNXHIST:", 9) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ HISTORY_PAGE_TITLE) &&
+ strcmp(curdoc.address, LYlist_temp_url())) ||
+ (!strncmp(links[curdoc.link].lname,
+ "LYNXPRINT:", 10) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ PRINT_OPTIONS_TITLE))) {
+ HTAlert(SPECIAL_VIA_EXTERNAL_DISALLOWED);
+ HTOutputFormat = WWW_PRESENT;
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ break;
+ }
+ /*
+ * Follow a normal link or anchor.
+ */
+ StrAllocCopy(newdoc.address, links[curdoc.link].lname);
+ StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ /*
+ * For internal links, retain POST content if present.
+ * If we are on the List Page, prevent pushing it on
+ * the history stack. Otherwise set try_internal to
+ * signal that the top of the loop should attempt to
+ * reposition directly, without calling getfile. - kw
+ */
+ /*
+ * Might be an internal link anchor in the same doc.
+ * If so, take the try_internal shortcut if we didn't
+ * fall through from LYK_NOCACHE. - kw
+ */
+ newdoc.internal_link =
+ (links[curdoc.link].type == WWW_INTERN_LINK_TYPE);
+ if (newdoc.internal_link) {
+ /*
+ * Special case of List Page document with an
+ * internal link indication, which may really stand
+ * for an internal link within the document the
+ * List Page is about. - kw
+ */
+ if (0==strcmp(curdoc.address, LYlist_temp_url()) &&
+ 0==strcmp((curdoc.title ? curdoc.title : ""),
+ LIST_PAGE_TITLE)) {
+ if (!curdoc.post_data ||
+ /*
+ * Normal case - List Page is not associated
+ * with post data. - kw
+ */
+ (!LYresubmit_posts && curdoc.post_data &&
+ history[nhist - 1].post_data &&
+ !strcmp(curdoc.post_data,
+ history[nhist - 1].post_data) &&
+ HText_getContentBase() &&
+ !strncmp(HText_getContentBase(),
+ strncmp(history[nhist - 1].address,
+ "LYNXIMGMAP:", 11) ?
+ history[nhist - 1].address :
+ history[nhist - 1].address + 11,
+ strlen(HText_getContentBase())))) {
+ /*
+ * Normal case - as best as we can check, the
+ * document at the top of the history stack
+ * seems to be the document the List Page is
+ * about (or a LYNXIMGMAP derived from it),
+ * and LYresubmit_posts is not set, so don't
+ * prompt here. If we actually have to repeat
+ * a POST because, against expectations, the
+ * underlying document isn't cached any more,
+ * HTAccess will prompt for confirmation,
+ * unless we had LYK_NOCACHE. - kw
+ */
+ LYinternal_flag = TRUE;
+ } else {
+ HTLastConfirmCancelled(); /* reset flag */
+ if (!confirm_post_resub(newdoc.address,
+ newdoc.title,
+ (LYresubmit_posts &&
+ HText_POSTReplyLoaded(&newdoc)) ? 1 : 2,
+ 2)) {
+ if (HTLastConfirmCancelled() ||
+ (LYresubmit_posts &&
+ cmd != LYK_NOCACHE &&
+ !HText_POSTReplyLoaded(&newdoc))) {
+ /* cancel the whole thing */
+ LYforce_no_cache = FALSE;
+ reloading = FALSE;
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title, curdoc.title);
+ newdoc.internal_link = curdoc.internal_link;
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ } else if (LYresubmit_posts &&
+ cmd != LYK_NOCACHE) {
+ /* If LYresubmit_posts is set, and the
+ answer was No, and the key wasn't
+ NOCACHE, and we have a cached copy,
+ then use it. - kw */
+ LYforce_no_cache = FALSE;
+ } else {
+ /* if No, but not ^C or ^G, drop
+ * the post data. Maybe the link
+ * wasn't meant to be internal after
+ * all, here we can recover from that
+ * assumption. - kw */
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ newdoc.internal_link = FALSE;
+ _statusline(DISCARDING_POST_DATA);
+ sleep(AlertSecs);
+ }
+ }
+ }
+ /*
+ * Don't push the List Page if we follow an
+ * internal link given by it. - kw
+ */
+ FREE(curdoc.address);
+ } else if (cmd != LYK_NOCACHE) {
+ try_internal = TRUE;
+ }
+ if (!(LYresubmit_posts && newdoc.post_data))
+ LYinternal_flag = TRUE;
+ /* We still set force_load so that history pushing
+ ** etc. will be done. - kw */
+ force_load = TRUE;
+ break;
+ } else {
+ /*
+ * Free POST content if not an internal link. - kw
+ */
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ }
+#endif /* TRACK_INTERNAL_LINKS */
+ /*
+ * Might be an anchor in the same doc from a POST
+ * form. If so, dont't free the content. -- FM
+ */
+ if (are_different(&curdoc, &newdoc)) {
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ }
+ if (!no_jump && lynxjumpfile && curdoc.address &&
+ !strcmp(lynxjumpfile, curdoc.address)) {
+ LYJumpFileURL = TRUE;
+ LYUserSpecifiedURL = TRUE;
+ } else if ((curdoc.title &&
+ !strcmp(curdoc.title, HISTORY_PAGE_TITLE)) ||
+ curdoc.bookmark != NULL ||
+ (lynxjumpfile &&
+ !strcmp(lynxjumpfile, curdoc.address))) {
+ LYUserSpecifiedURL = TRUE;
+ } else if (no_filereferer == TRUE &&
+ !strncmp(curdoc.address, "file:", 5)) {
+ LYNoRefererForThis = TRUE;
+ }
+ newdoc.link = 0;
+ force_load = TRUE; /* force MainLoop to reload */
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode) {
+ HTuncache_current_document();
+ /*
+ * Unescaping any slash chars in the URL,
+ * but avoid double unescaping and too-early
+ * unescaping of other chars. - KW
+ */
+ HTUnEscapeSome(newdoc.address,"/");
+ strip_trailing_slash(newdoc.address);
+ }
+#endif /* DIRED_SUPPORT */
+ if (!strncmp(curdoc.address, "LYNXCOOKIE:", 11)) {
+ HTuncache_current_document();
+ }
+ }
+ }
+ break;
+
+ case LYK_ELGOTO: /* edit URL of current link and go to it */
+ if (no_goto && !LYValidate) {
+ /*
+ * Go to not allowed. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(GOTO_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+ if (!(nlinks > 0 && curdoc.link > -1) ||
+ (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->type != F_SUBMIT_TYPE &&
+ links[curdoc.link].form->type != F_IMAGE_SUBMIT_TYPE &&
+ links[curdoc.link].form->type != F_TEXT_SUBMIT_TYPE)) {
+ /*
+ * No links on page, or not a normal link
+ * or form submit button. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NOT_ON_SUBMIT_OR_LINK);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+ if ((links[curdoc.link].type == WWW_FORM_LINK_TYPE) &&
+ (!links[curdoc.link].form->submit_action ||
+ *links[curdoc.link].form->submit_action == '\0')) {
+ /*
+ * Form submit button with no ACTION defined. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_FORM_ACTION);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+#ifdef DIRED_SUPPORT
+ if (!strncmp(links[curdoc.link].lname,
+ "LYNXDIRED:", 10) ||
+ !strcmp(curdoc.address, LYDiredFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ DIRED_MENU_TITLE) ||
+ !strcmp(curdoc.address, LYPermitFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE) ||
+ !strcmp(curdoc.address, LYUploadFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE)) {
+ /*
+ * Disallow editing of File Management URLs. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(EDIT_FM_MENU_URLS_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+#endif /* DIRED_SUPPORT */
+
+ /*
+ * Save the current user_input_buffer string,
+ * and load the current link's address. - FM
+ */
+ StrAllocCopy(temp, user_input_buffer);
+ LYstrncpy(user_input_buffer,
+ ((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
+ ?
+ links[curdoc.link].form->submit_action : links[curdoc.link].lname),
+ (sizeof(user_input_buffer) - 1));
+
+ /*
+ * Offer the current link's URL for editing. - FM
+ */
+ _statusline(EDIT_CURLINK_URL);
+ if (((ch = LYgetstr(user_input_buffer, VISIBLE,
+ sizeof(user_input_buffer), RECALL)) >= 0) &&
+ user_input_buffer[0] != '\0' &&
+ strcmp(user_input_buffer,
+ ((links[curdoc.link].type == WWW_FORM_LINK_TYPE)
+ ? links[curdoc.link].form->submit_action
+ : links[curdoc.link].lname))) {
+ LYTrimHead(user_input_buffer);
+ if (!strncasecomp(user_input_buffer, "lynxexec:", 9) ||
+ !strncasecomp(user_input_buffer, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(user_input_buffer, " \r\n\t");
+ convert_to_spaces(user_input_buffer, TRUE);
+ } else {
+ collapse_spaces(user_input_buffer);
+ }
+ if (user_input_buffer[0] != '\0') {
+ goto check_goto_URL;
+ }
+ }
+ /*
+ * User cancelled via ^G, a full deletion,
+ * or not modifying the URL. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ break;
+
+ case LYK_ECGOTO: /* edit current URL and go to to it */
+ if (no_goto && !LYValidate) {
+ /*
+ * Go to not allowed. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(GOTO_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+#ifdef DIRED_SUPPORT
+ if (!strcmp(curdoc.address, LYDiredFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ DIRED_MENU_TITLE) ||
+ !strcmp(curdoc.address, LYPermitFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE) ||
+ !strcmp(curdoc.address, LYUploadFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE)) {
+ /*
+ * Disallow editing of File Management URLs. - FM
+ */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(EDIT_FM_MENU_URLS_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+#endif /* DIRED_SUPPORT */
+
+ /*
+ * Save the current user_input_buffer string,
+ * and load the current document's address.
+ */
+ StrAllocCopy(temp, user_input_buffer);
+ LYstrncpy(user_input_buffer,
+ curdoc.address,
+ (sizeof(user_input_buffer) - 1));
+
+ /*
+ * Warn the user if the current document has POST
+ * data associated with it. - FM
+ */
+ if (curdoc.post_data)
+ HTAlert(CURRENT_DOC_HAS_POST_DATA);
+
+ /*
+ * Offer the current document's URL for editing. - FM
+ */
+ _statusline(EDIT_CURDOC_URL);
+ if (((ch = LYgetstr(user_input_buffer, VISIBLE,
+ sizeof(user_input_buffer), RECALL)) >= 0) &&
+ user_input_buffer[0] != '\0' &&
+ strcmp(user_input_buffer, curdoc.address)) {
+ LYTrimHead(user_input_buffer);
+ if (!strncasecomp(user_input_buffer, "lynxexec:", 9) ||
+ !strncasecomp(user_input_buffer, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(user_input_buffer, " \r\n\t");
+ convert_to_spaces(user_input_buffer, TRUE);
+ } else {
+ collapse_spaces(user_input_buffer);
+ }
+ if (user_input_buffer[0] != '\0') {
+ goto check_goto_URL;
+ }
+ }
+ /*
+ * User cancelled via ^G, a full deletion,
+ * or not modifying the URL. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ break;
+
+ case LYK_GOTO: /* 'g' to goto a random URL */
+ if (no_goto && !LYValidate) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(GOTO_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ StrAllocCopy(temp, user_input_buffer);
+ if (!goto_buffer)
+ *user_input_buffer = '\0';
+
+ URLTotal = (Goto_URLs ? HTList_count(Goto_URLs) : 0);
+ if (goto_buffer && *user_input_buffer) {
+ recall = ((URLTotal > 1) ? RECALL : NORECALL);
+ URLNum = 0;
+ FirstURLRecall = FALSE;
+ } else {
+ recall = ((URLTotal >= 1) ? RECALL : NORECALL);
+ URLNum = URLTotal;
+ FirstURLRecall = TRUE;
+ }
+
+ /*
+ * Ask the user.
+ */
+ _statusline(URL_TO_OPEN);
+ if ((ch = LYgetstr(user_input_buffer, VISIBLE,
+ sizeof(user_input_buffer), recall)) < 0 ) {
+ /*
+ * User cancelled the Goto via ^G.
+ * Restore user_input_buffer and break. - FM
+ */
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+check_recall:
+ /*
+ * Get rid of leading spaces (and any other spaces).
+ */
+ LYTrimHead(user_input_buffer);
+ if (!strncasecomp(user_input_buffer, "lynxexec:", 9) ||
+ !strncasecomp(user_input_buffer, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes expected
+ * white space without hex escaping, and did not check
+ * for hex escaping, so we'll continue to support that,
+ * until that code is redone in conformance with SGML
+ * principles. - FM
+ */
+ HTUnEscapeSome(user_input_buffer, " \r\n\t");
+ convert_to_spaces(user_input_buffer, TRUE);
+ } else {
+ collapse_spaces(user_input_buffer);
+ }
+ if (*user_input_buffer == '\0' &&
+ !(recall && (ch == UPARROW || ch == DNARROW))) {
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ if (recall && ch == UPARROW) {
+ if (FirstURLRecall) {
+ /*
+ * Use last URL in the list. - FM
+ */
+ FirstURLRecall = FALSE;
+ URLNum = 0;
+ } else {
+ /*
+ * Go back to the previous URL in the list. - FM
+ */
+ URLNum++;
+ }
+ if (URLNum >= URLTotal)
+ /*
+ * Roll around to the last URL in the list. - FM
+ */
+ URLNum = 0;
+ if ((cp = (char *)HTList_objectAt(Goto_URLs,
+ URLNum)) != NULL) {
+ strcpy(user_input_buffer, cp);
+ if (goto_buffer && *temp &&
+ !strcmp(temp, user_input_buffer)) {
+ _statusline(EDIT_CURRENT_GOTO);
+ } else if ((goto_buffer && URLTotal == 2) ||
+ (!goto_buffer && URLTotal == 1)) {
+ _statusline(EDIT_THE_PREV_GOTO);
+ } else {
+ _statusline(EDIT_A_PREV_GOTO);
+ }
+ if ((ch = LYgetstr(user_input_buffer, VISIBLE,
+ sizeof(user_input_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the Goto via ^G.
+ * Restore user_input_buffer and break. - FM
+ */
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstURLRecall) {
+ /*
+ * Use the first URL in the list. - FM
+ */
+ FirstURLRecall = FALSE;
+ URLNum = URLTotal - 1;
+ } else {
+ /*
+ * Advance to the next URL in the list. - FM
+ */
+ URLNum--;
+ }
+ if (URLNum < 0)
+ /*
+ * Roll around to the first URL in the list. - FM
+ */
+ URLNum = URLTotal - 1;
+ if ((cp=(char *)HTList_objectAt(Goto_URLs,
+ URLNum)) != NULL) {
+ strcpy(user_input_buffer, cp);
+ if (goto_buffer && *temp &&
+ !strcmp(temp, user_input_buffer)) {
+ _statusline(EDIT_CURRENT_GOTO);
+ } else if ((goto_buffer && URLTotal == 2) ||
+ (!goto_buffer && URLTotal == 1)) {
+ _statusline(EDIT_THE_PREV_GOTO);
+ } else {
+ _statusline(EDIT_A_PREV_GOTO);
+ }
+ if ((ch = LYgetstr(user_input_buffer, VISIBLE,
+ sizeof(user_input_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the Goto via ^G.
+ * Restore user_input_buffer and break. - FM
+ */
+ strcpy(user_input_buffer, temp);
+ FREE(temp);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ goto check_recall;
+ }
+ }
+
+check_goto_URL:
+ /*
+ * If its not a URL then make it one.
+ */
+ StrAllocCopy(temp, user_input_buffer);
+ LYFillLocalFileURL((char **)&temp, "file://localhost");
+ LYEnsureAbsoluteURL((char **)&temp, "");
+ sprintf(user_input_buffer, "%.*s",
+ (int)(sizeof(user_input_buffer) - 1), temp);
+ FREE(temp);
+ if ((no_file_url || no_goto_file) &&
+ !strncmp(user_input_buffer,"file:",5)) {
+ _statusline(GOTO_FILE_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if ((no_shell || no_goto_lynxexec
+#ifdef EXEC_LINKS
+ || local_exec_on_local_files
+#endif /* EXEC_LINKS */
+ ) &&
+ !strncmp(user_input_buffer, "lynxexec:",9)) {
+ _statusline(GOTO_EXEC_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if ((no_shell || no_goto_lynxprog
+#ifdef EXEC_LINKS
+ || local_exec_on_local_files
+#endif /* EXEC_LINKS */
+ ) &&
+ !strncmp(user_input_buffer, "lynxprog:",9)) {
+ _statusline(GOTO_PROG_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if ((no_shell || no_goto_lynxcgi) &&
+ !strncmp(user_input_buffer, "lynxcgi:", 8)) {
+ _statusline(GOTO_CGI_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (LYValidate &&
+ strncmp(user_input_buffer, "http:", 5) &&
+ strncmp(user_input_buffer, "https:", 6)) {
+ _statusline(GOTO_NON_HTTP_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_cso &&
+ !strncmp(user_input_buffer, "cso:", 4)) {
+ _statusline(GOTO_CSO_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_finger &&
+ !strncmp(user_input_buffer, "finger:", 7)) {
+ _statusline(GOTO_FINGER_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_ftp &&
+ !strncmp(user_input_buffer, "ftp:", 4)) {
+ _statusline(GOTO_FTP_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_gopher &&
+ !strncmp(user_input_buffer, "gopher:", 7)) {
+ _statusline(GOTO_GOPHER_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_http &&
+ !strncmp(user_input_buffer, "http:", 5)) {
+ _statusline(GOTO_HTTP_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_https &&
+ !strncmp(user_input_buffer, "https:", 6)) {
+ _statusline(GOTO_HTTPS_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_mailto &&
+ !strncmp(user_input_buffer, "mailto:", 7)) {
+ _statusline(GOTO_MAILTO_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_news &&
+ !strncmp(user_input_buffer, "news:", 5)) {
+ _statusline(GOTO_NEWS_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_nntp &&
+ !strncmp(user_input_buffer, "nntp:", 5)) {
+ _statusline(GOTO_NNTP_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_rlogin &&
+ !strncmp(user_input_buffer, "rlogin:", 7)) {
+ _statusline(GOTO_RLOGIN_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_snews &&
+ !strncmp(user_input_buffer, "snews:", 6)) {
+ _statusline(GOTO_SNEWS_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_telnet &&
+ !strncmp(user_input_buffer, "telnet:", 7)) {
+ _statusline(GOTO_TELNET_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_tn3270 &&
+ !strncmp(user_input_buffer, "tn3270:", 7)) {
+ _statusline(GOTO_TN3270_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (no_goto_wais &&
+ !strncmp(user_input_buffer, "wais:", 5)) {
+ _statusline(GOTO_WAIS_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else if (!strncmp(user_input_buffer, "LYNXCOOKIE:", 11) ||
+ !strncmp(user_input_buffer, "LYNXDIRED:", 10) ||
+ !strncmp(user_input_buffer, "LYNXDOWNLOAD:", 13) ||
+ !strncmp(user_input_buffer, "LYNXPRINT:", 10)) {
+ _statusline(GOTO_SPECIAL_DISALLOWED);
+ sleep(MessageSecs);
+
+ } else {
+ StrAllocCopy(newdoc.address, user_input_buffer);
+ newdoc.isHEAD = FALSE;
+ /*
+ * Might be an anchor in the same doc from a POST
+ * form. If so, dont't free the content. -- FM
+ */
+ if (are_different(&curdoc, &newdoc)) {
+ /*
+ * Make a name for this new URL.
+ */
+ StrAllocCopy(newdoc.title, "A URL specified by the user");
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ force_load = TRUE;
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode)
+ HTuncache_current_document();
+#endif /* DIRED_SUPPORT */
+ }
+ LYUserSpecifiedURL = TRUE;
+ HTAddGotoURL(newdoc.address);
+ }
+ break;
+
+ case LYK_HELP: /* show help file */
+ if (!STREQ(curdoc.address, helpfile)) {
+ /*
+ * Set the filename.
+ */
+ StrAllocCopy(newdoc.address, helpfile);
+ /*
+ * Make a name for this help file.
+ */
+ StrAllocCopy(newdoc.title, "Help Screen");
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ }
+ break;
+
+ case LYK_INDEX: /* index file */
+ /*
+ * Make sure we are not in the index already.
+ */
+ if (!STREQ(curdoc.address, indexfile)) {
+
+ if (indexfile[0]=='\0') { /* no defined index */
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_INDEX_FILE);
+ sleep(MessageSecs);
+ }
+
+ } else {
+ StrAllocCopy(newdoc.address, indexfile);
+ StrAllocCopy(newdoc.title, "System Index"); /* name it */
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ } /* end else */
+ } /* end if */
+ break;
+
+#ifdef NOT_USED
+ case LYK_FORM_UP: /* change form */
+ break; /* not implemented */
+ if (lynx_mode == FORMS_LYNX_MODE) {
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
+ c = change_form_link(&links[curdoc.link],
+ FORM_UP, &newdoc, &refresh_screen,
+ links[curdoc.link].form->name,
+ links[curdoc.link].form->value);
+ /*
+ * Code to handle multiple submit buttons?
+ * Taken out due to bug it causes.
+ if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+ links[curdoc.link].form->type == F_IMAGESUBMIT_TYPE) {
+ curdoc.address = NULL;
+ }
+ */
+ goto new_keyboard_input;
+ } else {
+ _statusline("'X' can only toggle a form link");
+ }
+ } else {
+ _statusline("'X' only toggles in forms mode");
+ }
+ break;
+
+ case LYK_FORM_DOWN: /* change form */
+ break; /* not implemented */
+ if (lynx_mode==FORMS_LYNX_MODE) {
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
+ c = change_form_link(&links[curdoc.link],
+ FORM_DOWN,&newdoc,&refresh_screen,
+ links[curdoc.link].form->name,
+ links[curdoc.link].form->value);
+ goto new_keyboard_input;
+ } else {
+ _statusline("'Z' can only toggle a form link");
+ }
+ } else {
+ _statusline("'Z' only toggles in forms mode");
+ }
+ break;
+#endif /* NOT_USED */
+
+ case LYK_MAIN_MENU: /* return to main screen */
+ /*
+ * If its already the homepage then don't reload it.
+ */
+ if (!STREQ(curdoc.address,homepage)) {
+
+ _statusline(CONFIRM_MAIN_SCREEN);
+ c = LYgetch();
+ if (TOUPPER(c)=='Y') {
+ StrAllocCopy(newdoc.address, homepage);
+ StrAllocCopy(newdoc.title, "Entry into main screen");
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ highlight(OFF, curdoc.link, prev_target);
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode)
+ HTuncache_current_document();
+#endif /* DIRED_SUPPORT */
+ }
+#ifdef VMS
+ if (HadVMSInterrupt)
+ HadVMSInterrupt = FALSE;
+#endif /* VMS */
+ } else {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(IN_MAIN_SCREEN);
+ sleep(MessageSecs);
+ }
+ }
+ break;
+
+ case LYK_OPTIONS: /* options screen */
+#ifdef DIRED_SUPPORT
+ c = dir_list_style;
+#endif /* DIRED_SUPPORT */
+ options(); /* do the options stuff */
+
+ if (keypad_mode_flag != keypad_mode ||
+ (user_mode_flag != user_mode &&
+ (user_mode_flag == NOVICE_MODE ||
+ user_mode == NOVICE_MODE)) ||
+ (((HTfileSortMethod_flag != HTfileSortMethod) ||
+#ifdef DIRED_SUPPORT
+ (c != dir_list_style) ||
+#endif /* DIRED_SUPPORT */
+ (show_dotfiles_flag != show_dotfiles)) &&
+ (!strncmp(curdoc.address, "file:", 5) ||
+ !strncmp(curdoc.address, "ftp:", 4))) ||
+ CurrentCharSet_flag != current_char_set ||
+ LYRawMode_flag != LYRawMode ||
+ LYSelectPopups_flag != LYSelectPopups ||
+ ((strcmp(CurrentUserAgent, (LYUserAgent ?
+ LYUserAgent : "")) ||
+ strcmp(CurrentNegoLanguage, (language ?
+ language : "")) ||
+ strcmp(CurrentNegoCharset, (pref_charset ?
+ pref_charset : ""))) &&
+ (!strncmp(curdoc.address, "http", 4) ||
+ !strncmp(curdoc.address, "lynxcgi:", 8)))) {
+ /*
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation of reload if the safe element
+ * is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ confirm_post_resub(curdoc.address, curdoc.title,
+ 2, 1) == FALSE) {
+ _statusline(WILL_NOT_RELOAD_DOC);
+ sleep(InfoSecs);
+
+ } else {
+ StrAllocCopy(newdoc.address, curdoc.address);
+ if (((strcmp(CurrentUserAgent, (LYUserAgent ?
+ LYUserAgent : "")) ||
+ strcmp(CurrentNegoLanguage,
+ (language ? language : "")) ||
+ strcmp(CurrentNegoCharset,
+ (pref_charset ? pref_charset : ""))) &&
+ (strncmp(curdoc.address, "http", 4) == 0 ||
+ strncmp(curdoc.address, "lynxcgi:", 8) == 0))) {
+ /*
+ * An option has changed which may influence
+ * content negotiation, and the resource is from
+ * a http or https or lynxcgi URL (the only protocols
+ * which currently do anything with this information).
+ * Set reloading = TRUE so that proxy caches will be
+ * flushed, which is necessary until the time when
+ * all proxies understand HTTP 1.1 Vary: and all
+ * Servers properly use it... Treat like
+ * case LYK_RELOAD (see comments there). - KW
+ */
+ reloading = TRUE;
+ }
+ if (lynx_mode == FORMS_LYNX_MODE) {
+ _statusline(RELOADING_FORM);
+ sleep(AlertSecs);
+ }
+ if (HTisDocumentSource()) {
+ HTOutputFormat = WWW_SOURCE;
+ }
+ HEAD_request = HTLoadedDocumentIsHEAD();
+ HTuncache_current_document();
+#ifdef NO_ASSUME_SAME_DOC
+ newdoc.line = 1;
+ newdoc.link = 0;
+#else
+ newdoc.line = ((curdoc.line > 0) ?
+ curdoc.line : 1);
+ newdoc.link = ((curdoc.link > -1) ?
+ curdoc.link : 0);
+#endif /* NO_ASSUME_SAME_DOC */
+ LYforce_no_cache = TRUE;
+ FREE(curdoc.address); /* So it doesn't get pushed. */
+ }
+ }
+ keypad_mode_flag = keypad_mode;
+ user_mode_flag = user_mode;
+ HTfileSortMethod_flag = HTfileSortMethod;
+ CurrentCharSet_flag = current_char_set;
+ show_dotfiles_flag = show_dotfiles;
+ LYRawMode_flag = LYRawMode;
+ LYSelectPopups_flag = LYSelectPopups;
+ StrAllocCopy(CurrentUserAgent, (LYUserAgent ?
+ LYUserAgent : ""));
+ StrAllocCopy(CurrentNegoLanguage, (language ?
+ language : ""));
+ StrAllocCopy(CurrentNegoCharset, (pref_charset ?
+ pref_charset : ""));
+ refresh_screen = TRUE; /* to repaint screen */
+ break;
+
+ case LYK_INDEX_SEARCH: /* search for a user string */
+ if (is_www_index) {
+ /*
+ * Perform a database search.
+ *
+ * do_www_search will try to go out and get the document.
+ * If it returns TRUE, a new document was returned and is
+ * named in the newdoc.address.
+ */
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ if (do_www_search(&newdoc) == NORMAL) {
+ /*
+ * Yah, the search succeeded.
+ */
+ if (TRACE && !LYUseTraceLog && LYCursesON) {
+ /*
+ * Make sure cursor is down.
+ */
+ move(LYlines-1, LYcols-1);
+#ifdef USE_SLANG
+ addstr("\n");
+#endif /* USE_SLANG */
+ refresh();
+ }
+ LYpush(&curdoc, ForcePush);
+ /*
+ * Make the curdoc.address the newdoc.address so that
+ * getfile doesn't try to get the newdoc.address.
+ * Since we have already gotten it.
+ */
+ StrAllocCopy(curdoc.address, newdoc.address);
+ StrAllocCopy(newdoc.post_data, curdoc.post_data);
+ newdoc.internal_link = FALSE;
+ curdoc.line = -1;
+ Newline = 0;
+ refresh_screen = TRUE; /* redisplay it */
+ } else if (use_this_url_instead != NULL) {
+ /*
+ * Got back a redirecting URL. Check it out.
+ */
+ _user_message("Using %s", use_this_url_instead);
+ /*
+ * Make a name for this URL.
+ */
+ StrAllocCopy(newdoc.title,
+ "A URL specified by redirection");
+ StrAllocCopy(newdoc.address, use_this_url_instead);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ FREE(use_this_url_instead);
+ force_load = TRUE;
+ break;
+ } else {
+ /*
+ * Yuk, the search failed. Restore the old file.
+ */
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.post_data, curdoc.post_data);
+ StrAllocCopy(newdoc.post_content_type,
+ curdoc.post_content_type);
+ StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+ newdoc.isHEAD = curdoc.isHEAD;
+ newdoc.safe = curdoc.safe;
+ newdoc.internal_link = curdoc.internal_link;
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NOT_ISINDEX);
+ sleep(MessageSecs);
+ }
+ break;
+
+ case LYK_WHEREIS: /* search within the document */
+ case LYK_NEXT: /* search for the next occurrence in the document */
+ /* user search */
+ {
+ BOOLEAN have_target_onscreen = (*prev_target != '\0' &&
+ HText_pageHasPrevTarget());
+ BOOL found;
+ int oldcur = curdoc.link; /* temporarily remember */
+ char *remember_old_target = NULL;
+ if (have_target_onscreen)
+ StrAllocCopy(remember_old_target, prev_target);
+ else
+ StrAllocCopy(remember_old_target, "");
+
+ if (cmd != LYK_NEXT) {
+ /*
+ * Reset prev_target to force prompting
+ * for a new search string and to turn
+ * off highlighting in no search string
+ * is entered by the user.
+ */
+ *prev_target = '\0';
+ found = textsearch(&curdoc, prev_target, FALSE);
+ } else {
+ /*
+ * When the third argument is TRUE, the previous
+ * search string, if any, will be recalled from
+ * a buffer, loaded into prev_target, and used
+ * for the search without prompting for a new
+ * search string. This allows the LYK_NEXT
+ * command to repeat a search in a new document,
+ * after prev_target was reset on fetch of that
+ * document.
+ */
+ found = textsearch(&curdoc, prev_target, TRUE);
+ }
+
+ /*
+ * Force a redraw to ensure highlighting of hits
+ * even when found on the same page, or clearing
+ * of highlighting is the default search string
+ * was erased without replacement. - FM
+ */
+ /*
+ ** Well let's try to avoid it at least in a few cases
+ ** where it is not needed. - kw
+ */
+ if (www_search_result >= 0 && www_search_result != curdoc.line) {
+ refresh_screen = TRUE; /* doesn't really matter */
+ } else if (!found) {
+ refresh_screen = have_target_onscreen;
+ } else if (!have_target_onscreen && found) {
+ refresh_screen = TRUE;
+ } else if (www_search_result == curdoc.line &&
+ curdoc.link == oldcur &&
+ curdoc.link >= 0 && nlinks > 0 &&
+ links[curdoc.link].ly >= (display_lines/3)) {
+ refresh_screen = TRUE;
+ } else if ((case_sensitive && 0!=strcmp(prev_target,
+ remember_old_target)) ||
+ (!case_sensitive && 0!=strcasecomp8(prev_target,
+ remember_old_target))) {
+ refresh_screen = TRUE;
+ }
+ FREE(remember_old_target);
+ }
+ break;
+
+ case LYK_COMMENT: /* reply by mail */
+ if (!owner_address &&
+ strncasecomp(curdoc.address, "http", 4)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_OWNER);
+ sleep(MessageSecs);
+ }
+ } else if (no_mail) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(MAIL_DISALLOWED);
+ sleep(MessageSecs);
+ }
+ } else {
+ _statusline(CONFIRM_COMMENT);
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ if (!owner_address) {
+ /*
+ * No owner defined, so make a guess and
+ * and offer it to the user. - FM
+ */
+ char *address = NULL;
+ temp = HTParse(curdoc.address, "", PARSE_PATH);
+
+ if (temp != NULL) {
+ HTUnEscape(temp);
+ if (*temp == '~' && strlen(temp) > 1) {
+ /*
+ * It's a ~user URL so guess user@host. - FM
+ */
+ if ((cp = strchr((temp+1), '/')) != NULL)
+ *cp = '\0';
+ StrAllocCopy(address, "mailto:");
+ StrAllocCat(address, (temp+1));
+ StrAllocCat(address, "@");
+ }
+ FREE(temp);
+ }
+ if (address == NULL)
+ /*
+ * Wasn't a ~user URL so guess WebMaster@host. - FM
+ */
+ StrAllocCopy(address, "mailto:WebMaster@");
+ temp = HTParse(curdoc.address, "", PARSE_HOST);
+ StrAllocCat(address, temp);
+ FREE(temp);
+ _user_message(NO_OWNER_USE, address);
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ StrAllocCopy(owner_address, address);
+ FREE(address);
+ } else {
+ FREE(address);
+ break;
+ }
+ }
+ if (is_url(owner_address) != MAILTO_URL_TYPE) {
+ /*
+ * The address is a URL. Just follow the link.
+ */
+ StrAllocCopy(newdoc.address, owner_address);
+ newdoc.internal_link = FALSE;
+ } else {
+ /*
+ * The owner_address is a mailto: URL.
+ */
+ cp = HText_getRevTitle();
+ if (strchr(owner_address,':')!=NULL)
+ /*
+ * Send a reply. The address is after the colon.
+ */
+ reply_by_mail(strchr(owner_address,':')+1,
+ curdoc.address,
+ (cp ? cp : ""));
+ else
+ reply_by_mail(owner_address, curdoc.address,
+ (cp ? cp : ""));
+
+ refresh_screen = TRUE; /* to force a showpage */
+ }
+ }
+ }
+ break;
+
+#ifdef DIRED_SUPPORT
+ case LYK_TAG_LINK: /* tag or untag the current link */
+ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
+ if (!strcmp(links[curdoc.link].hightext, ".."))
+ break; /* Never tag the parent directory */
+ if (dir_list_style == MIXED_STYLE) {
+ if (!strcmp(links[curdoc.link].hightext, "../"))
+ break;
+ } else if (!strncmp(links[curdoc.link].hightext, "Up to ", 6))
+ break;
+ {
+ /*
+ * HTList-based management of tag list, see LYLocal.c - KW
+ */
+ HTList * t1 = tagged;
+ char * tagname = NULL;
+ BOOLEAN found = FALSE;
+
+ while ((tagname = (char *)HTList_nextObject(t1)) != NULL) {
+ if (!strcmp(links[curdoc.link].lname, tagname)) {
+ found = TRUE;
+ HTList_removeObject(tagged, tagname);
+ FREE(tagname);
+ tagflag(OFF,curdoc.link);
+ break;
+ }
+ }
+ if (!found) {
+ if (tagged == NULL)
+ tagged = HTList_new();
+ tagname = NULL;
+ StrAllocCopy(tagname,links[curdoc.link].lname);
+ HTList_addObject(tagged,tagname);
+ tagflag(ON,curdoc.link);
+ }
+ }
+ if (curdoc.link < nlinks-1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link++;
+ } else if (!more && Newline == 1 && curdoc.link == nlinks-1) {
+ highlight(OFF, curdoc.link, prev_target);
+ curdoc.link = 0;
+ } else if (more) { /* next page */
+ Newline += (display_lines);
+ }
+ }
+ break;
+
+ case LYK_MODIFY: /* rename a file or directory */
+ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
+ int ret;
+
+ ret = local_modify(&curdoc, &newdoc.address);
+ if (ret == PERMIT_FORM_RESULT) { /* Permit form thrown up */
+ refresh_screen = TRUE;
+ } else if (ret) {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+ clear();
+ }
+ }
+ break;
+
+ case LYK_CREATE: /* create a new file or directory */
+ if (lynx_edit_mode && !no_dired_support) {
+ if (local_create(&curdoc)) {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link > -1 ? curdoc.link : 0;
+ clear();
+ }
+ }
+ break;
+#endif /* DIRED_SUPPORT */
+
+ case LYK_EDIT: /* edit */
+ if (no_editor) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(EDIT_DISABLED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+#ifdef DIRED_SUPPORT
+ /*
+ * Allow the user to edit the link rather
+ * than curdoc in edit mode.
+ */
+ if (lynx_edit_mode &&
+ editor && *editor != '\0' && !no_dired_support) {
+ if (nlinks > 0) {
+ cp = links[curdoc.link].lname;
+ if (is_url(cp) == FILE_URL_TYPE) {
+ if (!strncmp(cp, "file://localhost", 16)) {
+ /*
+ * This is the only case that should occur. - kw
+ */
+ StrAllocCopy(tp, cp + 16);
+ } else if (!strncmp(cp, "file:", 5)) {
+ StrAllocCopy(tp, cp + 5);
+ } else {
+ StrAllocCopy(tp, cp);
+ }
+ HTUnEscape(tp);
+ if (stat(tp, &dir_info) == -1) {
+ _statusline(NO_STATUS);
+ sleep(AlertSecs);
+ } else {
+ if (((dir_info.st_mode) & S_IFMT) == S_IFREG) {
+ StrAllocCopy(tp, cp);
+ HTUnEscapeSome(tp, "/");
+ if (edit_current_file(tp,
+ curdoc.link, Newline)) {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address,
+ curdoc.address);
+ FREE(curdoc.address);
+#ifdef NO_SEEK_OLD_POSITION
+ /*
+ * Go to top of file.
+ */
+ newdoc.line = 1;
+ newdoc.link = 0;
+#else
+ /*
+ * Seek old position,
+ * which probably changed.
+ */
+ newdoc.line =
+ ((curdoc.line > 0) ? curdoc.line : 1);
+ newdoc.link =
+ ((curdoc.link > -1) ? curdoc.link : 0);
+#endif /* NO_SEEK_OLD_POSITION */
+ clear(); /* clear the screen */
+ }
+ }
+ }
+ FREE(tp);
+ }
+ }
+ } else
+#endif /* DIRED_SUPPORT */
+ if (editor && *editor != '\0') {
+ if (edit_current_file(newdoc.address, curdoc.link, Newline)) {
+ HTuncache_current_document();
+ LYforce_no_cache = TRUE; /*force reload of document */
+ FREE(curdoc.address); /* so it doesn't get pushed */
+#ifdef NO_SEEK_OLD_POSITION
+ /*
+ * Go to top of file.
+ */
+ newdoc.line = 1;
+ newdoc.link = 0;
+#else
+ /*
+ * Seek old position, which probably changed.
+ */
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+#endif /* NO_SEEK_OLD_POSITION */
+ clear(); /* clear the screen */
+ }
+
+ } else {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_EDITOR);
+ sleep(MessageSecs);
+ }
+ }
+ break;
+
+ case LYK_DEL_BOOKMARK: /* remove a bookmark file link */
+#ifdef DIRED_SUPPORT
+ case LYK_REMOVE: /* remove files and directories */
+ c = 'N';
+ if (lynx_edit_mode && nlinks > 0 && !no_dired_support) {
+ local_remove(&curdoc);
+ c = 'Y';
+ } else
+#endif /* DIRED_SUPPORT */
+ if (curdoc.bookmark != NULL) {
+ _statusline(CONFIRM_BOOKMARK_DELETE);
+ c = LYgetch();
+ if (TOUPPER(c) != 'Y')
+ break;
+ remove_bookmark_link(links[curdoc.link].anchor_number-1,
+ curdoc.bookmark);
+ } else { /* behave like REFRESH for backward compatibility */
+ refresh_screen = TRUE;
+ if (old_c != real_c) {
+ old_c = real_c;
+ lynx_force_repaint();
+ }
+ break;
+ }
+ if (TOUPPER(c) == 'Y') {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ FREE(curdoc.address);
+ newdoc.line = curdoc.line;
+ if (curdoc.link == nlinks-1) {
+ /*
+ * We deleted the last link on the page. - FM
+ */
+ newdoc.link = curdoc.link-1;
+ } else {
+ newdoc.link = curdoc.link;
+ }
+ }
+ break;
+
+#ifdef DIRED_SUPPORT
+ case LYK_INSTALL: /* install a file into system area */
+ if (lynx_edit_mode && nlinks > 0 && !no_dired_support)
+ local_install(NULL, links[curdoc.link].lname, &newdoc.address);
+ break;
+#endif /* DIRED_SUPPORT */
+
+ case LYK_INFO: /* show document info */
+ /*
+ * Don't do if already viewing info page.
+ */
+ if (strcmp((curdoc.title ? curdoc.title : ""),
+ SHOWINFO_TITLE)) {
+ if (!showinfo(&curdoc, lines_in_file,
+ &newdoc, owner_address))
+ break;
+ StrAllocCopy(newdoc.title, SHOWINFO_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ LYforce_no_cache = TRUE;
+ if (LYValidate || check_realm)
+ LYPermitURL = TRUE;
+ } else {
+ /*
+ * If already in info page, get out.
+ */
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+ break;
+
+ case LYK_PRINT: /* print the file */
+ if (LYValidate) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(PRINT_DISABLED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * Don't do if already viewing print options page.
+ */
+ if (strcmp((curdoc.title ? curdoc.title : ""),
+ PRINT_OPTIONS_TITLE)) {
+
+ if (print_options(&newdoc.address, lines_in_file) < 0)
+ break;
+ StrAllocCopy(newdoc.title, PRINT_OPTIONS_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ ForcePush = TRUE;
+ if (check_realm)
+ LYPermitURL = TRUE;
+ refresh_screen = TRUE; /* redisplay */
+ }
+ break;
+
+ case LYK_LIST: /* list links in the current document */
+ /*
+ * Don't do if already viewing list page.
+ */
+ if (!strcmp((curdoc.title ? curdoc.title : ""),
+ LIST_PAGE_TITLE)) {
+ /*
+ * Already viewing list page, so get out.
+ */
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+
+ /*
+ * Print list page to file.
+ */
+ if (showlist(&newdoc, TRUE) < 0)
+ break;
+ StrAllocCopy(newdoc.title, LIST_PAGE_TITLE);
+ /*
+ * showlist will set newdoc's other fields. It may leave
+ * post_data intact so the list can be used to follow
+ * internal links in the current document even if it is
+ * a POST response. - kw
+ */
+
+ refresh_screen = TRUE; /* redisplay */
+ if (LYValidate || check_realm) {
+ LYPermitURL = TRUE;
+ StrAllocCopy(lynxlistfile, newdoc.address);
+ }
+ break;
+
+ case LYK_VLINKS: /* list links visited during the current session */
+ if (!strcmp((curdoc.title ? curdoc.title : ""),
+ VISITED_LINKS_TITLE)) {
+ /*
+ * Already viewing visited links page, so get out.
+ */
+ cmd = LYK_PREV_DOC;
+ goto new_cmd;
+ }
+
+ /*
+ * Print visited links page to file.
+ */
+ if (LYShowVisitedLinks(&newdoc.address) < 0) {
+ _statusline(VISITED_LINKS_EMPTY);
+ sleep(MessageSecs);
+ break;
+ }
+ StrAllocCopy(newdoc.title, VISITED_LINKS_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ refresh_screen = TRUE;
+ if (LYValidate || check_realm) {
+ LYPermitURL = TRUE;
+ StrAllocCopy(lynxlinksfile, newdoc.address);
+ }
+ break;
+
+ case LYK_TOOLBAR: /* go to Toolbar or Banner in current document */
+ if (!HText_hasToolbar(HTMainText)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_TOOLBAR);
+ sleep(MessageSecs);
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ if ((cp = strchr(curdoc.address, '#')) != NULL)
+ *cp = '\0';
+ toolbar = (char *)malloc(strlen(curdoc.address) +
+ strlen(LYToolbarName) + 2);
+ sprintf(toolbar, "%s#%s", curdoc.address, LYToolbarName);
+ if (cp)
+ *cp = '#';
+ StrAllocCopy(newdoc.address, toolbar);
+ FREE(toolbar);
+ try_internal = TRUE;
+ force_load = TRUE; /* force MainLoop to reload */
+ }
+ break;
+
+#if defined(DIRED_SUPPORT) || defined(VMS)
+ case LYK_DIRED_MENU: /* provide full file management menu */
+#ifdef VMS
+ /*
+ * Check if the CSwing Directory/File Manager is available.
+ * Will be disabled if LYCSwingPath is NULL, zero-length,
+ * or "none" (case insensitive), if no_file_url was set via
+ * the file_url restriction, if no_goto_file was set for
+ * the anonymous account, or if HTDirAccess was set to
+ * HT_DIR_FORBID or HT_DIR_SELECTIVE via the -nobrowse
+ * or -selective switches. - FM
+ */
+ if (!(LYCSwingPath && *LYCSwingPath) ||
+ !strcasecomp(LYCSwingPath, "none") ||
+ no_file_url || no_goto_file ||
+ HTDirAccess == HT_DIR_FORBID ||
+ HTDirAccess == HT_DIR_SELECTIVE) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(DFM_NOT_AVAILABLE);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * If we are viewing a local directory listing or a
+ * local file which is not temporary, invoke CSwing
+ * with the URL's directory converted to VMS path specs
+ * and passed as the argument, so we start up CSwing
+ * positioned on that node of the directory tree.
+ * Otherwise, pass the current default directory as
+ * the argument. - FM
+ */
+ if (LYisLocalFile(curdoc.address) &&
+ strncasecomp(curdoc.address,
+ lynx_temp_space, strlen(lynx_temp_space))) {
+ /*
+ * We are viewing a local directory or a local file
+ * which is not temporary. - FM
+ */
+ struct stat stat_info;
+
+ cp = HTParse(curdoc.address, "", PARSE_PATH|PARSE_PUNCTUATION);
+ HTUnEscape(cp);
+ if (HTStat(cp, &stat_info) == -1) {
+ if (TRACE)
+ fprintf(stderr, "mainloop: Can't stat %s\n", cp);
+ FREE(cp);
+ temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4));
+ if (temp == NULL)
+ outofmem(__FILE__, "mainloop");
+ sprintf(temp, "%s []", LYCSwingPath);
+ refresh_screen = TRUE; /* redisplay */
+ } else {
+ char *VMSdir = NULL;
+
+ if (((stat_info.st_mode) & S_IFMT) == S_IFDIR) {
+ /*
+ * We're viewing a local directory. Make
+ * that the CSwing argument. - FM
+ */
+ if (cp[(strlen(cp) - 1)] != '/')
+ StrAllocCat(cp, "/");
+ StrAllocCopy(VMSdir, HTVMS_name("", cp));
+ FREE(cp);
+ } else {
+ /*
+ * We're viewing a local file. Make it's
+ * directory the CSwing argument. - FM
+ */
+ StrAllocCopy(VMSdir, HTVMS_name("", cp));
+ FREE(cp);
+ if ((cp = strrchr(VMSdir, ']')) != NULL) {
+ *(cp + 1) = '\0';
+ cp == NULL;
+ } else if ((cp = strrchr(VMSdir, ':')) != NULL) {
+ *(cp + 1) = '\0';
+ cp == NULL;
+ }
+ }
+ temp = (char *)calloc(1,
+ (strlen(LYCSwingPath) +
+ strlen(VMSdir) +
+ 2));
+ if (temp == NULL)
+ outofmem(__FILE__, "mainloop");
+ sprintf(temp, "%s %s", LYCSwingPath, VMSdir);
+ FREE(VMSdir);
+ /*
+ * Uncache the current document in case we
+ * change, move, or delete it during the
+ * CSwing session. - FM
+ */
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.title,
+ curdoc.title ? curdoc.title : "");
+ StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+ FREE(curdoc.address);
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+ }
+ } else {
+ /*
+ * We're not viewing a local directory or file.
+ * Pass CSwing the current default directory as
+ * an argument and don't uncache the current
+ * document. - FM
+ */
+ temp = (char *)calloc(1, (strlen(LYCSwingPath) + 4));
+ if (temp == NULL)
+ outofmem(__FILE__, "mainloop");
+ sprintf(temp, "%s []", LYCSwingPath);
+ refresh_screen = TRUE; /* redisplay */
+ }
+ stop_curses();
+ system(temp);
+ start_curses();
+ FREE(temp);
+ break;
+#else
+ /*
+ * Don't do if not allowed or already viewing the menu.
+ */
+ if (lynx_edit_mode && !no_dired_support &&
+ strcmp(curdoc.address, LYDiredFileURL) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ DIRED_MENU_TITLE)) {
+ dired_options(&curdoc,&newdoc.address);
+ refresh_screen = TRUE; /* redisplay */
+ }
+ break;
+#endif /* VMS */
+#endif /* DIRED_SUPPORT || VMS*/
+
+#ifdef USE_EXTERNALS
+ case LYK_EXTERN: /* use external program on url */
+ run_external(links[curdoc.link].lname);
+ refresh_screen = TRUE;
+ break;
+#endif /* USE_EXTERNALS */
+
+ case LYK_ADD_BOOKMARK: /* add link to bookmark file */
+ if (LYValidate) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(BOOKMARKS_DISABLED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ if (strcmp((curdoc.title ? curdoc.title : ""),
+ HISTORY_PAGE_TITLE) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ SHOWINFO_TITLE) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ PRINT_OPTIONS_TITLE) &&
+#ifdef DIRED_SUPPORT
+ strcmp(curdoc.address, LYDiredFileURL) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ DIRED_MENU_TITLE) &&
+ strcmp(curdoc.address, LYPermitFileURL) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE) &&
+ strcmp(curdoc.address, LYUploadFileURL) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE) &&
+#endif /* DIRED_SUPPORT */
+ strcmp((curdoc.title ? curdoc.title : ""),
+ DOWNLOAD_OPTIONS_TITLE) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ COOKIE_JAR_TITLE) &&
+ ((nlinks <= 0) ||
+ (links[curdoc.link].lname != NULL &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXHIST:", 9) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXPRINT:", 10) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXDIRED:", 10) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXDOWNLOAD:", 13) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXCOOKIE:", 11) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXLIST:", 9)))) {
+ if (nlinks > 0) {
+ if (curdoc.post_data == NULL &&
+ curdoc.bookmark == NULL &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ LIST_PAGE_TITLE) &&
+ strcmp((curdoc.title ? curdoc.title : ""),
+ VISITED_LINKS_TITLE)) {
+ /*
+ * The document doesn't have POST content,
+ * and is not a bookmark file, nor is the
+ * list or visited links page, so we can
+ * save either that or the link. - FM
+ */
+ _statusline(BOOK_D_L_OR_CANCEL);
+ c = LYgetch();
+ if (TOUPPER(c) == 'D') {
+ save_bookmark_link(curdoc.address, curdoc.title);
+ refresh_screen = TRUE; /* MultiBookmark support */
+ goto check_add_bookmark_to_self;
+ }
+ } else {
+ if (LYMultiBookmarks == FALSE &&
+ curdoc.bookmark != NULL &&
+ strstr(curdoc.address,
+ (*bookmark_page == '.'
+ ?
+ (bookmark_page+1) : bookmark_page)) != NULL) {
+ /*
+ * If multiple bookmarks are disabled, offer
+ * the L)ink or C)ancel, but with wording
+ * which indicates that the link already
+ * exists in this bookmark file. - FM
+ */
+ _statusline(MULTIBOOKMARKS_SELF);
+ } else if (curdoc.post_data != NULL &&
+ links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
+ /*
+ * Internal link, and document has POST content.
+ */
+ _statusline(NOBOOK_POST_FORM);
+ sleep(MessageSecs);
+ break;
+ } else {
+ /*
+ * Only offer the link in a document with
+ * POST content, or if the current document
+ * is a bookmark file and multiple bookmarks
+ * are enabled. - FM
+ */
+ _statusline(BOOK_L_OR_CANCEL);
+ }
+ c = LYgetch();
+ }
+ if (TOUPPER(c) == 'L') {
+ if (curdoc.post_data != NULL &&
+ links[curdoc.link].type == WWW_INTERN_LINK_TYPE) {
+ /*
+ * Internal link, and document has POST content.
+ */
+ _statusline(NOBOOK_POST_FORM);
+ sleep(MessageSecs);
+ break;
+ }
+ /*
+ * User does want to save the link. - FM
+ */
+ if (links[curdoc.link].type != WWW_FORM_LINK_TYPE) {
+ save_bookmark_link(links[curdoc.link].lname,
+ links[curdoc.link].hightext);
+ refresh_screen = TRUE; /* MultiBookmark support */
+ } else {
+ _statusline(NOBOOK_FORM_FIELD);
+ sleep(MessageSecs);
+ break;
+ }
+ } else {
+ break;
+ }
+ } else if (curdoc.post_data != NULL) {
+ /*
+ * No links, and document has POST content. - FM
+ */
+ _statusline(NOBOOK_POST_FORM);
+ sleep(MessageSecs);
+ break;
+ } else if (curdoc.bookmark != NULL) {
+ /*
+ * It's a bookmark file from which all
+ * of the links were deleted. - FM
+ */
+ _statusline(BOOKMARKS_NOLINKS);
+ sleep(MessageSecs);
+ break;
+ } else {
+ _statusline(BOOK_D_OR_CANCEL);
+ c = LYgetch();
+ if (TOUPPER(c) == 'D') {
+ save_bookmark_link(curdoc.address, curdoc.title);
+ refresh_screen = TRUE; /* MultiBookmark support */
+ } else {
+ break;
+ }
+ }
+check_add_bookmark_to_self:
+ if (curdoc.bookmark && BookmarkPage &&
+ !strcmp(curdoc.bookmark, BookmarkPage)) {
+ HTuncache_current_document();
+ StrAllocCopy(newdoc.address, curdoc.address);
+ StrAllocCopy(newdoc.bookmark, curdoc.bookmark);
+ FREE(curdoc.address);
+ newdoc.line = curdoc.line;
+ newdoc.link = curdoc.link;
+ newdoc.internal_link = FALSE;
+ }
+ FREE(temp);
+ } else {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NOBOOK_HSML);
+ sleep(MessageSecs);
+ }
+ }
+ break;
+
+ case LYK_VIEW_BOOKMARK: /* v to view home page */
+ if (LYValidate) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(BOOKMARKS_DISABLED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * See if a bookmark exists.
+ * If it does replace newdoc.address with it's name.
+ */
+ if ((cp = get_bookmark_filename(&newdoc.address)) != NULL) {
+ if (*cp == '\0' || !strcmp(cp, " ") ||
+ !strcmp(curdoc.address, newdoc.address)) {
+ if (LYMultiBookmarks == TRUE)
+ refresh_screen = TRUE;
+ break;
+ }
+ LYforce_no_cache = TRUE; /*force the document to be reloaded*/
+ StrAllocCopy(newdoc.title, BOOKMARK_TITLE);
+ StrAllocCopy(newdoc.bookmark, BookmarkPage);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ } else {
+ if (old_c != real_c) {
+ old_c = real_c;
+ LYMBM_statusline(BOOKMARKS_NOT_OPEN);
+ sleep(AlertSecs);
+ if (LYMultiBookmarks == TRUE) {
+ refresh_screen = TRUE;
+ }
+ }
+ }
+ break;
+
+ case LYK_SHELL: /* shell escape */
+ if (!no_shell) {
+ stop_curses();
+ printf(SPAWNING_MSG);
+ fflush(stdout);
+ fflush(stderr);
+ if (LYTraceLogFP)
+ /*
+ * Set stderr back to its original value
+ * during the shell escape. - FM
+ */
+ *stderr = LYOrigStderr;
+#ifdef DOSPATH
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(0);
+ _go32_want_ctrl_break(1);
+#endif /* __DJGPP__ */
+ if (getenv("SHELL") != NULL) {
+ system(getenv("SHELL"));
+ } else {
+ system(getenv("COMSPEC") == NULL ? "command.com" : getenv("COMSPEC"));
+ }
+#ifdef __DJGPP__
+ __djgpp_set_ctrl_c(1);
+ _go32_want_ctrl_break(0);
+#endif /* __DJGPP__ */
+#else
+#ifdef VMS
+ system("");
+#else
+ system("exec $SHELL");
+#endif /* VMS */
+#endif /* DOSPATH */
+ if (LYTraceLogFP)
+ /*
+ * Set stderr back to the log file on
+ * return from the shell escape. - FM
+ */
+ *stderr = *LYTraceLogFP;
+ start_curses();
+ refresh_screen = TRUE; /* for an HText_pageDisplay() */
+ } else {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(SPAWNING_DISABLED);
+ sleep(MessageSecs);
+ }
+ }
+ break;
+
+ case LYK_DOWNLOAD:
+ /*
+ * Don't do if both download and disk_save are restricted.
+ */
+ if (LYValidate ||
+ (no_download && !override_no_download && no_disk_save)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(DOWNLOAD_DISABLED);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+
+ /*
+ * Don't do if already viewing download options page.
+ */
+ if (!strcmp((curdoc.title ? curdoc.title : ""),
+ DOWNLOAD_OPTIONS_TITLE))
+ break;
+
+ if (nlinks > 0) {
+ if (links[curdoc.link].type == WWW_FORM_LINK_TYPE) {
+ if (links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+ links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE) {
+ if (links[curdoc.link].form->submit_method ==
+ URL_MAIL_METHOD) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_MAILTO_ACTION);
+ sleep(MessageSecs);
+ }
+ break;
+ }
+ HTOutputFormat = HTAtom_for("www/download");
+ LYforce_no_cache = TRUE;
+ cmd = LYK_ACTIVATE;
+ goto new_cmd;
+ }
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_INPUT);
+ sleep(MessageSecs);
+ }
+
+ } else if (!strcmp((curdoc.title ? curdoc.title : ""),
+ COOKIE_JAR_TITLE)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_COOKIES);
+ sleep(MessageSecs);
+ }
+
+ } else if (!strcmp((curdoc.title ? curdoc.title : ""),
+ PRINT_OPTIONS_TITLE)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_PRINT_OP);
+ sleep(MessageSecs);
+ }
+
+#ifdef DIRED_SUPPORT
+ } else if (!strcmp(curdoc.address, LYUploadFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_UPLOAD_OP);
+ sleep(MessageSecs);
+ }
+
+ } else if (!strcmp(curdoc.address, LYPermitFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ PERMIT_OPTIONS_TITLE)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_PERMIT_OP);
+ sleep(MessageSecs);
+ }
+
+ } else if (lynx_edit_mode && !no_dired_support) {
+ /*
+ * Don't bother making a /tmp copy of the local file.
+ */
+ StrAllocCopy(temp, newdoc.address);
+ StrAllocCopy(newdoc.address, links[curdoc.link].lname);
+ if (LYdownload_options(&newdoc.address,
+ links[curdoc.link].lname) < 0)
+ StrAllocCopy(newdoc.address, temp);
+ else
+ newdoc.internal_link = FALSE;
+ FREE(temp);
+#endif /* DIRED_SUPPORT */
+
+ } else if (!strcmp((curdoc.title ? curdoc.title : ""),
+ HISTORY_PAGE_TITLE) &&
+ !strncmp(links[curdoc.link].lname, "LYNXHIST:", 9)) {
+ int number = atoi(links[curdoc.link].lname+9);
+ if ((history[number].post_data != NULL &&
+ history[number].safe != TRUE) &&
+ HTConfirm(CONFIRM_POST_RESUBMISSION) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ StrAllocCopy(newdoc.address, history[number].address);
+ StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
+ StrAllocCopy(newdoc.bookmark, history[number].bookmark);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ if (history[number].post_data)
+ StrAllocCopy(newdoc.post_data,
+ history[number].post_data);
+ if (history[number].post_content_type)
+ StrAllocCopy(newdoc.post_content_type,
+ history[number].post_content_type);
+ newdoc.isHEAD = history[number].isHEAD;
+ newdoc.safe = history[number].safe;
+ newdoc.internal_link = FALSE;
+ newdoc.link = 0;
+ HTOutputFormat = HTAtom_for("www/download");
+ LYUserSpecifiedURL = TRUE;
+ /*
+ * Force the document to be reloaded.
+ */
+ LYforce_no_cache = TRUE;
+
+ } else if (!strncmp(links[curdoc.link].lname, "data:", 5)) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ HTAlert(UNSUPPORTED_DATA_URL);
+ }
+
+ } else if (!strncmp(links[curdoc.link].lname,
+ "LYNXCOOKIE:", 11) ||
+ !strncmp(links[curdoc.link].lname,
+ "LYNXDIRED:", 10) ||
+ !strncmp(links[curdoc.link].lname,
+ "LYNXDOWNLOAD:", 13) ||
+ !strncmp(links[curdoc.link].lname,
+ "LYNXPRINT:", 10) ||
+ !strncmp(links[curdoc.link].lname,
+ "lynxexec:", 9) ||
+ !strncmp(links[curdoc.link].lname,
+ "lynxprog:", 9)) {
+ _statusline(NO_DOWNLOAD_SPECIAL);
+ sleep(MessageSecs);
+
+ } else { /* Not a forms, options or history link */
+ /*
+ * Follow a normal link or anchor. Note that
+ * if it's an anchor within the same document,
+ * entire document will be downloaded.
+ */
+ StrAllocCopy(newdoc.address, links[curdoc.link].lname);
+ StrAllocCopy(newdoc.title, links[curdoc.link].hightext);
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ /*
+ * Might be an internal link in the same doc from a
+ * POST form. If so, don't free the content. - kw
+ */
+ if (links[curdoc.link].type != WWW_INTERN_LINK_TYPE)
+#else
+ /*
+ * Might be an anchor in the same doc from a POST
+ * form. If so, don't free the content. -- FM
+ */
+ if (are_different(&curdoc, &newdoc))
+#endif /* TRACK_INTERNAL_LINKS */
+ {
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ }
+ newdoc.internal_link = FALSE;
+ newdoc.link = 0;
+ HTOutputFormat = HTAtom_for("www/download");
+ /*
+ * Force the document to be reloaded.
+ */
+ LYforce_no_cache = TRUE;
+ }
+ } else if (old_c != real_c) {
+ old_c = real_c;
+ _statusline(NO_DOWNLOAD_CHOICE);
+ sleep(MessageSecs);
+ }
+ break;
+
+#ifdef DIRED_SUPPORT
+ case LYK_UPLOAD:
+ /*
+ * Don't do if already viewing upload options page.
+ */
+ if (!strcmp(curdoc.address, LYUploadFileURL) ||
+ !strcmp((curdoc.title ? curdoc.title : ""),
+ UPLOAD_OPTIONS_TITLE))
+ break;
+
+ if (lynx_edit_mode && !no_dired_support) {
+ LYUpload_options((char **)&newdoc.address,
+ (char *)curdoc.address);
+ StrAllocCopy(newdoc.title, UPLOAD_OPTIONS_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ /*
+ * Uncache the current listing so that it will
+ * be updated to included the uploaded file if
+ * placed in the current directory. - FM
+ */
+ HTuncache_current_document();
+ }
+ break;
+#endif /* DIRED_SUPPORT */
+
+ case LYK_TRACE_TOGGLE: /* Toggle TRACE mode. */
+ if (WWW_TraceFlag)
+ WWW_TraceFlag = FALSE;
+ else
+ WWW_TraceFlag = TRUE;
+
+ _statusline(WWW_TraceFlag ? TRACE_ON : TRACE_OFF);
+ sleep(MessageSecs);
+
+ if (TRACE && LYUseTraceLog && LYTraceLogFP == NULL) {
+ /*
+ * We haven't yet started a TRACE log for this
+ * session. If we can't open the file with write
+ * access, turn off TRACE and give up. Otherwise,
+ * on VMS we'll close it and delete it and any
+ * log file from a previous session, so they don't
+ * accumulate, and then open it again, including
+ * "shr=get" to overcome open file locking when
+ * attempting to read the log via the TRACE_LOG
+ * command. - FM
+ */
+ if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag = FALSE;
+ _statusline(TRACELOG_OPEN_FAILED);
+ sleep(MessageSecs);
+ break;
+ }
+#ifdef VMS
+ fclose(LYTraceLogFP);
+ while (remove(LYTraceLogPath) == 0)
+ ;
+ if ((LYTraceLogFP = LYNewTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag == FALSE;
+ _statusline(TRACELOG_OPEN_FAILED);
+ sleep(MessageSecs);
+ break;
+ }
+#endif /* VMS */
+ *stderr = *LYTraceLogFP;
+ fprintf(stderr, "\t\t%s\n\n", LYNX_TRACELOG_TITLE);
+ }
+ break;
+
+ case LYK_TRACE_LOG: /* View TRACE log. */
+ /*
+ * Check whether we've started a TRACE log
+ * in this session. - FM
+ */
+ if (LYTraceLogFP == NULL) {
+ _statusline(NO_TRACELOG_STARTED);
+ sleep(MessageSecs);
+ break;
+ }
+
+ /*
+ * Don't do if already viewing the TRACE log. - FM
+ */
+ if (!strcmp((curdoc.title ? curdoc.title : ""),
+ LYNX_TRACELOG_TITLE))
+ break;
+
+ /*
+ * If TRACE mode is on, turn it off during this fetch of the
+ * TRACE log, so we don't enter stuff about this fetch, and
+ * set a flag for turning it back on when we return to this
+ * loop. Note that we'll miss any messages about memory
+ * exhaustion if it should occur. It seems unlikely that
+ * anything else bad might happen, but if it does, we'll
+ * miss messages about that too. We also fflush(), close,
+ * and open it again, to make sure all stderr messages thus
+ * far will be in the log. - FM
+ */
+ if (TRACE)
+ fprintf(stderr, "\nTurning off TRACE for fetch of log.\n");
+ fflush(stdout);
+ fflush(stderr);
+ fclose(LYTraceLogFP);
+ *stderr = LYOrigStderr;
+ if ((LYTraceLogFP = LYAppendToTxtFile(LYTraceLogPath)) == NULL) {
+ WWW_TraceFlag = FALSE;
+ _statusline(TRACELOG_OPEN_FAILED);
+ sleep(MessageSecs);
+ break;
+ }
+ *stderr = *LYTraceLogFP;
+ if (TRACE) {
+ WWW_TraceFlag = FALSE;
+ trace_mode_flag = TRUE;
+ }
+ StrAllocCopy(newdoc.address, "file://localhost");
+#ifdef VMS
+ StrAllocCat(newdoc.address, HTVMS_wwwName(LYTraceLogPath));
+#else
+ StrAllocCat(newdoc.address, LYTraceLogPath);
+#endif /* VMS */
+ StrAllocCopy(newdoc.title, LYNX_TRACELOG_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ if (LYValidate || check_realm) {
+ LYPermitURL = TRUE;
+ }
+ LYforce_no_cache = TRUE;
+ break;
+
+ case LYK_IMAGE_TOGGLE:
+ if (clickable_images)
+ clickable_images = FALSE;
+ else
+ clickable_images = TRUE;
+
+ _statusline(clickable_images ?
+ CLICKABLE_IMAGES_ON : CLICKABLE_IMAGES_OFF);
+ sleep(MessageSecs);
+ cmd = LYK_RELOAD;
+ goto new_cmd;
+ break;
+
+ case LYK_INLINE_TOGGLE:
+ if (pseudo_inline_alts)
+ pseudo_inline_alts = FALSE;
+ else
+ pseudo_inline_alts = TRUE;
+
+ _statusline(pseudo_inline_alts ?
+ PSEUDO_INLINE_ALTS_ON : PSEUDO_INLINE_ALTS_OFF);
+ sleep(MessageSecs);
+ cmd = LYK_RELOAD;
+ goto new_cmd;
+ break;
+
+ case LYK_RAW_TOGGLE:
+ if (LYUseDefaultRawMode)
+ LYUseDefaultRawMode = FALSE;
+ else
+ LYUseDefaultRawMode = TRUE;
+ _statusline(LYRawMode ? RAWMODE_OFF : RAWMODE_ON);
+ HTMLSetCharacterHandling(current_char_set);
+ LYRawMode_flag = LYRawMode;
+ sleep(MessageSecs);
+ cmd = LYK_RELOAD;
+ goto new_cmd;
+ break;
+
+ case LYK_HEAD:
+ if (nlinks > 0 &&
+ (links[curdoc.link].type != WWW_FORM_LINK_TYPE ||
+ links[curdoc.link].form->type == F_SUBMIT_TYPE ||
+ links[curdoc.link].form->type == F_IMAGE_SUBMIT_TYPE)) {
+ /*
+ * We have links, and the current link is a
+ * normal link or a form's submit button. - FM
+ */
+ _statusline(HEAD_D_L_OR_CANCEL);
+ c = LYgetch();
+ if (TOUPPER(c) == 'D') {
+ char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
+ curdoc.address : curdoc.address + 11;
+ if (LYCanDoHEAD(scheme) != TRUE) {
+ _statusline(DOC_NOT_HTTP_URL);
+ sleep(MessageSecs);
+ } else {
+ /*
+ * Check if this is a reply from a POST,
+ * and if so, seek confirmation if the
+ * safe element is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ HEAD_request = TRUE;
+ LYforce_no_cache = TRUE;
+ StrAllocCopy(newdoc.title, curdoc.title);
+ if (HTLoadedDocumentIsHEAD()) {
+ HTuncache_current_document();
+ FREE(curdoc.address);
+ } else {
+ StrAllocCat(newdoc.title, " - HEAD");
+ }
+ }
+ break;
+ } else if (TOUPPER(c) == 'L') {
+ if (links[curdoc.link].type != WWW_FORM_LINK_TYPE &&
+ strncmp(links[curdoc.link].lname, "http", 4) &&
+ strncmp(links[curdoc.link].lname,
+ "LYNXIMGMAP:http", 15) &&
+ LYCanDoHEAD(links[curdoc.link].lname) != TRUE &&
+ (links[curdoc.link].type != WWW_INTERN_LINK_TYPE ||
+ !curdoc.address ||
+ strncmp(curdoc.address, "http", 4))) {
+ _statusline(LINK_NOT_HTTP_URL);
+ sleep(MessageSecs);
+ } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->disabled) {
+ _statusline(FORM_ACTION_DISABLED);
+ sleep(MessageSecs);
+ } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ strncmp(links[curdoc.link].form->submit_action,
+ "lynxcgi:", 8) &&
+ strncmp(links[curdoc.link].form->submit_action,
+ "http", 4)) {
+ _statusline(FORM_ACTION_NOT_HTTP_URL);
+ sleep(MessageSecs);
+ } else if (links[curdoc.link].type == WWW_FORM_LINK_TYPE &&
+ links[curdoc.link].form->submit_method ==
+ URL_POST_METHOD &&
+ HTConfirm(CONFIRM_POST_LINK_HEAD) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ } else {
+ HEAD_request = TRUE;
+ LYforce_no_cache = TRUE;
+ cmd = LYK_ACTIVATE;
+ goto new_cmd;
+ }
+ break;
+ }
+ break;
+ } else {
+ /*
+ * We can offer only this document for a HEAD request.
+ * Check if this is a reply from a POST, and if so,
+ * seek confirmation if the safe element is not set. - FM
+ */
+ if ((curdoc.post_data != NULL &&
+ curdoc.safe != TRUE) &&
+ HTConfirm(CONFIRM_POST_DOC_HEAD) == FALSE) {
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ break;
+ } else if (nlinks > 0) {
+ /*
+ * The current link is a non-submittable form
+ * link, so prompt the user to make it clear
+ * that the HEAD request would be for the
+ * current document, not the form link. - FM
+ */
+ _statusline(HEAD_D_OR_CANCEL);
+ c = LYgetch();
+ } else {
+ /*
+ * No links, so we can just assume that
+ * the user wants a HEAD request for the
+ * current document. - FM
+ */
+ c = 'D';
+ }
+ if (TOUPPER(c) == 'D') {
+ char *scheme = strncmp(curdoc.address, "LYNXIMGMAP:", 11) ?
+ curdoc.address : curdoc.address + 11;
+ /*
+ * The user didn't cancel, so check if
+ * a HEAD request is appropriate for the
+ * current document. - FM
+ */
+ if (LYCanDoHEAD(scheme) != TRUE) {
+ _statusline(DOC_NOT_HTTP_URL);
+ sleep(MessageSecs);
+ } else {
+ HEAD_request = TRUE;
+ LYforce_no_cache = TRUE;
+ StrAllocCopy(newdoc.title, curdoc.title);
+ if (HTLoadedDocumentIsHEAD()) {
+ HTuncache_current_document();
+ FREE(curdoc.address);
+ } else {
+ StrAllocCat(newdoc.title, " - HEAD");
+ }
+ }
+ }
+ }
+ break;
+
+ case LYK_TOGGLE_HELP:
+ if (user_mode == NOVICE_MODE) {
+ toggle_novice_line();
+ noviceline(more);
+ }
+ break;
+
+ case LYK_KEYMAP:
+ if (old_c != real_c) {
+ old_c = real_c;
+ StrAllocCopy(newdoc.address, "LYNXKEYMAP:");
+ StrAllocCopy(newdoc.title, CURRENT_KEYMAP_TITLE);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ /*
+ * If vi_keys changed, the keymap did too,
+ * so force no cache, and reset the flag. - FM
+ */
+ if (vi_keys_flag != vi_keys ||
+ emacs_keys_flag != emacs_keys) {
+ LYforce_no_cache = TRUE;
+ vi_keys_flag = vi_keys;
+ emacs_keys_flag = emacs_keys;
+ }
+#if defined(DIRED_SUPPORT) && defined(OK_OVERRIDE)
+ /*
+ * Remember whether we are in dired menu
+ * so we can display the right keymap.
+ */
+ if (!no_dired_support) {
+ prev_lynx_edit_mode = lynx_edit_mode;
+ }
+#endif /* DIRED_SUPPORT && OK_OVERRIDE */
+ LYforce_no_cache = TRUE;
+ }
+ break;
+
+ case LYK_JUMP:
+ {
+ char *ret;
+
+ if (no_jump || JThead == NULL) {
+ if (old_c != real_c) {
+ old_c = real_c;
+ if (no_jump)
+ _statusline(JUMP_DISALLOWED);
+ else
+ _statusline(NO_JUMPFILE);
+ sleep(MessageSecs);
+ }
+ } else {
+ LYJumpFileURL = TRUE;
+ if ((ret = LYJump(c)) != NULL) {
+#ifdef PERMIT_GOTO_FROM_JUMP
+ if (!strncasecomp(ret, "Go ", 3)) {
+ LYJumpFileURL = FALSE;
+ StrAllocCopy(temp, user_input_buffer);
+ URLTotal = (Goto_URLs ?
+ HTList_count(Goto_URLs) : 0);
+ recall = ((URLTotal >= 1) ? RECALL : NORECALL);
+ URLNum = URLTotal;
+ FirstURLRecall = TRUE;
+ if (!strcasecomp(ret, "Go :")) {
+ if (recall) {
+ ch = UPARROW;
+ goto check_recall;
+ }
+ FREE(temp);
+ statusline(NO_RANDOM_URLS_YET);
+ sleep(MessageSecs);
+ break;
+ }
+ ret = HTParse((ret+3), startfile, PARSE_ALL);
+ strcpy(user_input_buffer, ret);
+ FREE(ret);
+ goto check_recall;
+ }
+#endif /* PERMIT_GOTO_FROM_JUMP */
+ ret = HTParse(ret, startfile, PARSE_ALL);
+ LYTrimHead(ret);
+ if (!strncasecomp(ret, "lynxexec:", 9) ||
+ !strncasecomp(ret, "lynxprog:", 9)) {
+ /*
+ * The original implementations of these schemes
+ * expected white space without hex escaping,
+ * and did not check for hex escaping, so we'll
+ * continue to support that, until that code is
+ * redone in conformance with SGML principles.
+ * - FM
+ */
+ HTUnEscapeSome(ret, " \r\n\t");
+ convert_to_spaces(ret, TRUE);
+ } else {
+ collapse_spaces(user_input_buffer);
+ }
+ StrAllocCopy(newdoc.address, ret);
+ StrAllocCopy(lynxjumpfile, ret);
+ FREE(newdoc.post_data);
+ FREE(newdoc.post_content_type);
+ FREE(newdoc.bookmark);
+ newdoc.isHEAD = FALSE;
+ newdoc.safe = FALSE;
+ newdoc.internal_link = FALSE;
+ FREE(ret);
+ LYUserSpecifiedURL = TRUE;
+ } else {
+ LYJumpFileURL = FALSE;
+ }
+ }
+ }
+ break;
+
+ case LYK_CLEAR_AUTH:
+ if (old_c != real_c) {
+ old_c = real_c;
+ if (HTConfirm(CLEAR_ALL_AUTH_INFO)) {
+ FREE(authentication_info[0]);
+ FREE(authentication_info[1]);
+ FREE(proxyauth_info[0]);
+ FREE(proxyauth_info[1]);
+ HTClearHTTPAuthInfo();
+ HTClearNNTPAuthInfo();
+ HTClearFTPPassword();
+ _statusline(AUTH_INFO_CLEARED);
+ } else {
+ _statusline(CANCELLED);
+ }
+ sleep(MessageSecs);
+ }
+ break;
+
+#ifdef NOT_USED
+ case LYK_VERSION:
+ if (old_c != real_c) {
+ char version[128];
+ old_c = real_c;
+ sprintf(version, "*** %s Version %s ***",
+ LYNX_NAME, LYNX_VERSION);
+ statusline(version);
+ sleep(AlertMessage);
+ }
+ break;
+#endif /* NOT_USED */
+
+ case LYK_DO_NOTHING: /* pretty self explanatory */
+ break;
+
+ } /* end of BIG switch */
+ }
+}
+
+/*
+ * Ask a post resubmission prompt with some indication of what would
+ * be resubmitted, useful especially for going backward in history.
+ * Try to use parts of the address or, if given, the title, depending
+ * on how much fits on the statusline.
+ * if_imgmap and if_file indicate how to handle an address that is
+ * a "LYNXIMGMAP:", or a "file:" URL (presumably the List Page file),
+ * respectively: 0: auto-deny, 1: auto-confirm, 2: prompt.
+ * - kw
+ */
+
+PRIVATE BOOL confirm_post_resub ARGS4(
+ CONST char*, address,
+ CONST char*, title,
+ int, if_imgmap,
+ int, if_file)
+{
+ size_t len1;
+ CONST char *msg = CONFIRM_POST_RESUBMISSION_TO;
+ char buf[240];
+ char *temp = NULL;
+ BOOL res;
+ size_t maxlen = LYcols - 6;
+ if (!address) {
+ return(NO);
+ } else if (!strncmp(address, "LYNXIMGMAP:", 11)) {
+ if (if_imgmap <= 0)
+ return(NO);
+ else if (if_imgmap == 1)
+ return(YES);
+ else
+ msg = CONFIRM_POST_LIST_RELOAD;
+ } else if (!strncmp(address, "file:", 5)) {
+ if (if_file <= 0)
+ return(NO);
+ else if (if_file == 1)
+ return(YES);
+ else
+ msg = CONFIRM_POST_LIST_RELOAD;
+ } else if (dump_output_immediately) {
+ return(NO);
+ }
+ if (maxlen >= sizeof(buf))
+ maxlen = sizeof(buf) - 1;
+ if ((len1 = strlen(msg)) +
+ strlen(address) <= maxlen) {
+ sprintf(buf, msg, address);
+ return HTConfirm(buf);
+ }
+ if (len1 + strlen(temp = HTParse(address, "",
+ PARSE_ACCESS+PARSE_HOST+PARSE_PATH
+ +PARSE_PUNCTUATION)) <= maxlen) {
+ sprintf(buf, msg, temp);
+ res = HTConfirm(buf);
+ FREE(temp);
+ return(res);
+ }
+ FREE(temp);
+ if (title && (len1 + strlen(title) <= maxlen)) {
+ sprintf(buf, msg, title);
+ return HTConfirm(buf);
+ }
+ if (len1 + strlen(temp = HTParse(address, "",
+ PARSE_ACCESS+PARSE_HOST
+ +PARSE_PUNCTUATION)) <= maxlen) {
+ sprintf(buf, msg, temp);
+ res = HTConfirm(buf);
+ FREE(temp);
+ return(res);
+ }
+ FREE(temp);
+ if ((temp = HTParse(address, "", PARSE_HOST)) && *temp &&
+ len1 + strlen(temp) <= maxlen) {
+ sprintf(buf, msg, temp);
+ res = HTConfirm(buf);
+ FREE(temp);
+ return(res);
+ }
+ FREE(temp);
+ return HTConfirm(CONFIRM_POST_RESUBMISSION);
+}
+
+PRIVATE int are_different ARGS2(
+ document *, doc1,
+ document *, doc2)
+{
+ char *cp1, *cp2;
+
+ /*
+ * Do we have two addresses?
+ */
+ if (!doc1->address || !doc2->address)
+ return (TRUE);
+
+ /*
+ * Do they differ in the type of request?
+ */
+ if (doc1->isHEAD != doc2->isHEAD)
+ return (TRUE);
+
+ /*
+ * See if the addresses are different, making sure
+ * we're not tripped up by multiple anchors in the
+ * the same document from a POST form. -- FM
+ */
+ if ((cp1 = strchr(doc1->address, '#')) != NULL)
+ *cp1 = '\0';
+ if ((cp2 = strchr(doc2->address, '#')) != NULL)
+ *cp2 = '\0';
+ /*
+ * Are the base addresses different?
+ */
+ if (strcmp(doc1->address, doc2->address))
+ {
+ if (cp1)
+ *cp1 = '#';
+ if (cp2)
+ *cp2 = '#';
+ return(TRUE);
+ }
+ if (cp1)
+ *cp1 = '#';
+ if (cp2)
+ *cp2 = '#';
+
+ /*
+ * Do the docs have different contents?
+ */
+ if (doc1->post_data)
+ {
+ if (doc2->post_data)
+ {
+ if (strcmp(doc1->post_data, doc2->post_data))
+ return(TRUE);
+ }
+ else
+ return(TRUE);
+ }
+ else
+ if (doc2->post_data)
+ return(TRUE);
+
+ /*
+ * We'll assume the two documents in fact are the same.
+ */
+ return(FALSE);
+}
+
+/* This determines whether two docs are _physically_ different,
+ * meaning they are "from different files". - kw
+ */
+#ifndef DONT_TRACK_INTERNAL_LINKS
+PRIVATE int are_phys_different ARGS2(
+ document *, doc1,
+ document *, doc2)
+{
+ char *cp1, *cp2, *ap1 = doc1->address, *ap2 = doc2->address;
+
+ /*
+ * Do we have two addresses?
+ */
+ if (!doc1->address || !doc2->address)
+ return (TRUE);
+
+ /*
+ * Do they differ in the type of request?
+ */
+ if (doc1->isHEAD != doc2->isHEAD)
+ return (TRUE);
+
+ /*
+ * Skip over possible LYNXIMGMAP parts. - kw
+ */
+ if (0==strncmp(doc1->address, "LYNXIMGMAP:", 11))
+ ap1 += 11;
+ if (0==strncmp(doc2->address, "LYNXIMGMAP:", 11))
+ ap2 += 11;
+ /*
+ * If there isn't any real URL in doc2->address, but maybe just
+ * a fragment, doc2 is assumed to be an internal reference in
+ * the same physical document, so return FALSE. - kw
+ */
+ if (*ap2 == '\0' || *ap2 == '#')
+ return(FALSE);
+
+ /*
+ * See if the addresses are different, making sure
+ * we're not tripped up by multiple anchors in the
+ * the same document from a POST form. -- FM
+ */
+ if ((cp1 = strchr(doc1->address, '#')) != NULL)
+ *cp1 = '\0';
+ if ((cp2 = strchr(doc2->address, '#')) != NULL)
+ *cp2 = '\0';
+ /*
+ * Are the base addresses different?
+ */
+ if (strcmp(ap1, ap2))
+ {
+ if (cp1)
+ *cp1 = '#';
+ if (cp2)
+ *cp2 = '#';
+ return(TRUE);
+ }
+ if (cp1)
+ *cp1 = '#';
+ if (cp2)
+ *cp2 = '#';
+
+ /*
+ * Do the docs have different contents?
+ */
+ if (doc1->post_data)
+ {
+ if (doc2->post_data)
+ {
+ if (strcmp(doc1->post_data, doc2->post_data))
+ return(TRUE);
+ }
+ else
+ return(TRUE);
+ }
+ else
+ if (doc2->post_data)
+ return(TRUE);
+
+ /*
+ * We'll assume the two documents in fact are the same.
+ */
+ return(FALSE);
+}
+#endif
+
+/*
+ * Utility for freeing the list of goto URLs. - FM
+ */
+PUBLIC void HTGotoURLs_free NOARGS
+{
+ char *url;
+ HTList *cur = Goto_URLs;
+
+ if (!cur)
+ return;
+
+ while (NULL != (url = (char *)HTList_nextObject(cur))) {
+ FREE(url);
+ }
+ HTList_delete(Goto_URLs);
+ Goto_URLs = NULL;
+ return;
+}
+
+/*
+ * Utility for listing Goto URLs, making any
+ * repeated URLs the most current in the list. - FM
+ */
+PUBLIC void HTAddGotoURL ARGS1(
+ char *, url)
+{
+ char *new;
+ char *old;
+ HTList *cur;
+
+ if (!(url && *url))
+ return;
+
+ if ((new = (char *)calloc(1, (strlen(url) + 1))) == NULL)
+ outofmem(__FILE__, "HTAddGotoURL");
+ strcpy(new, url);
+
+ if (!Goto_URLs) {
+ Goto_URLs = HTList_new();
+ atexit(HTGotoURLs_free);
+ HTList_addObject(Goto_URLs, new);
+ return;
+ }
+
+ cur = Goto_URLs;
+ while (NULL != (old = (char *)HTList_nextObject(cur))) {
+ if (!strcmp(old, new)) {
+ HTList_removeObject(Goto_URLs, old);
+ FREE(old);
+ break;
+ }
+ }
+ HTList_addObject(Goto_URLs, new);
+
+ return;
+}
diff --git a/gnu/usr.bin/lynx/src/LYMainLoop.h b/gnu/usr.bin/lynx/src/LYMainLoop.h
new file mode 100644
index 00000000000..b3a5bd99635
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMainLoop.h
@@ -0,0 +1,7 @@
+
+#ifndef LYMAINLOOP_H
+#define LYMAINLOOP_H
+
+extern int mainloop NOPARAMS;
+
+#endif /* LYMAINLOOP_H */
diff --git a/gnu/usr.bin/lynx/src/LYMap.c b/gnu/usr.bin/lynx/src/LYMap.c
new file mode 100644
index 00000000000..618bf368a0e
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMap.c
@@ -0,0 +1,590 @@
+/* Lynx Client-side Image MAP Support LYMap.c
+** ==================================
+**
+** Author: FM Foteos Macrides (macrides@sci.wfbr.edu)
+**
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTTP.h"
+#include "HTAnchor.h"
+#include "HTAccess.h"
+#include "HTFormat.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "LYUtils.h"
+#include "LYMap.h"
+#include "GridText.h"
+#include "LYSignal.h"
+#include "LYGlobalDefs.h"
+#include "LYKeymap.h"
+#include "LYCharUtils.h"
+
+#ifdef DIRED_SUPPORT
+#include "LYUpload.h"
+#include "LYLocal.h"
+#endif
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x=NULL;}
+
+typedef struct _LYMapElement {
+ char * address;
+ char * title;
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ BOOL intern_flag;
+#endif
+} LYMapElement;
+
+typedef struct _LYImageMap {
+ char * address;
+ char * title;
+ HTList * elements;
+} LYImageMap;
+
+struct _HTStream
+{
+ HTStreamClass * isa;
+};
+
+PRIVATE HTList * LynxMaps = NULL;
+
+PUBLIC BOOL LYMapsOnly = FALSE;
+
+/*
+ * Utility for freeing a list of MAPs.
+ */
+PUBLIC void ImageMapList_free ARGS1(
+ HTList *, theList)
+{
+ LYImageMap *map;
+ LYMapElement *element;
+ HTList *cur = theList;
+ HTList *current;
+
+ if (!cur)
+ return;
+
+ while (NULL != (map = (LYImageMap *)HTList_nextObject(cur))) {
+ FREE(map->address);
+ FREE(map->title);
+ if (map->elements) {
+ current = map->elements;
+ while (NULL !=
+ (element = (LYMapElement *)HTList_nextObject(current))) {
+ FREE(element->address);
+ FREE(element->title);
+ FREE(element);
+ }
+ HTList_delete(map->elements);
+ map->elements = NULL;
+ }
+ FREE(map);
+ }
+ HTList_delete(theList);
+ return;
+}
+
+/*
+ * Utility for freeing the global list of MAPs. - kw
+ */
+PRIVATE void LYLynxMaps_free NOARGS
+{
+ ImageMapList_free(LynxMaps);
+ LynxMaps = NULL;
+ return;
+}
+
+/*
+ * We keep two kinds of lists:
+ * - A global list (LynxMaps) shared by MAPs from all documents that
+ * do not have POST data.
+ * - For each response to a POST which contains MAPs, a list specific
+ * to this combination of URL and post_data. It is kept in the
+ * HTParentAnchor structure and is freed when the document is removed
+ * from memory, in the course of normal removal of anchors.
+ * MAPs from POST responses can only be accessed via internal links,
+ * i.e. from within the same document (with the same post_data).
+ * The notion of "same document" is extended, so that LYNXIMGMAP:
+ * and List Page screens are logically part of the document on which
+ * they are based. - kw
+ *
+ * If DONT_TRACK_INTERNAL_LINKS is defined, only the global list will
+ * be used for all MAPs.
+ *
+ */
+
+/*
+ * Utility for creating an LYImageMap list, if it doesn't
+ * exist already, adding LYImageMap entry structures if needed, and
+ * removing any LYMapElements in a pre-existing LYImageMap entry so that
+ * it will have only those from AREA tags for the current analysis of
+ * MAP element content. - FM
+ */
+PUBLIC BOOL LYAddImageMap ARGS3(
+ char *, address,
+ char *, title,
+ HTParentAnchor *, node_anchor)
+{
+ LYImageMap *new = NULL;
+ LYImageMap *old = NULL;
+ HTList *cur = NULL;
+ HTList *theList = NULL;
+ HTList *curele = NULL;
+ LYMapElement *ele = NULL;
+
+ if (!(address && *address))
+ return FALSE;
+ if (!(node_anchor && node_anchor->address))
+ return FALSE;
+
+ /*
+ * Set theList to either the global LynxMaps list or, if we
+ * are associated with post data, the specific list. The
+ * list is created if it doesn't already exist. - kw
+ */
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (node_anchor->post_data) {
+ /*
+ * We are handling a MAP element found while parsing
+ * node_anchor's stream of data, and node_anchor has
+ * post_data associated and should therefore represent
+ * a POST response, so use the specific list. - kw
+ */
+ theList = node_anchor->imaps;
+ if (!theList) {
+ theList = node_anchor->imaps = HTList_new();
+ }
+ } else
+#endif
+ {
+ if (!LynxMaps) {
+ LynxMaps = HTList_new();
+ atexit(LYLynxMaps_free);
+ }
+ theList = LynxMaps;
+ }
+
+ if (theList) {
+ cur = theList;
+ while (NULL != (old = (LYImageMap *)HTList_nextObject(cur))) {
+ if (!strcmp(old->address, address)) {
+ FREE(old->address);
+ FREE(old->title);
+ if (old->elements) {
+ curele = old->elements;
+ while (NULL !=
+ (ele = (LYMapElement *)HTList_nextObject(curele))) {
+ FREE(ele->address);
+ FREE(ele->title);
+ FREE(ele);
+ }
+ HTList_delete(old->elements);
+ old->elements = NULL;
+ }
+ break;
+ }
+ }
+ }
+
+ new = (old != NULL) ?
+ old : (LYImageMap *)calloc(1, sizeof(LYImageMap));
+ if (new == NULL) {
+ perror("Out of memory in LYAddImageMap");
+ return FALSE;
+ }
+ StrAllocCopy(new->address, address);
+ if (title && *title)
+ StrAllocCopy(new->title, title);
+ if (new != old)
+ HTList_addObject(theList, new);
+ return TRUE;
+}
+
+/*
+ * Utility for adding LYMapElements to LYImageMaps
+ * in the appropriate list. - FM
+ */
+PUBLIC BOOL LYAddMapElement ARGS5(
+ char *, map,
+ char *, address,
+ char *, title,
+ HTParentAnchor *, node_anchor,
+ BOOL, intern_flag)
+{
+ LYMapElement *new = NULL;
+ LYImageMap *theMap = NULL;
+ HTList *theList = NULL;
+ HTList *cur = NULL;
+
+ if (!(map && *map && address && *address))
+ return FALSE;
+ if (!(node_anchor && node_anchor->address))
+ return FALSE;
+
+ /*
+ * Set theList to either the global LynxMaps list or, if we
+ * are associated with post data, the specific list. The
+ * list should already exist, since this function is only called
+ * if the AREA tag we are handling was within a MAP element
+ * in node_anchor's stream of data, so that LYAddImageMap has
+ * been called. - kw
+ */
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (node_anchor->post_data) {
+ /*
+ * We are handling an AREA tag found while parsing
+ * node_anchor's stream of data, and node_anchor has
+ * post_data associated and should therefore represent
+ * a POST response, so use the specific list. - kw
+ */
+ theList = node_anchor->imaps;
+ if (!theList)
+ return FALSE;
+ } else
+#endif
+ {
+ if (!LynxMaps)
+ LYAddImageMap(map, NULL, node_anchor);
+ theList = LynxMaps;
+ }
+
+ cur = theList;
+ while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
+ if (!strcmp(theMap->address, map)) {
+ break;
+ }
+ }
+ if (!theMap)
+ return FALSE;
+ if (!theMap->elements)
+ theMap->elements = HTList_new();
+ cur = theMap->elements;
+ while (NULL != (new = (LYMapElement *)HTList_nextObject(cur))) {
+ if (!strcmp(new->address, address)) {
+ FREE(new->address);
+ FREE(new->title);
+ HTList_removeObject(theMap->elements, new);
+ FREE(new);
+ break;
+ }
+ }
+
+ new = (LYMapElement *)calloc(1, sizeof(LYMapElement));
+ if (new == NULL) {
+ perror("Out of memory in LYAddMapElement");
+ return FALSE;
+ }
+ StrAllocCopy(new->address, address);
+ if (title && *title)
+ StrAllocCopy(new->title, title);
+ else
+ StrAllocCopy(new->title, address);
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ new->intern_flag = intern_flag;
+#endif
+ HTList_appendObject(theMap->elements, new);
+ return TRUE;
+}
+
+/*
+ * Utility for checking whether an LYImageMap entry
+ * with a given address already exists in the LynxMaps
+ * structure. - FM
+ */
+PUBLIC BOOL LYHaveImageMap ARGS1(
+ char *, address)
+{
+ LYImageMap *Map;
+ HTList *cur = LynxMaps;
+
+ if (!(cur && address && *address != '\0'))
+ return FALSE;
+
+ while (NULL != (Map = (LYImageMap *)HTList_nextObject(cur))) {
+ if (!strcmp(Map->address, address)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Fills in a DocAddress structure for getting the HTParentAnchor of
+ * the underlying resource. ALso returns a pointer to that anchor in
+ * *punderlying if we are dealing with POST data. - kw
+ *
+ * address is the address of the underlying resource, i.e. the one
+ * containing the MAP element, the MAP's name appended as
+ * fragment is ignored.
+ * anAnchor is the LYNXIMGMAP: anchor; if it is associated with POST
+ * data, we want the specific list, otherwise the global list.
+ */
+PRIVATE void fill_DocAddress ARGS4(
+ DocAddress *, wwwdoc,
+ char *, address,
+ HTParentAnchor *, anAnchor,
+ HTParentAnchor **, punderlying)
+{
+ HTParentAnchor * underlying;
+ if (anAnchor && anAnchor->post_data) {
+ wwwdoc->address = address;
+ wwwdoc->post_data = anAnchor->post_data;
+ wwwdoc->post_content_type = anAnchor->post_content_type;
+ wwwdoc->bookmark = NULL;
+ wwwdoc->isHEAD = FALSE;
+ wwwdoc->safe = FALSE;
+ underlying = HTAnchor_parent(HTAnchor_findAddress(wwwdoc));
+ if (underlying->safe)
+ wwwdoc->safe = TRUE;
+ if (punderlying)
+ *punderlying = underlying;
+ } else {
+ wwwdoc->address = address;
+ wwwdoc->post_data = NULL;
+ wwwdoc->post_content_type = NULL;
+ wwwdoc->bookmark = NULL;
+ wwwdoc->isHEAD = FALSE;
+ wwwdoc->safe = FALSE;
+ if (punderlying)
+ *punderlying = NULL;
+ }
+}
+
+/*
+ * Get the appropriate list for creating a LYNXIMGMAP: pseudo-
+ * document: either the global list (LynxMaps), or the specific
+ * list if a List Page for a POST response is requested. Also
+ * fill in the DocAddress structure etc. by calling fill_DocAddress().
+ *
+ * address is the address of the underlying resource, i.e. the one
+ * containing the MAP element, the MAP's name appended as
+ * fragment is ignored.
+ * anchor is the LYNXIMGMAP: anchor for which LYLoadIMGmap() is
+ * requested; if it is associated with POST data, we want the
+ * specific list for this combination of address+post_data.
+ *
+ * if DONT_TRACK_INTERNAL_LINKS is defined, the Anchor passed to
+ * LYLoadIMGmap() will never have post_data, so that the global list
+ * will be used. - kw
+ */
+PRIVATE HTList * get_the_list ARGS4(
+ DocAddress *, wwwdoc,
+ char *, address,
+ HTParentAnchor *, anchor,
+ HTParentAnchor **, punderlying)
+{
+ if (anchor && anchor->post_data) {
+ fill_DocAddress(wwwdoc, address, anchor, punderlying);
+ if (punderlying && *punderlying)
+ return (*punderlying)->imaps;
+ return anchor->imaps;
+ } else {
+ fill_DocAddress(wwwdoc, address, NULL, punderlying);
+ return LynxMaps;
+ }
+}
+
+/* LYLoadIMGmap - F.Macrides (macrides@sci.wfeb.edu)
+** ------------
+** Create a text/html stream with a list of links
+** for HyperText References in AREAs of a MAP.
+*/
+
+PRIVATE int LYLoadIMGmap ARGS4 (
+ CONST char *, arg,
+ HTParentAnchor *, anAnchor,
+ HTFormat, format_out,
+ HTStream*, sink)
+{
+ HTFormat format_in = WWW_HTML;
+ HTStream *target = NULL;
+ char buf[1024];
+ LYMapElement *new = NULL;
+ LYImageMap *theMap = NULL;
+ char *MapTitle = NULL;
+ char *MapAddress = NULL;
+ HTList *theList;
+ HTList *cur = NULL;
+ char *address = NULL;
+ char *cp = NULL;
+ DocAddress WWWDoc;
+ HTParentAnchor * underlying;
+ BOOL old_cache_setting = LYforce_no_cache;
+ BOOL old_reloading = reloading;
+ HTFormat old_format_out = HTOutputFormat;
+
+ if (!strncasecomp(arg, "LYNXIMGMAP:", 11)) {
+ address = (char * )(arg + 11);
+ }
+ if (!(address && strchr(address, ':'))) {
+ HTAlert(MISDIRECTED_MAP_REQUEST);
+ return(HT_NOT_LOADED);
+ }
+
+ theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
+ if (WWWDoc.safe)
+ anAnchor->safe = TRUE;
+
+ if (!theList) {
+ if (anAnchor->post_data && !WWWDoc.safe &&
+ ((underlying && underlying->document && !LYforce_no_cache) ||
+ HTConfirm(
+#if __STDC__
+ "LYNXIMGMAP: "
+#endif
+ CONFIRM_POST_RESUBMISSION) != TRUE)) {
+ HTAlert("Image map from POST response not available!");
+ return(HT_NOT_LOADED);
+ }
+ LYforce_no_cache = TRUE;
+ reloading = TRUE;
+ HTOutputFormat = WWW_PRESENT;
+ LYMapsOnly = TRUE;
+ if (!HTLoadAbsolute(&WWWDoc)) {
+ LYforce_no_cache = old_cache_setting;
+ reloading = old_reloading;
+ HTOutputFormat = old_format_out;
+ LYMapsOnly = FALSE;
+ HTAlert(MAP_NOT_ACCESSIBLE);
+ return(HT_NOT_LOADED);
+ }
+ LYforce_no_cache = old_cache_setting;
+ reloading = old_reloading;
+ HTOutputFormat = old_format_out;
+ LYMapsOnly = FALSE;
+ theList = get_the_list(&WWWDoc, address, anAnchor, &underlying);
+ }
+
+ if (!theList) {
+ HTAlert(MAPS_NOT_AVAILABLE);
+ return(HT_NOT_LOADED);
+ }
+
+ cur = theList;
+ while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
+ if (!strcmp(theMap->address, address)) {
+ break;
+ }
+ }
+ if (!(theMap && theMap->elements)) {
+ if (anAnchor->post_data && !WWWDoc.safe &&
+ ((underlying && underlying->document && !LYforce_no_cache) ||
+ HTConfirm(
+#if __STDC__
+ "LYNXIMGMAP: "
+#endif
+ CONFIRM_POST_RESUBMISSION) != TRUE)) {
+ HTAlert("Image map from POST response not available!");
+ return(HT_NOT_LOADED);
+ }
+ LYforce_no_cache = TRUE;
+ reloading = TRUE;
+ HTOutputFormat = WWW_PRESENT;
+ LYMapsOnly = TRUE;
+ if (!HTLoadAbsolute(&WWWDoc)) {
+ LYforce_no_cache = old_cache_setting;
+ reloading = old_reloading;
+ HTOutputFormat = old_format_out;
+ LYMapsOnly = FALSE;
+ HTAlert(MAP_NOT_ACCESSIBLE);
+ return(HT_NOT_LOADED);
+ }
+ LYforce_no_cache = old_cache_setting;
+ reloading = old_reloading;
+ HTOutputFormat = old_format_out;
+ LYMapsOnly = FALSE;
+ cur = get_the_list(&WWWDoc, address, anAnchor, &underlying);
+ while (NULL != (theMap = (LYImageMap *)HTList_nextObject(cur))) {
+ if (!strcmp(theMap->address, address)) {
+ break;
+ }
+ }
+ if (!(theMap && theMap->elements)) {
+ HTAlert(MAP_NOT_AVAILABLE);
+ return(HT_NOT_LOADED);
+ }
+ }
+
+#ifdef DONT_TRACK_INTERNAL_LINKS
+ anAnchor->no_cache = TRUE;
+#endif
+
+ target = HTStreamStack(format_in,
+ format_out,
+ sink, anAnchor);
+
+ if (!target || target == NULL) {
+ sprintf(buf, CANNOT_CONVERT_I_TO_O,
+ HTAtom_name(format_in), HTAtom_name(format_out));
+ HTAlert(buf);
+ return(HT_NOT_LOADED);
+ }
+
+ if (theMap->title && *theMap->title) {
+ StrAllocCopy(MapTitle, theMap->title);
+ } else if (anAnchor->title && *anAnchor->title) {
+ StrAllocCopy(MapTitle, anAnchor->title);
+ } else if (LYRequestTitle && *LYRequestTitle &&
+ strcasecomp(LYRequestTitle, "[USEMAP]")) {
+ StrAllocCopy(MapTitle, LYRequestTitle);
+ } else if ((cp=strrchr(address, '#')) != NULL) {
+ StrAllocCopy(MapTitle, (cp+1));
+ }
+ if (!(MapTitle && *MapTitle)) {
+ StrAllocCopy(MapTitle, "[USEMAP]");
+ } else {
+ LYEntify(&MapTitle, TRUE);
+ }
+
+ sprintf(buf,"<head>\n<title>%s</title>\n</head>\n<body>\n", MapTitle);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf,"<h1><em>%s</em></h1>\n", MapTitle);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ StrAllocCopy(MapAddress, address);
+ LYEntify(&MapAddress, FALSE);
+ sprintf(buf,"<h2><em>MAP:</em>&nbsp;%s</h2>\n", MapAddress);
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ sprintf(buf, "<%s compact>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol" : "ul"));
+ (*target->isa->put_block)(target, buf, strlen(buf));
+ cur = theMap->elements;
+ while (NULL != (new=(LYMapElement *)HTList_nextObject(cur))) {
+ StrAllocCopy(MapAddress, new->address);
+ LYEntify(&MapAddress, FALSE);
+ (*target->isa->put_block)(target, "<li><a href=\"", 13);
+ (*target->isa->put_block)(target, MapAddress, strlen(MapAddress));
+#ifndef DONT_TRACK_INTERNAL_LINKS
+ if (new->intern_flag)
+ (*target->isa->put_block)(target, "\" TYPE=\"internal link\"\n>",24);
+ else
+#endif
+ (*target->isa->put_block)(target, "\"\n>", 3);
+ StrAllocCopy(MapTitle, new->title);
+ LYEntify(&MapTitle, TRUE);
+ (*target->isa->put_block)(target, MapTitle, strlen(MapTitle));
+ (*target->isa->put_block)(target, "</a>\n", 5);
+ }
+ sprintf(buf,"</%s>\n</body>\n", ((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "ol" : "ul"));
+ (*target->isa->put_block)(target, buf, strlen(buf));
+
+ (*target->isa->_free)(target);
+ FREE(MapAddress);
+ FREE(MapTitle);
+ return(HT_LOADED);
+}
+
+#ifdef GLOBALDEF_IS_MACRO
+#define _LYIMGMAP_C_GLOBALDEF_1_INIT { "LYNXIMGMAP", LYLoadIMGmap, 0}
+GLOBALDEF (HTProtocol,LYLynxIMGmap,_LYIMGMAP_C_GLOBALDEF_1_INIT);
+#else
+GLOBALDEF PUBLIC HTProtocol LYLynxIMGmap = {"LYNXIMGMAP", LYLoadIMGmap, 0};
+#endif /* GLOBALDEF_IS_MACRO */
diff --git a/gnu/usr.bin/lynx/src/LYMap.h b/gnu/usr.bin/lynx/src/LYMap.h
new file mode 100644
index 00000000000..ae0f9d6935b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYMap.h
@@ -0,0 +1,15 @@
+
+#ifndef LYMAP_H
+#define LYMAP_H
+
+extern BOOL LYMapsOnly;
+
+extern void ImageMapList_free PARAMS((HTList * list));
+extern BOOL LYAddImageMap PARAMS((char *address, char *title,
+ HTParentAnchor *node_anchor));
+extern BOOL LYAddMapElement PARAMS((char *map, char *address, char *title,
+ HTParentAnchor *node_anchor,
+ BOOL intern_flag));
+extern BOOL LYHaveImageMap PARAMS((char *address));
+
+#endif /* LYMAP_H */
diff --git a/gnu/usr.bin/lynx/src/LYNews.c b/gnu/usr.bin/lynx/src/LYNews.c
new file mode 100644
index 00000000000..77824ebd696
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYNews.c
@@ -0,0 +1,433 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTAccess.h"
+#include "HTCJK.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYSignal.h"
+#include "LYStructs.h"
+#include "LYUtils.h"
+#include "LYClean.h"
+#include "LYStrings.h"
+#include "LYGetFile.h"
+#include "LYHistory.h"
+#include "LYSystem.h"
+#include "GridText.h"
+#include "LYCharSets.h"
+#include "LYNews.h"
+
+#include "LYGlobalDefs.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+** Global variable for async i/o.
+*/
+BOOLEAN term_message = FALSE;
+PRIVATE void terminate_message PARAMS((int sig));
+
+/*
+** This function is called from HTLoadNews() to have the user
+** create a file with news headers and a body for posting of
+** a new message (based on a newspost://nntp_host/newsgroups
+** or snewspost://secure_nntp_host/newsgroups URL), or to post
+** a followup (based on a newsreply://nntp_host/newsgroups or
+** snewsreply://secure_nntp_host/newsgroups URL). The group
+** or comma-separated list of newsgroups is passed without
+** a lead slash, and followup is TRUE for newsreply or
+** snewsreply URLs. - FM
+*/
+PUBLIC char *LYNewsPost ARGS2(
+ char *, newsgroups,
+ BOOLEAN, followup)
+{
+ char user_input[1024];
+ char CJKinput[1024];
+ char *cp = NULL;
+ int c = 0; /* user input */
+ FILE *fd = NULL;
+ char my_tempfile[256];
+ FILE *fc = NULL;
+ char CJKfile[256];
+ char *postfile = NULL;
+ char *NewsGroups = NULL;
+ char *org = NULL;
+ FILE *fp = NULL;
+
+ /*
+ * Make sure a non-zero length newspost, newsreply,
+ * snewspost or snewsreply path was sent to us. - FM
+ */
+ if (!(newsgroups && *newsgroups))
+ return(postfile);
+
+ /*
+ * Open a temporary file for the headers
+ * and message body. - FM
+ */
+ tempname(my_tempfile, NEW_FILE);
+ if ((fd = LYNewTxtFile(my_tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(postfile);
+ }
+
+ /*
+ * If we're using a Japanese display character set,
+ * open a temporary file for a conversion to JIS. - FM
+ */
+ CJKfile[0] = '\0';
+ if (!strncmp(LYchar_set_names[current_char_set], "Japanese (EUC)", 14) ||
+ !strncmp(LYchar_set_names[current_char_set], "Japanese (SJIS)", 15)) {
+ tempname(CJKfile, NEW_FILE);
+ if ((fc = LYNewTxtFile(CJKfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ fclose(fd);
+#ifdef VMS
+ while (remove(my_tempfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(my_tempfile);
+#endif /* VMS */
+ return(postfile);
+ }
+ }
+
+ /*
+ * The newsgroups could be a comma-seperated list.
+ * It need not have spaces, but deal with any that
+ * may also have been hex escaped. - FM
+ */
+ StrAllocCopy(NewsGroups, newsgroups);
+ HTUnEscape(NewsGroups);
+
+ /*
+ * Allow ^C to cancel the posting,
+ * i.e., don't let SIGINTs exit Lynx.
+ */
+ signal(SIGINT, terminate_message);
+ term_message = FALSE;
+
+ /*
+ * Show the list of newsgroups. - FM
+ */
+ clear();
+ move(2,0);
+ scrollok(stdscr, TRUE); /* Enable scrolling. */
+ addstr("You will be posting to:");
+ addstr("\n\t");
+ addstr(NewsGroups);
+ addch('\n');
+
+ /*
+ * Get the mail address for the From header,
+ * offering personal_mail_address as default.
+ */
+ addstr("\n\n Please provide your mail address for the From: header\n");
+ strcpy(user_input, "From: ");
+ if (personal_mail_address)
+ strcat(user_input, personal_mail_address);
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0 ||
+ term_message) {
+ _statusline(NEWS_POST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ fprintf(fd, "%s\n", user_input);
+
+ /*
+ * Get the Subject header, offering the current
+ * document's title as the default if this is a
+ * followup rather than a new post. - FM
+ */
+ addstr("\n\n Please provide or edit the Subject: header\n");
+ strcpy(user_input, "Subject: ");
+ if ((followup == TRUE && nhist > 0) &&
+ (cp = HText_getTitle()) != NULL) {
+ /*
+ * Add the default subject.
+ */
+ while (isspace(*cp)) {
+ cp++;
+ }
+ if (strncasecomp(cp, "Re:", 3)) {
+ strcat(user_input, "Re: ");
+ }
+ strcat(user_input, cp);
+ }
+ cp = NULL;
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0 ||
+ term_message) {
+ _statusline(NEWS_POST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ fprintf(fd,"%s\n",user_input);
+
+ /*
+ * Add Organization: header.
+ */
+ StrAllocCopy(cp, "Organization: ");
+ if (((org = getenv("ORGANIZATION")) != NULL) && *org != '\0') {
+ StrAllocCat(cp, org);
+ } else if (((org = getenv("NEWS_ORGANIZATION")) != NULL) &&
+ *org != '\0') {
+ StrAllocCat(cp, org);
+#ifndef VMS
+ } else if ((fp = fopen("/etc/organization", "r")) != NULL) {
+ if (fgets(user_input, sizeof(user_input), fp) != NULL) {
+ if ((org = strchr(user_input, '\n')) != NULL) {
+ *org = '\0';
+ }
+ if (user_input[0] != '\0') {
+ StrAllocCat(cp, user_input);
+ }
+ }
+ fclose(fp);
+#endif /* !VMS */
+ }
+ LYstrncpy(user_input, cp, (sizeof(user_input) - 16));
+ FREE(cp);
+ addstr("\n\n Please provide or edit the Organization: header\n");
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0 ||
+ term_message) {
+ _statusline(NEWS_POST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ fprintf(fd, "%s\n", user_input);
+
+ /*
+ * Add Newsgroups Summary and Keywords headers.
+ */
+ fprintf(fd, "Newsgroups: %s\nSummary: \nKeywords: \n\n", NewsGroups);
+
+ /*
+ * Have the user create the message body.
+ */
+ if (!no_editor && editor && *editor != '\0') {
+ /*
+ * Use an external editor.
+ */
+ char *editor_arg = "";
+
+ if (followup && nhist > 0) {
+ /*
+ * Ask if the user wants to include the original message.
+ */
+ _statusline(INC_ORIG_MSG_PROMPT);
+ c = 0;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_message && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y')
+ /*
+ * The 1 will add the reply ">" in front of every line.
+ * We're assuming that if the display character set is
+ * Japanese and the document did not have a CJK charset,
+ * any non-EUC or non-SJIS 8-bit characters in it where
+ * converted to 7-bit equivalents. - FM
+ */
+ print_wwwfile_to_fd(fd, 1);
+ }
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ if (term_message || c == 7 || c == 3)
+ goto cleanup;
+
+ /*
+ * Spawn the user's editor on the news file.
+ */
+ if (strstr(editor, "pico")) {
+ editor_arg = " -t"; /* No prompt for filename to use */
+ }
+ sprintf(user_input,"%s%s %s", editor, editor_arg, my_tempfile);
+ _statusline(SPAWNING_EDITOR_FOR_NEWS);
+ stop_curses();
+ if (system(user_input)) {
+ start_curses();
+ _statusline(ERROR_SPAWNING_EDITOR);
+ sleep(AlertSecs);
+ } else {
+ start_curses();
+ }
+ } else {
+ /*
+ * Use the built in line editior.
+ */
+ addstr("\n\n Please enter your message below.");
+ addstr("\n When you are done, press enter and put a single period (.)");
+ addstr("\n on a line and press enter again.");
+ addstr("\n\n");
+ refresh();
+ *user_input = '\0';
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0 ||
+ term_message) {
+ _statusline(NEWS_POST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ while (!STREQ(user_input,".") && !term_message) {
+ addch('\n');
+ fprintf(fd,"%s\n",user_input);
+ *user_input = '\0';
+ if (LYgetstr(user_input, VISIBLE,
+ sizeof(user_input), NORECALL) < 0) {
+ _statusline(NEWS_POST_CANCELLED);
+ sleep(InfoSecs);
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ goto cleanup;
+ }
+ }
+ fprintf(fd, "\n");
+ fclose(fd); /* Close the temp file. */
+ scrollok(stdscr, FALSE); /* Stop scrolling. */
+ }
+
+ /*
+ * Confirm whether to post, and if so,
+ * whether to append the sig file. - FM
+ */
+ LYStatusLine = (LYlines - 1);
+ _statusline(POST_MSG_PROMPT);
+ c = 0;
+ LYStatusLine = -1;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_message && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) != 'Y') {
+ clear(); /* clear the screen */
+ goto cleanup;
+ }
+ if ((LynxSigFile != NULL) &&
+ (fp = fopen(LynxSigFile, "r")) != NULL) {
+ LYStatusLine = (LYlines - 1);
+ _user_message(APPEND_SIG_FILE, LynxSigFile);
+ c = 0;
+ LYStatusLine = -1;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' &&
+ !term_message && c != 7 && c != 3)
+ c = LYgetch();
+ if (TOUPPER(c) == 'Y') {
+ if ((fd = fopen(my_tempfile, "a")) != NULL) {
+ fputs("-- \n", fd);
+ while (fgets(user_input, sizeof(user_input), fp) != NULL) {
+ fputs(user_input, fd);
+ }
+ fclose(fd);
+ }
+ }
+ fclose(fp);
+ }
+ clear(); /* clear the screen */
+
+ /*
+ * If we are using a Japanese display character
+ * set, convert the contents of the temp file to
+ * JIS (nothing should change if it does not, in
+ * fact, contain EUC or SJIS di-bytes). Otherwise,
+ * use the temp file as is. - FM
+ */
+ if (CJKfile[0] != '\0') {
+ if ((fd = fopen(my_tempfile, "r")) != NULL) {
+ while (fgets(user_input, sizeof(user_input), fd) != NULL) {
+ TO_JIS((unsigned char *)user_input,
+ (unsigned char *)CJKinput);
+ fputs(CJKinput, fc);
+ }
+ fclose(fc);
+ StrAllocCopy(postfile, CJKfile);
+ fclose(fd);
+#ifdef VMS
+ while (remove(my_tempfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(my_tempfile);
+#endif /* VMS */
+ fd = fc;
+ strcpy(my_tempfile, CJKfile);
+ CJKfile[0] = '\0';
+ } else {
+ StrAllocCopy(postfile, my_tempfile);
+ }
+ } else {
+ StrAllocCopy(postfile, my_tempfile);
+ }
+ if (!followup) {
+ /*
+ * If it's not a followup, the current document
+ * most likely is the group listing, so force a
+ * to have the article show up in the list after
+ * the posting. Note, that if it's a followup
+ * via a link in a news article, the user must
+ * do a reload manually on returning to the
+ * group listing. - FM
+ */
+ LYforce_no_cache = TRUE;
+ }
+ LYStatusLine = (LYlines - 1);
+ statusline(POSTING_TO_NEWS);
+ LYStatusLine = -1;
+ sleep(MessageSecs);
+
+ /*
+ * Come here to cleanup and exit.
+ */
+cleanup:
+#ifndef VMS
+ signal(SIGINT, cleanup_sig);
+#endif /* !VMS */
+ term_message = FALSE;
+ if (!postfile) {
+#ifdef VMS
+ while (remove(my_tempfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(my_tempfile);
+#endif /* VMS */
+ }
+ if (CJKfile[0] != '\0') {
+#ifdef VMS
+ fclose(fc);
+ while (remove(CJKfile) == 0)
+ ; /* loop through all versions */
+#else
+ remove(CJKfile);
+#endif /* VMS */
+ }
+ FREE(NewsGroups);
+
+ return(postfile);
+}
+
+PRIVATE void terminate_message ARGS1(
+ int, sig GCC_UNUSED)
+{
+ term_message = TRUE;
+ /*
+ * Reassert the AST.
+ */
+ signal(SIGINT, terminate_message);
+#ifdef VMS
+ /*
+ * Refresh the screen to get rid of the "interrupt" message.
+ */
+ lynx_force_repaint();
+ refresh();
+#endif /* VMS */
+}
diff --git a/gnu/usr.bin/lynx/src/LYNews.h b/gnu/usr.bin/lynx/src/LYNews.h
new file mode 100644
index 00000000000..17d9d48adb2
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYNews.h
@@ -0,0 +1,13 @@
+#ifndef LYNEWSPOST_H
+#define LYNEWSPOST_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern BOOLEAN term_message;
+
+extern char *LYNewsPost PARAMS((char *newsgroups, BOOLEAN followup));
+
+#endif /* LYNEWSPOST_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYOptions.c b/gnu/usr.bin/lynx/src/LYOptions.c
new file mode 100644
index 00000000000..c63740a40cc
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYOptions.c
@@ -0,0 +1,3107 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFTP.h"
+#include "HTML.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "LYOptions.h"
+#include "LYSignal.h"
+#include "LYClean.h"
+#include "LYCharSets.h"
+#include "LYCharUtils.h"
+#include "UCMap.h"
+#include "UCAux.h"
+#include "LYKeymap.h"
+#include "LYrcFile.h"
+#include "HTAlert.h"
+#include "LYBookmark.h"
+#include "GridText.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+#define COL_OPTION_VALUES 36 /* display column where option values start */
+
+BOOLEAN term_options;
+PRIVATE void terminate_options PARAMS((int sig));
+PRIVATE int boolean_choice PARAMS((
+ int status,
+ int line,
+ int column,
+ char ** choices));
+PRIVATE int popup_choice PARAMS((
+ int cur_choice,
+ int line,
+ int column,
+ char ** choices,
+ int i_length,
+ int disabled));
+
+#define MAXCHOICES 10
+
+#define L_Bool_A (use_assume_charset ? L_BOOL_A + 1 : L_BOOL_A)
+#define L_Bool_B (use_assume_charset ? L_BOOL_B + 1 : L_BOOL_B)
+#define L_Exec (use_assume_charset ? L_EXEC + 1 : L_EXEC)
+#define L_Rawmode (use_assume_charset ? L_RAWMODE + 1 : L_RAWMODE)
+#define L_Charset (use_assume_charset ? L_CHARSET + 1 : L_CHARSET)
+#define L_Color (use_assume_charset ? L_COLOR + 1 : L_COLOR)
+#define L_Keypad (use_assume_charset ? L_KEYPAD + 1 : L_KEYPAD)
+#define L_Lineed (use_assume_charset ? L_LINEED + 1 : L_LINEED)
+#define L_Dired (use_assume_charset ? L_DIRED + 1 : L_DIRED)
+#define L_User_Mode (use_assume_charset ? L_USER_MODE + 1 : L_USER_MODE)
+#define L_User_Agent (use_assume_charset ? L_USER_AGENT + 1 : L_USER_AGENT)
+
+PRIVATE void option_statusline ARGS1(
+ CONST char *, text)
+{
+ /*
+ * Make sure we have a pointer to a string.
+ */
+ if (text == NULL)
+ return;
+
+ /*
+ * Don't print statusline messages if dumping to stdout.
+ */
+ if (dump_output_immediately)
+ return;
+
+ /*
+ * Use _statusline() set to output on the bottom line. - FM
+ */
+ LYStatusLine = (LYlines - 1);
+ _statusline(text);
+ LYStatusLine = -1;
+}
+
+PRIVATE void option_user_message ARGS2(
+ CONST char *, message,
+ char *, argument)
+{
+ /*
+ * Make sure we have a pointer to a string.
+ */
+ if (message == NULL || argument == NULL)
+ return;
+
+ /*
+ * Don't print statusline messages if dumping to stdout.
+ */
+ if (dump_output_immediately)
+ return;
+
+ /*
+ * Use _user_message() set to output on the bottom line.
+ */
+ LYStatusLine = (LYlines - 1);
+ _user_message(message, argument);
+ LYStatusLine = -1;
+}
+
+PUBLIC void options NOARGS
+{
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ int itmp;
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+ int response, ch;
+ /*
+ * If the user changes the display we need memory to put it in.
+ */
+ char display_option[256];
+#ifndef VMS
+ static char putenv_command[142];
+#endif /* !VMS */
+ char *choices[MAXCHOICES];
+ int CurrentCharSet = current_char_set;
+ int CurrentShowColor = LYShowColor;
+ int CurrentAssumeCharSet = UCLYhndl_for_unspec;
+ BOOLEAN CurrentRawMode = LYRawMode;
+ BOOLEAN AddValueAccepted = FALSE;
+ char *cp = NULL;
+ BOOL use_assume_charset, old_use_assume_charset;
+
+#ifdef DIRED_SUPPORT
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ if (LYlines < 24) {
+ HTAlert(OPTION_SCREEN_NEEDS_24);
+ return;
+ }
+#else
+ if (LYlines < 23) {
+ HTAlert(OPTION_SCREEN_NEEDS_23);
+ return;
+ }
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+#else
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ if (LYlines < 23) {
+ HTAlert(
+ "Screen height must be at least 23 lines for the Options menu!");
+ return;
+ }
+#else
+ if (LYlines < 22) {
+ HTAlert(OPTION_SCREEN_NEEDS_22);
+ return;
+ }
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+#endif /* DIRED_SUPPORT */
+
+ term_options = FALSE;
+ signal(SIGINT, terminate_options);
+ if (no_option_save) {
+ if (LYShowColor == SHOW_COLOR_NEVER) {
+ LYShowColor = SHOW_COLOR_OFF;
+ } else if (LYShowColor == SHOW_COLOR_ALWAYS) {
+ LYShowColor = SHOW_COLOR_ON;
+ }
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+ } else {
+ if (LYChosenShowColor == SHOW_COLOR_UNKNOWN) {
+ switch (LYrcShowColor) {
+ case SHOW_COLOR_NEVER:
+ LYChosenShowColor =
+ (LYShowColor >= SHOW_COLOR_ON) ?
+ SHOW_COLOR_ON :
+ SHOW_COLOR_NEVER;
+ break;
+ case SHOW_COLOR_ALWAYS:
+#if defined(COLOR_CURSES)
+ if (!has_colors())
+ LYChosenShowColor = SHOW_COLOR_ALWAYS;
+ else
+#endif
+ LYChosenShowColor =
+ (LYShowColor >= SHOW_COLOR_ON) ?
+ SHOW_COLOR_ALWAYS :
+ SHOW_COLOR_OFF;
+ break;
+ default:
+ LYChosenShowColor =
+ (LYShowColor >= SHOW_COLOR_ON) ?
+ SHOW_COLOR_ON :
+ SHOW_COLOR_OFF;
+ }
+ }
+#endif /* USE_SLANG || COLOR_CURSES */
+ }
+
+ old_use_assume_charset =
+ use_assume_charset = (user_mode == ADVANCED_MODE);
+
+draw_options:
+
+ old_use_assume_charset = use_assume_charset;
+ /*
+ * NOTE that printw() should be avoided for strings that
+ * might have non-ASCII or multibyte/CJK characters. - FM
+ */
+ response = 0;
+#if defined(FANCY_CURSES) || defined (USE_SLANG)
+ if (enable_scrollback) {
+ clear();
+ } else {
+ erase();
+ }
+#else
+ clear();
+#endif /* FANCY_CURSES || USE_SLANG */
+ move(0, 5);
+
+ lynx_start_h1_color ();
+ addstr(" Options Menu (");
+ addstr(LYNX_NAME);
+ addstr(" Version ");
+ addstr(LYNX_VERSION);
+ addch(')');
+ lynx_stop_h1_color ();
+ move(L_EDITOR, 5);
+ addstr("E)ditor : ");
+ addstr((editor && *editor) ? editor : "NONE");
+
+ move(L_DISPLAY, 5);
+ addstr("D)ISPLAY variable : ");
+ addstr((display && *display) ? display : "NONE");
+
+ move(L_HOME, 5);
+ addstr("mu(L)ti-bookmarks: ");
+ addstr((LYMultiBookmarks ?
+ (LYMBMAdvanced ? "ADVANCED"
+ : "STANDARD")
+ : "OFF "));
+ move(L_HOME, B_BOOK);
+ if (LYMultiBookmarks) {
+ addstr("review/edit B)ookmarks files");
+ } else {
+ addstr("B)ookmark file: ");
+ addstr((bookmark_page && *bookmark_page) ? bookmark_page : "NONE");
+ }
+
+ move(L_FTPSTYPE, 5);
+ addstr("F)TP sort criteria : ");
+ addstr((HTfileSortMethod == FILE_BY_NAME ? "By Filename" :
+ (HTfileSortMethod == FILE_BY_SIZE ? "By Size " :
+ (HTfileSortMethod == FILE_BY_TYPE ? "By Type " :
+ "By Date "))));
+
+ move(L_MAIL_ADDRESS, 5);
+ addstr("P)ersonal mail address : ");
+ addstr((personal_mail_address && *personal_mail_address) ?
+ personal_mail_address : "NONE");
+
+ move(L_SSEARCH, 5);
+ addstr("S)earching type : ");
+ addstr(case_sensitive ? "CASE SENSITIVE " : "CASE INSENSITIVE");
+
+ move(L_Charset, 5);
+ addstr("display (C)haracter set : ");
+ addstr((char *)LYchar_set_names[current_char_set]);
+
+ move(L_LANGUAGE, 5);
+ addstr("preferred document lan(G)uage: ");
+ addstr((language && *language) ? language : "NONE");
+
+ move(L_PREF_CHARSET, 5);
+ addstr("preferred document c(H)arset : ");
+ addstr((pref_charset && *pref_charset) ? pref_charset : "NONE");
+
+ if (use_assume_charset) {
+ move(L_ASSUME_CHARSET, 5);
+ addstr("^A)ssume charset if unknown : ");
+ if (UCAssume_MIMEcharset)
+ addstr(UCAssume_MIMEcharset);
+ else
+ addstr((UCLYhndl_for_unspec >= 0) ?
+ (char *)LYCharSet_UC[UCLYhndl_for_unspec].MIMEname
+ : "NONE");
+ }
+
+ move(L_Rawmode, 5);
+ addstr("Raw 8-bit or CJK m(O)de : ");
+ addstr(LYRawMode ? "ON " : "OFF");
+
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+ move(L_Color, B_COLOR);
+ addstr("show color (&) : ");
+ if (no_option_save) {
+ addstr((LYShowColor == SHOW_COLOR_OFF ? "OFF" :
+ "ON "));
+ } else {
+ switch (LYChosenShowColor) {
+ case SHOW_COLOR_NEVER:
+ addstr("NEVER ");
+ break;
+ case SHOW_COLOR_OFF:
+ addstr("OFF");
+ break;
+ case SHOW_COLOR_ON:
+ addstr("ON ");
+ break;
+ case SHOW_COLOR_ALWAYS:
+#if defined(COLOR_CURSES)
+ if (!has_colors())
+ addstr("Always try");
+ else
+#endif
+ addstr("ALWAYS ");
+ }
+ }
+#endif /* USE_SLANG || COLOR_CURSES */
+
+ move(L_Bool_A, B_VIKEYS);
+ addstr("V)I keys: ");
+ addstr(vi_keys ? "ON " : "OFF");
+
+ move(L_Bool_A, B_EMACSKEYS);
+ addstr("e(M)acs keys: ");
+ addstr(emacs_keys ? "ON " : "OFF");
+
+ move(L_Bool_A, B_SHOW_DOTFILES);
+ addstr("sho(W) dot files: ");
+ addstr((!no_dotfiles && show_dotfiles) ? "ON " : "OFF");
+
+ move(L_Bool_B, B_SELECT_POPUPS);
+ addstr("popups for selec(T) fields : ");
+ addstr(LYSelectPopups ? "ON " : "OFF");
+
+ move(L_Bool_B, B_SHOW_CURSOR);
+ addstr("show cursor (@) : ");
+ addstr(LYShowCursor ? "ON " : "OFF");
+
+ move(L_Keypad, 5);
+ addstr("K)eypad mode : ");
+ addstr((keypad_mode == NUMBERS_AS_ARROWS) ?
+ "Numbers act as arrows " :
+ ((keypad_mode == LINKS_ARE_NUMBERED) ?
+ "Links are numbered " :
+ "Links and form fields are numbered"));
+
+ move(L_Lineed, 5);
+ addstr("li(N)e edit style : ");
+ addstr(LYLineeditNames[current_lineedit]);
+
+#ifdef DIRED_SUPPORT
+ move(L_Dired, 5);
+ addstr("l(I)st directory style : ");
+ addstr((dir_list_style == FILES_FIRST) ? "Files first " :
+ ((dir_list_style == MIXED_STYLE) ? "Mixed style " :
+ "Directories first"));
+#endif /* DIRED_SUPPORT */
+
+ move(L_User_Mode, 5);
+ addstr("U)ser mode : ");
+ addstr( (user_mode == NOVICE_MODE) ? "Novice " :
+ ((user_mode == INTERMEDIATE_MODE) ? "Intermediate" :
+ "Advanced "));
+
+ move(L_User_Agent, 5);
+ addstr("user (A)gent : ");
+ addstr((LYUserAgent && *LYUserAgent) ? LYUserAgent : "NONE");
+
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ move(L_Exec, 5);
+ addstr("local e(X)ecution links : ");
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ addstr( local_exec ? "ALWAYS ON " :
+ (local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
+ "ALWAYS OFF "));
+#else
+ addstr(local_exec_on_local_files ? "FOR LOCAL FILES ONLY" :
+ "ALWAYS OFF ");
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+
+ move(LYlines-3, 2);
+ addstr(SELECT_SEGMENT);
+ start_bold();
+ addstr(CAP_LETT_SEGMENT);
+ stop_bold();
+ addstr(OF_OPT_LINE_SEGMENT);
+ if (!no_option_save) {
+ addstr(" '");
+ start_bold();
+ addstr(">");
+ stop_bold();
+ addstr("'");
+ addstr(TO_SAVE_SEGMENT);
+ }
+ addstr(OR_SEGMENT);
+ addstr("'");
+ start_bold();
+ addstr("r");
+ stop_bold();
+ addstr("'");
+ addstr(TO_RETURN_SEGMENT);
+
+ while (TOUPPER(response) != 'R' &&
+ !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
+ response != '>' && !term_options &&
+ response != 7 && response != 3) {
+ if (AddValueAccepted == TRUE) {
+ option_statusline(VALUE_ACCEPTED);
+ AddValueAccepted = FALSE;
+ }
+ move((LYlines - 2), 0);
+ lynx_start_prompt_color ();
+ addstr(COMMAND_PROMPT);
+ lynx_stop_prompt_color ();
+
+ refresh();
+ response = LYgetch();
+ if (term_options || response == 7 || response == 3)
+ response = 'R';
+ if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
+ lynx_force_repaint();
+ goto draw_options;
+ }
+ switch (response) {
+ case 'e': /* Change the editor. */
+ case 'E':
+ if (no_editor) {
+ option_statusline(EDIT_DISABLED);
+ } else if (system_editor ) {
+ option_statusline(EDITOR_LOCKED);
+ } else {
+ if (editor && *editor)
+ strcpy(display_option, editor);
+ else { /* clear the NONE */
+ move(L_EDITOR, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_EDITOR, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_EDITOR, COL_OPTION_VALUES);
+ if (term_options || ch == -1) {
+ addstr((editor && *editor) ?
+ editor : "NONE");
+ } else if (*display_option == '\0') {
+ FREE(editor);
+ addstr("NONE");
+ } else {
+ StrAllocCopy(editor, display_option);
+ addstr(display_option);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ }
+ response = ' ';
+ break;
+
+ case 'd': /* Change the display. */
+ case 'D':
+ if (display && *display) {
+ strcpy(display_option, display);
+ } else { /* clear the NONE */
+ move(L_DISPLAY, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_DISPLAY, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_DISPLAY, COL_OPTION_VALUES);
+ if ((term_options || ch == -1) ||
+ (display != NULL &&
+#ifdef VMS
+ !strcasecomp(display, display_option)))
+#else
+ !strcmp(display, display_option)))
+#endif /* VMS */
+ {
+ /*
+ * Cancelled, or a non-NULL display string
+ * wasn't changed. - FM
+ */
+ addstr((display && *display) ? display : "NONE");
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ response = ' ';
+ break;
+ } else if (*display_option == '\0') {
+ if ((display == NULL) ||
+ (display != NULL && *display == '\0')) {
+ /*
+ * NULL or zero-length display string
+ * wasn't changed. - FM
+ */
+ addstr("NONE");
+ clrtoeol();
+ option_statusline(VALUE_ACCEPTED);
+ response = ' ';
+ break;
+ }
+ }
+ /*
+ * Set the new DISPLAY variable. - FM
+ */
+#ifdef VMS
+ {
+ int i;
+ for (i = 0; display_option[i]; i++)
+ display_option[i] = TOUPPER(display_option[i]);
+ Define_VMSLogical(DISPLAY, display_option);
+ }
+#else
+ sprintf(putenv_command, "DISPLAY=%s", display_option);
+ putenv(putenv_command);
+#endif /* VMS */
+ if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
+ StrAllocCopy(display, cp);
+ } else {
+ FREE(display);
+ }
+ cp = NULL;
+ addstr(display ? display : "NONE");
+ clrtoeol();
+ if ((display == NULL && *display_option == '\0') ||
+ (display != NULL &&
+ !strcmp(display, display_option))) {
+ if (display == NULL &&
+ LYisConfiguredForX == TRUE) {
+ option_statusline(VALUE_ACCEPTED_WARNING_X);
+ } else if (display != NULL &&
+ LYisConfiguredForX == FALSE) {
+ option_statusline(VALUE_ACCEPTED_WARNING_NONX);
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ } else {
+ if (*display_option) {
+ option_statusline(FAILED_TO_SET_DISPLAY);
+ } else {
+ option_statusline(FAILED_CLEAR_SET_DISPLAY);
+ }
+ }
+ response = ' ';
+ break;
+
+ case 'l': /* Change multibookmarks option. */
+ case 'L':
+ if (LYMBMBlocked) {
+ option_statusline(MULTIBOOKMARKS_DISALLOWED);
+ response = ' ';
+ break;
+ }
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF ");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "STANDARD");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2], "ADVANCED");
+ choices[3] = NULL;
+ if (!LYSelectPopups) {
+ LYMultiBookmarks = boolean_choice((LYMultiBookmarks *
+ (1 + LYMBMAdvanced)),
+ L_HOME, C_MULTI,
+ choices);
+ } else {
+ LYMultiBookmarks = popup_choice((LYMultiBookmarks *
+ (1 + LYMBMAdvanced)),
+ L_HOME, (C_MULTI - 1),
+ choices,
+ 3, FALSE);
+ }
+ if (LYMultiBookmarks == 2) {
+ LYMultiBookmarks = TRUE;
+ LYMBMAdvanced = TRUE;
+ } else {
+ LYMBMAdvanced = FALSE;
+ }
+#if defined(VMS) || defined(USE_SLANG)
+ if (LYSelectPopups) {
+ move(L_HOME, C_MULTI);
+ clrtoeol();
+ addstr(choices[(LYMultiBookmarks * (1 + LYMBMAdvanced))]);
+ }
+#endif /* VMS || USE_SLANG */
+ FREE(choices[0]);
+ FREE(choices[1]);
+ FREE(choices[2]);
+#if !defined(VMS) && !defined(USE_SLANG)
+ if (!LYSelectPopups)
+#endif /* !VMS && !USE_SLANG */
+ {
+ move(L_HOME, B_BOOK);
+ clrtoeol();
+ if (LYMultiBookmarks) {
+ addstr("review/edit B)ookmarks files");
+ } else {
+ addstr("B)ookmark file: ");
+ addstr((bookmark_page && *bookmark_page) ?
+ bookmark_page : "NONE");
+ }
+ }
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+ case 'b': /* Change the bookmark page location. */
+ case 'B':
+ /*
+ * Anonymous users should not be allowed to
+ * change the bookmark page.
+ */
+ if (!no_bookmark) {
+ if (LYMultiBookmarks) {
+ edit_bookmarks();
+ signal(SIGINT, terminate_options);
+ goto draw_options;
+ }
+ if (bookmark_page && *bookmark_page) {
+ strcpy(display_option, bookmark_page);
+ } else { /* clear the NONE */
+ move(L_HOME, C_DEFAULT);
+ clrtoeol();
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_HOME, C_DEFAULT);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_HOME, C_DEFAULT);
+ if (term_options ||
+ ch == -1 || *display_option == '\0') {
+ addstr((bookmark_page && *bookmark_page) ?
+ bookmark_page : "NONE");
+ } else if (!LYPathOffHomeOK(display_option,
+ sizeof(display_option))) {
+ addstr((bookmark_page && *bookmark_page) ?
+ bookmark_page : "NONE");
+ clrtoeol();
+ option_statusline(USE_PATH_OFF_HOME);
+ response = ' ';
+ break;
+ } else {
+ StrAllocCopy(bookmark_page, display_option);
+ StrAllocCopy(MBM_A_subbookmark[0],
+ bookmark_page);
+ addstr(bookmark_page);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ } else { /* anonymous */
+ option_statusline(BOOKMARK_CHANGE_DISALLOWED);
+ }
+ response = ' ';
+ break;
+
+ case 'f': /* Change ftp directory sorting. */
+ case 'F': /* (also local for non-DIRED) */
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "By Filename");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "By Type ");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2], "By Size ");
+ choices[3] = NULL;
+ StrAllocCopy(choices[3], "By Date ");
+ choices[4] = NULL;
+ if (!LYSelectPopups) {
+ HTfileSortMethod = boolean_choice(HTfileSortMethod,
+ L_FTPSTYPE, -1,
+ choices);
+ } else {
+ HTfileSortMethod = popup_choice(HTfileSortMethod,
+ L_FTPSTYPE, -1,
+ choices,
+ 4, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_FTPSTYPE, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(choices[HTfileSortMethod]);
+#endif /* VMS || USE_SLANG */
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ FREE(choices[2]);
+ FREE(choices[3]);
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+ case 'p': /* Change personal mail address for From headers. */
+ case 'P':
+ if (personal_mail_address && *personal_mail_address) {
+ strcpy(display_option, personal_mail_address);
+ } else { /* clear the NONE */
+ move(L_MAIL_ADDRESS, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_MAIL_ADDRESS, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_MAIL_ADDRESS, COL_OPTION_VALUES);
+ if (term_options || ch == -1) {
+ addstr((personal_mail_address &&
+ *personal_mail_address) ?
+ personal_mail_address : "NONE");
+ } else if (*display_option == '\0') {
+ FREE(personal_mail_address);
+ addstr("NONE");
+ } else {
+ StrAllocCopy(personal_mail_address, display_option);
+ addstr(display_option);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ response = ' ';
+ break;
+
+ case 's': /* Change case sentitivity for searches. */
+ case 'S':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "CASE INSENSITIVE");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "CASE SENSITIVE ");
+ choices[2] = NULL;
+ case_sensitive = boolean_choice(case_sensitive,
+ L_SSEARCH, -1, choices);
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+ case '\001': /* Change assume_charset setting. */
+ if (use_assume_charset) {
+ int i, curval;
+ char ** assume_list;
+ assume_list = (char **)calloc(LYNumCharsets + 1, sizeof(char *));
+ if (!assume_list) {
+ outofmem(__FILE__, "options");
+ }
+ for (i = 0; i < LYNumCharsets; i++) {
+ assume_list[i] = (char *)LYCharSet_UC[i].MIMEname;
+ }
+ curval = UCLYhndl_for_unspec;
+ if (curval == current_char_set && UCAssume_MIMEcharset) {
+ curval = UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+ }
+ if (curval < 0)
+ curval = LYRawMode ? current_char_set : 0;
+ if (!LYSelectPopups) {
+ UCLYhndl_for_unspec = boolean_choice(curval,
+ L_ASSUME_CHARSET, -1,
+ assume_list);
+ } else {
+ UCLYhndl_for_unspec = popup_choice(curval,
+ L_ASSUME_CHARSET, -1,
+ assume_list,
+ 0, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_ASSUME_CHARSET, COL_OPTION_VALUES);
+ clrtoeol();
+ if (UCLYhndl_for_unspec >= 0)
+ addstr((char *)
+ LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
+#endif /* VMS || USE_SLANG */
+ }
+
+ /*
+ * Set the raw 8-bit or CJK mode defaults and
+ * character set if changed. - FM
+ */
+ if (CurrentAssumeCharSet != UCLYhndl_for_unspec ||
+ UCLYhndl_for_unspec != curval) {
+ if (UCLYhndl_for_unspec != CurrentAssumeCharSet) {
+ StrAllocCopy(UCAssume_MIMEcharset,
+ LYCharSet_UC[UCLYhndl_for_unspec].MIMEname);
+ }
+ LYRawMode = (UCLYhndl_for_unspec == current_char_set);
+ HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
+ HTMLUseCharacterSet(current_char_set);
+ CurrentAssumeCharSet = UCLYhndl_for_unspec;
+ CurrentRawMode = LYRawMode;
+#if !defined(VMS) && !defined(USE_SLANG)
+ if (!LYSelectPopups)
+#endif /* !VMS && !USE_SLANG */
+ {
+ move(L_Rawmode, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(LYRawMode ? "ON " : "OFF");
+ }
+ }
+ FREE(assume_list);
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ } else {
+ option_statusline(NEED_ADVANCED_USER_MODE);
+ AddValueAccepted = FALSE;
+ }
+ break;
+
+ case 'c': /* Change charset setting. */
+ case 'C':
+ if (!LYSelectPopups) {
+ current_char_set = boolean_choice(current_char_set,
+ L_Charset, -1,
+ (char **)LYchar_set_names);
+ } else {
+ current_char_set = popup_choice(current_char_set,
+ L_Charset, -1,
+ (char **)LYchar_set_names,
+ 0, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_Charset, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr((char *)LYchar_set_names[current_char_set]);
+#endif /* VMS || USE_SLANG */
+ }
+ /*
+ * Set the raw 8-bit or CJK mode defaults and
+ * character set if changed. - FM
+ */
+ if (CurrentCharSet != current_char_set) {
+ HTMLSetRawModeDefault(current_char_set);
+ LYUseDefaultRawMode = TRUE;
+ HTMLUseCharacterSet(current_char_set);
+ CurrentCharSet = current_char_set;
+ CurrentRawMode = LYRawMode;
+#if !defined(VMS) && !defined(USE_SLANG)
+ if (!LYSelectPopups)
+#endif /* !VMS && !USE_SLANG */
+ {
+ move(L_Rawmode, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(LYRawMode ? "ON " : "OFF");
+ }
+ }
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+ case 'o': /* Change raw mode setting. */
+ case 'O':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ LYRawMode = boolean_choice(LYRawMode, L_Rawmode, -1, choices);
+ /*
+ * Set the LYUseDefaultRawMode value and character
+ * handling if LYRawMode was changed. - FM
+ */
+ if (CurrentRawMode != LYRawMode) {
+ HTMLSetUseDefaultRawMode(current_char_set, LYRawMode);
+ HTMLSetCharacterHandling(current_char_set);
+ CurrentRawMode = LYRawMode;
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+ case 'g': /* Change language preference. */
+ case 'G':
+ if (language && *language) {
+ strcpy(display_option, language);
+ } else { /* clear the NONE */
+ move(L_LANGUAGE, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_LANGUAGE, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_LANGUAGE, COL_OPTION_VALUES);
+ if (term_options || ch == -1) {
+ addstr((language && *language) ?
+ language : "NONE");
+ } else if (*display_option == '\0') {
+ FREE(language);
+ addstr("NONE");
+ } else {
+ StrAllocCopy(language, display_option);
+ addstr(display_option);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ response = ' ';
+ break;
+
+ case 'h': /* Change charset preference. */
+ case 'H':
+ if (pref_charset && *pref_charset) {
+ strcpy(display_option, pref_charset);
+ } else { /* clear the NONE */
+ move(L_PREF_CHARSET, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA);
+ move(L_PREF_CHARSET, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_PREF_CHARSET, COL_OPTION_VALUES);
+ if (term_options || ch == -1) {
+ addstr((pref_charset && *pref_charset) ?
+ pref_charset : "NONE");
+ } else if (*display_option == '\0') {
+ FREE(pref_charset);
+ addstr("NONE");
+ } else {
+ StrAllocCopy(pref_charset, display_option);
+ addstr(display_option);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ response = ' ';
+ break;
+
+ case 'v': /* Change VI keys setting. */
+ case 'V':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ vi_keys = boolean_choice(vi_keys,
+ L_Bool_A, C_VIKEYS,
+ choices);
+ if (vi_keys) {
+ set_vi_keys();
+ } else {
+ reset_vi_keys();
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+ case 'M': /* Change emacs keys setting. */
+ case 'm':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ emacs_keys = boolean_choice(emacs_keys,
+ L_Bool_A, C_EMACSKEYS,
+ choices);
+ if (emacs_keys) {
+ set_emacs_keys();
+ } else {
+ reset_emacs_keys();
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+ case 'W': /* Change show dotfiles setting. */
+ case 'w':
+ if (no_dotfiles) {
+ option_statusline(DOTFILE_ACCESS_DISABLED);
+ } else {
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ show_dotfiles = boolean_choice(show_dotfiles,
+ L_Bool_A,
+ C_SHOW_DOTFILES,
+ choices);
+ FREE(choices[0]);
+ FREE(choices[1]);
+ }
+ response = ' ';
+ break;
+
+ case 't': /* Change select popups setting. */
+ case 'T':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ LYSelectPopups = boolean_choice(LYSelectPopups,
+ L_Bool_B,
+ C_SELECT_POPUPS,
+ choices);
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+ case '&': /* Change show color setting. */
+ if (no_option_save) {
+#if defined(COLOR_CURSES)
+ if (!has_colors()) {
+ char * terminal = getenv("TERM");
+ if (terminal)
+ option_user_message(
+ COLOR_TOGGLE_DISABLED_FOR_TERM,
+ terminal);
+ else
+ option_statusline(COLOR_TOGGLE_DISABLED);
+ sleep(AlertSecs);
+ }
+#endif
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ LYShowColor = boolean_choice((LYShowColor - 1),
+ L_Color,
+ C_COLOR,
+ choices);
+ if (LYShowColor == 0) {
+ LYShowColor = SHOW_COLOR_OFF;
+ } else {
+ LYShowColor = SHOW_COLOR_ON;
+ }
+ } else { /* !no_option_save */
+ BOOLEAN again = FALSE;
+ int chosen;
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "NEVER ");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "OFF ");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2], "ON ");
+ choices[3] = NULL;
+#if defined(COLOR_CURSES)
+ if (!has_colors())
+ StrAllocCopy(choices[3], "Always try");
+ else
+#endif
+ StrAllocCopy(choices[3], "ALWAYS ");
+ choices[4] = NULL;
+ do {
+ if (!LYSelectPopups) {
+ chosen = boolean_choice(LYChosenShowColor,
+ L_Color,
+ C_COLOR,
+ choices);
+ } else {
+ chosen = popup_choice(LYChosenShowColor,
+ L_Color,
+ C_COLOR,
+ choices, 4, FALSE);
+ }
+#if defined(COLOR_CURSES)
+ again = (chosen == 2 && !has_colors());
+ if (again) {
+ char * terminal = getenv("TERM");
+ if (terminal)
+ option_user_message(
+ COLOR_TOGGLE_DISABLED_FOR_TERM,
+ terminal);
+ else
+ option_statusline(COLOR_TOGGLE_DISABLED);
+ sleep(AlertSecs);
+ }
+#endif
+ } while (again);
+ LYChosenShowColor = chosen;
+#if defined(VMS)
+ if (LYSelectPopups) {
+ move(L_Color, C_COLOR);
+ clrtoeol();
+ addstr(choices[LYChosenShowColor]);
+ }
+#endif /* VMS */
+#if defined(COLOR_CURSES)
+ if (has_colors())
+#endif
+ LYShowColor = chosen;
+ FREE(choices[2]);
+ FREE(choices[3]);
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ if (CurrentShowColor != LYShowColor) {
+ lynx_force_repaint();
+ }
+ CurrentShowColor = LYShowColor;
+#ifdef USE_SLANG
+ SLtt_Use_Ansi_Colors = (LYShowColor > 1 ? 1 : 0);
+#endif
+ response = ' ';
+ if (LYSelectPopups && !no_option_save) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+#endif /* USE_SLANG or COLOR_CURSES */
+
+ case '@': /* Change show cursor setting. */
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "OFF");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "ON ");
+ choices[2] = NULL;
+ LYShowCursor = boolean_choice(LYShowCursor,
+ L_Bool_B,
+ C_SHOW_CURSOR,
+ choices);
+ FREE(choices[0]);
+ FREE(choices[1]);
+ response = ' ';
+ break;
+
+ case 'k': /* Change keypad mode. */
+ case 'K':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0],
+ "Numbers act as arrows ");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1],
+ "Links are numbered ");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2],
+ "Links and form fields are numbered");
+ choices[3] = NULL;
+ if (!LYSelectPopups) {
+ keypad_mode = boolean_choice(keypad_mode,
+ L_Keypad, -1,
+ choices);
+ } else {
+ keypad_mode = popup_choice(keypad_mode,
+ L_Keypad, -1,
+ choices,
+ 3, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_Keypad, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(choices[keypad_mode]);
+#endif /* VMS || USE_SLANG */
+ }
+ if (keypad_mode == NUMBERS_AS_ARROWS) {
+ set_numbers_as_arrows();
+ } else {
+ reset_numbers_as_arrows();
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ FREE(choices[2]);
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+ case 'n': /* Change line editor key bindings. */
+ case 'N':
+ if (!LYSelectPopups) {
+ current_lineedit = boolean_choice(current_lineedit,
+ L_Lineed, -1,
+ LYLineeditNames);
+ } else {
+ current_lineedit = popup_choice(current_lineedit,
+ L_Lineed, -1,
+ LYLineeditNames,
+ 0, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_Lineed, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(LYLineeditNames[current_lineedit]);
+#endif /* VMS || USE_SLANG */
+ }
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+#ifdef DIRED_SUPPORT
+ case 'i': /* Change local directory sorting. */
+ case 'I':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "Directories first");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "Files first ");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2], "Mixed style ");
+ choices[3] = NULL;
+ if (!LYSelectPopups) {
+ dir_list_style = boolean_choice(dir_list_style,
+ L_Dired, -1,
+ choices);
+ } else {
+ dir_list_style = popup_choice(dir_list_style,
+ L_Dired, -1,
+ choices,
+ 3, FALSE);
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_Dired, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(choices[dir_list_style]);
+#endif /* VMS || USE_SLANG */
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ FREE(choices[2]);
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+#endif /* DIRED_SUPPORT */
+
+ case 'u': /* Change user mode. */
+ case 'U':
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "Novice ");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "Intermediate");
+ choices[2] = NULL;
+ StrAllocCopy(choices[2], "Advanced ");
+ choices[3] = NULL;
+ if (!LYSelectPopups) {
+ user_mode = boolean_choice(user_mode,
+ L_User_Mode, -1,
+ choices);
+ use_assume_charset = (user_mode >= 2);
+ } else {
+ user_mode = popup_choice(user_mode,
+ L_User_Mode, -1,
+ choices,
+ 3, FALSE);
+ use_assume_charset = (user_mode >= 2);
+#if defined(VMS) || defined(USE_SLANG)
+ if (use_assume_charset == old_use_assume_charset) {
+ move(L_User_Mode, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(choices[user_mode]);
+ }
+#endif /* VMS || USE_SLANG */
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+ FREE(choices[2]);
+ if (user_mode == NOVICE_MODE) {
+ display_lines = (LYlines - 4);
+ } else {
+ display_lines = LYlines-2;
+ }
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+ if (use_assume_charset != old_use_assume_charset)
+ goto draw_options;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+
+ case 'a': /* Change user agent string. */
+ case 'A':
+ if (!no_useragent) {
+ if (LYUserAgent && *LYUserAgent) {
+ strcpy(display_option, LYUserAgent);
+ } else { /* clear the NONE */
+ move(L_HOME, COL_OPTION_VALUES);
+ addstr(" ");
+ *display_option = '\0';
+ }
+ option_statusline(ACCEPT_DATA_OR_DEFAULT);
+ move(L_User_Agent, COL_OPTION_VALUES);
+ start_bold();
+ ch = LYgetstr(display_option, VISIBLE,
+ sizeof(display_option), NORECALL);
+ stop_bold();
+ move(L_User_Agent, COL_OPTION_VALUES);
+ if (term_options || ch == -1) {
+ addstr((LYUserAgent &&
+ *LYUserAgent) ?
+ LYUserAgent : "NONE");
+ } else if (*display_option == '\0') {
+ StrAllocCopy(LYUserAgent, LYUserAgentDefault);
+ addstr((LYUserAgent &&
+ *LYUserAgent) ?
+ LYUserAgent : "NONE");
+ } else {
+ StrAllocCopy(LYUserAgent, display_option);
+ addstr(display_option);
+ }
+ clrtoeol();
+ if (ch == -1) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else if (LYUserAgent && *LYUserAgent &&
+ !strstr(LYUserAgent, "Lynx") &&
+ !strstr(LYUserAgent, "lynx")) {
+ option_statusline(UA_COPYRIGHT_WARNING);
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ } else { /* disallowed */
+ option_statusline(UA_COPYRIGHT_WARNING);
+ }
+ response = ' ';
+ break;
+
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ case 'x': /* Change local exec restriction. */
+ case 'X':
+ if (exec_frozen && !LYSelectPopups) {
+ option_statusline(CHANGE_OF_SETTING_DISALLOWED);
+ response = ' ';
+ break;
+ }
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ if (local_exec) {
+ itmp = 2;
+ } else
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+ {
+ if (local_exec_on_local_files) {
+ itmp= 1;
+ } else {
+ itmp = 0;
+ }
+ }
+ /*
+ * Copy strings into choice array.
+ */
+ choices[0] = NULL;
+ StrAllocCopy(choices[0], "ALWAYS OFF ");
+ choices[1] = NULL;
+ StrAllocCopy(choices[1], "FOR LOCAL FILES ONLY");
+ choices[2] = NULL;
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ StrAllocCopy(choices[2], "ALWAYS ON ");
+ choices[3] = NULL;
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+ if (!LYSelectPopups) {
+ itmp = boolean_choice(itmp,
+ L_Exec, -1,
+ choices);
+ } else {
+ itmp = popup_choice(itmp,
+ L_Exec, -1,
+ choices,
+ 0, (exec_frozen ? TRUE : FALSE));
+#if defined(VMS) || defined(USE_SLANG)
+ move(L_Exec, COL_OPTION_VALUES);
+ clrtoeol();
+ addstr(choices[itmp]);
+#endif /* VMS || USE_SLANG */
+ }
+ FREE(choices[0]);
+ FREE(choices[1]);
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ FREE(choices[2]);
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+ if (!exec_frozen) {
+ switch (itmp) {
+ case 0:
+ local_exec = FALSE;
+ local_exec_on_local_files = FALSE;
+ break;
+ case 1:
+ local_exec = FALSE;
+ local_exec_on_local_files = TRUE;
+ break;
+#ifndef NEVER_ALLOW_REMOTE_EXEC
+ case 2:
+ local_exec = TRUE;
+ local_exec_on_local_files = FALSE;
+ break;
+#endif /* !NEVER_ALLOW_REMOTE_EXEC */
+ } /* end switch */
+ }
+ response = ' ';
+ if (LYSelectPopups) {
+#if !defined(VMS) || defined(USE_SLANG)
+ if (exec_frozen || term_options) {
+ term_options = FALSE;
+ } else {
+ AddValueAccepted = TRUE;
+ }
+ goto draw_options;
+#else
+ term_options = FALSE;
+#endif /* !VMS || USE_SLANG */
+ }
+ break;
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+
+ case '>': /* Save current options to RC file. */
+ if (!no_option_save) {
+ option_statusline(SAVING_OPTIONS);
+ if (save_rc()) {
+ LYrcShowColor = LYChosenShowColor;
+ option_statusline(OPTIONS_SAVED);
+ } else {
+ HTAlert(OPTIONS_NOT_SAVED);
+ }
+ } else {
+ option_statusline(R_TO_RETURN_TO_LYNX);
+ /*
+ * Change response so that we don't exit
+ * the options menu.
+ */
+ response = ' ';
+ }
+ break;
+
+ case 'r': /* Return to document (quit options menu). */
+ case 'R':
+ break;
+
+ default:
+ if (!no_option_save) {
+ option_statusline(SAVE_OR_R_TO_RETURN_TO_LYNX);
+ } else {
+ option_statusline(R_TO_RETURN_TO_LYNX);
+ }
+ } /* end switch */
+ } /* end while */
+
+ term_options = FALSE;
+ signal(SIGINT, cleanup_sig);
+}
+
+/*
+ * Take a boolean status,prompt the user for a new status,
+ * and return it.
+ */
+PRIVATE int boolean_choice ARGS4(
+ int, cur_choice,
+ int, line,
+ int, column,
+ char **, choices)
+{
+ int response = 0;
+ int cmd = 0;
+ int number = 0;
+ int col = (column >= 0 ? column : COL_OPTION_VALUES);
+ int orig_choice = cur_choice;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
+
+ /*
+ * Get the number of choices and then make
+ * number zero-based.
+ */
+ for (number = 0; choices[number] != NULL; number++)
+ ; /* empty loop body */
+ number--;
+
+ /*
+ * Update the statusline.
+ */
+ option_statusline(ANY_KEY_CHANGE_RET_ACCEPT);
+
+ /*
+ * Highlight the current choice.
+ */
+ move(line, col);
+ start_reverse();
+ addstr(choices[cur_choice]);
+ if (LYShowCursor)
+ move(line, (col - 1));
+ refresh();
+
+ /*
+ * Get the keyboard entry, and leave the
+ * cursor at the choice, to indicate that
+ * it can be changed, until the user accepts
+ * the current choice.
+ */
+ term_options = FALSE;
+ while (1) {
+ move(line, col);
+ if (term_options == FALSE) {
+ response = LYgetch();
+ }
+ if (term_options || response == 7 || response == 3) {
+ /*
+ * Control-C or Control-G.
+ */
+ response = '\n';
+ term_options = TRUE;
+ cur_choice = orig_choice;
+ }
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ response = '\n';
+ term_options = TRUE;
+ cur_choice = orig_choice;
+ }
+#endif /* VMS */
+ if ((response != '\n' && response != '\r') &&
+ (cmd = keymap[response+1]) != LYK_ACTIVATE) {
+ switch (cmd) {
+ case LYK_HOME:
+ cur_choice = 0;
+ break;
+
+ case LYK_END:
+ cur_choice = number;
+ break;
+
+ case LYK_REFRESH:
+ lynx_force_repaint();
+ refresh();
+ break;
+
+ case LYK_QUIT:
+ case LYK_ABORT:
+ case LYK_PREV_DOC:
+ cur_choice = orig_choice;
+ term_options = TRUE;
+ break;
+
+ case LYK_PREV_PAGE:
+ case LYK_UP_HALF:
+ case LYK_UP_TWO:
+ case LYK_PREV_LINK:
+ case LYK_UP_LINK:
+ case LYK_LEFT_LINK:
+ if (cur_choice == 0)
+ cur_choice = number; /* go back to end */
+ else
+ cur_choice--;
+ break;
+
+ case LYK_1:
+ case LYK_2:
+ case LYK_3:
+ case LYK_4:
+ case LYK_5:
+ case LYK_6:
+ case LYK_7:
+ case LYK_8:
+ case LYK_9:
+ if((cmd - LYK_1 + 1) <= number) {
+ cur_choice = cmd -LYK_1 + 1;
+ break;
+ } /* else fall through! */
+ default:
+ if (cur_choice == number)
+ cur_choice = 0; /* go over the top and around */
+ else
+ cur_choice++;
+ } /* end of switch */
+ addstr(choices[cur_choice]);
+ if (LYShowCursor)
+ move(line, (col - 1));
+ refresh();
+ } else {
+ /*
+ * Unhighlight choice.
+ */
+ move(line, col);
+ stop_reverse();
+ addstr(choices[cur_choice]);
+
+ if (term_options) {
+ term_options = FALSE;
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ option_statusline("");
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ }
+ return(cur_choice);
+ }
+ }
+}
+
+PRIVATE void terminate_options ARGS1(
+ int, sig GCC_UNUSED)
+{
+ term_options = TRUE;
+ /*
+ * Reassert the AST.
+ */
+ signal(SIGINT, terminate_options);
+#ifdef VMS
+ /*
+ * Refresh the screen to get rid of the "interrupt" message.
+ */
+ if (!dump_output_immediately) {
+ lynx_force_repaint();
+ refresh();
+ }
+#endif /* VMS */
+}
+
+/*
+ * Multi-Bookmark On-Line editing support. - FMG & FM
+ */
+PUBLIC void edit_bookmarks NOARGS
+{
+ int response = 0, def_response = 0, ch;
+ int MBM_current = 1;
+#define MULTI_OFFSET 8
+ int a; /* misc counter */
+ char MBM_tmp_line[256]; /* buffer for LYgetstr */
+ char ehead_buffer[265];
+
+ /*
+ * We need (MBM_V_MAXFILES + MULTI_OFFSET) lines to display
+ * the whole list at once. Otherwise break it up into two
+ * segments. We know it won't be less than that because
+ * 'o'ptions needs 23-24 at LEAST.
+ */
+ term_options = FALSE;
+ signal(SIGINT, terminate_options);
+
+draw_bookmark_list:
+ /*
+ * Display menu of bookmarks. NOTE that we avoid printw()'s
+ * to increase the chances that any non-ASCII or multibyte/CJK
+ * characters will be handled properly. - FM
+ */
+#if defined(FANCY_CURSES) || defined (USE_SLANG)
+ if (enable_scrollback) {
+ clear();
+ } else {
+ erase();
+ }
+#else
+ clear();
+#endif /* FANCY_CURSES || USE_SLANG */
+ move(0, 5);
+ lynx_start_h1_color ();
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
+ sprintf(ehead_buffer, MULTIBOOKMARKS_EHEAD_MASK, MBM_current);
+ addstr(ehead_buffer);
+ } else {
+ addstr(MULTIBOOKMARKS_EHEAD);
+ }
+ lynx_stop_h1_color ();
+
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
+ for (a = ((MBM_V_MAXFILES/2 + 1) * (MBM_current - 1));
+ a <= ((float)MBM_V_MAXFILES/2 * MBM_current); a++) {
+ move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)), 5);
+ addch((unsigned char)(a + 'A'));
+ addstr(" : ");
+ if (MBM_A_subdescript[a])
+ addstr(MBM_A_subdescript[a]);
+ move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)), 35);
+ addstr("| ");
+ if (MBM_A_subbookmark[a]) {
+ addstr(MBM_A_subbookmark[a]);
+ }
+ }
+ } else {
+ for (a = 0; a <= MBM_V_MAXFILES; a++) {
+ move(3 + a, 5);
+ addch((unsigned char)(a + 'A'));
+ addstr(" : ");
+ if (MBM_A_subdescript[a])
+ addstr(MBM_A_subdescript[a]);
+ move(3 + a, 35);
+ addstr("| ");
+ if (MBM_A_subbookmark[a]) {
+ addstr(MBM_A_subbookmark[a]);
+ }
+ }
+ }
+
+ /*
+ * Only needed when we have 2 screens.
+ */
+ if (LYlines < MBM_V_MAXFILES + MULTI_OFFSET) {
+ move((LYlines - 4), 0);
+ addstr("'");
+ start_bold();
+ addstr("[");
+ stop_bold();
+ addstr("' ");
+ addstr(PREVIOUS);
+ addstr(", '");
+ start_bold();
+ addstr("]");
+ stop_bold();
+ addstr("' ");
+ addstr(NEXT_SCREEN);
+ }
+
+ move((LYlines - 3), 0);
+ if (!no_option_save) {
+ addstr("'");
+ start_bold();
+ addstr(">");
+ stop_bold();
+ addstr("'");
+ addstr(TO_SAVE_SEGMENT);
+ }
+ addstr(OR_SEGMENT);
+ addstr("'");
+ start_bold();
+ addstr("^G");
+ stop_bold();
+ addstr("'");
+ addstr(TO_RETURN_SEGMENT);
+
+ while (!term_options &&
+ !LYisNonAlnumKeyname(response, LYK_PREV_DOC) &&
+ response != 7 && response != 3 &&
+ response != '>') {
+
+ move((LYlines - 2), 0);
+ lynx_start_prompt_color ();
+ addstr(MULTIBOOKMARKS_LETTER);
+ lynx_stop_prompt_color ();
+
+ refresh();
+ response = (def_response ? def_response : LYgetch());
+ def_response = 0;
+
+ /*
+ * Check for a cancel.
+ */
+ if (term_options ||
+ response == 7 || response == 3 ||
+ LYisNonAlnumKeyname(response, LYK_PREV_DOC))
+ continue;
+
+ /*
+ * Check for a save.
+ */
+ if (response == '>') {
+ if (!no_option_save) {
+ option_statusline(SAVING_OPTIONS);
+ if (save_rc())
+ option_statusline(OPTIONS_SAVED);
+ else
+ HTAlert(OPTIONS_NOT_SAVED);
+ } else {
+ option_statusline(R_TO_RETURN_TO_LYNX);
+ /*
+ * Change response so that we don't exit
+ * the options menu.
+ */
+ response = ' ';
+ }
+ continue;
+ }
+
+ /*
+ * Check for a refresh.
+ */
+ if (LYisNonAlnumKeyname(response, LYK_REFRESH)) {
+ lynx_force_repaint();
+ continue;
+ }
+
+ /*
+ * Move between the screens - if we can't show it all at once.
+ */
+ if ((response == ']' ||
+ LYisNonAlnumKeyname(response, LYK_NEXT_PAGE)) &&
+ LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
+ MBM_current++;
+ if (MBM_current >= 3)
+ MBM_current = 1;
+ goto draw_bookmark_list;
+ }
+ if ((response == '[' ||
+ LYisNonAlnumKeyname(response, LYK_PREV_PAGE)) &&
+ LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
+ MBM_current--;
+ if (MBM_current <= 0)
+ MBM_current = 2;
+ goto draw_bookmark_list;
+ }
+
+ /*
+ * Instead of using 26 case statements, we set up
+ * a scan through the letters and edit the lines
+ * that way.
+ */
+ for (a = 0; a <= MBM_V_MAXFILES; a++) {
+ if ((TOUPPER(response) - 'A') == a) {
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET)) {
+ if (MBM_current == 1 && a > (MBM_V_MAXFILES/2)) {
+ MBM_current = 2;
+ def_response = response;
+ goto draw_bookmark_list;
+ }
+ if (MBM_current == 2 && a < (MBM_V_MAXFILES/2)) {
+ MBM_current = 1;
+ def_response = response;
+ goto draw_bookmark_list;
+ }
+ }
+ option_statusline(ACCEPT_DATA);
+
+ if (a > 0) {
+ start_bold();
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
+ move(
+ (3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)),
+ 9);
+ else
+ move((3 + a), 9);
+ strcpy(MBM_tmp_line,
+ (!MBM_A_subdescript[a] ?
+ "" : MBM_A_subdescript[a]));
+ ch = LYgetstr(MBM_tmp_line, VISIBLE,
+ sizeof(MBM_tmp_line), NORECALL);
+ stop_bold();
+
+ if (strlen(MBM_tmp_line) < 1) {
+ FREE(MBM_A_subdescript[a]);
+ } else {
+ StrAllocCopy(MBM_A_subdescript[a], MBM_tmp_line);
+ }
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
+ move(
+ (3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)),
+ 5);
+ else
+ move((3 + a), 5);
+ addch((unsigned char)(a + 'A'));
+ addstr(" : ");
+ if (MBM_A_subdescript[a])
+ addstr(MBM_A_subdescript[a]);
+ clrtoeol();
+ refresh();
+ }
+
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
+ move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current - 1)),
+ 35);
+ else
+ move((3 + a), 35);
+ addstr("| ");
+
+ start_bold();
+ strcpy(MBM_tmp_line,
+ (!MBM_A_subbookmark[a] ? "" : MBM_A_subbookmark[a]));
+ ch = LYgetstr(MBM_tmp_line, VISIBLE,
+ sizeof(MBM_tmp_line), NORECALL);
+ stop_bold();
+
+ if (*MBM_tmp_line == '\0') {
+ if (a == 0)
+ StrAllocCopy(MBM_A_subbookmark[a], bookmark_page);
+ else
+ FREE(MBM_A_subbookmark[a]);
+ } else if (!LYPathOffHomeOK(MBM_tmp_line,
+ sizeof(MBM_tmp_line))) {
+ LYMBM_statusline(USE_PATH_OFF_HOME);
+ sleep(AlertSecs);
+ } else {
+ StrAllocCopy(MBM_A_subbookmark[a], MBM_tmp_line);
+ if (a == 0) {
+ StrAllocCopy(bookmark_page, MBM_A_subbookmark[a]);
+ }
+ }
+ if (LYlines < (MBM_V_MAXFILES + MULTI_OFFSET))
+ move((3 + a) - ((MBM_V_MAXFILES/2 + 1)*(MBM_current-1)),
+ 35);
+ else
+ move((3 + a), 35);
+ addstr("| ");
+ if (MBM_A_subbookmark[a])
+ addstr(MBM_A_subbookmark[a]);
+ clrtoeol();
+ move(LYlines-1, 0);
+ clrtoeol();
+ break;
+ }
+ } /* end for */
+ } /* end while */
+
+ term_options = FALSE;
+ signal(SIGINT, cleanup_sig);
+}
+
+/*
+** This function prompts for a choice or page number.
+** If a 'g' or 'p' suffix is included, that will be
+** loaded into c. Otherwise, c is zeroed. - FM
+*/
+PRIVATE int get_popup_choice_number ARGS1(
+ int *, c)
+{
+ char temp[120];
+
+ /*
+ * Load the c argument into the prompt buffer.
+ */
+ temp[0] = *c;
+ temp[1] = '\0';
+ option_statusline(OPTION_CHOICE_NUMBER);
+
+ /*
+ * Get the number, possibly with a suffix, from the user.
+ */
+ if (LYgetstr(temp, VISIBLE, sizeof(temp), NORECALL) < 0 ||
+ *temp == 0 || term_options) {
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ *c = '\0';
+ term_options = FALSE;
+ return(0);
+ }
+
+ /*
+ * If we had a 'g' or 'p' suffix, load it into c.
+ * Otherwise, zero c. Then return the number.
+ */
+ if (strchr(temp, 'g') != NULL || strchr(temp, 'G') != NULL) {
+ *c = 'g';
+ } else if (strchr(temp, 'p') != NULL || strchr(temp, 'P') != NULL) {
+ *c = 'p';
+ } else {
+ *c = '\0';
+ }
+ return(atoi(temp));
+}
+
+/*
+ * This function offers the choices for values of an
+ * option via a popup window which functions like
+ * that for selection of options in a form. - FM
+ */
+PRIVATE int popup_choice ARGS6(
+ int, cur_choice,
+ int, line,
+ int, column,
+ char **, choices,
+ int, i_length,
+ int, disabled)
+{
+ int ly = line;
+ int lx = (column >= 0 ? column : (COL_OPTION_VALUES - 1));
+ int c = 0, cmd = 0, i = 0, j = 0;
+ int orig_choice = cur_choice;
+#ifndef USE_SLANG
+ WINDOW * form_window;
+#endif /* !USE_SLANG */
+ int num_choices = 0, top, bottom, length = -1, width = 0;
+ char ** Cptr = choices;
+ int window_offset = 0;
+ int DisplayLines = (LYlines - 2);
+ char Cnum[64];
+ int Lnum;
+ int npages;
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt; /* Flag from cleanup_sig() AST */
+#endif /* VMS */
+ static char prev_target[512]; /* Search string buffer */
+ static char prev_target_buffer[512]; /* Next search buffer */
+ static BOOL first = TRUE;
+ char *cp;
+ int ch = 0, recall;
+ int QueryTotal;
+ int QueryNum;
+ BOOLEAN FirstRecall = TRUE;
+ BOOLEAN ReDraw = FALSE;
+ int number;
+ char buffer[512];
+
+ /*
+ * Initialize the search string buffer. - FM
+ */
+ if (first) {
+ *prev_target_buffer = '\0';
+ first = FALSE;
+ }
+ *prev_target = '\0';
+ QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
+ recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+
+ /*
+ * Count the number of choices to be displayed, where
+ * num_choices ranges from 0 to n, and set width to the
+ * longest choice string length. Also set Lnum to the
+ * length for the highest choice number, then decrement
+ * num_choices so as to be zero-based. The window width
+ * will be based on the sum of width and Lnum. - FM
+ */
+ for (num_choices = 0; Cptr[num_choices] != NULL; num_choices++) {
+ if (strlen(Cptr[num_choices]) > width) {
+ width = strlen(Cptr[num_choices]);
+ }
+ }
+ sprintf(Cnum, "%d: ", num_choices);
+ Lnum = strlen(Cnum);
+ num_choices--;
+
+ /*
+ * Let's assume for the sake of sanity that ly is the number
+ * corresponding to the line the option is on.
+ * Let's also assume that cur_choice is the number of the
+ * choice that should be initially selected, with 0 being
+ * the first choice.
+ * So what we have, is the top equal to the current screen line
+ * subtracting the cur_choice + 1 (the one must be for the top
+ * line we will draw in a box). If the top goes under 0, then
+ * consider it 0.
+ */
+ top = ly - (cur_choice + 1);
+ if (top < 0)
+ top = 0;
+
+ /*
+ * Check and see if we need to put the i_length parameter up to
+ * the number of real choices.
+ */
+ if (i_length < 1) {
+ i_length = num_choices;
+ } else {
+ /*
+ * Otherwise, it is really one number too high.
+ */
+ i_length--;
+ }
+
+ /*
+ * The bottom is the value of the top plus the number of choices
+ * to view plus 3 (one for the top line, one for the bottom line,
+ * and one to offset the 0 counted in the num_choices).
+ */
+ bottom = top + i_length + 3;
+
+ /*
+ * Hmm... If the bottom goes beyond the number of lines available,
+ */
+ if (bottom > DisplayLines) {
+ /*
+ * Position the window at the top if we have more
+ * choices than will fit in the window.
+ */
+ if ((i_length + 3) > DisplayLines) {
+ top = 0;
+ bottom = (top + (i_length + 3));
+ if (bottom > DisplayLines)
+ bottom = (DisplayLines + 1);
+ } else {
+ /*
+ * Try to position the window so that the selected choice will
+ * appear where the choice box currently is positioned.
+ * It could end up too high, at this point, but we'll move it
+ * down latter, if that has happened.
+ */
+ top = (DisplayLines + 1) - (i_length + 3);
+ bottom = (DisplayLines + 1);
+ }
+ }
+
+ /*
+ * This is really fun, when the length is 4, it means 0 to 4, or 5.
+ */
+ length = (bottom - top) - 2;
+
+ /*
+ * Move the window down if it's too high.
+ */
+ if (bottom < ly + 2) {
+ bottom = ly + 2;
+ if (bottom > DisplayLines + 1)
+ bottom = DisplayLines + 1;
+ top = bottom - length - 2;
+ }
+
+ /*
+ * Set up the overall window, including the boxing characters ('*'),
+ * if it all fits. Otherwise, set up the widest window possible. - FM
+ */
+#ifdef USE_SLANG
+ SLsmg_fill_region(top, lx - 1, bottom - top, (Lnum + width + 4), ' ');
+#else
+ if (!(form_window = newwin(bottom - top, (Lnum + width + 4),
+ top, (lx - 1))) &&
+ !(form_window = newwin(bottom - top, 0, top, 0))) {
+ option_statusline(POPUP_FAILED);
+ return(orig_choice);
+ }
+ scrollok(form_window, TRUE);
+#ifdef PDCURSES
+ keypad(form_window, TRUE);
+#endif /* PDCURSES */
+#ifdef NCURSES
+ LYsubwindow(form_window);
+#endif
+#if defined(HAVE_GETBKGD) /* not defined in ncurses 1.8.7 */
+ wbkgd(form_window, getbkgd(stdscr));
+ wbkgdset(form_window, getbkgd(stdscr));
+#endif
+#endif /* USE_SLANG */
+
+ /*
+ * Clear the command line and write
+ * the popup statusline. - FM
+ */
+ move((LYlines - 2), 0);
+ clrtoeol();
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+
+ /*
+ * Set up the window_offset for choices.
+ * cur_choice ranges from 0...n
+ * length ranges from 0...m
+ */
+ if (cur_choice >= length) {
+ window_offset = cur_choice - length + 1;
+ }
+
+ /*
+ * Compute the number of popup window pages. - FM
+ */
+ npages = ((num_choices + 1) > length) ?
+ (((num_choices + 1) + (length - 1))/(length))
+ : 1;
+/*
+ * OH! I LOVE GOTOs! hack hack hack
+ */
+redraw:
+ Cptr = choices;
+
+ /*
+ * Display the boxed choices.
+ */
+ for (i = 0; i <= num_choices; i++) {
+ if (i >= window_offset && i - window_offset < length) {
+ sprintf(Cnum, "%s%d: ",
+ ((num_choices > 8 && i < 9) ?
+ " " : ""),
+ (i + 1));
+#ifdef USE_SLANG
+ SLsmg_gotorc(top + ((i + 1) - window_offset), (lx - 1 + 2));
+ addstr(Cnum);
+ SLsmg_write_nstring(Cptr[i], width);
+#else
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ wclrtoeol(form_window);
+ waddstr(form_window, Cnum);
+ waddstr(form_window, Cptr[i]);
+#endif /* USE_SLANG */
+ }
+ }
+#ifdef USE_SLANG
+ SLsmg_draw_box(top, (lx - 1), (bottom - top), (Lnum + width + 4));
+#else
+#ifdef VMS
+ VMSbox(form_window, (bottom - top), (Lnum + width + 4));
+#else
+ LYbox(form_window, FALSE);
+#endif /* VMS */
+ wrefresh(form_window);
+#endif /* USE_SLANG */
+ Cptr = NULL;
+
+ /*
+ * Loop on user input.
+ */
+ while (cmd != LYK_ACTIVATE) {
+ /*
+ * Unreverse cur choice.
+ */
+ if (Cptr != NULL) {
+ sprintf(Cnum, "%s%d: ",
+ ((num_choices > 8 && i < 9) ?
+ " " : ""),
+ (i + 1));
+#ifdef USE_SLANG
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+ addstr(Cnum);
+ SLsmg_write_nstring(Cptr[i], width);
+#else
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ waddstr(form_window, Cnum);
+ waddstr(form_window, Cptr[i]);
+#endif /* USE_SLANG */
+ }
+ Cptr = choices;
+ i = cur_choice;
+ sprintf(Cnum, "%s%d: ",
+ ((num_choices > 8 && i < 9) ?
+ " " : ""),
+ (i + 1));
+#ifdef USE_SLANG
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 2));
+ addstr(Cnum);
+ SLsmg_set_color(2);
+ SLsmg_write_nstring(Cptr[i], width);
+ SLsmg_set_color(0);
+ /*
+ * If LYShowCursor is ON, move the cursor to the left
+ * of the current choice, so that blind users, who are
+ * most likely to have LYShowCursor ON, will have it's
+ * string spoken or passed to the braille interface as
+ * each choice is made current. Otherwise, move it to
+ * the bottom, right column of the screen, to "hide"
+ * the cursor as for the main document, and let sighted
+ * users rely on the current choice's highlighting or
+ * color without the distraction of a blinking cursor
+ * in the window. - FM
+ */
+ if (LYShowCursor)
+ SLsmg_gotorc((top + ((i + 1) - window_offset)), (lx - 1 + 1));
+ else
+ SLsmg_gotorc((LYlines - 1), (LYcols - 1));
+ SLsmg_refresh();
+#else
+ wmove(form_window, ((i + 1) - window_offset), 2);
+ waddstr(form_window, Cnum);
+ wstart_reverse(form_window);
+ waddstr(form_window, Cptr[i]);
+ wstop_reverse(form_window);
+ /*
+ * If LYShowCursor is ON, move the cursor to the left
+ * of the current choice, so that blind users, who are
+ * most likely to have LYShowCursor ON, will have it's
+ * string spoken or passed to the braille interface as
+ * each choice is made current. Otherwise, leave it to
+ * the right of the current choice, since we can't move
+ * it out of the window, and let sighted users rely on
+ * the highlighting of the current choice without the
+ * distraction of a blinking cursor preceding it. - FM
+ */
+ if (LYShowCursor)
+ wmove(form_window, ((i + 1) - window_offset), 1);
+ wrefresh(form_window);
+#endif /* USE_SLANG */
+
+ term_options = FALSE;
+ c = LYgetch();
+ if (term_options || c == 3 || c == 7) {
+ /*
+ * Control-C or Control-G
+ */
+ cmd = LYK_QUIT;
+ } else {
+ cmd = keymap[c+1];
+ }
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ cmd = LYK_QUIT;
+ }
+#endif /* VMS */
+
+ switch(cmd) {
+ case LYK_F_LINK_NUM:
+ c = '\0';
+ case LYK_1:
+ case LYK_2:
+ case LYK_3:
+ case LYK_4:
+ case LYK_5:
+ case LYK_6:
+ case LYK_7:
+ case LYK_8:
+ case LYK_9:
+ /*
+ * Get a number from the user, possibly with
+ * a 'g' or 'p' suffix (which will be loaded
+ * into c). - FM & LE
+ */
+ number = get_popup_choice_number((int *)&c);
+
+ /*
+ * Check for a 'p' suffix. - FM
+ */
+ if (c == 'p') {
+ /*
+ * Treat 1 or less as the first page. - FM
+ */
+ if (number <= 1) {
+ if (window_offset == 0) {
+ option_statusline(ALREADY_AT_CHOICE_BEGIN);
+ sleep(MessageSecs);
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ break;
+ }
+ window_offset = 0;
+ cur_choice = 0;
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * Treat a number equal to or greater than the
+ * number of pages as the last page. - FM
+ */
+ if (number >= npages) {
+ if (window_offset >= ((num_choices - length) + 1)) {
+ option_statusline(ALREADY_AT_CHOICE_END);
+ sleep(MessageSecs);
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ break;
+ }
+ window_offset = ((npages - 1) * length);
+ if (window_offset > (num_choices - length)) {
+ window_offset = (num_choices - length + 1);
+ }
+ if (cur_choice < window_offset)
+ cur_choice = window_offset;
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * We want an intermediate page. - FM
+ */
+ if (((number - 1) * length) == window_offset) {
+ sprintf(buffer, ALREADY_AT_CHOICE_PAGE, number);
+ option_statusline(buffer);
+ sleep(MessageSecs);
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ break;
+ }
+ cur_choice = window_offset = ((number - 1) * length);
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ goto redraw;
+
+ }
+
+ /*
+ * Check for a positive number, which signifies
+ * that a choice should be sought. - FM
+ */
+ if (number > 0) {
+ /*
+ * Decrement the number so as to correspond
+ * with our cur_choice values. - FM
+ */
+ number--;
+
+ /*
+ * If the number is in range and had no legal
+ * suffix, select the indicated choice. - FM
+ */
+ if (number <= num_choices && c == '\0') {
+ cur_choice = number;
+ cmd = LYK_ACTIVATE;
+ break;
+ }
+
+ /*
+ * Verify that we had a 'g' suffix,
+ * and act on the number. - FM
+ */
+ if (c == 'g') {
+ if (cur_choice == number) {
+ /*
+ * The choice already is current. - FM
+ */
+ sprintf(buffer,
+ CHOICE_ALREADY_CURRENT, (number + 1));
+ option_statusline(buffer);
+ sleep(MessageSecs);
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ break;
+ }
+
+ if (number <= num_choices) {
+ /*
+ * The number is in range and had a 'g'
+ * suffix, so make it the current choice,
+ * scrolling if needed. - FM
+ */
+ j = (number - cur_choice);
+ cur_choice = number;
+ if ((j > 0) &&
+ (cur_choice - window_offset) >= length) {
+ window_offset += j;
+ if (window_offset > (num_choices - length + 1))
+ window_offset = (num_choices - length + 1);
+ } else if ((cur_choice - window_offset) < 0) {
+ window_offset -= abs(j);
+ if (window_offset < 0)
+ window_offset = 0;
+ }
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ goto redraw;
+ }
+
+ /*
+ * Not in range. - FM
+ */
+ option_statusline(BAD_CHOICE_NUM_ENTERED);
+ sleep(MessageSecs);
+ }
+ }
+
+ /*
+ * Restore the popup statusline. - FM
+ */
+ if (disabled) {
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ } else {
+ option_statusline(CHOICE_LIST_MESSAGE);
+ }
+ break;
+
+ case LYK_PREV_LINK:
+ case LYK_UP_LINK:
+
+ if (cur_choice > 0)
+ cur_choice--;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_choice - window_offset) < 0) {
+ window_offset--;
+ goto redraw;
+ }
+ break;
+
+ case LYK_NEXT_LINK:
+ case LYK_DOWN_LINK:
+ if (cur_choice < num_choices)
+ cur_choice++;
+
+ /*
+ * Scroll the window down if necessary
+ */
+ if ((cur_choice - window_offset) >= length) {
+ window_offset++;
+ goto redraw;
+ }
+ break;
+
+ case LYK_NEXT_PAGE:
+ /*
+ * Okay, are we on the last page of the choices list?
+ * If not then,
+ */
+ if (window_offset != (num_choices - length + 1)) {
+ /*
+ * Modify the current choice to not be a
+ * coordinate in the list, but a coordinate
+ * on the item selected in the window.
+ */
+ cur_choice -= window_offset;
+
+ /*
+ * Page down the proper length for the list.
+ * If simply to far, back up.
+ */
+ window_offset += length;
+ if (window_offset > (num_choices - length)) {
+ window_offset = (num_choices - length + 1);
+ }
+
+ /*
+ * Readjust the current choice to be a choice
+ * list coordinate rather than window.
+ * Redraw this thing.
+ */
+ cur_choice += window_offset;
+ goto redraw;
+ }
+ else if (cur_choice < num_choices) {
+ /*
+ * Already on last page of the choice list so
+ * just redraw it with the last item selected.
+ */
+ cur_choice = num_choices;
+ }
+ break;
+
+ case LYK_PREV_PAGE:
+ /*
+ * Are we on the first page of the choice list?
+ * If not then,
+ */
+ if (window_offset != 0) {
+ /*
+ * Modify the current choice to not be a choice
+ * list coordinate, but a window coordinate.
+ */
+ cur_choice -= window_offset;
+
+ /*
+ * Page up the proper length.
+ * If too far, back up.
+ */
+ window_offset -= length;
+ if (window_offset < 0) {
+ window_offset = 0;
+ }
+
+ /*
+ * Readjust the current choice.
+ */
+ cur_choice += window_offset;
+ goto redraw;
+ } else if (cur_choice > 0) {
+ /*
+ * Already on the first page so just
+ * back up to the first item.
+ */
+ cur_choice = 0;
+ }
+ break;
+
+ case LYK_HOME:
+ cur_choice = 0;
+ if (window_offset > 0) {
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_END:
+ cur_choice = num_choices;
+ if (window_offset != (num_choices - length + 1)) {
+ window_offset = (num_choices - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_DOWN_TWO:
+ cur_choice += 2;
+ if (cur_choice > num_choices)
+ cur_choice = num_choices;
+
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_choice - window_offset) >= length) {
+ window_offset += 2;
+ if (window_offset > (num_choices - length + 1))
+ window_offset = (num_choices - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_UP_TWO:
+ cur_choice -= 2;
+ if (cur_choice < 0)
+ cur_choice = 0;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_choice - window_offset) < 0) {
+ window_offset -= 2;
+ if (window_offset < 0)
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_DOWN_HALF:
+ cur_choice += (length/2);
+ if (cur_choice > num_choices)
+ cur_choice = num_choices;
+
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_choice - window_offset) >= length) {
+ window_offset += (length/2);
+ if (window_offset > (num_choices - length + 1))
+ window_offset = (num_choices - length + 1);
+ goto redraw;
+ }
+ break;
+
+ case LYK_UP_HALF:
+ cur_choice -= (length/2);
+ if (cur_choice < 0)
+ cur_choice = 0;
+
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_choice - window_offset) < 0) {
+ window_offset -= (length/2);
+ if (window_offset < 0)
+ window_offset = 0;
+ goto redraw;
+ }
+ break;
+
+ case LYK_REFRESH:
+ lynx_force_repaint();
+ refresh();
+ break;
+
+ case LYK_NEXT:
+ if (recall && *prev_target_buffer == '\0') {
+ /*
+ * We got a 'n'ext command with no prior query
+ * specified within the popup window. See if
+ * one was entered when the popup was retracted,
+ * and if so, assume that's what's wanted. Note
+ * that it will become the default within popups,
+ * unless another is entered within a popup. If
+ * the within popup default is to be changed at
+ * that point, use WHEREIS ('/') and enter it,
+ * or the up- or down-arrow keys to seek any of
+ * the previously entered queries, regardless of
+ * whether they were entered within or outside
+ * of a popup window. - FM
+ */
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ 0)) != NULL) {
+ strcpy(prev_target_buffer, cp);
+ QueryNum = 0;
+ FirstRecall = FALSE;
+ }
+ }
+ strcpy(prev_target, prev_target_buffer);
+ case LYK_WHEREIS:
+ if (*prev_target == '\0' ) {
+ option_statusline(ENTER_WHEREIS_QUERY);
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ }
+
+check_recall:
+ if (*prev_target == '\0' &&
+ !(recall && (ch == UPARROW || ch == DNARROW))) {
+ /*
+ * No entry. Simply break. - FM
+ */
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or
+ * last query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = (QueryTotal - 1);
+ QueryNum > 0; QueryNum--) {
+ if ((cp = (char *)HTList_objectAt(
+ search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = 0;
+ }
+ } else {
+ /*
+ * Go back to the previous query in the list. - FM
+ */
+ QueryNum++;
+ }
+ if (QueryNum >= QueryTotal)
+ /*
+ * Roll around to the last query in the list. - FM
+ */
+ QueryNum = 0;
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ option_statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer && QueryTotal == 2) ||
+ (!(*prev_target_buffer) &&
+ QueryTotal == 1)) {
+ option_statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ option_statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer), recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or
+ * first query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = 0;
+ QueryNum < (QueryTotal - 1); QueryNum++) {
+ if ((cp = (char *)HTList_objectAt(
+ search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = (QueryTotal - 1);
+ }
+ } else {
+ /*
+ * Advance to the next query in the list. - FM
+ */
+ QueryNum--;
+ }
+ if (QueryNum < 0)
+ /*
+ * Roll around to the first query in the list. - FM
+ */
+ QueryNum = (QueryTotal - 1);
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ option_statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer &&
+ QueryTotal == 2) ||
+ (!(*prev_target_buffer) &&
+ QueryTotal == 1)) {
+ option_statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ option_statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer),
+ recall)) < 0) {
+ /*
+ * User cancelled the search via ^G. - FM
+ */
+ option_statusline(CANCELLED);
+ sleep(InfoSecs);
+ goto restore_popup_statusline;
+ }
+ goto check_recall;
+ }
+ }
+ /*
+ * Replace the search string buffer with the new target. - FM
+ */
+ strcpy(prev_target_buffer, prev_target);
+ HTAddSearchQuery(prev_target_buffer);
+
+ /*
+ * Start search at the next choice. - FM
+ */
+ for (j = 1; Cptr[i+j] != NULL; j++) {
+ sprintf(buffer, "%s%d: %s",
+ ((num_choices > 8 && (j + i) < 9) ?
+ " " : ""),
+ (i + j + 1),
+ Cptr[i+j]);
+ if (case_sensitive) {
+ if (strstr(buffer, prev_target_buffer) != NULL)
+ break;
+ } else {
+ if (LYstrstr(buffer, prev_target_buffer) != NULL)
+ break;
+ }
+ }
+ if (Cptr[i+j] != NULL) {
+ /*
+ * We have a hit, so make that choice the current. - FM
+ */
+ cur_choice += j;
+ /*
+ * Scroll the window down if necessary.
+ */
+ if ((cur_choice - window_offset) >= length) {
+ window_offset += j;
+ if (window_offset > (num_choices - length + 1))
+ window_offset = (num_choices - length + 1);
+ ReDraw = TRUE;
+ }
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * If we started at the beginning, it can't be present. - FM
+ */
+ if (cur_choice == 0) {
+ option_user_message(STRING_NOT_FOUND, prev_target_buffer);
+ sleep(MessageSecs);
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * Search from the beginning to the current choice. - FM
+ */
+ for (j = 0; j < cur_choice; j++) {
+ sprintf(buffer, "%s%d: %s",
+ ((num_choices > 8 && j < 9) ?
+ " " : ""),
+ (j + 1),
+ Cptr[j]);
+ if (case_sensitive) {
+ if (strstr(buffer, prev_target_buffer) != NULL)
+ break;
+ } else {
+ if (LYstrstr(buffer, prev_target_buffer) != NULL)
+ break;
+ }
+ }
+ if (j < cur_choice) {
+ /*
+ * We have a hit, so make that choice the current. - FM
+ */
+ j = (cur_choice - j);
+ cur_choice -= j;
+ /*
+ * Scroll the window up if necessary.
+ */
+ if ((cur_choice - window_offset) < 0) {
+ window_offset -= j;
+ if (window_offset < 0)
+ window_offset = 0;
+ ReDraw = TRUE;
+ }
+ goto restore_popup_statusline;
+ }
+
+ /*
+ * Didn't find it in the preceding choices either. - FM
+ */
+ option_user_message(STRING_NOT_FOUND, prev_target_buffer);
+ sleep(MessageSecs);
+
+restore_popup_statusline:
+ /*
+ * Restore the popup statusline and
+ * reset the search variables. - FM
+ */
+ if (disabled)
+ option_statusline(CHOICE_LIST_UNM_MSG);
+ else
+ option_statusline(CHOICE_LIST_MESSAGE);
+ *prev_target = '\0';
+ QueryTotal = (search_queries ? HTList_count(search_queries)
+ : 0);
+ recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+ if (ReDraw == TRUE) {
+ ReDraw = FALSE;
+ goto redraw;
+ }
+ break;
+
+ case LYK_QUIT:
+ case LYK_ABORT:
+ case LYK_PREV_DOC:
+ cur_choice = orig_choice;
+ term_options = TRUE;
+ option_statusline(CANCELLED);
+ sleep(MessageSecs);
+ cmd = LYK_ACTIVATE; /* to exit */
+ break;
+ }
+ }
+#ifndef USE_SLANG
+ delwin(form_window);
+#ifdef NCURSES
+ LYsubwindow(0);
+#endif
+#endif /* !USE_SLANG */
+
+ if (disabled || term_options) {
+ option_statusline("");
+ return(orig_choice);
+ } else {
+ option_statusline(VALUE_ACCEPTED);
+ return(cur_choice);
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/LYOptions.h b/gnu/usr.bin/lynx/src/LYOptions.h
new file mode 100644
index 00000000000..ea9e914a8ac
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYOptions.h
@@ -0,0 +1,65 @@
+#ifndef LYOPTIONS_H
+#define LYOPTIONS_H
+
+extern BOOLEAN term_options;
+
+extern void options NOPARAMS;
+extern void edit_bookmarks NOPARAMS;
+
+/*
+ * Values for the options menu. - FM
+ *
+ * L_foo values are the Y coordinates for the menu item.
+ * B_foo values are the X coordinates for the item's prompt string.
+ * C_foo values are the X coordinates for the item's value string.
+ */
+#define L_EDITOR 2
+#define L_DISPLAY 3
+
+#define L_HOME 4
+#define C_MULTI 24
+#define B_BOOK 34
+#define C_DEFAULT 50
+
+#define L_FTPSTYPE 5
+#define L_MAIL_ADDRESS 6
+#define L_SSEARCH 7
+#define L_LANGUAGE 8
+#define L_PREF_CHARSET 9
+#define L_ASSUME_CHARSET (L_PREF_CHARSET + 1)
+#define L_CHARSET 10
+#define L_RAWMODE 11
+
+#define L_COLOR L_RAWMODE
+#define B_COLOR 44
+#define C_COLOR 62
+
+#define L_BOOL_A 12
+#define B_VIKEYS 5
+#define C_VIKEYS 15
+#define B_EMACSKEYS 22
+#define C_EMACSKEYS 36
+#define B_SHOW_DOTFILES 44
+#define C_SHOW_DOTFILES 62
+
+#define L_BOOL_B 13
+#define B_SELECT_POPUPS 5
+#define C_SELECT_POPUPS 36
+#define B_SHOW_CURSOR 44
+#define C_SHOW_CURSOR 62
+
+#define L_KEYPAD 14
+#define L_LINEED 15
+
+#ifdef DIRED_SUPPORT
+#define L_DIRED 16
+#define L_USER_MODE 17
+#define L_USER_AGENT 18
+#define L_EXEC 19
+#else
+#define L_USER_MODE 16
+#define L_USER_AGENT 17
+#define L_EXEC 18
+#endif /* DIRED_SUPPORT */
+
+#endif /* LYOPTIONS_H */
diff --git a/gnu/usr.bin/lynx/src/LYPrint.c b/gnu/usr.bin/lynx/src/LYPrint.c
new file mode 100644
index 00000000000..0405199098c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYPrint.c
@@ -0,0 +1,1365 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTAccess.h"
+#include "HTList.h"
+#include "HTAlert.h"
+#include "HTFile.h"
+#include "LYCurses.h"
+#include "GridText.h"
+#include "LYUtils.h"
+#include "LYPrint.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYStrings.h"
+#include "LYClean.h"
+#include "LYGetFile.h"
+#include "LYHistory.h"
+#include "LYSystem.h"
+#include "LYList.h"
+#include "LYCharSets.h" /* To get current charset for mail header. */
+#ifdef VMS
+#include "HTVMSUtils.h"
+#endif /* VMS */
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * printfile prints out the current file minus the links and targets
+ * to a veriaty of places
+ */
+
+/* it parses an incoming link that looks like
+ *
+ * LYNXPRINT://LOCAL_FILE/lines=##
+ * LYNXPRINT://MAIL_FILE/lines=##
+ * LYNXPRINT://TO_SCREEN/lines=##
+ * LYNXPRINT://PRINTER/lines=##/number=#
+ */
+
+#define TO_FILE 1
+#define TO_SCREEN 2
+#define MAIL 3
+#define PRINTER 4
+
+#ifdef VMS
+PRIVATE int remove_quotes PARAMS((char *string));
+#endif /* VMS */
+
+PUBLIC int printfile ARGS1(
+ document *, newdoc)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ char buffer[LINESIZE];
+ char filename[LINESIZE];
+ char user_response[256];
+ int lines_in_file = 0;
+ int printer_number = 0;
+ int pages = 0;
+ int type = 0, c, len;
+ FILE *outfile_fp;
+ char *cp = NULL;
+ lynx_printer_item_type *cur_printer;
+ char *sug_filename = NULL;
+ char *link_info = NULL;
+ DocAddress WWWDoc;
+ int pagelen = 0;
+ int ch, recall;
+ int FnameTotal;
+ int FnameNum;
+ BOOLEAN FirstRecall = TRUE;
+ char *content_base = NULL, *content_location = NULL;
+ HTFormat format;
+ HTAtom *encoding;
+ BOOL use_mime, use_cte, use_type;
+ CONST char *disp_charset;
+ static BOOLEAN first_mail_preparsed = TRUE;
+ char *envbuffer = NULL;
+#ifdef VMS
+ BOOLEAN isPMDF = FALSE;
+ char hdrfile[256];
+ FILE *hfd;
+
+ if (!strncasecomp(system_mail, "PMDF SEND", 9)) {
+ isPMDF = TRUE;
+ }
+#endif /* VMS */
+
+ /*
+ * Extract useful info from URL.
+ */
+ StrAllocCopy(link_info, newdoc->address+12);
+
+ /*
+ * Reload the file we want to print into memory.
+ */
+ LYpop(newdoc);
+ WWWDoc.address = newdoc->address;
+ WWWDoc.post_data = newdoc->post_data;
+ WWWDoc.post_content_type = newdoc->post_content_type;
+ WWWDoc.bookmark = newdoc->bookmark;
+ WWWDoc.isHEAD = newdoc->isHEAD;
+ WWWDoc.safe = newdoc->safe;
+ if (!HTLoadAbsolute(&WWWDoc))
+ return(NOT_FOUND);
+
+ /*
+ * If we have an explicit content-base, we may use it even
+ * if not in source mode. - kw
+ */
+ if (HText_getContentBase()) {
+ StrAllocCopy(content_base, HText_getContentBase());
+ collapse_spaces(content_base);
+ if (!(content_base && *content_base)) {
+ FREE(content_base);
+ }
+ }
+ /*
+ * If document is source, load the content_base
+ * and content_location strings. - FM
+ */
+ if (HTisDocumentSource()) {
+ if (HText_getContentLocation()) {
+ StrAllocCopy(content_location, HText_getContentLocation());
+ collapse_spaces(content_location);
+ if (!(content_location && *content_location)) {
+ FREE(content_location);
+ }
+ }
+ if (!content_base) {
+ if ((content_location) && is_url(content_location)) {
+ StrAllocCopy(content_base, content_location);
+ } else {
+ StrAllocCopy(content_base, newdoc->address);
+ }
+ }
+ if (!content_location) {
+ StrAllocCopy(content_location, newdoc->address);
+ }
+ }
+
+ /*
+ * Load the suggested filename string. - FM
+ */
+ if (HText_getSugFname() != NULL)
+ StrAllocCopy(sug_filename, HText_getSugFname()); /* must be freed */
+ else
+ StrAllocCopy(sug_filename, newdoc->address); /* must be freed */
+ /*
+ * Strip any gzip or compress suffix, if present. - FM
+ */
+ cp = NULL;
+ if (strlen(sug_filename) > 3) {
+ cp = (char *)&sug_filename[(strlen(sug_filename) - 3)];
+ if ((*cp == '.' || *cp == '-' || *cp == '_') &&
+ !strcasecomp((cp + 1), "gz")) {
+ *cp = '\0';
+ } else {
+ cp = NULL;
+ }
+ }
+ if ((cp == NULL) && strlen(sug_filename) > 2) {
+ cp = (char *)&sug_filename[(strlen(sug_filename) - 2)];
+ if ((*cp == '.' || *cp == '-' || *cp == '_') &&
+ !strcasecomp((cp + 1), "Z")) {
+ *cp = '\0';
+ }
+ }
+ cp = NULL;
+
+ /*
+ * Get the number of lines in the file.
+ */
+ if ((cp = (char *)strstr(link_info, "lines=")) != NULL) {
+ /*
+ * Terminate prev string here.
+ */
+ *cp = '\0';
+ /*
+ * Number of characters in "lines=".
+ */
+ cp += 6;
+
+ lines_in_file = atoi(cp);
+ pages = lines_in_file/66;
+ }
+
+ /*
+ * Determine the type.
+ */
+ if (strstr(link_info, "LOCAL_FILE")) {
+ type = TO_FILE;
+ } else if (strstr(link_info, "TO_SCREEN")) {
+ type = TO_SCREEN;
+ } else if (strstr(link_info, "MAIL_FILE")) {
+ type = MAIL;
+ } else if (strstr(link_info, "PRINTER")) {
+ type = PRINTER;
+
+ if ((cp = (char *)strstr(link_info, "number=")) != NULL) {
+ /* number of characters in "number=" */
+ cp += 7;
+ printer_number = atoi(cp);
+ }
+ if ((cp = (char *)strstr(link_info, "pagelen=")) != NULL) {
+ /* number of characters in "pagelen=" */
+ cp += 8;
+ pagelen = atoi(cp);
+ } else {
+ /* default to 66 lines */
+ pagelen = 66;
+ }
+ }
+
+ /*
+ * Set up the sug_filenames recall buffer.
+ */
+ FnameTotal = (sug_filenames ? HTList_count(sug_filenames) : 0);
+ recall = ((FnameTotal >= 1) ? RECALL : NORECALL);
+ FnameNum = FnameTotal;
+
+ /*
+ * Act on the request. - FM
+ */
+ switch (type) {
+ case TO_FILE:
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_TEXT;
+#endif /* __DJGPP__ or _WINDOWS */
+ _statusline(FILENAME_PROMPT);
+ retry: strcpy(filename, sug_filename); /* add suggestion info */
+ /* make the sug_filename conform to system specs */
+ change_sug_filename(filename);
+ if (!(HTisDocumentSource()) &&
+ (cp = strrchr(filename, '.')) != NULL) {
+ format = HTFileFormat(filename, &encoding, NULL);
+ if (!strcasecomp(format->name, "text/html") ||
+ !IsUnityEnc(encoding)) {
+ *cp = '\0';
+ strcat(filename, ".txt");
+ }
+ }
+ if (lynx_save_space && *lynx_save_space) {
+ strcpy(buffer, lynx_save_space);
+ strcat(buffer, filename);
+ strcpy(filename, buffer);
+ }
+ check_recall:
+ if ((ch = LYgetstr(filename, VISIBLE,
+ sizeof(filename), recall)) < 0 ||
+ *filename == '\0' || ch == UPARROW || ch == DNARROW) {
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the last Fname in the list. - FM
+ */
+ FnameNum = 0;
+ } else {
+ /*
+ * Go back to the previous Fname
+ * in the list. - FM
+ */
+ FnameNum++;
+ }
+ if (FnameNum >= FnameTotal) {
+ /*
+ * Reset the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto retry;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(filename, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the first Fname in the list. - FM
+ */
+ FnameNum = FnameTotal - 1;
+ } else {
+ /*
+ * Advance to the next Fname in the list. - FM
+ */
+ FnameNum--;
+ }
+ if (FnameNum < 0) {
+ /*
+ * Set the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto retry;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(filename, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_recall;
+ }
+ }
+
+ /*
+ * Save cancelled.
+ */
+ _statusline(SAVE_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ if (no_dotfiles || !show_dotfiles) {
+ if (*filename == '.' ||
+#ifdef VMS
+ ((cp = strrchr(filename, ':')) && *(cp+1) == '.') ||
+ ((cp = strrchr(filename, ']')) && *(cp+1) == '.') ||
+#endif /* VMS */
+ ((cp = strrchr(filename, '/')) && *(cp+1) == '.')) {
+ HTAlert(FILENAME_CANNOT_BE_DOT);
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+ }
+ /*
+ * Cancel if the user entered "/dev/null" on Unix,
+ * or an "nl:" path (case-insensitive) on VMS. - FM
+ */
+#ifdef VMS
+ if (!strncasecomp(filename, "nl:", 3) ||
+ !strncasecomp(filename, "/nl/", 4))
+#else
+ if (!strcmp(filename, "/dev/null"))
+#endif /* VMS */
+ {
+ _statusline(SAVE_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ if ((cp = strchr(filename, '~'))) {
+ *(cp++) = '\0';
+ strcpy(buffer, filename);
+ if ((len=strlen(buffer)) > 0 && buffer[len-1] == '/')
+ buffer[len-1] = '\0';
+#ifdef DOSPATH
+ strcat(buffer, HTDOS_wwwName((char *)Home_Dir()));
+#else
+#ifdef VMS
+ strcat(buffer, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ strcat(buffer, Home_Dir());
+#endif /* VMS */
+#endif /* DOSPATH */
+ strcat(buffer, cp);
+ strcpy(filename, buffer);
+ }
+#ifdef VMS
+ if (strchr(filename, '/') != NULL) {
+ strcpy(buffer, HTVMS_name("", filename));
+ strcpy(filename, buffer);
+ }
+ if (filename[0] != '/' && strchr(filename, ':') == NULL) {
+ strcpy(buffer, "sys$disk:");
+ if (strchr(filename, ']') == NULL)
+ strcat(buffer, "[]");
+ strcat(buffer, filename);
+ } else {
+ strcpy(buffer, filename);
+ }
+#else
+ if (*filename != '/')
+ cp = getenv("PWD");
+ else
+ cp = NULL;
+ if (cp)
+#ifdef DOSPATH
+ sprintf(buffer, "%s/%s", cp, HTDOS_name(filename));
+#else
+ sprintf(buffer, "%s/%s", cp, filename);
+#endif
+ else
+#ifdef DOSPATH
+ strcpy(buffer, HTDOS_name(filename));
+#else
+ strcpy(buffer, filename);
+#endif
+#endif /* VMS */
+
+ /*
+ * See if it already exists.
+ */
+ if ((outfile_fp = fopen(buffer, "r")) != NULL) {
+ fclose(outfile_fp);
+#ifdef VMS
+ _statusline(FILE_EXISTS_HPROMPT);
+#else
+ _statusline(FILE_EXISTS_OPROMPT);
+#endif /* VMS */
+ c = 0;
+ while (TOUPPER(c)!='Y' && TOUPPER(c)!='N' &&
+ c != 7 && c != 3)
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ _statusline(SAVE_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+#endif /* VMS */
+ if (c == 7 || c == 3) { /* Control-G or Control-C */
+ _statusline(SAVE_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ if (TOUPPER(c) == 'N') {
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+ }
+
+ if ((outfile_fp = LYNewTxtFile(buffer)) == NULL) {
+ HTAlert(CANNOT_WRITE_TO_FILE);
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto retry;
+ }
+
+ if (LYPrependBaseToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's base as a BASE tag
+ * to the top of the file. May create
+ * technically invalid HTML, but will help
+ * get any partial or relative URLs resolved
+ * properly if no BASE tag is present to
+ * replace it. - FM
+ */
+ fprintf(outfile_fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n",
+ newdoc->address, content_base);
+ }
+
+ if (LYPrependCharsetToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's charset as a META CHARSET tag
+ * to the top of the file. May create
+ * technically invalid HTML, but will help to resolve
+ * properly the document converted via chartrans:
+ * printed document correspond to a display charset
+ * and we *should* override both assume_local_charset
+ * and original document's META CHARSET (if any).
+ *
+ * Currently, if several META CHARSETs are found Lynx uses
+ * the first only, and it is opposite to BASE where the
+ * original BASE in the <HEAD> overrides ones from the
+ * top.
+ *
+ * As in print-to-email we write charset only if the
+ * document has 8-bit characters, and we have no CJK or an
+ * unofficial "x-" charset.
+ */
+ use_cte = HTLoadedDocumentEightbit();
+ disp_charset = LYCharSet_UC[current_char_set].MIMEname;
+ if (!use_cte || LYHaveCJKCharacterSet ||
+ strncasecomp(disp_charset, "x-", 2) == 0) {
+ } else {
+ fprintf(outfile_fp,
+ "<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=%s\">\n\n",
+ disp_charset);
+ }
+ }
+
+ print_wwwfile_to_fd(outfile_fp,0);
+ if (keypad_mode)
+ printlist(outfile_fp,FALSE);
+
+ fclose(outfile_fp);
+#ifdef VMS
+ if (0 == strncasecomp(buffer, "sys$disk:", 9)) {
+ if (0 == strncmp((buffer+9), "[]", 2)) {
+ HTAddSugFilename(buffer+11);
+ } else {
+ HTAddSugFilename(buffer+9);
+ }
+ } else {
+ HTAddSugFilename(buffer);
+ }
+#else
+ HTAddSugFilename(buffer);
+#endif /* VMS */
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_BINARY;
+#endif /* __DJGPP__ or _WINDOWS */
+ break;
+
+ case MAIL:
+ if (LYPreparsedSource && first_mail_preparsed &&
+ HTisDocumentSource()) {
+ _statusline(CONFIRM_MAIL_SOURCE_PREPARSED);
+ c = 0;
+ while (TOUPPER(c)!='Y' && TOUPPER(c)!='N' &&
+ c != 7 && c != 3)
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ _statusline(MAIL_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+#endif /* VMS */
+ if (c == RTARROW || c == 'y' || c== 'Y'
+ || c == '\n' || c == '\r') {
+ addstr(" Ok...");
+ first_mail_preparsed = FALSE;
+ } else {
+ _statusline(MAIL_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ }
+
+ _statusline(MAIL_ADDRESS_PROMPT);
+ strcpy(user_response, (personal_mail_address ?
+ personal_mail_address : ""));
+ if (LYgetstr(user_response, VISIBLE,
+ sizeof(user_response), NORECALL) < 0 ||
+ *user_response == '\0') {
+ _statusline(MAIL_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ /*
+ * Determine which mail headers should be sent.
+ * Use Content-Type and MIME-Version headers only
+ * if needed. We need them if we are mailing HTML
+ * source, or if we have 8-bit characters and will
+ * be sending Content-Transfer-Encoding to indicate
+ * this. We will append a charset parameter to the
+ * Content-Type if we do not have an "x-" charset,
+ * and we will include the Content-Transfer-Encoding
+ * only if we are appending the charset parameter,
+ * because indicating an 8-bit transfer without also
+ * indicating the charset can cause problems with
+ * many mailers. - FM & KW
+ */
+ disp_charset = LYCharSet_UC[current_char_set].MIMEname;
+ use_cte = HTLoadedDocumentEightbit();
+ if (!(use_cte && strncasecomp(disp_charset, "x-", 2))) {
+ disp_charset = NULL;
+ use_cte = FALSE;
+ }
+ use_type = (disp_charset || HTisDocumentSource());
+
+ change_sug_filename(sug_filename);
+#ifdef VMS
+ if (strchr(user_response,'@') && !strchr(user_response,':') &&
+ !strchr(user_response,'%') && !strchr(user_response,'"')) {
+ sprintf(filename, mail_adrs, user_response);
+ strcpy(user_response, filename);
+ }
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ if (isPMDF) {
+ tempname(hdrfile, NEW_FILE);
+ if ((len = strlen(hdrfile)) > 4) {
+ len -= 5;
+ if (!strcasecomp((hdrfile + len), ".html")) {
+ hdrfile[len] = '\0';
+ strcat(hdrfile, ".txt");
+ }
+ }
+ }
+ first = FALSE;
+ } else {
+ remove(tempfile); /* remove duplicates */
+ }
+ if (HTisDocumentSource()) {
+ if ((len = strlen(tempfile)) > 3) {
+ len -= 4;
+ if (!strcasecomp((tempfile + len), ".txt")) {
+ tempfile[len] = '\0';
+ strcat(tempfile, ".html");
+ }
+ }
+ } else if ((len = strlen(tempfile)) > 4) {
+ len -= 5;
+ if (!strcasecomp((tempfile + len), ".html")) {
+ tempfile[len] = '\0';
+ strcat(tempfile, ".txt");
+ }
+ }
+ if ((outfile_fp = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(UNABLE_TO_OPEN_TEMPFILE);
+ break;
+ }
+
+ if (isPMDF) {
+ if ((hfd = LYNewTxtFile(hdrfile)) == NULL) {
+ HTAlert(UNABLE_TO_OPEN_TEMPFILE);
+ break;
+ }
+ if (use_type) {
+ fprintf(hfd, "Mime-Version: 1.0\n");
+ if (use_cte) {
+ fprintf(hfd,
+ "Content-Transfer-Encoding: 8bit\n");
+ }
+ }
+ if (HTisDocumentSource()) {
+ /*
+ * Add Content-Type, Content-Location, and
+ * Content-Base headers for HTML source. - FM
+ */
+ fprintf(hfd, "Content-Type: text/html");
+ if (disp_charset != NULL) {
+ fprintf(hfd,
+ "; charset=%s\n",
+ disp_charset);
+ } else {
+ fprintf(hfd, "\n");
+ }
+ fprintf(hfd,
+ "Content-Base: %s\n",
+ content_base);
+ fprintf(hfd,
+ "Content-Location: %s\n",
+ content_location);
+ } else {
+ /*
+ * Add Content-Type: text/plain if we have 8-bit
+ * characters and a valid charset for non-source
+ * documents. - FM
+ */
+ if (disp_charset != NULL) {
+ fprintf(hfd,
+ "Content-Type: text/plain; charset=%s\n",
+ disp_charset);
+ }
+ }
+ /*
+ * X-URL header. - FM
+ */
+ fprintf(hfd, "X-URL: %s\n", newdoc->address);
+ }
+
+ /*
+ * Write the contents to a temp file.
+ */
+ if (LYPrependBaseToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's base as a BASE tag to
+ * the top of the message body. May create
+ * technically invalid HTML, but will help
+ * get any partial or relative URLs resolved
+ * properly if no BASE tag is present to
+ * replace it. - FM
+ */
+ fprintf(outfile_fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n",
+ newdoc->address, content_base);
+ } else if (!isPMDF) {
+ fprintf(outfile_fp, "X-URL: %s\n\n", newdoc->address);
+ }
+ print_wwwfile_to_fd(outfile_fp, 0);
+ if (keypad_mode)
+ printlist(outfile_fp, FALSE);
+ fclose(outfile_fp);
+
+ if (isPMDF) {
+ /*
+ * For PMDF, put the subject in the
+ * header file and close it. - FM
+ */
+ fprintf(hfd, "Subject: %.70s\n\n", sug_filename);
+ fclose(hfd);
+ /*
+ * Now set up the command. - FM
+ */
+ sprintf(buffer,
+ "%s %s %s,%s %s",
+ system_mail,
+ system_mail_flags,
+ hdrfile,
+ tempfile,
+ user_response);
+ } else {
+ /*
+ * For "generic" VMS MAIL, include
+ * the subject in the command. - FM
+ */
+ remove_quotes(sug_filename);
+ sprintf(buffer,
+ "%s %s/subject=\"%.70s\" %s %s",
+ system_mail,
+ system_mail_flags,
+ sug_filename,
+ tempfile,
+ user_response);
+ }
+
+ stop_curses();
+ printf(MAILING_FILE);
+ fflush(stdout);
+ system(buffer);
+ fflush(stdout);
+ sleep(AlertSecs);
+ start_curses();
+ if (isPMDF) {
+ /*
+ * Delete the header file. - FM
+ */
+ remove(hdrfile);
+ }
+#else /* Unix: */
+ sprintf(buffer, "%s %s", system_mail, system_mail_flags);
+
+#ifdef DOSPATH
+ sprintf(tempfile, "%s%s", lynx_temp_space, "temp_mail.txt");
+ if ((outfile_fp = LYNewTxtFile(tempfile)) == NULL) {
+ _statusline(MAIL_REQUEST_FAILED);
+ sleep(AlertSecs);
+ return;
+ }
+#else
+ if ((outfile_fp = popen(buffer, "w")) == NULL) {
+ _statusline(MAIL_REQUEST_FAILED);
+ sleep(AlertSecs);
+ break;
+ }
+#endif
+
+ /*
+ * Determine which mail headers should be sent.
+ * Use Content-Type and MIME-Version headers only
+ * if needed. We need them if we are mailing HTML
+ * source, or if we have 8-bit characters and will
+ * be sending Content-Transfer-Encoding to indicate
+ * this.
+ *
+ * Send Content-Transfer-Encoding only if the document
+ * has 8-bit characters. Send a charset parameter only
+ * if the document has 8-bit characters and we we seem
+ * to have a valid charset. - kw
+ */
+ use_cte = HTLoadedDocumentEightbit();
+ disp_charset = LYCharSet_UC[current_char_set].MIMEname;
+ /*
+ * Don't send a charset if we have a CJK character set
+ * selected, since it may not be appropriate for mail...
+ * Also don't use an inofficial "x-" charset. - kw
+ */
+ if (!use_cte || LYHaveCJKCharacterSet ||
+ strncasecomp(disp_charset, "x-", 2) == 0) {
+ disp_charset = NULL;
+ }
+#ifdef NOTDEFINED
+ /* Enable this if indicating an 8-bit transfer without
+ * also indicating the charset causes problems. - kw */
+ if (use_cte && !disp_charse)
+ use_cte = FALSE;
+#endif /* NOTDEFINED */
+ use_type = (disp_charset || HTisDocumentSource());
+ use_mime = (use_cte || use_type);
+
+ if (use_mime) {
+ fprintf(outfile_fp, "Mime-Version: 1.0\n");
+ if (use_cte) {
+ fprintf(outfile_fp,
+ "Content-Transfer-Encoding: 8bit\n");
+ }
+ }
+
+ if (HTisDocumentSource()) {
+ /*
+ * Add Content-Type, Content-Location, and
+ * Content-Base headers for HTML source. - FM
+ */
+ fprintf(outfile_fp, "Content-Type: text/html");
+ if (disp_charset != NULL) {
+ fprintf(outfile_fp, "; charset=%s\n",
+ disp_charset);
+ } else {
+ fprintf(outfile_fp, "\n");
+ }
+ } else {
+ /*
+ * Add Content-Type: text/plain if we have 8-bit
+ * characters and a valid charset for non-source
+ * documents. - KW
+ */
+ if (disp_charset != NULL) {
+ fprintf(outfile_fp,
+ "Content-Type: text/plain; charset=%s\n",
+ disp_charset);
+ }
+ }
+ /*
+ * If we are using MIME headers, add content-base and
+ * content-location if we have them. This will always
+ * be the case if the document is source. - kw
+ */
+ if (use_mime) {
+ if (content_base)
+ fprintf(outfile_fp, "Content-Base: %s\n",
+ content_base);
+ if (content_location)
+ fprintf(outfile_fp, "Content-Location: %s\n",
+ content_location);
+ }
+
+ /*
+ * Add the To, Subject, and X-URL headers. - FM
+ */
+ fprintf(outfile_fp, "To: %s\nSubject: %s\n",
+ user_response, sug_filename);
+ fprintf(outfile_fp, "X-URL: %s\n\n", newdoc->address);
+ if (LYPrependBaseToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's base as a BASE tag to
+ * the top of the message body. May create
+ * technically invalid HTML, but will help
+ * get any partial or relative URLs resolved
+ * properly if no BASE tag is present to
+ * replace it. - FM
+ */
+ fprintf(outfile_fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n",
+ newdoc->address, content_base);
+ }
+ print_wwwfile_to_fd(outfile_fp, 0);
+ if (keypad_mode)
+ printlist(outfile_fp, FALSE);
+
+#ifdef DOSPATH
+ sprintf(buffer, "%s -t \"%s\" -F %s", system_mail, user_response, tempfile);
+ fclose(outfile_fp); /* Close the tmpfile. */
+ stop_curses();
+ printf("Sending \n\n$ %s\n\nPlease wait...", buffer);
+ system(buffer);
+ sleep(MessageSecs);
+ start_curses();
+ remove(tempfile); /* Delete the tmpfile. */
+#else
+ pclose(outfile_fp);
+#endif
+#endif /* VMS */
+ break;
+
+ case TO_SCREEN:
+ pages = lines_in_file/(LYlines+1);
+ /* count fractional pages ! */
+ if ((lines_in_file % (LYlines+1)) > 0)
+ pages++;
+ if (pages > 4) {
+ sprintf(filename, CONFIRM_LONG_SCREEN_PRINT, pages);
+ _statusline(filename);
+ c=LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+#endif /* VMS */
+ if (c == RTARROW || c == 'y' || c== 'Y'
+ || c == '\n' || c == '\r') {
+ addstr(" Ok...");
+ } else {
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ }
+
+ _statusline(PRESS_RETURN_TO_BEGIN);
+ *filename = '\0';
+ if (LYgetstr(filename, VISIBLE,
+ sizeof(filename), NORECALL) < 0) {
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ outfile_fp = stdout;
+
+ stop_curses();
+#ifndef VMS
+ signal(SIGINT, SIG_IGN);
+#endif /* !VMS */
+
+ if (LYPrependBaseToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's base as a BASE tag
+ * to the top of the file. May create
+ * technically invalid HTML, but will help
+ * get any partial or relative URLs resolved
+ * properly if no BASE tag is present to
+ * replace it. - FM
+ */
+ fprintf(outfile_fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n",
+ newdoc->address, content_base);
+ }
+ print_wwwfile_to_fd(outfile_fp, 0);
+ if (keypad_mode)
+ printlist(outfile_fp, FALSE);
+
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ start_curses();
+ break;
+ }
+#endif /* VMS */
+ fprintf(stdout,"\n\n%s", PRESS_RETURN_TO_FINISH);
+
+ fflush(stdout); /* refresh to screen */
+ LYgetch(); /* grab some user input to pause */
+#ifdef VMS
+ HadVMSInterrupt = FALSE;
+#endif /* VMS */
+ start_curses();
+ break;
+
+ case PRINTER:
+ pages = lines_in_file/pagelen;
+ /* count fractional pages ! */
+ if ((lines_in_file % pagelen) > 0)
+ pages++;
+ if (pages > 4) {
+ sprintf(filename, CONFIRM_LONG_PAGE_PRINT, pages);
+ _statusline(filename);
+ c=LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+#endif /* VMS */
+ if (c == RTARROW || c == 'y' || c== 'Y'
+ || c == '\n' || c == '\r') {
+ addstr(" Ok...");
+ } else {
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ }
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ first = FALSE;
+ } else {
+ remove(tempfile); /* Remove previous tempfile. */
+ }
+ if (((cp = strrchr(tempfile, '.')) != NULL) &&
+#ifdef VMS
+ NULL == strchr(cp, ']') &&
+#endif /* VMS */
+ NULL == strchr(cp, '/')) {
+ if (HTisDocumentSource() &&
+ strcasecomp(cp, HTML_SUFFIX)) {
+ *cp = '\0';
+ strcat(tempfile, HTML_SUFFIX);
+ } else if (!HTisDocumentSource() &&
+ strcasecomp(cp, ".txt")) {
+ *cp = '\0';
+ strcat(tempfile, ".txt");
+ }
+ }
+ if ((outfile_fp = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(FILE_ALLOC_FAILED);
+ break;
+ }
+
+ if (LYPrependBaseToSource && HTisDocumentSource()) {
+ /*
+ * Added the document's base as a BASE tag
+ * to the top of the file. May create
+ * technically invalid HTML, but will help
+ * get any partial or relative URLs resolved
+ * properly if no BASE tag is present to
+ * replace it. - FM
+ */
+ fprintf(outfile_fp,
+ "<!-- X-URL: %s -->\n<BASE HREF=\"%s\">\n\n",
+ newdoc->address, content_base);
+ }
+ print_wwwfile_to_fd(outfile_fp, 0);
+ if (keypad_mode)
+ printlist(outfile_fp, FALSE);
+
+ fclose(outfile_fp);
+
+ /* find the right printer number */
+ {
+ int count=0;
+ for (cur_printer = printers;
+ count < printer_number;
+ count++, cur_printer = cur_printer->next)
+ ; /* null body */
+ }
+
+ /*
+ * Commands have the form "command %s [%s] [etc]"
+ * where %s is the filename and the second optional
+ * %s is the suggested filename.
+ */
+ if (cur_printer->command != NULL) {
+ /*
+ * Check for two '%s' and ask for the second filename
+ * argument if there is.
+ */
+ char *first_s = strstr(cur_printer->command, "%s");
+ if (first_s && strstr(first_s+1, "%s")) {
+ _statusline(FILENAME_PROMPT);
+ again: strcpy(filename, sug_filename);
+ change_sug_filename(filename);
+ if (!(HTisDocumentSource()) &&
+ (cp = strrchr(filename, '.')) != NULL) {
+ format = HTFileFormat(filename, &encoding, NULL);
+ if (!strcasecomp(format->name, "text/html") ||
+ !IsUnityEnc(encoding)) {
+ *cp = '\0';
+ strcat(filename, ".txt");
+ }
+ }
+ check_again:
+ if ((ch = LYgetstr(filename, VISIBLE,
+ sizeof(filename), recall)) < 0 ||
+ *filename == '\0' ||
+ ch == UPARROW || ch == DNARROW) {
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the last Fname in the list. - FM
+ */
+ FnameNum = 0;
+ } else {
+ /*
+ * Go back to the previous Fname
+ * in the list. - FM
+ */
+ FnameNum++;
+ }
+ if (FnameNum >= FnameTotal) {
+ /*
+ * Reset the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto again;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(filename, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_again;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ FirstRecall = FALSE;
+ /*
+ * Use the first Fname in the list. - FM
+ */
+ FnameNum = FnameTotal - 1;
+ } else {
+ /*
+ * Advance to the next Fname
+ * in the list. - FM
+ */
+ FnameNum--;
+ }
+ if (FnameNum < 0) {
+ /*
+ * Set the FirstRecall flag,
+ * and use sug_file or a blank. - FM
+ */
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ _statusline(FILENAME_PROMPT);
+ goto again;
+ } else if ((cp = (char *)HTList_objectAt(
+ sug_filenames,
+ FnameNum)) != NULL) {
+ strcpy(filename, cp);
+ if (FnameTotal == 1) {
+ _statusline(EDIT_THE_PREV_FILENAME);
+ } else {
+ _statusline(EDIT_A_PREV_FILENAME);
+ }
+ goto check_again;
+ }
+ }
+
+ /*
+ * Printer cancelled.
+ */
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+
+ if (no_dotfiles || !show_dotfiles) {
+ if (*filename == '.' ||
+#ifdef VMS
+ ((cp = strrchr(filename, ':')) &&
+ *(cp+1) == '.') ||
+ ((cp = strrchr(filename, ']')) &&
+ *(cp+1) == '.') ||
+#endif /* VMS */
+ ((cp = strrchr(filename, '/')) &&
+ *(cp+1) == '.')) {
+ HTAlert(FILENAME_CANNOT_BE_DOT);
+ _statusline(NEW_FILENAME_PROMPT);
+ FirstRecall = TRUE;
+ FnameNum = FnameTotal;
+ goto again;
+ }
+ }
+ /*
+ * Cancel if the user entered "/dev/null" on Unix,
+ * or an "nl:" path (case-insensitive) on VMS. - FM
+ */
+#ifdef VMS
+ if (!strncasecomp(filename, "nl:", 3) ||
+ !strncasecomp(filename, "/nl/", 4))
+#else
+ if (!strcmp(filename, "/dev/null"))
+#endif /* VMS */
+ {
+ _statusline(PRINT_REQUEST_CANCELLED);
+ sleep(InfoSecs);
+ break;
+ }
+ HTAddSugFilename(filename);
+ }
+
+#ifdef VMS
+ sprintf(buffer, cur_printer->command, tempfile, filename,
+ "", "", "", "", "", "", "", "", "", "");
+#else /* Unix: */
+ /*
+ * Prevent spoofing of the shell.
+ */
+ cp = quote_pathname(filename);
+ sprintf(buffer, cur_printer->command, tempfile, cp,
+ "", "", "", "", "", "", "", "", "", "");
+ FREE(cp);
+#endif /* !VMS */
+
+ } else {
+ HTAlert(PRINTER_MISCONF_ERROR);
+ break;
+ }
+
+ /*
+ * Move the cursor to the top of the screen so that
+ * output from system'd commands don't scroll up
+ * the screen.
+ */
+ move(1,1);
+
+ stop_curses();
+ if (TRACE)
+ fprintf(stderr, "command: %s\n", buffer);
+ printf(PRINTING_FILE);
+#ifdef VMS
+ /*
+ * Set document's title as a VMS logical. - FM
+ */
+ StrAllocCopy(envbuffer, HText_getTitle());
+ if (!(envbuffer && *envbuffer))
+ StrAllocCopy(envbuffer, "No Title");
+ Define_VMSLogical("LYNX_PRINT_TITLE", envbuffer);
+#else
+ /*
+ * Set document's title as an environment variable. - JKT
+ */
+ StrAllocCopy(envbuffer, "LYNX_PRINT_TITLE=");
+ StrAllocCat(envbuffer, HText_getTitle());
+ putenv(envbuffer);
+#endif /* VMS */
+ fflush(stdout);
+ system(buffer);
+#ifdef VMS
+ /*
+ * Remove LYNX_PRINT_TITLE logical. - FM
+ */
+ Define_VMSLogical("LYNX_PRINT_TITLE", "");
+#else
+ /*
+ * Remove LYNX_PRINT_TITLE value from environment. - KW
+ */
+ envbuffer[17] = '\0'; /* truncate after '=' */
+ putenv(envbuffer);
+#endif /* VMS */
+ FREE(envbuffer);
+ fflush(stdout);
+#ifndef VMS
+ signal(SIGINT, cleanup_sig);
+#endif /* !VMS */
+ sleep(MessageSecs);
+ start_curses();
+ /* don't remove(tempfile); */
+ } /* end switch */
+
+ FREE(link_info);
+ FREE(sug_filename);
+ FREE(content_base);
+ FREE(content_location);
+ return(NORMAL);
+}
+
+#ifdef VMS
+PRIVATE int remove_quotes ARGS1(
+ char *, string)
+{
+ int i;
+
+ for(i = 0; string[i] != '\0'; i++)
+ if(string[i] == '"')
+ string[i] = ' ';
+ else if(string[i] == '&')
+ string[i] = ' ';
+ else if(string[i] == '|')
+ string[i] = ' ';
+
+ return(0);
+}
+#endif /* VMS */
+
+/*
+ * print_options writes out the current printer choices to a file
+ * so that the user can select printers in the same way that
+ * they select all other links
+ * printer links look like
+ * LYNXPRINT://LOCAL_FILE/lines=# print to a local file
+ * LYNXPRINT://TO_SCREEN/lines=# print to the screen
+ * LYNXPRINT://MAIL_FILE/lines=# mail the file
+ * LYNXPRINT://PRINTER/lines=#/number=# print to printer number #
+ */
+PUBLIC int print_options ARGS2(
+ char **, newfile,
+ int, lines_in_file)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ static char print_filename[256];
+ char buffer[LINESIZE];
+ int count;
+ int pages;
+ FILE *fp0;
+ lynx_printer_item_type *cur_printer;
+
+ pages = lines_in_file/66 + 1;
+
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(print_filename, "file://localhost/%s", tempfile);
+#else
+ sprintf(print_filename, "file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* !VMS */
+ }
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(UNABLE_TO_OPEN_PRINTOP_FILE);
+ return(-1);
+ }
+
+ StrAllocCopy(*newfile, print_filename);
+ LYforce_no_cache = TRUE;
+
+ fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+ PRINT_OPTIONS_TITLE);
+
+ fprintf(fp0,"<h1>Printing Options (%s Version %s)</h1><pre>\n",
+ LYNX_NAME, LYNX_VERSION);
+
+ pages = (lines_in_file+65)/66;
+ sprintf(buffer,
+ " There are %d lines, or approximately %d page%s, to print.\n",
+ lines_in_file, pages, (pages > 1 ? "s" : ""));
+ fputs(buffer,fp0);
+
+ if (no_print || no_disk_save || child_lynx || no_mail)
+ fprintf(fp0, " Some print functions have been disabled!!!\n");
+
+ fprintf(fp0, " You have the following print choices.\n");
+ fprintf(fp0, " Please select one:\n\n");
+
+ if (child_lynx == FALSE && no_disk_save == FALSE && no_print == FALSE)
+ fprintf(fp0,
+ " <a href=\"LYNXPRINT://LOCAL_FILE/lines=%d\">Save to a local file</a>\n",
+ lines_in_file);
+ else
+ fprintf(fp0," Save to disk disabled.\n");
+ if (child_lynx == FALSE && no_mail == FALSE)
+ fprintf(fp0,
+ " <a href=\"LYNXPRINT://MAIL_FILE/lines=%d\">Mail the file</a>\n",
+ lines_in_file);
+ fprintf(fp0,
+ " <a href=\"LYNXPRINT://TO_SCREEN/lines=%d\">Print to the screen</a>\n",
+ lines_in_file);
+
+ for (count = 0, cur_printer = printers; cur_printer != NULL;
+ cur_printer = cur_printer->next, count++)
+ if (no_print == FALSE || cur_printer->always_enabled) {
+ fprintf(fp0,
+ " <a href=\"LYNXPRINT://PRINTER/number=%d/pagelen=%d/lines=%d\">",
+ count, cur_printer->pagelen, lines_in_file);
+ fprintf(fp0, (cur_printer->name ?
+ cur_printer->name : "No Name Given"));
+ fprintf(fp0, "</a>\n");
+ }
+ fprintf(fp0, "</pre>\n</body>\n");
+ fclose(fp0);
+
+ LYforce_no_cache = TRUE;
+ return(0);
+}
diff --git a/gnu/usr.bin/lynx/src/LYPrint.h b/gnu/usr.bin/lynx/src/LYPrint.h
new file mode 100644
index 00000000000..b4cfdf1a700
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYPrint.h
@@ -0,0 +1,15 @@
+
+#ifndef LYPRINT_H
+#define LYPRINT_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern int printfile PARAMS((document *newdoc));
+extern int print_options PARAMS((char **newfile, int lines_in_file));
+
+#define PRINT_OPTIONS_TITLE "Lynx Printing Options"
+
+#endif /* LYPRINT_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYReadCFG.c b/gnu/usr.bin/lynx/src/LYReadCFG.c
new file mode 100644
index 00000000000..736aeab43e9
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYReadCFG.c
@@ -0,0 +1,1321 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFile.h"
+#include "UCMap.h"
+
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYStructs.h"
+#include "LYGlobalDefs.h"
+#include "LYCharSets.h"
+#include "LYKeymap.h"
+#include "LYJump.h"
+#include "LYGetFile.h"
+#include "LYCgi.h"
+#include "LYCurses.h"
+#include "LYSignal.h"
+#include "LYBookmark.h"
+#include "LYReadCFG.h"
+
+#ifdef DIRED_SUPPORT
+#include "LYLocal.h"
+#endif /* DIRED_SUPPORT */
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern int HTNewsMaxChunk; /* Max news articles before chunking (HTNews.c) */
+extern int HTNewsChunkSize; /* Number of news articles per chunk (HTNews.c) */
+
+PUBLIC BOOLEAN have_read_cfg=FALSE;
+PUBLIC BOOLEAN LYUseNoviceLineTwo=TRUE;
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+/*
+ * Translate a TRUE/FALSE field in a string buffer.
+ */
+PRIVATE int is_true ARGS1(
+ char *, string)
+{
+ if (!strncasecomp(string,"TRUE",4))
+ return(TRUE);
+ else
+ return(FALSE);
+}
+
+/*
+ * Find an unescaped colon in a string buffer.
+ */
+PRIVATE char *find_colon ARGS1(
+ char *, buffer)
+{
+ char ch, *buf = buffer;
+
+ if (buf == NULL)
+ return NULL;
+
+ while ((ch = *buf) != 0) {
+ if (ch == ':')
+ return buf;
+ if (ch == '\\') {
+ buf++;
+ if (*buf == 0)
+ break;
+ }
+ buf++;
+ }
+ return NULL;
+}
+
+/*
+ * Function for freeing the DOWNLOADER and UPLOADER menus list. - FM
+ */
+PRIVATE void free_item_list NOARGS
+{
+ lynx_html_item_type *cur;
+ lynx_html_item_type *next;
+
+ cur = downloaders;
+ while (cur) {
+ next = cur->next;
+ FREE(cur->name);
+ FREE(cur->command);
+ FREE(cur);
+ cur = next;
+ }
+ downloaders = NULL;
+
+#ifdef DIRED_SUPPORT
+ cur = uploaders;
+ while (cur) {
+ next = cur->next;
+ FREE(cur->name);
+ FREE(cur->command);
+ FREE(cur);
+ cur = next;
+ }
+ uploaders = NULL;
+#endif /* DIRED_SUPPORT */
+
+#ifdef USE_EXTERNALS
+ cur = externals;
+ while (cur) {
+ next = cur->next;
+ FREE(cur->name);
+ FREE(cur->command);
+ FREE(cur);
+ cur = next;
+ }
+ externals = NULL;
+#endif /* USE_EXTERNALS */
+
+ return;
+}
+
+/*
+ * Process string buffer fields for DOWNLOADER or UPLOADER menus.
+ */
+PRIVATE void add_item_to_list ARGS2(
+ char *, buffer,
+ lynx_html_item_type **, list_ptr)
+{
+ char *colon, *next_colon;
+ lynx_html_item_type *cur_item, *prev_item;
+
+ /*
+ * Make a linked list
+ */
+ if (*list_ptr == NULL) {
+ /*
+ * First item.
+ */
+ cur_item = (lynx_html_item_type *)calloc(sizeof(lynx_html_item_type),1);
+ if (cur_item == NULL)
+ perror("Out of memory in read_cfg");
+ *list_ptr = cur_item;
+ atexit(free_item_list);
+ } else {
+ /*
+ * Find the last item.
+ */
+ for (prev_item = *list_ptr;
+ prev_item->next != NULL;
+ prev_item = prev_item->next)
+ ; /* null body */
+ cur_item = (lynx_html_item_type *)calloc(sizeof(lynx_html_item_type),1);
+ if (cur_item == NULL)
+ perror("Out of memory in read_cfg");
+ else
+ prev_item->next = cur_item;
+ }
+ cur_item->next = NULL;
+ cur_item->name = NULL;
+ cur_item->command = NULL;
+ cur_item->always_enabled = FALSE;
+
+ /*
+ * Find first unescaped colon and process fields
+ */
+ if ((colon = find_colon(buffer)) != NULL) {
+ /*
+ * Process name field
+ */
+ cur_item->name = (char *)calloc((colon-buffer+1),sizeof(char));
+ if (cur_item->name == NULL)
+ perror("Out of memory in read_cfg");
+ LYstrncpy(cur_item->name, buffer, (int)(colon-buffer));
+ remove_backslashes(cur_item->name);
+
+ /*
+ * Process TRUE/FALSE field
+ */
+ if ((next_colon = find_colon(colon+1)) != NULL) {
+ cur_item->command = (char *)calloc(next_colon-colon, sizeof(char));
+ if (cur_item->command == NULL)
+ perror("Out of memory in read_cfg");
+ LYstrncpy(cur_item->command, colon+1, (int)(next_colon-(colon+1)));
+ remove_backslashes(cur_item->command);
+ cur_item->always_enabled = is_true(next_colon+1);
+ }
+ }
+}
+
+
+/*
+ * Function for freeing the PRINTER menus list. - FM
+ */
+PRIVATE void free_printer_item_list NOARGS
+{
+ lynx_printer_item_type *cur = printers;
+ lynx_printer_item_type *next;
+
+ while (cur) {
+ next = cur->next;
+ FREE(cur->name);
+ FREE(cur->command);
+ FREE(cur);
+ cur = next;
+ }
+ printers = NULL;
+
+ return;
+}
+
+/*
+ * Process string buffer fields for PRINTER menus.
+ */
+PRIVATE void add_printer_to_list ARGS2(
+ char *, buffer,
+ lynx_printer_item_type **, list_ptr)
+{
+ char *colon, *next_colon;
+ lynx_printer_item_type *cur_item, *prev_item;
+
+ /*
+ * Make a linked list.
+ */
+ if (*list_ptr == NULL) {
+ /*
+ * First item.
+ */
+ cur_item = (lynx_printer_item_type *)calloc(sizeof(lynx_printer_item_type),1);
+ if (cur_item == NULL)
+ perror("Out of memory in read_cfg");
+ *list_ptr = cur_item;
+ atexit(free_printer_item_list);
+ } else {
+ /*
+ * Find the last item.
+ */
+ for (prev_item = *list_ptr;
+ prev_item->next != NULL;
+ prev_item = prev_item->next)
+ ; /* null body */
+
+ cur_item = (lynx_printer_item_type *)calloc(sizeof(lynx_printer_item_type),1);
+ if (cur_item == NULL)
+ perror("Out of memory in read_cfg");
+ else
+ prev_item->next = cur_item;
+ }
+ cur_item->next = NULL;
+ cur_item->name = NULL;
+ cur_item->command = NULL;
+ cur_item->always_enabled = FALSE;
+
+ /*
+ * Find first unescaped colon and process fields.
+ */
+ if ((colon = find_colon(buffer)) != NULL) {
+ /*
+ * Process name field.
+ */
+ cur_item->name = (char *)calloc((colon-buffer+1), sizeof(char));
+ if (cur_item->name == NULL)
+ perror("Out of memory in read_cfg");
+ LYstrncpy(cur_item->name, buffer, (int)(colon-buffer));
+ remove_backslashes(cur_item->name);
+
+ /*
+ * Process TRUE/FALSE field.
+ */
+ if ((next_colon = find_colon(colon+1)) != NULL) {
+ cur_item->command = (char *)calloc(next_colon-colon, sizeof(char));
+ if (cur_item->command == NULL)
+ perror("Out of memory in read_cfg");
+ LYstrncpy(cur_item->command, colon+1, (int)(next_colon-(colon+1)));
+ remove_backslashes(cur_item->command);
+ cur_item->always_enabled = is_true(next_colon+1);
+ }
+
+ /*
+ * Process pagelen field.
+ */
+ if ((next_colon = find_colon(next_colon+1)) != NULL) {
+ cur_item->pagelen = atoi(next_colon+1);
+ } else {
+ /* default to 66 lines */
+ cur_item->pagelen = 66;
+ }
+ }
+}
+
+#if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
+
+#ifdef USE_SLANG
+#define COLOR_WHITE 7
+#define COLOR_BLACK 0
+#endif
+
+int default_fg = COLOR_WHITE;
+int default_bg = COLOR_BLACK;
+
+static char *Color_Strings[16] =
+{
+ "black",
+ "red",
+ "green",
+ "brown",
+ "blue",
+ "magenta",
+ "cyan",
+ "lightgray",
+ "gray",
+ "brightred",
+ "brightgreen",
+ "yellow",
+ "brightblue",
+ "brightmagenta",
+ "brightcyan",
+ "white"
+};
+
+#ifdef DOSPATH
+/*
+ * PDCurses (and possibly some other implementations) use a non-ANSI set of
+ * codes for colors.
+ */
+PRIVATE int ColorCode ARGS1(
+ int, color)
+{
+ static int map[] = {
+ 0, 4, 2, 6, 1, 5, 3, 7,
+ 8, 12, 10, 14, 9, 13, 11, 15 };
+ return map[color];
+}
+#else
+#define ColorCode(color) (color)
+#endif
+
+/*
+ * Validator for COLOR fields.
+ */
+PUBLIC int check_color ARGS2(
+ char *, color,
+ int, the_default)
+{
+ int i;
+
+ if (!strcasecomp(color, "default"))
+ return the_default;
+ if (!strcasecomp(color, "nocolor"))
+ return NO_COLOR;
+
+ for (i = 0; i < 16; i++) {
+ if (!strcasecomp(color, Color_Strings[i]))
+ return ColorCode(i);
+ }
+ return ERR_COLOR;
+}
+#endif /* USE_COLOR_STYLE || USE_COLOR_TABLE */
+
+#if defined(USE_COLOR_TABLE)
+
+/*
+ * Exit routine for failed COLOR parsing.
+ */
+PRIVATE void exit_with_color_syntax ARGS1(
+ char *, error_line)
+{
+ unsigned int i;
+ fprintf (stderr, "\
+Syntax Error parsing COLOR in configuration file:\n\
+The line must be of the form:\n\
+COLOR:INTEGER:FOREGROUND:BACKGROUND\n\
+\n\
+Here FOREGROUND and BACKGROUND must be one of:\n\
+The special strings 'nocolor' or 'default', or\n"
+ );
+ for (i = 0; i < 16; i += 4) {
+ fprintf(stderr, "%16s %16s %16s %16s\n",
+ Color_Strings[i], Color_Strings[i + 1],
+ Color_Strings[i + 2], Color_Strings[i + 3]);
+ }
+ fprintf (stderr, "Offending line:\n%s\n",error_line);
+
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+}
+
+/*
+ * Process string buffer fields for COLOR setting.
+ */
+PRIVATE void parse_color ARGS1(
+ char *, buffer)
+{
+ int color;
+ char *fg, *bg;
+ char temp[501];
+
+ if (strlen(buffer) < sizeof(temp))
+ strcpy(temp, buffer);
+ else
+ strcpy(temp, "Color config line too long");
+
+ /*
+ * We are expecting a line of the form:
+ * INTEGER:FOREGROUND:BACKGROUND
+ */
+ color = atoi(buffer);
+ if (NULL == (fg = find_colon(buffer)))
+ exit_with_color_syntax(temp);
+ *fg++ = '\0';
+
+ if (NULL == (bg = find_colon(fg)))
+ exit_with_color_syntax(temp);
+ *bg++ = '\0';
+
+#if defined(USE_SLANG)
+ if ((check_color(fg, default_fg) < 0) ||
+ (check_color(bg, default_bg) < 0))
+ exit_with_color_syntax(temp);
+
+ SLtt_set_color(color, NULL, fg, bg);
+#else
+ if (lynx_chg_color(color,
+ check_color(fg, default_fg),
+ check_color(bg, default_bg)) < 0)
+ exit_with_color_syntax(temp);
+#endif
+}
+#endif /* USE_COLOR_TABLE */
+
+/*
+ * Process the configuration file (lynx.cfg).
+ */
+PUBLIC void read_cfg ARGS1(
+ char *, cfg_filename)
+{
+ FILE *fp;
+ char buffer[501];
+ char temp[501];
+ char *cp, *cp1;
+ int i, j, len;
+
+ /*
+ * Locate and open the file.
+ */
+ if (!cfg_filename || strlen(cfg_filename) == 0) {
+ if (TRACE)
+ fprintf(stderr,"No filename following -cfg switch!\n");
+ return;
+ }
+ if ((fp = fopen(cfg_filename,"r")) == NULL) {
+ if (TRACE)
+ fprintf(stderr,"lynx.cfg file not found as %s\n",cfg_filename);
+ return;
+ }
+ have_read_cfg=TRUE;
+
+ /*
+ * Process each line in the file.
+ */
+ while (fgets(buffer, 500, fp) != NULL) {
+ /*
+ * Strip off \n at the end.
+ */
+ if ((cp = (char *)strchr(buffer, '\n')) != NULL)
+ *cp = '\0';
+
+ /*
+ * Trim off any trailing comments.
+ */
+ if ((cp = (char *)strrchr(buffer, ':')) != NULL) {
+ if ((cp1 = (char *)strchr(cp, '#')) != NULL) {
+ cp1--;
+ if (isspace((unsigned char)*cp1)) {
+ *cp1 = '\0';
+ }
+ }
+ }
+
+ /*
+ * Strip off trailing white space.
+ */
+ len = strlen(buffer);
+ while (len && isspace(buffer[len-1])) {
+ len--;
+ buffer[len] = '\0';
+ }
+
+ /*
+ * Skip any blank or purely comment lines.
+ */
+ if (buffer[0] == '\0' || buffer[0] == '#')
+ continue;
+
+ /*
+ * Process the string buffer.
+ */
+ switch (TOUPPER(buffer[0])) {
+
+ case 'A':
+ if (!strncasecomp(buffer, "ALERTSECS:", 10)) {
+ strcpy(temp, buffer+10);
+ for (i = 0; temp[i]; i++) {
+ if (!isdigit(temp[i])) {
+ temp[i] = '\0';
+ break;
+ }
+ }
+ if (temp[0])
+ AlertSecs = atoi(temp);
+
+ } else if (!strncasecomp(buffer, "ALWAYS_RESUBMIT_POSTS:", 22)) {
+ LYresubmit_posts = is_true(buffer+22);
+
+#ifdef EXEC_LINKS
+ } else if (!strncasecomp(buffer, "ALWAYS_TRUSTED_EXEC:", 20)) {
+ add_trusted(&buffer[20], ALWAYS_EXEC_PATH); /* Add exec path */
+#endif /* EXEC_LINKS */
+
+ } else if (!strncasecomp(buffer, "ASSUME_CHARSET:", 15)) {
+ StrAllocCopy(UCAssume_MIMEcharset, buffer+15);
+ for (i = 0; UCAssume_MIMEcharset[i]; i++)
+ UCAssume_MIMEcharset[i] = TOLOWER(UCAssume_MIMEcharset[i]);
+ UCLYhndl_for_unspec =
+ UCGetLYhndl_byMIME(UCAssume_MIMEcharset);
+
+ } else if (!strncasecomp(buffer, "ASSUME_LOCAL_CHARSET:", 21)) {
+ StrAllocCopy(UCAssume_localMIMEcharset, buffer+21);
+ for (i = 0; UCAssume_localMIMEcharset[i]; i++)
+ UCAssume_localMIMEcharset[i] =
+ TOLOWER(UCAssume_localMIMEcharset[i]);
+ UCLYhndl_HTFile_for_unspec =
+ UCGetLYhndl_byMIME(UCAssume_localMIMEcharset);
+
+ } else if (!strncasecomp(buffer, "ASSUME_UNREC_CHARSET:", 21)) {
+ StrAllocCopy(UCAssume_unrecMIMEcharset, buffer+21);
+ for (i = 0; UCAssume_unrecMIMEcharset[i]; i++)
+ UCAssume_unrecMIMEcharset[i] =
+ TOLOWER(UCAssume_unrecMIMEcharset[i]);
+ UCLYhndl_for_unrec =
+ UCGetLYhndl_byMIME(UCAssume_unrecMIMEcharset);
+ }
+ break;
+
+ case 'B':
+ if (!strncasecomp(buffer, "BLOCK_MULTI_BOOKMARKS:", 22)) {
+ LYMBMBlocked = is_true(buffer+22);
+
+ } else if (!strncasecomp(buffer, "BOLD_H1:", 8)) {
+ bold_H1 = is_true(buffer+8);
+
+ } else if (!strncasecomp(buffer, "BOLD_HEADERS:", 13)) {
+ bold_headers = is_true(buffer+13);
+
+ } else if (!strncasecomp(buffer, "BOLD_NAME_ANCHORS:", 18)) {
+ bold_name_anchors = is_true(buffer+18);
+ }
+ break;
+
+ case 'C':
+ if (!strncasecomp(buffer, "CASE_SENSITIVE_ALWAYS_ON:", 25)) {
+ case_sensitive = is_true(buffer+25);
+
+ } else if (!strncasecomp(buffer, "CHARACTER_SET:", 14)) {
+ for (i = 0; LYchar_set_names[i]; i++) {
+ if (!strncmp(buffer+14,
+ LYchar_set_names[i], strlen(buffer+14))) {
+ current_char_set=i;
+ HTMLSetRawModeDefault(i);
+ break;
+ }
+ }
+
+ } else if (!strncasecomp(buffer, "CHECKMAIL:", 10)) {
+ check_mail = is_true(buffer+10);
+
+ } else if (!strncasecomp(buffer, "COLLAPSE_BR_TAGS:", 17)) {
+ LYCollapseBRs = is_true(buffer+17);
+
+#if USE_COLOR_TABLE
+ } else if (!strncasecomp(buffer, "COLOR:", 6)) {
+ parse_color(buffer + 6);
+#endif /* USE_COLOR_TABLE */
+
+ } else if (!strncasecomp(buffer, "cso_proxy:", 10)) {
+ if (getenv("cso_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "cso_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[10]);
+#else
+ strcpy(temp, "cso_proxy=");
+ StrAllocCopy(cso_proxy_putenv_cmd, temp);
+ StrAllocCat(cso_proxy_putenv_cmd, (char *)&buffer[10]);
+ putenv(cso_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+#ifdef VMS
+ } else if (!strncasecomp(buffer, "CSWING_PATH:", 12)) {
+ StrAllocCopy(LYCSwingPath, buffer+12);
+#endif /* VMS */
+ }
+ break;
+
+ case 'D':
+ if (!strncasecomp(buffer, "DEFAULT_BOOKMARK_FILE:", 22)) {
+ StrAllocCopy(bookmark_page, buffer+22);
+ StrAllocCopy(BookmarkPage, bookmark_page);
+ StrAllocCopy(MBM_A_subbookmark[0], bookmark_page);
+ StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT);
+
+ } else if (!strncasecomp(buffer, "DEFAULT_CACHE_SIZE:", 19)) {
+ HTCacheSize = atoi(buffer+19);
+
+ } else if (!system_editor &&
+ !strncasecomp(buffer, "DEFAULT_EDITOR:", 15)) {
+ StrAllocCopy(editor, buffer+15);
+
+ } else if (!strncasecomp(buffer, "DEFAULT_INDEX_FILE:", 19)) {
+ StrAllocCopy(indexfile, buffer+19);
+
+ } else if (!strncasecomp(buffer,
+ "DEFAULT_KEYPAD_MODE_IS_NUMBERS_AS_ARROWS:", 41)) {
+ if (is_true(buffer+41))
+ keypad_mode = NUMBERS_AS_ARROWS;
+ else
+ keypad_mode = LINKS_ARE_NUMBERED;
+
+ } else if (!strncasecomp(buffer, "DEFAULT_USER_MODE:", 18)) {
+ if (!strncasecomp(buffer+18, "NOVICE", 6))
+ user_mode = NOVICE_MODE;
+ else if (!strncasecomp(buffer+18, "INTER", 5))
+ user_mode = INTERMEDIATE_MODE;
+ else if (!strncasecomp(buffer+18, "ADVANCE", 7))
+ user_mode = ADVANCED_MODE;
+
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+ } else if (!strncasecomp(buffer,
+ "DEFAULT_VIRTUAL_MEMORY_SIZE:", 28)) {
+ HTVirtualMemorySize = atoi(buffer+28);
+#endif /* VMS && VAXC && !__DECC */
+
+#ifdef DIRED_SUPPORT
+ } else if (!strncasecomp(buffer, "DIRED_MENU:", 11)) {
+ add_menu_item(&buffer[11]);
+#endif /* DIRED_SUPPORT */
+
+ } else if (!strncasecomp(buffer, "DOWNLOADER:", 11)) {
+ add_item_to_list(&buffer[11], &downloaders);
+ }
+ break;
+
+ case 'E':
+ if (!strncasecomp(buffer, "EMACS_KEYS_ALWAYS_ON:", 21)) {
+ emacs_keys = is_true(buffer+21);
+
+ } else if (!strncasecomp(buffer, "ENABLE_SCROLLBACK:", 18)) {
+ enable_scrollback = is_true(buffer+18);
+ }
+#ifdef USE_EXTERNALS
+ else if(!strncasecomp(buffer,"EXTERNAL:",9)) {
+ add_item_to_list(&buffer[9],&externals);
+ }
+#endif
+ break;
+
+ case 'F':
+ if (!strncasecomp(buffer, "finger_proxy:", 13)) {
+ if (getenv("finger_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "finger_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[13]);
+#else
+ strcpy(temp, "finger_proxy=");
+ StrAllocCopy(finger_proxy_putenv_cmd, temp);
+ StrAllocCat(finger_proxy_putenv_cmd, (char *)&buffer[13]);
+ putenv(finger_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "FORCE_SSL_COOKIES_SECURE:", 25)) {
+ LYForceSSLCookiesSecure = is_true(buffer+25);
+
+ } else if (!strncasecomp(buffer, "ftp_proxy:", 10)) {
+ if (getenv("ftp_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "ftp_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[10]);
+#else
+ strcpy(temp, "ftp_proxy=");
+ StrAllocCopy(ftp_proxy_putenv_cmd, temp);
+ StrAllocCat(ftp_proxy_putenv_cmd, (char *)&buffer[10]);
+ putenv(ftp_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+ }
+ break;
+
+ case 'G':
+ if (!strncasecomp(buffer, "GLOBAL_EXTENSION_MAP:", 21)) {
+ StrAllocCopy(global_extension_map, buffer+21);
+
+ } else if (!strncasecomp(buffer, "GLOBAL_MAILCAP:", 15)) {
+ StrAllocCopy(global_type_map, buffer+15);
+
+ } else if (!strncasecomp(buffer, "gopher_proxy:", 13)) {
+ if (getenv("gopher_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "gopher_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[13]);
+#else
+ strcpy(temp, "gopher_proxy=");
+ StrAllocCopy(gopher_proxy_putenv_cmd, temp);
+ StrAllocCat(gopher_proxy_putenv_cmd, (char *)&buffer[13]);
+ putenv(gopher_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "GOTOBUFFER:", 11)) {
+ goto_buffer = is_true(buffer+11);
+ }
+ break;
+
+ case 'H':
+ if (!strncasecomp(buffer, "HELPFILE:", 9)) {
+ StrAllocCopy(helpfile, buffer+9);
+
+ } else if (!strncasecomp(buffer, "HISTORICAL_COMMENTS:", 20)) {
+ historical_comments = is_true(buffer+20);
+
+ } else if (!strncasecomp(buffer, "http_proxy:", 11)) {
+ if (getenv("http_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "http_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[11]);
+#else
+ strcpy(temp, "http_proxy=");
+ StrAllocCopy(http_proxy_putenv_cmd, temp);
+ StrAllocCat(http_proxy_putenv_cmd, (char *)&buffer[11]);
+ putenv(http_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "https_proxy:", 12)) {
+ if (getenv("https_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "https_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[12]);
+#else
+ strcpy(temp, "https_proxy=");
+ StrAllocCopy(https_proxy_putenv_cmd, temp);
+ StrAllocCat(https_proxy_putenv_cmd, (char *)&buffer[12]);
+ putenv(https_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+ }
+ break;
+
+ case 'I':
+ if (!strncasecomp(buffer, "INFOSECS:", 9)) {
+ strcpy(temp, buffer+9);
+ for (i = 0; temp[i]; i++) {
+ if (!isdigit(temp[i])) {
+ temp[i] = '\0';
+ break;
+ }
+ }
+ if (temp[0])
+ InfoSecs = atoi(temp);
+ }
+ break;
+
+ case 'J':
+ if (!strncasecomp(buffer, "JUMP_PROMPT:", 12)) {
+ StrAllocCopy(jumpprompt, buffer+12);
+
+ } else if (!strncasecomp(buffer, "JUMPBUFFER:", 11)) {
+ jump_buffer = is_true(buffer+11);
+
+ } else if (!strncasecomp(buffer, "JUMPFILE:", 9)) {
+ if (!LYJumpInit(buffer)) {
+ if (TRACE)
+ fprintf(stderr, "Failed to register %s\n", buffer);
+ }
+ }
+ break;
+
+ case 'K':
+ if (!strncasecomp(buffer, "KEYMAP:", 7)) {
+ char *key;
+ char *func;
+
+ key = buffer + 7;
+ if ((func = strchr(key, ':')) != NULL) {
+ *func++ = '\0';
+ /* Allow comments on the ends of key remapping lines. - DT */
+ if (!remap(key, strtok(func, " \t\n#")))
+ fprintf(stderr,
+ "key remapping of %s to %s failed\n",key,func);
+ else if (!strcmp("TOGGLE_HELP", strtok(func, " \t\n#")))
+ LYUseNoviceLineTwo = FALSE;
+ }
+ }
+ break;
+
+ case 'L':
+ if (!strncasecomp(buffer, "LIST_NEWS_NUMBERS:", 18)) {
+ LYListNewsNumbers = is_true(buffer+18);
+
+ } else if (!strncasecomp(buffer, "LIST_NEWS_DATES:", 16)) {
+ LYListNewsDates = is_true(buffer+16);
+
+#ifndef VMS
+ } else if (!strncasecomp(buffer, "LIST_FORMAT:", 12)) {
+ StrAllocCopy(list_format, buffer+12);
+#endif /* !VMS */
+
+ } else if (!strncasecomp(buffer, "LOCALHOST_ALIAS:", 16)) {
+ LYAddLocalhostAlias(buffer+16);
+
+ } else if (!strncasecomp(buffer, "LOCAL_DOMAIN:", 13)) {
+ StrAllocCopy(LYLocalDomain, buffer+13);
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ } else if (!strncasecomp(buffer,
+ "LOCAL_EXECUTION_LINKS_ALWAYS_ON:", 32)) {
+ local_exec = is_true(buffer+32);
+
+ } else if (!strncasecomp(buffer,
+ "LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE:", 40)) {
+ local_exec_on_local_files = is_true(buffer+40);
+#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */
+
+#ifdef LYNXCGI_LINKS
+ } else if (!strncasecomp(buffer, "LYNXCGI_ENVIRONMENT:", 20)) {
+ add_lynxcgi_environment(buffer+20);
+
+#ifndef VMS
+ /* WebSter Mods - Next 2 Lines -jkt */
+ } else if (!strncasecomp(buffer, "LYNXCGI_DOCUMENT_ROOT:", 22)) {
+ StrAllocCopy(LYCgiDocumentRoot, buffer+22);
+#endif /* !VMS */
+#endif /* LYNXCGI_LINKS */
+
+ } else if (!strncasecomp(buffer, "LYNX_HOST_NAME:", 15)) {
+ StrAllocCopy(LYHostName, buffer+15);
+
+ } else if (!strncasecomp(buffer, "LYNX_SIG_FILE:", 14)) {
+ strcpy(temp, (buffer+14));
+ if (LYPathOffHomeOK(temp, 256)) {
+ StrAllocCopy(LynxSigFile, temp);
+ LYAddPathToHome(temp, 256, LynxSigFile);
+ StrAllocCopy(LynxSigFile, temp);
+ if (TRACE)
+ fprintf(stderr,
+ "LYNX_SIG_FILE set to '%s'\n", LynxSigFile);
+ } else {
+ if (TRACE)
+ fprintf(stderr, "LYNX_SIG_FILE '%s' is bad. Ignoring.\n",
+ LYNX_SIG_FILE);
+ }
+ }
+ break;
+
+ case 'M':
+ if (!strncasecomp(buffer, "MAIL_SYSTEM_ERROR_LOGGING:", 26)) {
+ error_logging = is_true(buffer+26);
+
+#ifdef VMS
+ } else if (!strncasecomp(buffer, "MAIL_ADRS:", 10)) {
+ StrAllocCopy(mail_adrs, buffer+10);
+#endif /* VMS */
+
+ } else if (!strncasecomp(buffer, "MAKE_LINKS_FOR_ALL_IMAGES:", 26)) {
+ clickable_images = is_true(buffer+26);
+
+ } else if (!strncasecomp(buffer,
+ "MAKE_PSEUDO_ALTS_FOR_INLINES:", 29)) {
+ pseudo_inline_alts = is_true(buffer+29);
+
+ } else if (!strncasecomp(buffer, "MESSAGESECS:", 12)) {
+ strcpy(temp, buffer+12);
+ for (i = 0; temp[i]; i++) {
+ if (!isdigit(temp[i])) {
+ temp[i] = '\0';
+ break;
+ }
+ }
+ if (temp[0])
+ MessageSecs = atoi(temp);
+
+ } else if (!strncasecomp(buffer, "MINIMAL_COMMENTS:", 17)) {
+ minimal_comments = is_true(buffer+17);
+
+ } else if (!strncasecomp(buffer, "MULTI_BOOKMARK_SUPPORT:", 23)) {
+ LYMultiBookmarks = is_true(buffer+23);
+ }
+ break;
+
+ case 'N':
+ if (!strncasecomp(buffer, "NEWS_CHUNK_SIZE:", 16)) {
+ HTNewsChunkSize = atoi(buffer+16);
+ /*
+ * If the new HTNewsChunkSize exceeds the maximum,
+ * increase HTNewsMaxChunk to this size. - FM
+ */
+ if (HTNewsChunkSize > HTNewsMaxChunk) {
+ HTNewsMaxChunk = HTNewsChunkSize;
+ }
+
+ } else if (!strncasecomp(buffer, "NEWS_MAX_CHUNK:", 15)) {
+ HTNewsMaxChunk = atoi(buffer+15);
+ /*
+ * If HTNewsChunkSize exceeds the new maximum,
+ * reduce HTNewsChunkSize to this maximum. - FM
+ */
+ if (HTNewsChunkSize > HTNewsMaxChunk) {
+ HTNewsChunkSize = HTNewsMaxChunk;
+ }
+
+ } else if (!strncasecomp(buffer, "NEWS_POSTING:", 13)) {
+ LYNewsPosting = is_true(buffer+13);
+ no_newspost = (LYNewsPosting == FALSE);
+
+ } else if (!strncasecomp(buffer, "news_proxy:", 11)) {
+ if (getenv("news_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "news_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[11]);
+#else
+ strcpy(temp, "news_proxy=");
+ StrAllocCopy(news_proxy_putenv_cmd, temp);
+ StrAllocCat(news_proxy_putenv_cmd, (char *)&buffer[11]);
+ putenv(news_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "newspost_proxy:", 15)) {
+ if (getenv("newspost_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "newspost_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[15]);
+#else
+ strcpy(temp, "newspost_proxy=");
+ StrAllocCopy(newspost_proxy_putenv_cmd, temp);
+ StrAllocCat(newspost_proxy_putenv_cmd, (char *)&buffer[15]);
+ putenv(newspost_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "newsreply_proxy:", 16)) {
+ if (getenv("newsreply_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "newsreply_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[16]);
+#else
+ strcpy(temp, "newsreply_proxy=");
+ StrAllocCopy(newsreply_proxy_putenv_cmd, temp);
+ StrAllocCat(newsreply_proxy_putenv_cmd, (char *)&buffer[16]);
+ putenv(newsreply_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "nntp_proxy:", 11)) {
+ if (getenv("nntp_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "nntp_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[11]);
+#else
+ strcpy(temp, "nntp_proxy=");
+ StrAllocCopy(nntp_proxy_putenv_cmd, temp);
+ StrAllocCat(nntp_proxy_putenv_cmd, (char *)&buffer[11]);
+ putenv(nntp_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "NNTPSERVER:", 11)) {
+ if (getenv("NNTPSERVER") == NULL) {
+#ifdef VMS
+ strcpy(temp, "NNTPSERVER");
+ Define_VMSLogical(temp, (char *)&buffer[11]);
+#else
+ strcpy(temp, "NNTPSERVER=");
+ StrAllocCopy(NNTPSERVER_putenv_cmd, temp);
+ StrAllocCat(NNTPSERVER_putenv_cmd, (char *)&buffer[11]);
+ putenv(NNTPSERVER_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "NO_DOT_FILES:", 13)) {
+ no_dotfiles = is_true(buffer+13);
+
+ } else if (!strncasecomp(buffer, "NO_FILE_REFERER:", 16)) {
+ no_filereferer = is_true(buffer+16);
+
+#ifndef VMS
+ } else if (!strncasecomp(buffer, "NO_FORCED_CORE_DUMP:", 20)) {
+ LYNoCore = is_true(buffer+20);
+#endif /* !VMS */
+
+ } else if (!strncasecomp(buffer, "NO_FROM_HEADER:", 15)) {
+ LYNoFromHeader = is_true(buffer+15);
+
+ } else if (!strncasecomp(buffer, "NO_ISMAP_IF_USEMAP:", 19)) {
+ LYNoISMAPifUSEMAP = is_true(buffer+19);
+
+ } else if (!strncasecomp(buffer, "no_proxy:", 9)) {
+ if (getenv("no_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "no_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[9]);
+#else
+ strcpy(temp, "no_proxy=");
+ StrAllocCopy(no_proxy_putenv_cmd, temp);
+ StrAllocCat(no_proxy_putenv_cmd, (char *)&buffer[9]);
+ putenv(no_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "NO_REFERER_HEADER:", 18)) {
+ LYNoRefererHeader = is_true(buffer+18);
+ }
+ break;
+
+ case 'P':
+ if (!strncasecomp(buffer, "PERSONAL_MAILCAP:", 17)) {
+ StrAllocCopy(personal_type_map, buffer+17);
+
+ } else if (!strncasecomp(buffer, "PERSONAL_EXTENSION_MAP:", 23)) {
+ StrAllocCopy(personal_extension_map, buffer+23);
+
+ } else if (!strncasecomp(buffer, "PREFERRED_CHARSET:", 18)) {
+ StrAllocCopy(pref_charset, buffer+18);
+
+ } else if (!strncasecomp(buffer, "PREFERRED_LANGUAGE:", 19)) {
+ StrAllocCopy(language, buffer+19);
+
+ } else if (!strncasecomp(buffer, "PREPEND_BASE_TO_SOURCE:", 23)) {
+ LYPrependBaseToSource = is_true(buffer+23);
+
+ } else if (!strncasecomp(buffer, "PREPEND_CHARSET_TO_SOURCE:", 26)) {
+ LYPrependCharsetToSource = is_true(buffer+26);
+
+ } else if (!strncasecomp(buffer, "PRINTER:", 8)) {
+ add_printer_to_list(&buffer[8], &printers);
+ }
+ break;
+
+#ifdef RAWDOSKEYHACK
+ case 'R':
+ if (!strncasecomp(buffer, "RAW_DOS_KEY_HACK:", 17)) {
+ raw_dos_key_hack = is_true(buffer+17);
+ }
+ break;
+#endif /* RAWDOSKEYHACK */
+
+ case 'Q':
+ if (!strncasecomp(buffer, "QUIT_DEFAULT_YES:", 17)) {
+ LYQuitDefaultYes = is_true(buffer+17);
+ }
+ break;
+
+ case 'S':
+ if (!strncasecomp(buffer, "SAVE_SPACE:", 11)) {
+ StrAllocCopy(lynx_save_space, buffer+11);
+
+ } else if (!strncasecomp(buffer, "SCAN_FOR_BURIED_NEWS_REFS:", 26)) {
+ scan_for_buried_news_references = is_true(buffer+26);
+
+ } else if (!strncasecomp(buffer, "SEEK_FRAG_AREA_IN_CUR:", 22)) {
+ LYSeekFragAREAinCur = is_true(buffer+22);
+
+ } else if (!strncasecomp(buffer, "SEEK_FRAG_MAP_IN_CUR:", 21)) {
+ LYSeekFragMAPinCur = is_true(buffer+21);
+
+ } else if (!strncasecomp(buffer, "SET_COOKIES:", 12)) {
+ LYSetCookies = is_true(buffer+12);
+
+ } else if (!strncasecomp(buffer, "SHOW_CURSOR:", 12)) {
+ LYShowCursor = is_true(buffer+12);
+
+ } else if (!strncasecomp(buffer, "snews_proxy:", 12)) {
+ if (getenv("snews_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "snews_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[12]);
+#else
+ strcpy(temp, "snews_proxy=");
+ StrAllocCopy(snews_proxy_putenv_cmd, temp);
+ StrAllocCat(snews_proxy_putenv_cmd, (char *)&buffer[12]);
+ putenv(snews_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "snewspost_proxy:", 16)) {
+ if (getenv("snewspost_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "snewspost_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[16]);
+#else
+ strcpy(temp, "snewspost_proxy=");
+ StrAllocCopy(snewspost_proxy_putenv_cmd, temp);
+ StrAllocCat(snewspost_proxy_putenv_cmd, (char *)&buffer[16]);
+ putenv(snewspost_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "snewsreply_proxy:", 17)) {
+ if (getenv("snewsreply_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "snewsreply_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[17]);
+#else
+ strcpy(temp, "snewsreply_proxy=");
+ StrAllocCopy(snewsreply_proxy_putenv_cmd, temp);
+ StrAllocCat(snewsreply_proxy_putenv_cmd, (char *)&buffer[17]);
+ putenv(snewsreply_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+
+ } else if (!strncasecomp(buffer, "SOFT_DQUOTES:", 13)) {
+ soft_dquotes = is_true(buffer+13);
+
+ } else if (!strncasecomp(buffer, "STARTFILE:", 10)) {
+ StrAllocCopy(startfile, buffer+10);
+
+ } else if (!strncasecomp(buffer, "STRIP_DOTDOT_URLS:", 18)) {
+ LYStripDotDotURLs = is_true(buffer+18);
+
+ } else if (!strncasecomp(buffer, "SUBSTITUTE_UNDERSCORES:", 23)) {
+ use_underscore = is_true(buffer+23);
+
+ } else if (!strncasecomp(buffer, "SUFFIX:", 7)) {
+ char *extention;
+ char *mime_type;
+
+ if (strlen(buffer) > 9) {
+ extention = buffer + 7;
+ if ((mime_type = strchr(extention, ':')) != NULL) {
+ *mime_type++ = '\0';
+ for (i = 0, j = 0; mime_type[i]; i++) {
+ if (mime_type[i] != ' ') {
+ mime_type[j++] = TOLOWER(mime_type[i]);
+ }
+ }
+ mime_type[j] = '\0';
+ if (strstr(mime_type, "tex") != NULL ||
+ strstr(mime_type, "postscript") != NULL ||
+ strstr(mime_type, "sh") != NULL ||
+ strstr(mime_type, "troff") != NULL ||
+ strstr(mime_type, "rtf") != NULL)
+ HTSetSuffix(extention, mime_type, "8bit", 1.0);
+ else
+ HTSetSuffix(extention, mime_type, "binary", 1.0);
+ }
+ }
+
+ } else if (!strncasecomp(buffer, "SYSTEM_EDITOR:", 14)) {
+ StrAllocCopy(editor, buffer+14);
+ system_editor = TRUE;
+
+ } else if (!strncasecomp(buffer, "SYSTEM_MAIL:", 12)) {
+ StrAllocCopy(system_mail, buffer+12);
+
+ } else if (!strncasecomp(buffer, "SYSTEM_MAIL_FLAGS:", 18)) {
+ StrAllocCopy(system_mail_flags, buffer+18);
+ }
+ break;
+
+ case 'T':
+#ifdef EXEC_LINKS
+ if (!strncasecomp(buffer, "TRUSTED_EXEC:", 13)) {
+ add_trusted(&buffer[13], EXEC_PATH); /* Add exec path */
+ }
+#endif /* EXEC_LINKS */
+
+#ifdef LYNXCGI_LINKS
+ if (!strncasecomp(buffer, "TRUSTED_LYNXCGI:", 16)) {
+ add_trusted(&buffer[16], CGI_PATH); /* Add CGI path */
+ }
+#endif /* LYNXCGI_LINKS */
+ break;
+
+ case 'U':
+ if (!strncasecomp(buffer, "URL_DOMAIN_PREFIXES:", 20)) {
+ StrAllocCopy(URLDomainPrefixes, buffer+20);
+
+ } else if (!strncasecomp(buffer, "URL_DOMAIN_SUFFIXES:", 20)) {
+ StrAllocCopy(URLDomainSuffixes, buffer+20);
+
+#ifdef DIRED_SUPPORT
+ } else if (!strncasecomp(buffer, "UPLOADER:", 9)) {
+ add_item_to_list(&buffer[9], &uploaders);
+#endif /* DIRED_SUPPORT */
+
+#ifdef VMS
+ } else if (!strncasecomp(buffer, "USE_FIXED_RECORDS:", 18)) {
+ UseFixedRecords = is_true(buffer+18);
+#endif /* VMS */
+
+#if defined(NCURSES_MOUSE_VERSION) || defined(USE_SLANG_MOUSE)
+ } else if(!strncasecomp(buffer, "USE_MOUSE:",10)) {
+ LYUseMouse = is_true(buffer+10);
+#endif
+
+ } else if (!strncasecomp(buffer, "USE_SELECT_POPUPS:", 18)) {
+ LYSelectPopups = is_true(buffer+18);
+ }
+ break;
+
+ case 'V':
+ if (!strncasecomp(buffer, "VI_KEYS_ALWAYS_ON:", 18)) {
+ vi_keys = is_true(buffer+18);
+
+ } else if (!strncasecomp(buffer, "VIEWER:", 7)) {
+ char *mime_type;
+ char *viewer;
+ char *environment;
+
+ if (strlen(buffer) > 9) {
+ mime_type = buffer + 7;
+ if ((viewer = strchr(mime_type, ':')) != NULL) {
+ *viewer++ = '\0';
+ for (i = 0, j = 0; mime_type[i]; i++) {
+ if (mime_type[i] != ' ') {
+ mime_type[j++] = TOLOWER(mime_type[i]);
+ }
+ }
+ mime_type[j] = '\0';
+ environment = strrchr(viewer, ':');
+ if ((environment != NULL) &&
+ (strlen(viewer) > 1) && *(environment-1) != '\\') {
+ *environment++ = '\0';
+ remove_backslashes(viewer);
+ /*
+ * If environment equals xwindows then only
+ * assign the presentation if there is a display
+ * variable.
+ */
+ if (!strcasecomp(environment,"XWINDOWS")) {
+ if ((cp = getenv(DISPLAY)) != NULL &&
+ *cp != '\0')
+ HTSetPresentation(mime_type, viewer,
+ 1.0, 3.0, 0.0, 0);
+ } else if (!strcasecomp(environment,"NON_XWINDOWS")) {
+ if ((cp = getenv(DISPLAY)) == NULL ||
+ *cp == '\0')
+ HTSetPresentation(mime_type, viewer,
+ 1.0, 3.0, 0.0, 0);
+ } else {
+ HTSetPresentation(mime_type, viewer,
+ 1.0, 3.0, 0.0, 0);
+ }
+ } else {
+ remove_backslashes(viewer);
+ HTSetPresentation(mime_type, viewer,
+ 1.0, 3.0, 0.0, 0);
+ }
+ }
+ }
+ }
+ break;
+
+ case 'W':
+ if (!strncasecomp(buffer, "wais_proxy:", 11)) {
+ if (getenv("wais_proxy") == NULL) {
+#ifdef VMS
+ strcpy(temp, "wais_proxy");
+ Define_VMSLogical(temp, (char *)&buffer[11]);
+#else
+ strcpy(temp, "wais_proxy=");
+ StrAllocCopy(wais_proxy_putenv_cmd, temp);
+ StrAllocCat(wais_proxy_putenv_cmd, (char *)&buffer[11]);
+ putenv(wais_proxy_putenv_cmd);
+#endif /* VMS */
+ }
+ }
+ break;
+
+ case 'X':
+ if (!strncasecomp(buffer, "XLOADIMAGE_COMMAND:", 19)) {
+ StrAllocCopy(XLoadImageCommand, (char *)&buffer[19]);
+ }
+ break;
+
+ default:
+ break;
+
+ } /* end of Huge switch */
+ } /* end of while */
+ fclose(fp);
+
+ /*
+ * If any DOWNLOADER: commands have always_enabled set (:TRUE),
+ * make override_no_download TRUE, so that other restriction
+ * settings will not block presentation of a download menu
+ * with those always_enabled options still available. - FM
+ */
+ if (downloaders != NULL) {
+ int count;
+ lynx_html_item_type *cur_download;
+
+ for (count = 0, cur_download = downloaders;
+ cur_download != NULL;
+ cur_download = cur_download->next, count++) {
+ if (cur_download->always_enabled) {
+ override_no_download = TRUE;
+ break;
+ }
+ }
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/LYReadCFG.h b/gnu/usr.bin/lynx/src/LYReadCFG.h
new file mode 100644
index 00000000000..5e94f0d83e3
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYReadCFG.h
@@ -0,0 +1,49 @@
+#ifndef LYREADCFG_H
+#define LYREADCFG_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+#if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
+
+#define DEFAULT_COLOR -1
+#define NO_COLOR -2
+#define ERR_COLOR -3
+
+/* Note: the sense of colors that Lynx uses for defaults is the reverse of
+ * the standard for color-curses.
+ */
+#ifdef USE_DEFAULT_COLORS
+# ifdef USE_SLANG
+# define DEFAULT_FG "default"
+# define DEFAULT_BG "default"
+# else
+# ifdef HAVE_USE_DEFAULT_COLORS
+# define DEFAULT_FG DEFAULT_COLOR
+# define DEFAULT_BG DEFAULT_COLOR
+# else
+# define DEFAULT_FG COLOR_BLACK
+# define DEFAULT_BG COLOR_WHITE
+# endif
+# endif
+#else
+# ifdef USE_SLANG
+# define DEFAULT_FG "black"
+# define DEFAULT_BG "white"
+# else
+# define DEFAULT_FG COLOR_BLACK
+# define DEFAULT_BG COLOR_WHITE
+# endif
+#endif /* USE_DEFAULT_COLORS */
+
+extern int default_fg;
+extern int default_bg;
+
+extern int check_color PARAMS((char * color, int the_default));
+#endif
+
+extern void read_cfg PARAMS((char *cfg_filename));
+extern BOOLEAN have_read_cfg;
+
+#endif /* LYREADCFG_H */
diff --git a/gnu/usr.bin/lynx/src/LYSearch.c b/gnu/usr.bin/lynx/src/LYSearch.c
new file mode 100644
index 00000000000..d03fc08d5f1
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYSearch.c
@@ -0,0 +1,385 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYSearch.h"
+#include "LYGlobalDefs.h"
+#include "GridText.h"
+#include "LYSignal.h"
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * Search for the target string inside of the links
+ * that are currently displayed on the screen beginning
+ * with the one after the currently selected one.
+ * If found set cur to the new value and return TRUE.
+ * If not found do not reset cur and return FALSE.
+ */
+
+PRIVATE int check_for_target_in_links ARGS2(
+ int *, cur,
+ char *, new_target)
+{
+ int i = *cur + 1;
+ OptionType *option;
+ char *stars = NULL, *cp;
+
+ if (nlinks == 0)
+ return(FALSE);
+
+ for (; i < nlinks; i++) {
+ /*
+ * Search the hightext string, and hightext2 if present,
+ * taking the case_sensitive setting into account. - FM
+ */
+ if (((links[i].hightext != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(links[i].hightext, new_target)) ||
+ ((links[i].hightext != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(links[i].hightext, new_target))) {
+ break;
+ }
+ if (((links[i].hightext2 != NULL && case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(links[i].hightext2, new_target)) ||
+ ((links[i].hightext2 != NULL && case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(links[i].hightext2, new_target))) {
+ break;
+ }
+
+ /*
+ * Search the relevant form fields, taking the
+ * case_sensitive setting into account. - FM
+ */
+ if ((links[i].form != NULL && links[i].form->value != NULL) &&
+ links[i].form->type != F_HIDDEN_TYPE) {
+ if (links[i].form->type == F_PASSWORD_TYPE) {
+ /*
+ * Check the actual, hidden password, and then
+ * the displayed string. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(links[i].form->value,
+ new_target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(links[i].form->value,
+ new_target))) {
+ break;
+ }
+ StrAllocCopy(stars, links[i].form->value);
+ for (cp = stars; *cp != '\0'; cp++)
+ *cp = '*';
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(stars, new_target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(stars, new_target))) {
+ FREE(stars);
+ break;
+ }
+ FREE(stars);
+ } else if (links[i].form->type == F_OPTION_LIST_TYPE) {
+ /*
+ * Search the option strings that are displayed
+ * when the popup is invoked. - FM
+ */
+ option = links[i].form->select_list;
+ while (option != NULL) {
+ if (((option->name != NULL &&
+ case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(option->name, new_target)) ||
+ ((option->name != NULL &&
+ case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(option->name,
+ new_target))) {
+ break;
+ }
+ option = option->next;
+ }
+ if (option != NULL) {
+ break;
+ }
+ } else if (links[i].form->type == F_RADIO_TYPE) {
+ /*
+ * Search for checked or unchecked parens. - FM
+ */
+ if (links[i].form->num_value) {
+ cp = checked_radio;
+ } else {
+ cp = unchecked_radio;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, new_target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, new_target))) {
+ break;
+ }
+ } else if (links[i].form->type == F_CHECKBOX_TYPE) {
+ /*
+ * Search for checked or unchecked square brackets. - FM
+ */
+ if (links[i].form->num_value) {
+ cp = checked_box;
+ } else {
+ cp = unchecked_box;
+ }
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(cp, new_target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(cp, new_target))) {
+ break;
+ }
+ } else {
+ /*
+ * Check the values intended for display.
+ * May have been found already via the
+ * hightext search, but make sure here
+ * that the entire value is searched. - FM
+ */
+ if (((case_sensitive == TRUE) &&
+ LYno_attr_char_strstr(links[i].form->value,
+ new_target)) ||
+ ((case_sensitive == FALSE) &&
+ LYno_attr_char_case_strstr(links[i].form->value,
+ new_target))) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (i == nlinks)
+ return(FALSE);
+
+ *cur = i;
+ return(TRUE);
+}
+
+/*
+ * Textsearch checks the prev_target variable to see if it is empty.
+ * If it is then it requests a new search string. It then searches
+ * the current file for the next instance of the search string and
+ * finds the line number that the string is on
+ *
+ * This is the primary USER search engine and is case sensitive
+ * or case insensitive depending on the 'case_sensitive' global
+ * variable
+ *
+ */
+
+PUBLIC BOOL textsearch ARGS3(
+ document *, cur_doc,
+ char *, prev_target,
+ BOOL, next)
+{
+ int offset;
+ int oldcur = cur_doc->link;
+ static char prev_target_buffer[512]; /* Search string buffer */
+ static BOOL first = TRUE;
+ char *cp;
+ int ch = 0, recall;
+ int QueryTotal;
+ int QueryNum;
+ BOOLEAN FirstRecall = TRUE;
+
+ /*
+ * Initialize the search string buffer. - FM
+ */
+ if (first) {
+ *prev_target_buffer = '\0';
+ first = FALSE;
+ }
+
+ QueryTotal = (search_queries ? HTList_count(search_queries) : 0);
+ recall = ((QueryTotal >= 1) ? RECALL : NORECALL);
+ QueryNum = QueryTotal;
+
+ if (next)
+ /*
+ * LYK_NEXT was pressed, so copy the
+ * buffer into prev_target. - FM
+ */
+ strcpy(prev_target, prev_target_buffer);
+
+ if (strlen(prev_target) == 0 ) {
+ /*
+ * This is a new WHEREIS search ('/'), or
+ * LYK_NEXT was pressed but there was no
+ * previous search, so we need to get a
+ * search string from the user. - FM
+ */
+ _statusline(ENTER_WHEREIS_QUERY);
+
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer), recall)) < 0) {
+ /*
+ * User cancelled the search via ^G.
+ * Restore prev_target and return. - FM
+ */
+ strcpy(prev_target, prev_target_buffer);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(FALSE);
+ }
+ }
+
+check_recall:
+ if (strlen(prev_target) == 0 &&
+ !(recall && (ch == UPARROW || ch == DNARROW))) {
+ /*
+ * No entry. Simply return, retaining the current buffer.
+ * Because prev_target is now reset, highlighting of the
+ * previous search string will no longer occur, but it can
+ * be used again via LYK_NEXT. - FM
+ */
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(FALSE);
+ }
+
+ if (recall && ch == UPARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or last query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = (QueryTotal - 1); QueryNum > 0; QueryNum--) {
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = 0;
+ }
+ } else {
+ /*
+ * Go back to the previous query in the list. - FM
+ */
+ QueryNum++;
+ }
+ if (QueryNum >= QueryTotal)
+ /*
+ * Roll around to the last query in the list. - FM
+ */
+ QueryNum = 0;
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer && QueryTotal == 2) ||
+ (!(*prev_target_buffer) && QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer), recall)) < 0) {
+ /*
+ * User cancelled the search via ^G.
+ * Restore prev_target and return. - FM
+ */
+ strcpy(prev_target, prev_target_buffer);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(FALSE);
+ }
+ goto check_recall;
+ }
+ } else if (recall && ch == DNARROW) {
+ if (FirstRecall) {
+ /*
+ * Use the current string or first query in the list. - FM
+ */
+ FirstRecall = FALSE;
+ if (*prev_target_buffer) {
+ for (QueryNum = 0; QueryNum < (QueryTotal - 1); QueryNum++) {
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL &&
+ !strcmp(prev_target_buffer, cp)) {
+ break;
+ }
+ }
+ } else {
+ QueryNum = QueryTotal - 1;
+ }
+ } else {
+ /*
+ * Advance to the next query in the list. - FM
+ */
+ QueryNum--;
+ }
+ if (QueryNum < 0)
+ /*
+ * Roll around to the first query in the list. - FM
+ */
+ QueryNum = QueryTotal - 1;
+ if ((cp = (char *)HTList_objectAt(search_queries,
+ QueryNum)) != NULL) {
+ strcpy(prev_target, cp);
+ if (*prev_target_buffer &&
+ !strcmp(prev_target_buffer, prev_target)) {
+ _statusline(EDIT_CURRENT_QUERY);
+ } else if ((*prev_target_buffer && QueryTotal == 2) ||
+ (!(*prev_target_buffer) && QueryTotal == 1)) {
+ _statusline(EDIT_THE_PREV_QUERY);
+ } else {
+ _statusline(EDIT_A_PREV_QUERY);
+ }
+ if ((ch = LYgetstr(prev_target, VISIBLE,
+ sizeof(prev_target_buffer), recall)) < 0) {
+ /*
+ * User cancelled the search via ^G.
+ * Restore prev_target and return. - FM
+ */
+ strcpy(prev_target, prev_target_buffer);
+ _statusline(CANCELLED);
+ sleep(InfoSecs);
+ return(FALSE);
+ }
+ goto check_recall;
+ }
+ }
+ /*
+ * Replace the search string buffer with the new target. - FM
+ */
+ strcpy(prev_target_buffer, prev_target);
+ HTAddSearchQuery(prev_target_buffer);
+
+ /*
+ * Search the links on the currently displayed page for
+ * the string, starting after the current link. - FM
+ */
+ if (check_for_target_in_links(&cur_doc->link, prev_target)) {
+ /*
+ * Found in link, changed cur, we're done.
+ */
+ highlight(OFF, oldcur, prev_target);
+ return(TRUE);
+ }
+
+ /*
+ * We'll search the text starting from the
+ * link we are on, or the next page.
+ */
+ if (nlinks == 0)
+ offset = (display_lines - 1);
+ else
+ offset = links[cur_doc->link].ly - 1;
+
+ /*
+ * Resume search, this time for all text.
+ * Set www_search_result if string found,
+ * and position the hit near top of screen.
+ */
+ www_user_search((cur_doc->line + offset), cur_doc, prev_target);
+ if (cur_doc->link != oldcur) {
+ highlight(OFF, oldcur, prev_target);
+ return(TRUE);
+ }
+ return(www_search_result > 0);
+}
diff --git a/gnu/usr.bin/lynx/src/LYSearch.h b/gnu/usr.bin/lynx/src/LYSearch.h
new file mode 100644
index 00000000000..cff7b8065eb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYSearch.h
@@ -0,0 +1,20 @@
+
+#ifndef LYSEARCH_H
+#define LYSEARCH_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCT_H */
+
+extern BOOL textsearch PARAMS((document *cur_doc,
+ char *prev_target, BOOL next));
+
+#define IN_FILE 1
+#define IN_LINKS 2
+
+#ifndef NOT_FOUND
+#define NOT_FOUND 0
+#endif /* NOT_FOUND */
+
+
+#endif /* LYSEARCH_H */
diff --git a/gnu/usr.bin/lynx/src/LYShowInfo.c b/gnu/usr.bin/lynx/src/LYShowInfo.c
new file mode 100644
index 00000000000..dfb2f211d73
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYShowInfo.c
@@ -0,0 +1,365 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "HTTP.h"
+#include "LYCurses.h"
+#include "LYStrings.h"
+#include "LYUtils.h"
+#include "LYStructs.h"
+#include "LYGlobalDefs.h"
+#include "LYShowInfo.h"
+#include "LYSignal.h"
+#include "LYCharUtils.h"
+#include "GridText.h"
+
+#include "LYLeaks.h"
+
+#ifdef DIRED_SUPPORT
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include "LYLocal.h"
+#endif /* DIRED_SUPPORT */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * Showinfo prints a page of info about the current file and the link
+ * that the cursor is on.
+ */
+
+PUBLIC int showinfo ARGS4(
+ document *, doc,
+ int, size_of_file,
+ document *, newdoc,
+ char *, owner_address)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ static char info_url[256];
+ int url_type;
+ FILE *fp0;
+ char *Address = NULL, *Title = NULL;
+ char *cp;
+
+#ifdef DIRED_SUPPORT
+ char temp[300];
+ struct stat dir_info;
+ struct passwd *pw;
+ struct group *grp;
+#endif /* DIRED_SUPPORT */
+ if (first) {
+ tempname(tempfile, NEW_FILE);
+ /*
+ * Make the temporary file a URL now.
+ */
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(info_url, "file://localhost/%s", tempfile);
+#else
+ sprintf(info_url, "file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(0);
+ }
+
+ /*
+ * Point the address pointer at this Url
+ */
+ StrAllocCopy(newdoc->address, info_url);
+
+ if (nlinks > 0 && links[doc->link].lname != NULL &&
+ (url_type = is_url(links[doc->link].lname)) != 0 &&
+ (url_type == LYNXEXEC_URL_TYPE ||
+ url_type == LYNXPROG_URL_TYPE)) {
+ char *last_slash = strrchr(links[doc->link].lname,'/');
+ int next_to_last = strlen(links[doc->link].lname) - 1;
+
+ if ((last_slash - links[doc->link].lname) == next_to_last) {
+ links[doc->link].lname[next_to_last] = '\0';
+ }
+ }
+
+ fprintf(fp0, "<head>\n");
+ LYAddMETAcharsetToFD(fp0, -1);
+ fprintf(fp0, "<title>%s</title>\n</head>\n<body>\n",
+ SHOWINFO_TITLE);
+ fprintf(fp0,"<h1>You have reached the Information Page</h1>\n");
+ fprintf(fp0,"<h2>%s Version %s</h2>\n", LYNX_NAME, LYNX_VERSION);
+
+#ifdef DIRED_SUPPORT
+ if (lynx_edit_mode && nlinks > 0) {
+ fprintf(fp0,
+ "<h2>Directory that you are currently viewing</h2>\n<pre>");
+
+ cp = doc->address;
+ if (!strncmp(cp, "file://localhost", 16))
+ cp += 16;
+ else if (!strncmp(cp, "file:", 5))
+ cp += 5;
+ strcpy(temp, cp);
+ HTUnEscape(temp);
+
+ fprintf(fp0," <em>Name:</em> %s\n", temp);
+ fprintf(fp0," <em> URL:</em> %s\n", doc->address);
+
+ cp = links[doc->link].lname;
+ if (!strncmp(cp, "file://localhost", 16))
+ cp += 16;
+ else if (!strncmp(cp, "file:", 5))
+ cp += 5;
+ strcpy(temp, cp);
+ HTUnEscape(temp);
+ if (lstat(temp, &dir_info) == -1) {
+ _statusline(CURRENT_LINK_STATUS_FAILED);
+ sleep(AlertSecs);
+ } else {
+ char modes[80];
+ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR) {
+ fprintf(fp0,
+ "\nDirectory that you have currently selected\n\n");
+ } else if (((dir_info.st_mode) & S_IFMT) == S_IFREG) {
+ fprintf(fp0,
+ "\nFile that you have currently selected\n\n");
+#ifdef S_IFLNK
+ } else if (((dir_info.st_mode) & S_IFMT) == S_IFLNK) {
+ fprintf(fp0,
+ "\nSymbolic link that you have currently selected\n\n");
+#endif
+ } else {
+ fprintf(fp0,
+ "\nItem that you have currently selected\n\n");
+ }
+ fprintf(fp0," <em>Full name:</em> %s\n", temp);
+#ifdef S_IFLNK
+ if (((dir_info.st_mode) & S_IFMT) == S_IFLNK) {
+ char buf[1025];
+ int buf_size;
+
+ if ((buf_size = readlink(temp, buf, sizeof(buf)-1)) != -1) {
+ buf[buf_size] = '\0';
+ } else {
+ strcpy(buf, "Unable to follow link");
+ }
+ fprintf(fp0, " <em>Points to file:</em> %s\n", buf);
+ }
+#endif
+ pw = getpwuid(dir_info.st_uid);
+ if (pw)
+ fprintf(fp0, " <em>Name of owner:</em> %s\n", pw->pw_name);
+ grp = getgrgid(dir_info.st_gid);
+ if (grp && grp->gr_name)
+ fprintf(fp0, " <em>Group name:</em> %s\n", grp->gr_name);
+ if (((dir_info.st_mode) & S_IFMT) == S_IFREG) {
+ sprintf(temp, " <em>File size:</em> %ld (bytes)\n",
+ (long)dir_info.st_size);
+ fprintf(fp0, "%s", temp);
+ }
+ /*
+ * Include date and time information.
+ */
+ cp = ctime(&dir_info.st_ctime);
+ fprintf(fp0, " <em>Creation date:</em> %s", cp);
+
+ cp = ctime(&dir_info.st_mtime);
+ fprintf(fp0, " <em>Last modified:</em> %s", cp);
+
+ cp = ctime(&dir_info.st_atime);
+ fprintf(fp0, " <em>Last accessed:</em> %s\n", cp);
+
+ fprintf(fp0, " <em>Access Permissions</em>\n");
+ fprintf(fp0, " <em>Owner:</em> ");
+ modes[0] = '\0';
+ modes[1] = '\0'; /* In case there are no permissions */
+ modes[2] = '\0';
+ if ((dir_info.st_mode & S_IRUSR))
+ strcat(modes, ", read");
+ if ((dir_info.st_mode & S_IWUSR))
+ strcat(modes, ", write");
+ if ((dir_info.st_mode & S_IXUSR)) {
+ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR)
+ strcat(modes, ", search");
+ else {
+ strcat(modes, ", execute");
+ if ((dir_info.st_mode & S_ISUID))
+ strcat(modes, ", setuid");
+ }
+ }
+ fprintf(fp0, "%s\n", (char *)&modes[2]); /* Skip leading ', ' */
+
+ fprintf(fp0, " <em>Group:</em> ");
+ modes[0] = '\0';
+ modes[1] = '\0'; /* In case there are no permissions */
+ modes[2] = '\0';
+ if ((dir_info.st_mode & S_IRGRP))
+ strcat(modes, ", read");
+ if ((dir_info.st_mode & S_IWGRP))
+ strcat(modes, ", write");
+ if ((dir_info.st_mode & S_IXGRP)) {
+ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR)
+ strcat(modes, ", search");
+ else {
+ strcat(modes, ", execute");
+ if ((dir_info.st_mode & S_ISGID))
+ strcat(modes, ", setgid");
+ }
+ }
+ fprintf(fp0, "%s\n", (char *)&modes[2]); /* Skip leading ', ' */
+
+ fprintf(fp0, " <em>World:</em> ");
+ modes[0] = '\0';
+ modes[1] = '\0'; /* In case there are no permissions */
+ modes[2] = '\0';
+ if ((dir_info.st_mode & S_IROTH))
+ strcat(modes, ", read");
+ if ((dir_info.st_mode & S_IWOTH))
+ strcat(modes, ", write");
+ if ((dir_info.st_mode & S_IXOTH)) {
+ if (((dir_info.st_mode) & S_IFMT) == S_IFDIR)
+ strcat(modes, ", search");
+ else {
+ strcat(modes, ", execute");
+#ifdef S_ISVTX
+ if ((dir_info.st_mode & S_ISVTX))
+ strcat(modes, ", sticky");
+#endif
+ }
+ }
+ fprintf(fp0, "%s\n", (char *)&modes[2]); /* Skip leading ', ' */
+ }
+ fprintf(fp0,"</pre>\n");
+ } else {
+#endif /* DIRED_SUPPORT */
+
+ fprintf(fp0,
+ "<h2>File that you are currently viewing</h2>\n<dl compact>");
+
+ StrAllocCopy(Title, doc->title);
+ LYEntify(&Title, TRUE);
+ fprintf(fp0, "<dt><em>Linkname:</em> %s%s\n",
+ Title, (doc->isHEAD ? " (HEAD)" : ""));
+
+ StrAllocCopy(Address, doc->address);
+ LYEntify(&Address, TRUE);
+ fprintf(fp0,
+ "<dt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>URL:</em> %s\n", Address);
+
+ if (HTLoadedDocumentCharset()) {
+ fprintf(fp0, "<dt><em>&nbsp;Charset:</em> %s\n",
+ HTLoadedDocumentCharset());
+ } else {
+ LYUCcharset * p_in = HTAnchor_getUCInfoStage(HTMainAnchor,
+ UCT_STAGE_PARSER);
+ if (!p_in || !(p_in->MIMEname) || !*(p_in->MIMEname) ||
+ HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_PARSER) < 0) {
+ p_in = HTAnchor_getUCInfoStage(HTMainAnchor, UCT_STAGE_MIME);
+ }
+ if (p_in && p_in->MIMEname && *(p_in->MIMEname) &&
+ HTAnchor_getUCLYhndl(HTMainAnchor, UCT_STAGE_MIME) >= 0) {
+ fprintf(fp0, "<dt><em>&nbsp;Charset:</em> %s (assumed)\n",
+ p_in->MIMEname);
+ }
+ }
+
+ if ((cp = HText_getServer()) != NULL && *cp != '\0')
+ fprintf(fp0, "<dt><em>&nbsp;&nbsp;Server:</em> %s\n", cp);
+
+ if ((cp = HText_getDate()) != NULL && *cp != '\0')
+ fprintf(fp0, "<dt><em>&nbsp;&nbsp;&nbsp;&nbsp;Date:</em> %s\n", cp);
+
+ if ((cp = HText_getLastModified()) != NULL && *cp != '\0')
+ fprintf(fp0, "<dt><em>Last Mod:</em> %s\n", cp);
+
+ if (doc->post_data) {
+ fprintf(fp0,
+ "<dt><em>Post Data:</em> <xmp>%s</xmp>\n", doc->post_data);
+ fprintf(fp0,
+ "<dt><em>Post Content Type:</em> %s\n", doc->post_content_type);
+ }
+
+ if (owner_address) {
+ StrAllocCopy(Address, owner_address);
+ LYEntify(&Address, TRUE);
+ } else {
+ StrAllocCopy(Address, "None");
+ }
+ fprintf(fp0, "<dt><em>Owner(s):</em> %s\n", Address);
+
+ fprintf(fp0,
+ "<dt>&nbsp;&nbsp;&nbsp;&nbsp;<em>size:</em> %d lines\n", size_of_file);
+
+ fprintf(fp0, "<dt>&nbsp;&nbsp;&nbsp;&nbsp;<em>mode:</em> %s%s%s\n",
+ (lynx_mode == FORMS_LYNX_MODE ?
+ "forms mode" : "normal"),
+ (doc->safe ? ", safe" : ""),
+ (doc->internal_link ? ", internal link" : "")
+ );
+
+ fprintf(fp0, "</dl>\n"); /* end of list */
+
+ if (nlinks > 0) {
+ fprintf(fp0,
+ "<h2>Link that you currently have selected</h2>\n<dl compact>");
+ StrAllocCopy(Title, links[doc->link].hightext);
+ LYEntify(&Title, TRUE);
+ fprintf(fp0, "<dt><em>Linkname:</em> %s\n", Title);
+ if (lynx_mode == FORMS_LYNX_MODE &&
+ links[doc->link].type == WWW_FORM_LINK_TYPE) {
+ if (links[doc->link].form->submit_method) {
+ int method = links[doc->link].form->submit_method;
+ char *enctype = links[doc->link].form->submit_enctype;
+
+ fprintf(fp0, "<dt>&nbsp;&nbsp;<em>Method:</em> %s\n",
+ (method == URL_POST_METHOD) ? "POST" :
+ (method == URL_MAIL_METHOD) ? "(email)" :
+ "GET");
+ fprintf(fp0, "<dt>&nbsp;<em>Enctype:</em> %s\n",
+ (enctype &&
+ *enctype ?
+ enctype : "application/x-www-form-urlencoded"));
+ }
+ if (links[doc->link].form->submit_action) {
+ StrAllocCopy(Address, links[doc->link].form->submit_action);
+ LYEntify(&Address, TRUE);
+ fprintf(fp0, "<dt>&nbsp;&nbsp;<em>Action:</em> %s\n", Address);
+ }
+ if (!(links[doc->link].form->submit_method &&
+ links[doc->link].form->submit_action)) {
+ fprintf(fp0,"<dt>&nbsp;(Form field)\n");
+ }
+ } else {
+ if (links[doc->link].lname) {
+ StrAllocCopy(Title, links[doc->link].lname);
+ LYEntify(&Title, TRUE);
+ } else {
+ StrAllocCopy(Title, "");
+ }
+ fprintf(fp0,
+ "<dt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em>URL:</em> %s\n", Title);
+ }
+ fprintf(fp0, "</dl>\n"); /* end of list */
+
+ } else
+ fprintf(fp0, "<h2>No Links on the current page</h2>");
+
+#ifdef DIRED_SUPPORT
+ }
+#endif /* DIRED_SUPPORT */
+ fprintf(fp0, "</body>\n");
+
+ refresh();
+
+ fclose(fp0);
+ FREE(Address);
+ FREE(Title);
+
+ return(1);
+}
diff --git a/gnu/usr.bin/lynx/src/LYShowInfo.h b/gnu/usr.bin/lynx/src/LYShowInfo.h
new file mode 100644
index 00000000000..78b3306437f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYShowInfo.h
@@ -0,0 +1,16 @@
+
+#ifndef LYSHOWINFO_H
+#define LYSHOWINFO_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern int showinfo PARAMS((document *doc, int size_of_file, document *newdoc,
+ char *owner_address));
+
+#define SHOWINFO_TITLE "Information about the current document"
+
+
+#endif /* LYSHOWINFO_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYSignal.h b/gnu/usr.bin/lynx/src/LYSignal.h
new file mode 100644
index 00000000000..9db409187b7
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYSignal.h
@@ -0,0 +1,15 @@
+
+#ifndef LYSIGNAL_H
+#define LYSIGNAL_H
+
+#include <signal.h>
+
+#ifdef VMS
+extern void *VMSsignal PARAMS((int sig, void (*func)()));
+#ifdef signal
+#undef signal
+#endif /* signal */
+#define signal(a,b) VMSsignal(a,b) /* use LYCurses.c routines for interrupts */
+#endif /* VMS */
+
+#endif /* LYSIGNAL_H */
diff --git a/gnu/usr.bin/lynx/src/LYStrings.c b/gnu/usr.bin/lynx/src/LYStrings.c
new file mode 100644
index 00000000000..2111b9181b6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYStrings.c
@@ -0,0 +1,1680 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTCJK.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "GridText.h"
+#include "LYKeymap.h"
+#include "LYSignal.h"
+#include "LYClean.h"
+#include "LYMail.h"
+#include "LYNews.h"
+#include "LYOptions.h"
+#include "LYCharSets.h"
+#include "HTString.h"
+
+#include <ctype.h>
+
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern BOOL HTPassHighCtrlRaw;
+extern HTCJKlang HTCJK;
+
+/* If you want to add mouse support for some new platform, it's fairly
+** simple to do. Once you've determined the X and Y coordinates of
+** the mouse event, loop through the elements in the links[] array and
+** see if the coordinates fall within a highlighted link area. If so,
+** the code must set mouse_link to the index of the chosen link,
+** and return a key value that corresponds to LYK_ACTIVATE. The
+** LYK_ACTIVATE code in LYMainLoop.c will then check mouse_link
+** and activate that link. If the mouse event didn't fall within a
+** link, the code should just set mouse_link to -1 and return -1. --AMK
+**/
+
+/* The number of the link selected w/ the mouse (-1 if none) */
+static int mouse_link = -1;
+
+/* Return the value of mouse_link, erasing it */
+PUBLIC int get_mouse_link NOARGS
+{
+ int t;
+ t=mouse_link;
+ mouse_link = -1;
+ return t;
+}
+
+/* Given X and Y coordinates of a mouse event, set mouse_link to the
+** index of the corresponding hyperlink, or set mouse_link to -1 if no
+** link matches the event. Returns -1 if no link matched the click,
+** or a keycode that must be returned from LYgetch() to activate the
+** link.
+**/
+
+PRIVATE int set_clicked_link ARGS2(int,x,int,y)
+{
+ int i;
+
+ /* Loop over the links and see if we can get a match */
+ for(i=0; i < nlinks && mouse_link == -1; i++) {
+ /* Check the first line of the link */
+ if ( links[i].hightext != NULL &&
+ links[i].ly == y &&
+ (x - links[i].lx) < (int)strlen(links[i].hightext ) ) {
+ mouse_link=i;
+ }
+ /* Check the second line */
+ if (links[i].hightext2 != NULL &&
+ 1+links[i].ly == y &&
+ (x - links[i].hightext2_offset) < (int)strlen(links[i].hightext2) ) {
+ mouse_link=i;
+ }
+ }
+ /* If no link was found, just return a do-nothing code */
+ if (mouse_link == -1) return -1;
+
+ /* If a link was hit, we must look for a key which will activate LYK_ACTIVATE
+ ** XXX The 127 in the following line will depend on the size of the keymap[]
+ ** array. However, usually we'll find LYK_ACTIVATE somewhere in the first
+ ** 127 keys (it's usually mapped to the Enter key)
+ **/
+ for (i=0; i<127; i++) {
+ if (LYisNonAlnumKeyname(i, LYK_ACTIVATE)) {
+ return i;
+ }
+ }
+ /* Whoops! Nothing's defined as LYK_ACTIVATE!
+ Well, who are we to argue with the user?
+ Forget about the mouse click */
+ mouse_link = -1;
+ return -1;
+}
+
+
+/*
+ * LYstrncpy() terminates strings with a null byte.
+ * Writes a null byte into the n+1 byte of dst.
+ */
+PUBLIC char *LYstrncpy ARGS3(
+ char *, dst,
+ CONST char *, src,
+ int, n)
+{
+ char *val;
+ int len=strlen(src);
+
+ if (n < 0)
+ n = 0;
+
+ val = strncpy(dst, src, n);
+ if (len < n)
+ *(dst+len) = '\0';
+ else
+ *(dst+n) = '\0';
+ return val;
+}
+
+#define IS_NEW_GLYPH(ch) (utf_flag && ((unsigned char)(ch)&0xc0) != 0x80)
+#define IS_UTF_EXTRA(ch) (utf_flag && ((unsigned char)(ch)&0xc0) == 0x80)
+
+/*
+ * LYmbcsstrncpy() terminates strings with a null byte.
+ * It takes account of multibyte characters.
+ * The src string is copied until either end of string or max number of
+ * either bytes or glyphs (mbcs sequences) (CJK or UTF8). The utf_flag
+ * argument should be TRUE for UTF8. - KW & FM
+ */
+PUBLIC char * LYmbcsstrncpy ARGS5(
+ char *, dst,
+ CONST char *, src,
+ int, n_bytes,
+ int, n_glyphs,
+ BOOL, utf_flag)
+{
+ char *val = dst;
+ int i_bytes = 0, i_glyphs = 0;
+
+ if (n_bytes < 0)
+ n_bytes = 0;
+ if (n_glyphs < 0)
+ n_glyphs = 0;
+
+ for (; *src != '\0' && i_bytes < n_bytes; i_bytes++) {
+ if (IS_NEW_GLYPH(*src)) {
+ if (i_glyphs++ >= n_glyphs) {
+ *dst = '\0';
+ return val;
+ }
+ }
+ *(dst++) = *(src++);
+ }
+ *dst = '\0';
+
+ return val;
+}
+
+/*
+ * LYmbcs_skip_glyphs() skips a given number of display positions
+ * in a string and returns the resulting pointer. It takes account
+ * of UTF-8 encoded characters. - KW
+ */
+PUBLIC char * LYmbcs_skip_glyphs ARGS3(
+ char *, data,
+ int, n_glyphs,
+ BOOL, utf_flag)
+{
+ int i_glyphs = 0;
+
+ if (n_glyphs < 0)
+ n_glyphs = 0;
+
+ if (!data)
+ return NULL;
+ if (!utf_flag)
+ return (data + n_glyphs);
+
+ while (*data) {
+ if (IS_NEW_GLYPH(*data)) {
+ if (i_glyphs++ >= n_glyphs) {
+ return data;
+ }
+ }
+ data++;
+ }
+ return data;
+}
+
+/*
+ * LYmbcsstrlen() returns the printable length of a string
+ * that might contain IsSpecial or multibyte (CJK or UTF8)
+ * characters. - FM
+ */
+PUBLIC int LYmbcsstrlen ARGS2(
+ char *, str,
+ BOOL, utf_flag)
+{
+ int i, j, len = 0;
+
+ if (!str && *str)
+ return(len);
+
+ for (i = 0; str[i] != '\0'; i++) {
+ if (IsSpecialAttrChar(str[i])) {
+ continue;
+ } else {
+ len++;
+ }
+ if (IS_NEW_GLYPH(str[i])) {
+ j = 0;
+ while (str[(i + 1)] != '\0' &&
+ !IsSpecialAttrChar(str[(i + 1)]) &&
+ j < 5 &&
+ IS_UTF_EXTRA(str[(i + 1)])) {
+ i++;
+ j++;
+ }
+ } else if (!utf_flag && HTCJK != NOCJK && !isascii(str[i]) &&
+ str[(i + 1)] != '\0' &&
+ !IsSpecialAttrChar(str[(i + 1)])) {
+ i++;
+ }
+ }
+
+ return(len);
+}
+
+#undef GetChar
+
+#ifdef USE_SLANG
+#ifdef VMS
+#define GetChar() ttgetc()
+#else
+#define GetChar (int)SLang_getkey
+#endif /* VMS */
+#endif /* USE_SLANG */
+
+#if !defined(GetChar) && defined(NCURSES)
+#define GetChar() wgetch(my_subwindow ? my_subwindow : stdscr)
+#endif
+
+#if !defined(GetChar) && defined(SNAKE)
+#define GetChar() wgetch(stdscr)
+#endif
+
+#if !defined(GetChar) && defined(VMS)
+#define GetChar() ttgetc()
+#endif
+
+#if !defined(GetChar)
+#if HAVE_KEYPAD
+#define GetChar getch
+#else
+#ifndef USE_GETCHAR
+#define USE_GETCHAR
+#endif /* !USE_GETCHAR */
+#define GetChar() getchar() /* used to be "getc(stdin)" and "getch()" */
+#endif /* HAVE_KEYPAD */
+#endif /* !defined(GetChar) */
+
+#if defined(NCURSES)
+/*
+ * Workaround a bug in ncurses order-of-refresh by setting a pointer to
+ * the topmost window that should be displayed.
+ */
+PRIVATE WINDOW *my_subwindow;
+
+PUBLIC void LYsubwindow ARGS1(WINDOW *, param)
+{
+ my_subwindow = param;
+}
+#endif
+
+#ifdef USE_SLANG_MOUSE
+PRIVATE int sl_parse_mouse_event ARGS3(int *, x, int *, y, int *, button)
+{
+ /* "ESC [ M" has already been processed. There more characters are
+ * expected: BUTTON X Y
+ */
+ *button = SLang_getkey ();
+ switch (*button)
+ {
+ case 040: /* left button */
+ case 041: /* middle button */
+ case 042: /* right button */
+ *button -= 040;
+ break;
+
+ default: /* Hmmm.... */
+ SLang_flush_input ();
+ return -1;
+ }
+
+ *x = SLang_getkey () - 33;
+ *y = SLang_getkey () - 33;
+ return 0;
+}
+#endif
+
+#if defined(USE_SLANG_MOUSE) || defined(NCURSES_MOUSE_VERSION)
+PRIVATE int map_function_to_key ARGS1(char, keysym)
+{
+ int i;
+
+ /* I would prefer to use sizeof keymap but its size is not available.
+ * A better method would be to declare it as some fixed size.
+ */
+ for (i = 1; i < 256; i++)
+ {
+ if (keymap[i] == keysym)
+ return i - 1;
+ }
+ return -1;
+}
+#endif
+
+PRIVATE BOOLEAN csi_is_csi = TRUE;
+PUBLIC void ena_csi ARGS1(
+ BOOLEAN, flag)
+{
+ csi_is_csi = flag;
+}
+/*
+ * LYgetch() translates some escape sequences and may fake noecho.
+ */
+PUBLIC int LYgetch NOARGS
+{
+ int a, b, c, d = -1;
+
+#if defined(IGNORE_CTRL_C) || defined(USE_GETCHAR) || !defined(NCURSES)
+re_read:
+#endif /* IGNORE_CTRL_C || USE_GETCHAR */
+#ifndef USE_SLANG
+ clearerr(stdin); /* needed here for ultrix and SOCKETSHR, but why? - FM */
+#endif /* !USE_SLANG */
+#if !defined(USE_SLANG) || defined(VMS)
+ c = GetChar();
+#else
+ if (LYCursesON) {
+ c = GetChar();
+ } else {
+ c = getchar();
+ if (c == EOF && errno == EINTR) /* Ctrl-Z causes EINTR in getchar() */
+ clearerr(stdin);
+ if (feof(stdin) || ferror(stdin) || c == EOF) {
+#ifdef IGNORE_CTRL_C
+ if (sigint)
+ sigint = FALSE;
+#endif /* IGNORE_CTRL_C */
+ return(7); /* use ^G to cancel whatever called us. */
+ }
+ }
+#endif /* !USE_SLANG || VMS */
+
+#ifdef RAWDOSKEYHACK
+ if (raw_dos_key_hack) {
+ if (c == 0) c = '/';
+ if (c > 255) { /* handle raw dos keys */
+ switch (c)
+ {
+ case 464: c = '-'; break; /* keypad minus*/
+ case 465: c = '+'; break; /* keypad plus*/
+ case 459: c = 13; break; /* keypad enter*/
+ case 463: c = '*'; break; /* keypad * */
+ case 440: c = 'Q'; break; /* alt x */
+ case 265: c = 'H'; break; /* F1 */
+ default: break;
+ }
+ }
+ }
+#endif /* RAWDOSKEYHACK */
+
+#ifdef USE_GETCHAR
+ if (c == EOF && errno == EINTR) /* Ctrl-Z causes EINTR in getchar() */
+ goto re_read;
+#endif /* USE_GETCHAR */
+
+#ifdef USE_SLANG
+ if (c == 0xFFFF && LYCursesON) {
+#ifdef IGNORE_CTRL_C
+ if (sigint) {
+ sigint = FALSE;
+ goto re_read;
+ }
+#endif /* IGNORE_CTRL_C */
+ return(7); /* use ^G to cancel whatever called us. */
+ }
+#else
+ if (feof(stdin) || ferror(stdin) || c == EOF) {
+ if (recent_sizechange)
+ return(7); /* use ^G to cancel whatever called us. */
+#ifdef IGNORE_CTRL_C
+ if (sigint) {
+ sigint = FALSE;
+ /* clearerr(stdin); don't need here if stays above - FM */
+ goto re_read;
+ }
+#endif /* IGNORE_CTRL_C */
+#if !defined(USE_GETCHAR) && !defined(VMS) && !defined(NCURSES)
+ if (c == ERR && errno == EINTR) /* may have been handled signal - kw */
+ goto re_read;
+#endif /* USE_GETCHAR */
+
+ cleanup();
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(0);
+ }
+#endif /* USE_SLANG */
+
+ if (c == 27 || (csi_is_csi && c == 155)) { /* handle escape sequence */
+ b = GetChar();
+
+ if (b == '[' || b == 'O') {
+ a = GetChar();
+ } else {
+ a = b;
+ }
+
+ switch (a) {
+ case 'A': c = UPARROW; break;
+ case 'x': c = UPARROW; break; /* keypad up on pc ncsa telnet */
+ case 'B': c = DNARROW; break;
+ case 'r': c = DNARROW; break; /* keypad down on pc ncsa telnet */
+ case 'C': c = RTARROW; break;
+ case 'v': c = RTARROW; break; /* keypad right on pc ncsa telnet */
+ case 'D': c = LTARROW; break;
+ case 't': c = LTARROW; break; /* keypad left on pc ncsa telnet */
+ case 'y': c = PGUP; break; /* keypad on pc ncsa telnet */
+ case 's': c = PGDOWN; break; /* keypad on pc ncsa telnet */
+ case 'w': c = HOME; break; /* keypad on pc ncsa telnet */
+ case 'q': c = END; break; /* keypad on pc ncsa telnet */
+ case 'M':
+#ifdef USE_SLANG_MOUSE
+ if ((c == 27) && (b == '['))
+ {
+ int mouse_x, mouse_y, button;
+
+ mouse_link = -1;
+ c = -1;
+ if (-1 != sl_parse_mouse_event (&mouse_x, &mouse_y, &button))
+ {
+ if (button == 0) /* left */
+ c = set_clicked_link (mouse_x, mouse_y);
+ else if (button == 2) /* right */
+ {
+ /* Right button: go back to prev document.
+ * The problem is that we need to determine
+ * what to return to achieve this.
+ */
+ c = map_function_to_key (LYK_PREV_DOC);
+ }
+ }
+ }
+ else
+#endif
+ c = '\n'; /* keypad enter on pc ncsa telnet */
+ break;
+
+ case 'm':
+#ifdef VMS
+ if (b != 'O')
+#endif /* VMS */
+ c = '-'; /* keypad on pc ncsa telnet */
+ break;
+ case 'k':
+ if (b == 'O')
+ c = '+'; /* keypad + on my xterminal :) */
+ break;
+ case 'l':
+#ifdef VMS
+ if (b != 'O')
+#endif /* VMS */
+ c = '+'; /* keypad on pc ncsa telnet */
+ break;
+ case 'P':
+#ifdef VMS
+ if (b != 'O')
+#endif /* VMS */
+ c = F1;
+ break;
+ case 'u':
+#ifdef VMS
+ if (b != 'O')
+#endif /* VMS */
+ c = F1; /* macintosh help button */
+ break;
+ case 'p':
+#ifdef VMS
+ if (b == 'O')
+#endif /* VMS */
+ c = '0'; /* keypad 0 */
+ break;
+ case '1': /** VTxxx Find **/
+ if ((b == '[' || c == 155) && (d=GetChar()) == '~')
+ c = FIND_KEY;
+ break;
+ case '2':
+ if (b == '[' || c == 155) {
+ if ((d=GetChar())=='~') /** VTxxx Insert **/
+ c = INSERT_KEY;
+ else if ((d == '8' ||
+ d == '9') &&
+ GetChar() == '~')
+ {
+ if (d == '8') /** VTxxx Help **/
+ c = F1;
+ else if (d == '9') /** VTxxx Do **/
+ c = DO_KEY;
+ d = -1;
+ }
+ }
+ break;
+ case '3': /** VTxxx Delete **/
+ if ((b == '[' || c == 155) && (d=GetChar()) == '~')
+ c = REMOVE_KEY;
+ break;
+ case '4': /** VTxxx Select **/
+ if ((b == '[' || c == 155) && (d=GetChar()) == '~')
+ c = SELECT_KEY;
+ break;
+ case '5': /** VTxxx PrevScreen **/
+ if ((b == '[' || c == 155) && (d=GetChar()) == '~')
+ c = PGUP;
+ break;
+ case '6': /** VTxxx NextScreen **/
+ if ((b == '[' || c == 155) && (d=GetChar()) == '~')
+ c = PGDOWN;
+ break;
+ case '[': /** Linux F1-F5: ^[[[A etc. **/
+ if (b == '[' || c == 155) {
+ if ((d=GetChar()) == 'A')
+ c = F1;
+ break;
+ }
+ default:
+ if (TRACE) {
+ fprintf(stderr,"Unknown key sequence: %d:%d:%d\n",c,b,a);
+ if (!LYTraceLogFP) {
+ sleep(MessageSecs);
+ }
+ }
+ }
+ if (isdigit(a) && (b == '[' || c == 155) && d != -1 && d != '~')
+ d = GetChar();
+ }
+#if HAVE_KEYPAD
+ else {
+ /*
+ * Convert keypad() mode keys into Lynx defined keys.
+ */
+ switch(c) {
+ case KEY_DOWN: /* The four arrow keys ... */
+ c = DNARROW;
+ break;
+ case KEY_UP:
+ c = UPARROW;
+ break;
+ case KEY_LEFT:
+ c = LTARROW;
+ break;
+ case KEY_RIGHT: /* ... */
+ c = RTARROW;
+ break;
+ case KEY_HOME: /* Home key (upward+left arrow) */
+ c = HOME;
+ break;
+ case KEY_CLEAR: /* Clear screen */
+ c = 18; /* CTRL-R */
+ break;
+ case KEY_NPAGE: /* Next page */
+ c = PGDOWN;
+ break;
+ case KEY_PPAGE: /* Previous page */
+ c = PGUP;
+ break;
+ case KEY_LL: /* home down or bottom (lower left) */
+ c = END;
+ break;
+ /* The keypad is arranged like this:*/
+ /* a1 up a3 */
+ /* left b2 right */
+ /* c1 down c3 */
+ case KEY_A1: /* upper left of keypad */
+ c = HOME;
+ break;
+ case KEY_A3: /* upper right of keypad */
+ c = PGUP;
+ break;
+ case KEY_B2: /* center of keypad */
+ c = DO_NOTHING;
+ break;
+ case KEY_C1: /* lower left of keypad */
+ c = END;
+ break;
+ case KEY_C3: /* lower right of keypad */
+ c = PGDOWN;
+ break;
+#ifdef KEY_END
+ case KEY_END: /* end key 001 */
+ c = END;
+ break;
+#endif /* KEY_END */
+#ifdef KEY_HELP
+ case KEY_HELP: /* help key 001 */
+ c = F1;
+ break;
+#endif /* KEY_HELP */
+#ifdef KEY_BACKSPACE
+ case KEY_BACKSPACE:
+ c = 127; /* backspace key (delete, not Ctrl-H) */
+ break;
+#endif /* KEY_BACKSPACE */
+#ifdef KEY_F
+ case KEY_F(1):
+ c = F1; /* VTxxx Help */
+ break;
+ case KEY_F(16):
+ c = DO_KEY; /* VTxxx Do */
+ break;
+#endif /* KEY_F */
+#ifdef KEY_REDO
+ case KEY_REDO: /* VTxxx Do */
+ c = DO_KEY;
+ break;
+#endif /* KEY_REDO */
+#ifdef KEY_FIND
+ case KEY_FIND:
+ c = FIND_KEY; /* VTxxx Find */
+ break;
+#endif /* KEY_FIND */
+#ifdef KEY_SELECT
+ case KEY_SELECT:
+ c = SELECT_KEY; /* VTxxx Select */
+ break;
+#endif /* KEY_SELECT */
+#ifdef KEY_IC
+ case KEY_IC:
+ c = INSERT_KEY; /* VTxxx Insert */
+ break;
+#endif /* KEY_IC */
+#ifdef KEY_DC
+ case KEY_DC:
+ c = REMOVE_KEY; /* VTxxx Remove */
+ break;
+#endif /* KEY_DC */
+#ifdef NCURSES_MOUSE_VERSION
+ case KEY_MOUSE:
+ {
+#ifndef DOSPATH
+ MEVENT event;
+ int err;
+
+ c = -1;
+ mouse_link = -1;
+ err=getmouse(&event);
+ if (event.bstate & BUTTON1_CLICKED) {
+ c = set_clicked_link(event.x, event.y);
+ } else if (event.bstate & BUTTON3_CLICKED) {
+ c = map_function_to_key (LYK_PREV_DOC);
+ }
+#else /* pdcurses version */
+ int left,right;
+ /* yes, I am assuming that my screen will be a certain width. */
+ left = 6;
+ right = LYcols-6;
+ c = -1;
+ mouse_link = -1;
+ request_mouse_pos();
+ if (Mouse_status.button[0] & BUTTON_CLICKED) {
+ if (Mouse_status.y == (LYlines-1))
+ if (Mouse_status.x < left) c=LTARROW;
+ else if (Mouse_status.x > right) c='\b';
+ else c=PGDOWN;
+ else if (Mouse_status.y == 0)
+ if (Mouse_status.x < left) c=LTARROW;
+ else if (Mouse_status.x > right) c='\b';
+ else c=PGUP;
+ else c = set_clicked_link(Mouse_status.x, Mouse_status.y);
+ }
+#endif /* _WINDOWS */
+ }
+ break;
+#endif /* NCURSES_MOUSE_VERSION */
+ }
+ }
+#endif /* HAVE_KEYPAD */
+
+ if (c > DO_NOTHING) {
+ /*
+ * Don't return raw values for KEYPAD symbols which we may have
+ * missed in the switch above if they are obviously invalid when
+ * used as an index into (e.g.) keypad[]. - KW
+ */
+ return (0);
+ } else {
+ return(c);
+ }
+}
+
+
+/*
+** Display the current value of the string and allow the user
+** to edit it.
+*/
+
+#define EDREC EditFieldData
+
+/*
+ * Shorthand to get rid of all most of the "edit->suchandsos".
+ */
+#define Buf edit->buffer
+#define Pos edit->pos
+#define StrLen edit->strlen
+#define MaxLen edit->maxlen
+#define DspWdth edit->dspwdth
+#define DspStart edit->xpan
+#define Margin edit->margin
+
+PUBLIC void LYSetupEdit ARGS4(
+ EDREC *, edit,
+ char *, old,
+ int, maxstr,
+ int, maxdsp)
+{
+ /*
+ * Initialize edit record
+ */
+ LYGetYX(edit->sy, edit->sx);
+ edit->pad = ' ';
+ edit->dirty = TRUE;
+ edit->panon = FALSE;
+
+ StrLen = strlen(old);
+ MaxLen = maxstr;
+ DspWdth = maxdsp;
+ Margin = 0;
+ Pos = strlen(old);
+ DspStart = 0;
+
+ if (maxstr > maxdsp) { /* Need panning? */
+ if (DspWdth > 4) /* Else "{}" take up precious screen space */
+ edit->panon = TRUE;
+
+ /*
+ * Figure out margins. If too big, we do a lot of unnecessary
+ * scrolling. If too small, user doesn't have sufficient
+ * look-ahead. Let's say 25% for each margin, upper bound is
+ * 10 columns.
+ */
+ Margin = DspWdth/4;
+ if (Margin > 10)
+ Margin = 10;
+ }
+
+ /*
+ * We expect the called function to pass us a default (old) value
+ * with a length that is less than or equal to maxstr, and to
+ * handle any messaging associated with actions to achieve that
+ * requirement. However, in case the calling function screwed
+ * up, we'll check it here, and ensure that no buffer overrun can
+ * occur by loading only as much of the head as fits. - FM
+ */
+ if (strlen(old) >= maxstr) {
+ strncpy(edit->buffer, old, maxstr);
+ edit->buffer[maxstr] = '\0';
+ StrLen = maxstr;
+ } else {
+ strcpy(edit->buffer, old);
+ }
+}
+
+PUBLIC int LYEdit1 ARGS4(
+ EDREC *, edit,
+ int, ch,
+ int, action,
+ BOOL, maxMessage)
+{ /* returns 0 character processed
+ * ch otherwise
+ */
+ int i;
+ int length;
+
+ if (MaxLen <= 0)
+ return(0); /* Be defensive */
+
+ length=strlen(&Buf[0]);
+ StrLen = length;
+
+ switch (action) {
+ case LYE_AIX:
+ /*
+ * Hex 97.
+ * Fall through as a character for CJK, or if this is a valid
+ * character in the current display character set.
+ * Otherwise, we treat this as LYE_ENTER.
+ */
+ if (HTCJK == NOCJK && LYlowest_eightbit[current_char_set] > 0x97)
+ return(ch);
+ case LYE_CHAR:
+ /*
+ * ch is printable or ISO-8859-1 escape character.
+ */
+ if (Pos <= (MaxLen) && StrLen < (MaxLen)) {
+ for(i = length; i >= Pos; i--) /* Make room */
+ Buf[i+1] = Buf[i];
+ Buf[length+1]='\0';
+ Buf[Pos] = (unsigned char) ch;
+ Pos++;
+ } else if (maxMessage) {
+ _statusline(MAXLEN_REACHED_DEL_OR_MOV);
+ }
+ break;
+
+ case LYE_BACKW:
+ /*
+ * Backword.
+ * Definition of word is very naive: 1 or more a/n characters.
+ */
+ while (Pos && !isalnum(Buf[Pos-1]))
+ Pos--;
+ while (Pos && isalnum(Buf[Pos-1]))
+ Pos--;
+ break;
+
+ case LYE_FORWW:
+ /*
+ * Word forward.
+ */
+ while (isalnum(Buf[Pos]))
+ Pos++; /* '\0' is not a/n */
+ while (!isalnum(Buf[Pos]) && Buf[Pos])
+ Pos++ ;
+ break;
+
+ case LYE_ERASE:
+ /*
+ * Erase the line to start fresh.
+ */
+ Buf[0] = '\0';
+ /* fall through */
+
+ case LYE_BOL:
+ /*
+ * Go to first column.
+ */
+ Pos = 0;
+ break;
+
+ case LYE_EOL:
+ /*
+ * Go to last column.
+ */
+ Pos = length;
+ break;
+
+ case LYE_DELNW:
+ /*
+ * Delete next word.
+ */
+ {
+ int pos0 = Pos;
+ LYEdit1 (edit, 0, LYE_FORWW, FALSE);
+ while (Pos > pos0)
+ LYEdit1(edit, 0, LYE_DELP, FALSE);
+ }
+ break;
+
+ case LYE_DELPW:
+ /*
+ * Delete previous word.
+ */
+ {
+ int pos0 = Pos;
+ LYEdit1 (edit, 0, LYE_BACKW, FALSE);
+ pos0 -= Pos;
+ while (pos0--)
+ LYEdit1(edit, 0, LYE_DELN, FALSE);
+ }
+ break;
+
+ case LYE_DELN:
+ /*
+ * Delete next character
+ */
+ if (Pos >= length)
+ break;
+ Pos++;
+ /* fall through */
+
+ case LYE_DELP:
+ /*
+ * Delete preceding character.
+ */
+ if (length == 0 || Pos == 0)
+ break;
+ Pos--;
+ for (i = Pos; i < length; i++)
+ Buf[i] = Buf[i+1];
+ i--;
+ Buf[i] = 0;
+ break;
+
+ case LYE_DELC:
+ /*
+ * Delete current character.
+ */
+ if (length == 0 || Pos == length)
+ break;
+ for (i = Pos; i < length; i++)
+ Buf[i] = Buf[i+1];
+ i--;
+ Buf[i] = 0;
+ break;
+
+ case LYE_FORW:
+ /*
+ * Move cursor to the right.
+ */
+ if (Pos < length)
+ Pos++;
+ break;
+
+ case LYE_BACK:
+ /*
+ * Left-arrow move cursor to the left.
+ */
+ if (Pos > 0)
+ Pos--;
+ break;
+
+ case LYE_UPPER:
+ for (i = 0; Buf[i]; i++)
+ Buf[i] = TOUPPER(Buf[i]);
+ break;
+
+ case LYE_LOWER:
+ for (i = 0; Buf[i]; i++)
+ Buf[i] = TOLOWER(Buf[i]);
+ break;
+
+ default:
+ return(ch);
+ }
+ edit->dirty = TRUE;
+ StrLen = strlen(&Buf[0]);
+ return(0);
+}
+
+
+PUBLIC void LYRefreshEdit ARGS1(
+ EDREC *, edit)
+{
+ int i;
+ int length;
+ int nrdisplayed;
+ int padsize;
+ char *str;
+ char buffer[3];
+
+ buffer[0] = buffer[1] = buffer[2] = '\0';
+ if (!edit->dirty || (DspWdth == 0))
+ return;
+ edit->dirty = FALSE;
+
+ length=strlen(&Buf[0]);
+ edit->strlen = length;
+/*
+ * Now we have:
+ * .--DspWdth---.
+ * +---------+=============+-----------+
+ * | |M M| | (M=margin)
+ * +---------+=============+-----------+
+ * 0 DspStart length
+ *
+ * Insertion point can be anywhere between 0 and stringlength.
+ * Figure out new display starting point.
+ *
+ * The first "if" below makes Lynx scroll several columns at a time when
+ * extending the string. Looks awful, but that way we can keep up with
+ * data entry at low baudrates.
+ */
+ if ((DspStart + DspWdth) <= length)
+ if (Pos >= (DspStart + DspWdth) - Margin)
+ DspStart=(Pos - DspWdth) + Margin;
+
+ if (Pos < DspStart + Margin) {
+ DspStart = Pos - Margin;
+ if (DspStart < 0)
+ DspStart = 0;
+ }
+
+ str = &Buf[DspStart];
+
+ nrdisplayed = length-DspStart;
+ if (nrdisplayed > DspWdth)
+ nrdisplayed = DspWdth;
+
+ move(edit->sy, edit->sx);
+ if (edit->hidden) {
+ for (i = 0; i < nrdisplayed; i++)
+ addch('*');
+ } else {
+ for (i = 0; i < nrdisplayed; i++)
+ if ((buffer[0] = str[i]) == 1 || buffer[0] == 2 ||
+ ((unsigned char)buffer[0] == 160 &&
+ !(HTPassHighCtrlRaw || HTCJK != NOCJK ||
+ (LYCharSet_UC[current_char_set].enc != UCT_ENC_8859 &&
+ !(LYCharSet_UC[current_char_set].like8859
+ & UCT_R_8859SPECL))))) {
+ addch(' ');
+ } else {
+ /* For CJK strings, by Masanobu Kimura */
+ if (HTCJK != NOCJK && !isascii(buffer[0])) {
+ if (i < (nrdisplayed - 1))
+ buffer[1] = str[++i];
+ addstr(buffer);
+ buffer[1] = '\0';
+ } else {
+ addstr(buffer);
+ }
+ }
+ }
+
+ /*
+ * Erase rest of input area.
+ */
+ padsize = DspWdth-nrdisplayed;
+ while (padsize--)
+ addch((unsigned char)edit->pad);
+
+ /*
+ * Scrolling indicators.
+ */
+ if (edit->panon) {
+ if ((DspStart + nrdisplayed) < length) {
+ move(edit->sy, edit->sx+nrdisplayed-1);
+ addch('}');
+ }
+ if (DspStart) {
+ move(edit->sy, edit->sx);
+ addch('{');
+ }
+ }
+
+ move(edit->sy, edit->sx + Pos - DspStart);
+ refresh();
+}
+
+
+PUBLIC int LYgetstr ARGS4(
+ char *, inputline,
+ int, hidden,
+ size_t, bufsize,
+ int, recall)
+{
+ int x, y, MaxStringSize;
+ int ch;
+ EditFieldData MyEdit;
+
+ LYGetYX(y, x); /* Use screen from cursor position to eol */
+ MaxStringSize = (bufsize < sizeof(MyEdit.buffer)) ?
+ (bufsize - 1) : (sizeof(MyEdit.buffer) - 1);
+ LYSetupEdit(&MyEdit, inputline, MaxStringSize, (LYcols-1)-x);
+ MyEdit.hidden = hidden ;
+
+ for (;;) {
+again:
+ LYRefreshEdit(&MyEdit);
+ ch = LYgetch();
+#ifdef VMS
+ if (term_letter || term_options || term_message || HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ ch = 7;
+ }
+#else
+ if (term_letter || term_options || term_message)
+ ch = 7;
+#endif /* VMS */
+ if (recall && (ch == UPARROW || ch == DNARROW)) {
+ strcpy(inputline, MyEdit.buffer);
+ return(ch);
+ }
+ if (keymap[ch + 1] == LYK_REFRESH)
+ goto again;
+ switch (EditBinding(ch)) {
+ case LYE_TAB:
+ ch = '\t';
+ /* fall through */
+ case LYE_AIX:
+ /*
+ * Hex 97.
+ * Treat as a character for CJK, or if this is a valid
+ * character in the current display character set.
+ * Otherwise, we treat this as LYE_ENTER.
+ */
+ if (ch != '\t' &&
+ (HTCJK != NOCJK ||
+ LYlowest_eightbit[current_char_set] <= 0x97)) {
+ LYLineEdit(&MyEdit,ch, FALSE);
+ break;
+ }
+ case LYE_ENTER:
+ /*
+ * Terminate the string and return.
+ */
+ strcpy(inputline, MyEdit.buffer);
+ return(ch);
+ break;
+
+ case LYE_ABORT:
+ /*
+ * Control-C or Control-G aborts.
+ */
+ inputline[0] = '\0';
+ return(-1);
+ break;
+
+ case LYE_LKCMD:
+ /*
+ * Used only in form_getstr() for invoking
+ * the LYK_F_LINK_NUM prompt when in form
+ * text fields. - FM
+ */
+ break;
+
+ default:
+ LYLineEdit(&MyEdit, ch, FALSE);
+ }
+ }
+}
+
+/*
+ * LYstrstr will find the first occurrence of the string
+ * pointed to by tarptr in the string pointed to by chptr.
+ * It returns NULL if string not found.
+ * It is a case insensitive search.
+ */
+PUBLIC char * LYstrstr ARGS2(
+ char *, chptr,
+ char *, tarptr)
+{
+ int len = strlen(tarptr);
+
+ for(; *chptr != '\0'; chptr++) {
+ if (0 == UPPER8(*chptr, *tarptr)) {
+ if (0 == strncasecomp8(chptr+1, tarptr+1, len-1))
+ return(chptr);
+ }
+ } /* end for */
+
+ return(NULL); /* string not found or initial chptr was empty */
+}
+
+/*
+ * LYno_attr_char_case_strstr will find the first occurrence of the
+ * string pointed to by tarptr in the string pointed to by chptr.
+ * It ignores the characters: LY_UNDERLINE_START_CHAR and
+ * LY_UNDERLINE_END_CHAR
+ * LY_BOLD_START_CHAR
+ * LY_BOLD_END_CHAR
+ * LY_SOFT_HYPHEN
+ * if present in chptr.
+ * It is a case insensitive search.
+ */
+PUBLIC char * LYno_attr_char_case_strstr ARGS2(
+ char *, chptr,
+ char *, tarptr)
+{
+ register char *tmpchptr, *tmptarptr;
+
+ if (!chptr)
+ return(NULL);
+
+ while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
+ chptr++;
+
+ for (; *chptr != '\0'; chptr++) {
+ if (0 == UPPER8(*chptr, *tarptr)) {
+ /*
+ * See if they line up.
+ */
+ tmpchptr = chptr+1;
+ tmptarptr = tarptr+1;
+
+ if (*tmptarptr == '\0') /* one char target */
+ return(chptr);
+
+ while (1) {
+ if (!IsSpecialAttrChar(*tmpchptr)) {
+ if (0 != UPPER8(*tmpchptr, *tmptarptr))
+ break;
+ tmpchptr++;
+ tmptarptr++;
+ } else {
+ tmpchptr++;
+ }
+ if (*tmptarptr == '\0')
+ return(chptr);
+ if (*tmpchptr == '\0')
+ break;
+ }
+ }
+ } /* end for */
+
+ return(NULL);
+}
+
+/*
+ * LYno_attr_char_strstr will find the first occurrence of the
+ * string pointed to by tarptr in the string pointed to by chptr.
+ * It ignores the characters: LY_UNDERLINE_START_CHAR and
+ * LY_UNDERLINE_END_CHAR
+ * LY_BOLD_START_CHAR
+ * LY_BOLD_END_CHAR
+ * LY_SOFT_HYPHEN
+ * if present in chptr.
+ * It is a case sensitive search.
+ */
+PUBLIC char * LYno_attr_char_strstr ARGS2(
+ char *, chptr,
+ char *, tarptr)
+{
+ register char *tmpchptr, *tmptarptr;
+
+ if (!chptr)
+ return(NULL);
+
+ while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
+ chptr++;
+
+ for (; *chptr != '\0'; chptr++) {
+ if ((*chptr) == (*tarptr)) {
+ /*
+ * See if they line up.
+ */
+ tmpchptr = chptr + 1;
+ tmptarptr = tarptr + 1;
+
+ if (*tmptarptr == '\0') /* one char target */
+ return(chptr);
+
+ while (1) {
+ if (!IsSpecialAttrChar(*tmpchptr)) {
+ if ((*tmpchptr) != (*tmptarptr))
+ break;
+ tmpchptr++;
+ tmptarptr++;
+ } else {
+ tmpchptr++;
+ }
+ if (*tmptarptr == '\0')
+ return(chptr);
+ if (*tmpchptr == '\0')
+ break;
+ }
+ }
+ } /* end for */
+
+ return(NULL);
+}
+
+/*
+ * LYno_attr_mbcs_case_strstr will find the first occurrence of the string
+ * pointed to by tarptr in the string pointed to by chptr.
+ * It takes account of MultiByte Character Sequences (UTF8).
+ * The physical length of the displayed string up to the end of the target
+ * string is returned in *nendp if the search is successful.
+ * It ignores the characters: LY_UNDERLINE_START_CHAR and
+ * LY_UNDERLINE_END_CHAR
+ * LY_BOLD_START_CHAR
+ * LY_BOLD_END_CHAR
+ * LY_SOFT_HYPHEN
+ * if present in chptr.
+ * It assumes UTF8 if utf_flag is set.
+ * It is a case insensitive search. - KW & FM
+ */
+PUBLIC char * LYno_attr_mbcs_case_strstr ARGS5(
+ char *, chptr,
+ char *, tarptr,
+ BOOL, utf_flag,
+ int *, nstartp,
+ int *, nendp)
+{
+ register char *tmpchptr, *tmptarptr;
+ int len = 0;
+ int offset;
+
+ if (!(chptr && tarptr))
+ return(NULL);
+
+ /*
+ * Skip initial IsSpecial chars. - FM
+ */
+ while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
+ chptr++;
+
+ /*
+ * Seek a first target match. - FM
+ */
+ for (; *chptr != '\0'; chptr++) {
+ if ((!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+ *chptr == *tarptr &&
+ *(chptr + 1) != '\0' &&
+ !IsSpecialAttrChar(*(chptr + 1))) ||
+ (0 == UPPER8(*chptr, *tarptr))) {
+ int tarlen = 0;
+ offset = len;
+ len++;
+
+ /*
+ * See if they line up.
+ */
+ tmpchptr = (chptr + 1);
+ tmptarptr = (tarptr + 1);
+
+ if (*tmptarptr == '\0') {
+ /*
+ * One char target.
+ */
+ *nstartp = offset;
+ *nendp = len;
+ return(chptr);
+ }
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+ *chptr == *tarptr &&
+ *tmpchptr != '\0' &&
+ !IsSpecialAttrChar(*tmpchptr)) {
+ /*
+ * Check the CJK multibyte. - FM
+ */
+ if (*tmpchptr == *tmptarptr) {
+ /*
+ * It's a match. Advance to next char. - FM
+ */
+ tmpchptr++;
+ tmptarptr++;
+ if (*tmptarptr == '\0') {
+ /*
+ * One character match. - FM
+ */
+ *nstartp = offset;
+ *nendp = len + tarlen;
+ return(chptr);
+ }
+ tarlen++;
+ } else {
+ /*
+ * It's not a match, so go back to
+ * seeking a first target match. - FM
+ */
+ chptr++;
+ continue;
+ }
+ }
+ /*
+ * See if the rest of the target matches. - FM
+ */
+ while (1) {
+ if (!IsSpecialAttrChar(*tmpchptr)) {
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*tmpchptr)) {
+ if (*tmpchptr == *tmptarptr &&
+ *(tmpchptr + 1) == *(tmptarptr + 1) &&
+ !IsSpecialAttrChar(*(tmpchptr + 1))) {
+ tmpchptr++;
+ tmptarptr++;
+ } else {
+ break;
+ }
+ } else if (0 != UPPER8(*tmpchptr, *tmptarptr)) {
+ break;
+ }
+
+ if (!IS_UTF_EXTRA(*tmptarptr)) {
+ tarlen++;
+ }
+ tmpchptr++;
+ tmptarptr++;
+
+ } else {
+ tmpchptr++;
+ }
+
+ if (*tmptarptr == '\0') {
+ *nstartp = offset;
+ *nendp = len + tarlen;
+ return(chptr);
+ }
+ if (*tmpchptr == '\0') {
+ break;
+ }
+ }
+ } else if (!(IS_UTF_EXTRA(*chptr) ||
+ IsSpecialAttrChar(*chptr))) {
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+ *(chptr + 1) != '\0' &&
+ !IsSpecialAttrChar(*(chptr + 1))) {
+ chptr++;
+ }
+ len++;
+ }
+ } /* end for */
+
+ return(NULL);
+}
+
+/*
+ * LYno_attr_mbcs_strstr will find the first occurrence of the string
+ * pointed to by tarptr in the string pointed to by chptr.
+ * It takes account of CJK and MultiByte Character Sequences (UTF8).
+ * The physical lengths of the displayed string up to the start and
+ * end of the target string are returned in *nstartp and *nendp if
+ * the search is successful.
+ * It ignores the characters: LY_UNDERLINE_START_CHAR and
+ * LY_UNDERLINE_END_CHAR
+ * LY_BOLD_START_CHAR
+ * LY_BOLD_END_CHAR
+ * LY_SOFT_HYPHEN
+ * if present in chptr.
+ * It assumes UTF8 if utf_flag is set.
+ * It is a case sensitive search. - KW & FM
+ */
+PUBLIC char * LYno_attr_mbcs_strstr ARGS5(
+ char *, chptr,
+ char *, tarptr,
+ BOOL, utf_flag,
+ int *, nstartp,
+ int *, nendp)
+{
+ register char *tmpchptr, *tmptarptr;
+ int len = 0;
+ int offset;
+
+ if (!(chptr && tarptr))
+ return(NULL);
+
+ /*
+ * Skip initial IsSpecial chars. - FM
+ */
+ while (IsSpecialAttrChar(*chptr) && *chptr != '\0')
+ chptr++;
+
+ /*
+ * Seek a first target match. - FM
+ */
+ for (; *chptr != '\0'; chptr++) {
+ if ((*chptr) == (*tarptr)) {
+ int tarlen = 0;
+ offset = len;
+ len++;
+
+ /*
+ * See if they line up.
+ */
+ tmpchptr = (chptr + 1);
+ tmptarptr = (tarptr + 1);
+
+ if (*tmptarptr == '\0') {
+ /*
+ * One char target.
+ */
+ *nstartp = offset;
+ *nendp = len + 1;
+ return(chptr);
+ }
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+ *tmpchptr != '\0' &&
+ !IsSpecialAttrChar(*tmpchptr)) {
+ /*
+ * Check the CJK multibyte. - FM
+ */
+ if (*tmpchptr == *tmptarptr) {
+ /*
+ * It's a match. Advance to next char. - FM
+ */
+ tmpchptr++;
+ tmptarptr++;
+ if (*tmptarptr == '\0') {
+ /*
+ * One character match. - FM
+ */
+ *nstartp = offset;
+ *nendp = len + tarlen;
+ return(chptr);
+ }
+ tarlen++;
+ } else {
+ /*
+ * It's not a match, so go back to
+ * seeking a first target match. - FM
+ */
+ chptr++;
+ continue;
+ }
+ }
+ /*
+ * See if the rest of the target matches. - FM
+ */
+ while (1) {
+ if (!IsSpecialAttrChar(*tmpchptr)) {
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*tmpchptr)) {
+ if (*tmpchptr == *tmptarptr &&
+ *(tmpchptr + 1) == *(tmptarptr + 1) &&
+ !IsSpecialAttrChar(*(tmpchptr + 1))) {
+ tmpchptr++;
+ tmptarptr++;
+ } else {
+ break;
+ }
+ } else if ((*tmpchptr) != (*tmptarptr)) {
+ break;
+ }
+
+ if (!IS_UTF_EXTRA(*tmptarptr)) {
+ tarlen++;
+ }
+ tmpchptr++;
+ tmptarptr++;
+ } else {
+ tmpchptr++;
+ }
+
+ if (*tmptarptr == '\0') {
+ *nstartp = offset;
+ *nendp = len + tarlen;
+ return(chptr);
+ }
+ if (*tmpchptr == '\0') {
+ break;
+ }
+ }
+ } else if (!(IS_UTF_EXTRA(*chptr) ||
+ IsSpecialAttrChar(*chptr))) {
+ if (!utf_flag && HTCJK != NOCJK && !isascii(*chptr) &&
+ *(chptr + 1) != '\0' &&
+ !IsSpecialAttrChar(*(chptr + 1))) {
+ chptr++;
+ }
+ len++;
+ }
+ } /* end for */
+
+ return(NULL);
+}
+
+/*
+ * Allocate a new copy of a string, and returns it.
+ */
+PUBLIC char * SNACopy ARGS3(
+ char **, dest,
+ CONST char *, src,
+ int, n)
+{
+ FREE(*dest);
+ if (src) {
+ *dest = (char *)calloc(1, n + 1);
+ if (*dest == NULL) {
+ if (TRACE)
+ fprintf(stderr, "Tried to calloc %d bytes\n", n);
+ outofmem(__FILE__, "SNACopy");
+ }
+ strncpy (*dest, src, n);
+ *(*dest + n) = '\0'; /* terminate */
+ }
+ return *dest;
+}
+
+/*
+ * String Allocate and Concatenate.
+ */
+PUBLIC char * SNACat ARGS3(
+ char **, dest,
+ CONST char *, src,
+ int, n)
+{
+ if (src && *src) {
+ if (*dest) {
+ int length = strlen(*dest);
+ *dest = (char *)realloc(*dest, length + n + 1);
+ if (*dest == NULL)
+ outofmem(__FILE__, "SNACat");
+ strncpy(*dest + length, src, n);
+ *(*dest + length + n) = '\0'; /* terminate */
+ } else {
+ *dest = (char *)calloc(1, strlen(src) + 1);
+ if (*dest == NULL)
+ outofmem(__FILE__, "SNACat");
+ strncpy(*dest, src, n);
+ *dest[n] = '\0'; /* terminate */
+ }
+ }
+ return *dest;
+}
+
+
+/*
+** UPPER8 ?
+** it was "TOUPPER(a) - TOUPPER(b)" in its previous life...
+**
+** It was realized that case-insensitive user search
+** got information about upper/lower mapping from TOUPPER
+** (precisely from "(TOUPPER(a) - TOUPPER(b))==0").
+** This function depends on locale in its 8bit mapping
+** and usually fails with DOS/WINDOWS display charsets
+** as well as on non-UNIX systems.
+**
+** We extend this function for 8bit letters
+** using Lynx internal chartrans feature:
+** we assume that upper/lower case letters
+** have their "7bit approximation" images (in def7_uni.tbl)
+** matched case-insensitive (7bit).
+**
+** By this technique we automatically cover *any* charset
+** known for Lynx chartrans and need no any extra information for it.
+**
+** The cost of this assumption is that several differently accented letters
+** may be interpreted as equal, but this side effect is negligible
+** if the user search string is more than one character long. - LP
+**
+** Currently we enable new technique only for DOS/WINDOWS display charsets
+** and also for EXP_8BIT_TOUPPER compilation symbol.
+*/
+PUBLIC int UPPER8 ARGS2(int,ch1, int,ch2)
+{
+
+ /* case-insensitive match for us-ascii */
+ if ((unsigned char)ch1 < 128 && (unsigned char)ch2 < 128)
+ return(TOUPPER(ch1) - TOUPPER(ch2));
+
+ /* case-insensitive match for upper half */
+ if ((unsigned char)ch1 > 127 && (unsigned char)ch2 >127)
+ {
+ CONST char *disp_charset;
+ disp_charset = LYCharSet_UC[current_char_set].MIMEname;
+
+#if !defined(EXP_8BIT_TOUPPER)
+ if (!(strncasecomp(disp_charset, "cp", 2) ||
+ strncasecomp(disp_charset, "windows", 7))) {
+
+ return(TOUPPER(ch1) - TOUPPER(ch2)); /* old-style */
+ } else
+#endif
+ {
+ /* compare "7bit approximation" for letters >127 */
+ /* BTW, if we remove the check for >127 above */
+ /* we get even more "relaxed" insensitive match... */
+
+ int charset_in, charset_out, uck1, uck2;
+ char replace_buf1 [10], replace_buf2 [10];
+
+ charset_in = UCGetLYhndl_byMIME(disp_charset);
+ charset_out = UCGetLYhndl_byMIME("us-ascii");
+
+ uck1 = UCTransCharStr(replace_buf1, sizeof(replace_buf1), ch1,
+ charset_in, charset_out, YES);
+ uck2 = UCTransCharStr(replace_buf2, sizeof(replace_buf2), ch2,
+ charset_in, charset_out, YES);
+
+ if ((uck1 > 0) && (uck2 > 0)) /* both replacement strings found */
+ return (strcasecomp(replace_buf1, replace_buf2));
+
+ /* check to be sure we have not lost any strange characters */
+ /* which are not found in def7_uni.tbl but _equal_ in fact. */
+ if ((unsigned char)ch1==(unsigned char)ch2)
+ return(0); /* match */
+ }
+ }
+
+ return(-10); /* mismatch, if we come to here */
+}
diff --git a/gnu/usr.bin/lynx/src/LYStrings.h b/gnu/usr.bin/lynx/src/LYStrings.h
new file mode 100644
index 00000000000..350b88f35aa
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYStrings.h
@@ -0,0 +1,175 @@
+#ifndef LYSTRINGS_H
+#define LYSTRINGS_H
+
+#include <string.h>
+
+#if !defined(EXP_8BIT_TOUPPER) && !defined(LOCALE)
+#define EXP_8BIT_TOUPPER
+#endif
+
+/* UPPER8(ch1,ch2) is an extension of (TOUPPER(ch1) - TOUPPER(ch2)) */
+extern int UPPER8 PARAMS((
+ int ch1,
+ int ch2));
+
+extern int get_mouse_link NOPARAMS;
+extern char * LYstrncpy PARAMS((
+ char * dst,
+ CONST char * src,
+ int n));
+extern void ena_csi PARAMS((BOOLEAN flag));
+extern int LYgetch NOPARAMS;
+extern int LYgetstr PARAMS((
+ char * inputline,
+ int hidden,
+ size_t bufsize,
+ int recall));
+extern char * LYstrstr PARAMS((
+ char * chptr,
+ char * tarptr));
+extern char * LYmbcsstrncpy PARAMS((
+ char * dst,
+ CONST char * src,
+ int n_bytes,
+ int n_glyphs,
+ BOOL utf_flag));
+extern char * LYmbcs_skip_glyphs PARAMS((
+ char * data,
+ int n_glyphs,
+ BOOL utf_flag));
+extern int LYmbcsstrlen PARAMS((
+ char * str,
+ BOOL utf_flag));
+extern char * LYno_attr_mbcs_strstr PARAMS((
+ char * chptr,
+ char * tarptr,
+ BOOL utf_flag,
+ int * nstartp,
+ int * nendp));
+extern char * LYno_attr_mbcs_case_strstr PARAMS((
+ char * chptr,
+ char * tarptr,
+ BOOL utf_flag,
+ int * nstartp,
+ int * nendp));
+extern char * LYno_attr_char_strstr PARAMS((
+ char * chptr,
+ char * tarptr));
+extern char * LYno_attr_char_case_strstr PARAMS((
+ char * chptr,
+ char * tarptr));
+
+extern char * SNACopy PARAMS((
+ char ** dest,
+ CONST char * src,
+ int n));
+extern char * SNACat PARAMS((
+ char ** dest,
+ CONST char * src,
+ int n));
+#define StrnAllocCopy(dest, src, n) SNACopy (&(dest), src, n)
+#define StrnAllocCat(dest, src, n) SNACat (&(dest), src, n)
+
+#define printable(c) (((c)>31 && (c)<=255) || (c)==9 || (c)==10 || (c)<0 )
+
+/* values for LYgetch */
+#define UPARROW 256 /* 0x100 */
+#define DNARROW 257 /* 0x101 */
+#define RTARROW 258 /* 0x102 */
+#define LTARROW 259 /* 0x103 */
+#define PGDOWN 260 /* 0x104 */
+#define PGUP 261 /* 0x105 */
+#define HOME 262 /* 0x106 */
+#define END 263 /* 0x107 */
+#define F1 264 /* 0x108 */
+#define DO_KEY 265 /* 0x109 */
+#define FIND_KEY 266 /* 0x10A */
+#define SELECT_KEY 267 /* 0x10B */
+#define INSERT_KEY 268 /* 0x10C */
+#define REMOVE_KEY 269 /* 0x10D */
+#define DO_NOTHING 270 /* 0x10E */
+
+#define VISIBLE 0
+#define HIDDEN 1
+#define NORECALL 0
+#define RECALL 1
+
+/* EditFieldData preserves state between calls to LYEdit1
+ */
+typedef struct _EditFieldData {
+
+ int sx; /* Origin of editfield */
+ int sy;
+ int dspwdth; /* Screen real estate for editting */
+
+ int strlen; /* Current size of string. */
+ int maxlen; /* Max size of string, excluding zero at end */
+ char pad; /* Right padding typically ' ' or '_' */
+ BOOL hidden; /* Masked password entry flag */
+
+ BOOL dirty; /* accumulate refresh requests */
+ BOOL panon; /* Need horizontal scroll indicator */
+ int xpan; /* Horizontal scroll offset */
+ int pos; /* Insertion point in string */
+ int margin; /* Number of columns look-ahead/look-back */
+
+ char buffer[1024]; /* String buffer */
+
+} EditFieldData;
+
+/* line-edit action encoding */
+
+#define LYE_NOP 0 /* Do Nothing */
+#define LYE_CHAR (LYE_NOP +1) /* Insert printable char */
+#define LYE_ENTER (LYE_CHAR +1) /* Input complete, return char */
+#define LYE_TAB (LYE_ENTER +1) /* Input complete, return TAB */
+#define LYE_ABORT (LYE_TAB +1) /* Input cancelled */
+
+#define LYE_DELN (LYE_ABORT +1) /* Delete next char */
+#define LYE_DELC (LYE_DELN +1) /* Delete current char */
+#define LYE_DELP (LYE_DELC +1) /* Delete prev char */
+#define LYE_DELNW (LYE_DELP +1) /* Delete next word */
+#define LYE_DELPW (LYE_DELNW +1) /* Delete prev word */
+
+#define LYE_ERASE (LYE_DELPW +1) /* Erase the line */
+
+#define LYE_BOL (LYE_ERASE +1) /* Go to begin of line */
+#define LYE_EOL (LYE_BOL +1) /* Go to end of line */
+#define LYE_FORW (LYE_EOL +1) /* Cursor forwards */
+#define LYE_BACK (LYE_FORW +1) /* Cursor backwards */
+#define LYE_FORWW (LYE_BACK +1) /* Word forward */
+#define LYE_BACKW (LYE_FORWW +1) /* Word back */
+
+#define LYE_LOWER (LYE_BACKW +1) /* Lower case the line */
+#define LYE_UPPER (LYE_LOWER +1) /* Upper case the line */
+
+#define LYE_LKCMD (LYE_UPPER +1) /* Invoke command prompt */
+
+#define LYE_AIX (LYE_LKCMD +1) /* Hex 97 */
+
+extern void LYSetupEdit PARAMS((
+ EditFieldData * edit,
+ char * old,
+ int maxstr,
+ int maxdsp));
+extern void LYRefreshEdit PARAMS((
+ EditFieldData * edit));
+extern int LYEdit1 PARAMS((
+ EditFieldData * edit,
+ int ch,
+ int action,
+ BOOL maxMessage));
+
+
+extern int current_lineedit;
+extern char * LYLineeditNames[];
+extern char * LYLineEditors[];
+
+/* Push a chacter through the linedit machinery */
+#define EditBinding(c) (LYLineEditors[current_lineedit][c])
+#define LYLineEdit(e,c,m) LYEdit1(e,c,EditBinding(c),m)
+
+/* Dummy initializer for LYEditmap.c */
+extern int LYEditmapDeclared NOPARAMS;
+
+#endif /* LYSTRINGS_H */
diff --git a/gnu/usr.bin/lynx/src/LYStructs.h b/gnu/usr.bin/lynx/src/LYStructs.h
new file mode 100644
index 00000000000..1c22447958f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYStructs.h
@@ -0,0 +1,112 @@
+
+#ifndef LYSTRUCTS_H
+#define LYSTRUCTS_H
+
+#ifndef USERDEFS_H
+#include "userdefs.h"
+#endif /* USERDEFS_H */
+
+#ifndef HTANCHOR_H
+#include "HTAnchor.h"
+#endif /* HTANCHOR_H */
+
+typedef struct link {
+ char *lname;
+ char *target;
+ char *hightext;
+ char *hightext2;
+ int hightext2_offset;
+ BOOL inUnderline; /* TRUE when this link is in underlined context. */
+ int lx;
+ int ly;
+ int type; /* Type of link, Forms, WWW, etc. */
+ int anchor_number; /* The anchor number within the HText structure. */
+ int anchor_line_num;/* The anchor line number in the HText structure. */
+ struct _FormInfo *form; /* Pointer to form info. */
+} linkstruct;
+extern linkstruct links[MAXLINKS];
+extern int nlinks;
+
+typedef struct _document {
+ char * title;
+ char * address;
+ char * post_data;
+ char * post_content_type;
+ BOOL safe;
+ BOOL isHEAD;
+ char * bookmark;
+ int link;
+ int line;
+ BOOL internal_link; /* whether doc was reached via an internal
+ (fragment) link. - kw */
+#ifdef USE_HASH
+ char * style;
+#endif
+} document;
+
+#ifndef HTFORMS_H
+#include "HTForms.h"
+#endif /* HTFORMS_H */
+
+typedef struct _histstruct {
+ char * title;
+ char * address;
+ char * post_data;
+ char * post_content_type;
+ BOOL safe;
+ char * bookmark;
+ BOOL isHEAD;
+ int link;
+ int page;
+ BOOL internal_link; /* whether doc was reached via an internal
+ (fragment) link. - kw */
+ int intern_seq_start; /* indicates which element on the history
+ is the start of this sequence of
+ "internal links", otherwise -1 */
+} histstruct;
+
+typedef struct _VisitedLink {
+ char * title;
+ char * address;
+} VisitedLink;
+
+extern histstruct history[MAXHIST];
+extern int nhist;
+
+typedef struct _lynx_html_item_type {
+ struct _lynx_html_item_type *next; /* the next item in the linked list */
+ char *name; /* a description of the item */
+ char *command; /* the command to execute */
+ int always_enabled; /* a constant to tell whether or
+ * not to disable the printer
+ * when the no_print option is on
+ */
+} lynx_html_item_type;
+
+/* for printer commands */
+typedef struct _lynx_printer_item_type {
+ struct _lynx_printer_item_type *next; /* next item in the linked list */
+ char *name; /* a description of the item */
+ char *command; /* the command to execute */
+ int always_enabled; /* a constant to tell whether or
+ * not to disable the printer
+ * when the no_print option is on
+ */
+ int pagelen; /* an integer to store the printer's
+ * page length
+ */
+} lynx_printer_item_type;
+extern lynx_printer_item_type *printers;
+
+/* for download commands */
+extern lynx_html_item_type *downloaders;
+
+/* for upload commands */
+extern lynx_html_item_type *uploaders;
+
+#ifdef USE_EXTERNALS
+/* for external commands */
+extern lynx_html_item_type *externals;
+#endif
+
+#endif /* LYSTRUCTS_H */
diff --git a/gnu/usr.bin/lynx/src/LYStyle.c b/gnu/usr.bin/lynx/src/LYStyle.c
new file mode 100644
index 00000000000..78086e52e78
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYStyle.c
@@ -0,0 +1,406 @@
+/* character level styles for Lynx
+ * (c) 1996 Rob Partington -- donated to the Lyncei (if they want it :-)
+ * $Id: LYStyle.c,v 1.1 1998/03/11 17:48:00 maja Exp $
+ */
+#include "HTUtils.h"
+#include "HTML.h"
+#include "tcp.h"
+#include "LYSignal.h"
+#include "LYGlobalDefs.h"
+
+#include "LYStructs.h"
+#include "LYReadCFG.h"
+#include "LYCurses.h"
+#include "LYCharUtils.h"
+#include "AttrList.h"
+#include "SGML.h"
+#include "HTMLDTD.h"
+
+/* Hash table definitions */
+#include "LYHash.h"
+#include "LYStyle.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#ifdef USE_COLOR_STYLE
+
+PUBLIC bucket hashStyles[CSHASHSIZE];
+
+/* definitions for the mono attributes we can use */
+static int ncursesMono[7] = {
+ A_NORMAL, A_BOLD, A_REVERSE, A_UNDERLINE, A_STANDOUT, A_BLINK, A_DIM
+};
+
+/*
+ * If these strings don't match the meanings of the above attributes,
+ * you'll confuse the hell out of people, so make them the same. - RP
+ */
+static char *Mono_Strings[7] =
+{
+ "normal", "bold", "reverse", "underline", "standout", "blink", "dim"
+};
+
+/* Remember the hash codes for common elements */
+PUBLIC int s_alink = NOSTYLE, s_a = NOSTYLE, s_status = NOSTYLE,
+ s_label = NOSTYLE, s_value = NOSTYLE, s_high = NOSTYLE,
+ s_normal = NOSTYLE, s_alert = NOSTYLE, s_title = NOSTYLE;
+
+/* start somewhere safe */
+PRIVATE int colorPairs = 0;
+PRIVATE int last_fA = COLOR_WHITE, last_bA = COLOR_BLACK;
+
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/* icky parsing of the style options */
+PRIVATE void parse_attributes ARGS5(char*,mono,char*,fg,char*,bg,int,style,char*,element)
+{
+ int i;
+ int mA = 0, fA = default_fg, bA = default_bg, cA = A_NORMAL;
+ int newstyle = hash_code(element);
+
+ if (TRACE)
+ fprintf(stderr, "CSS(PA):style d=%d / h=%d, e=%s\n", style, newstyle,element);
+
+ for (i = 0; i <7; i++)
+ {
+ if (!strcasecomp(Mono_Strings[i], mono))
+ {
+ mA = ncursesMono[i];
+ }
+ }
+ if (TRACE)
+ fprintf(stderr, "CSS(CP):%d\n", colorPairs);
+
+ fA = check_color(fg, default_fg);
+ bA = check_color(bg, default_bg);
+ if (fA == NO_COLOR) {
+ bA = NO_COLOR;
+ } else {
+ if (fA >= COLORS || bA >= COLORS)
+ cA = A_BOLD;
+ if (fA >= COLORS)
+ fA %= COLORS;
+ if (bA > COLORS)
+ bA %= COLORS;
+ }
+
+ /*
+ * If we have colour, and space to create a new colour attribute,
+ * and we have a valid colour description, then add this style
+ */
+ if (lynx_has_color && colorPairs < COLOR_PAIRS-1 && fA != NO_COLOR)
+ {
+ if (colorPairs <= 0 || fA != last_fA || bA != last_bA) {
+ colorPairs++;
+ init_pair(colorPairs, fA, bA);
+ last_fA = fA;
+ last_bA = bA;
+ }
+ if (style < DSTYLE_ELEMENTS)
+ setStyle(style, COLOR_PAIR(colorPairs)|cA, cA, mA);
+ setHashStyle(newstyle, COLOR_PAIR(colorPairs)|cA, cA, mA, element);
+ }
+ else
+ {
+ /* only mono is set */
+ if (style < DSTYLE_ELEMENTS)
+ setStyle(style, -1, -1, mA);
+ setHashStyle(newstyle, -1, -1, mA, element);
+ }
+}
+
+/* parse a style option of the format
+ * STYLE:<OBJECT>:FG:BG
+ */
+PRIVATE void parse_style ARGS1(char*,buffer)
+{
+ char *tmp = strchr(buffer, ':');
+ char *element, *mono, *fg, *bg;
+
+ if(!tmp)
+ {
+ fprintf (stderr, "\
+Syntax Error parsing style in lss file:\n\
+[%s]\n\
+The line must be of the form:\n\
+OBJECT:MONO:COLOR (ie em:bold:brightblue:white)\n\
+where OBJECT is one of EM,STRONG,B,I,U,BLINK etc.\n\n", buffer);
+ if (!dump_output_immediately) {
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+ exit(1);
+ }
+ {
+ char *i;
+ for (i = buffer; *i; *i++ = tolower(*i))
+ ;
+ }
+ *tmp = '\0';
+ element = buffer;
+
+ mono = tmp + 1;
+ tmp = strchr(mono, ':');
+
+ if (!tmp)
+ {
+ fg = "nocolor";
+ bg = "nocolor";
+ }
+ else
+ {
+ *tmp = '\0';
+ fg = tmp+1;
+ tmp = strchr(fg, ':');
+ if (!tmp)
+ bg = "default";
+ else
+ {
+ *tmp = '\0';
+ bg = tmp + 1;
+ }
+ }
+
+ if (TRACE)
+ {
+ int bkt = hash_code(element);
+ fprintf(stderr, "CSSPARSE:%s => %d %s\n",
+ element, bkt,
+ (hashStyles[bkt].name ? "used" : ""));
+ }
+
+ strtolower(element);
+
+ /*
+ * We use some pseudo-elements, so catch these first
+ */
+ if (!strncasecomp(element, "alink", 5)) /* active link */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_ALINK,"alink");
+ }
+ else if (!strcasecomp(element, "a")) /* normal link */
+ {
+ parse_attributes(mono,fg,bg, DSTYLE_LINK,"a");
+ parse_attributes(mono,fg,bg, HTML_A,"a");
+ }
+ else if (!strncasecomp(element, "status", 4)) /* status bar */
+ {
+ parse_attributes(mono,fg,bg, DSTYLE_STATUS,"status");
+ }
+ else if (!strncasecomp(element, "label", 6)) /* [INLINE]'s */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_OPTION,"label");
+ }
+ else if (!strncasecomp(element, "value", 5)) /* [INLINE]'s */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_VALUE,"value");
+ }
+ else if (!strncasecomp(element, "high", 4)) /* [INLINE]'s */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_HIGH,"high");
+ }
+ else if (!strcasecomp(element, "normal")) /* added - kw */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_NORMAL,"html");
+ }
+ /* this may vanish */
+ else if (!strncasecomp(element, "candy", 5)) /* [INLINE]'s */
+ {
+ parse_attributes(mono,fg,bg,DSTYLE_CANDY,"candy");
+ }
+ /* Ok, it must be a HTML element, so look through the list until we
+ * find it
+ */
+ else
+ {
+#if !defined(USE_HASH)
+ int i;
+ for (i = 0; i <HTML_ELEMENTS; i++)
+ {
+ if (!strcasecomp (HTML_dtd.tags[i].name, element))
+ {
+ if (TRACE)
+ fprintf(stderr, "PARSECSS:applying style <%s,%s,%s> for HTML_%s\n",mono,fg,bg,HTML_dtd.tags[i].name);
+ parse_attributes(mono,fg,bg,i+STARTAT,element);
+ break;
+ }
+ }
+#else
+ int element_number = -1;
+ HTTag * t = SGMLFindTag(&HTML_dtd, element);
+ if (t && t->name) {
+ element_number = t - HTML_dtd.tags;
+ }
+ if (element_number >= HTML_A &&
+ element_number < HTML_ELEMENTS)
+ parse_attributes(mono,fg,bg, element_number+STARTAT,element);
+ else
+ parse_attributes(mono,fg,bg, DSTYLE_ELEMENTS,element);
+#endif
+ }
+}
+
+PRIVATE void free_colorstylestuff NOARGS
+{
+ style_initialiseHashTable();
+ style_deleteStyleList();
+}
+
+/*
+ * initialise the default style sheet
+ * This should be able to be read from a file in CSS format :-)
+ */
+PRIVATE void initialise_default_stylesheet NOARGS
+{
+}
+
+/* Set all the buckets in the hash table to be empty */
+PUBLIC void style_initialiseHashTable NOARGS
+{
+ int i;
+ static int firsttime = 1;
+
+ for (i = 0; i <CSHASHSIZE; i++)
+ {
+ if (firsttime)
+ hashStyles[i].name = NULL;
+ else
+ FREE(hashStyles[i].name);
+ hashStyles[i].color = -1;
+ hashStyles[i].cattr = -1;
+ hashStyles[i].mono = -1;
+ }
+ if (firsttime) {
+ firsttime = 0;
+ atexit(free_colorstylestuff);
+ }
+ s_high = hash_code("high");
+ s_alink = hash_code("alink");
+ s_value = hash_code("value");
+ s_label = hash_code("label");
+ s_a = hash_code("a");
+ s_status = hash_code("status");
+ s_alert = hash_code("alert");
+ s_title = hash_code("title");
+}
+
+/* because curses isn't started when we parse the config file, we
+ * need to remember the STYLE: lines we encounter and parse them
+ * after curses has started
+ */
+HTList *lss_styles = NULL;
+
+PUBLIC void parse_userstyles NOARGS
+{
+ char *name;
+ HTList *cur = lss_styles;
+ colorPairs = 0;
+ style_initialiseHashTable();
+
+ /* set our styles to be the same as vanilla-curses-lynx */
+ initialise_default_stylesheet();
+
+ while ((name = HTList_nextObject(cur)) != NULL)
+ {
+ if (TRACE)
+ fprintf(stderr, "LSS:%s\n", name ? name : "!?! empty !?!");
+ if (name != NULL)
+ parse_style(name);
+ }
+}
+
+
+/* Add a STYLE: option line to our list */
+PUBLIC void HStyle_addStyle ARGS1(char*,buffer)
+{
+ char *name = NULL;
+ StrAllocCopy(name, buffer);
+ if (lss_styles == NULL)
+ lss_styles = HTList_new();
+ strtolower(name);
+ if (TRACE)
+ fprintf(stderr, "READCSS:%s\n", name ? name : "!?! empty !?!");
+ HTList_addObject (lss_styles, name);
+}
+
+PUBLIC void style_deleteStyleList NOARGS
+{
+ char *name;
+ while ((name = HTList_removeLastObject(lss_styles)) != NULL)
+ FREE(name);
+ HTList_delete (lss_styles);
+ lss_styles = NULL;
+}
+
+char* default_stylesheet[] = {
+ "a:bold", "em:bold", "strong:bold", "b:bold", "i:bold",
+ "alink:reverse", "status:reverse", NULL
+};
+
+PUBLIC void style_defaultStyleSheet NOARGS
+{
+ int i;
+ for (i = 0; default_stylesheet[i]; i++)
+ HStyle_addStyle(default_stylesheet[i]);
+}
+
+PUBLIC int style_readFromFile ARGS1(char*, file)
+{
+ FILE *fh;
+ char buffer[1024];
+ int len;
+
+ if (TRACE)
+ fprintf(stderr, "CSS:Reading styles from file: %s\n", file ? file : "?!? empty ?!?");
+ if (file == NULL || *file == '\0')
+ return -1;
+ fh = fopen(file, "r");
+ if (!fh)
+ {
+ /* this should probably be an alert or something */
+ if (TRACE)
+ fprintf(stderr, "CSS:Can't open style file %s, using defaults\n", file);
+ return -1;
+ }
+
+ style_initialiseHashTable();
+ style_deleteStyleList();
+
+ while (!feof(fh)
+ && fgets(buffer, sizeof(buffer)-1, fh) != NULL)
+ {
+ len = strlen(buffer);
+ if (len > 0) {
+ if (buffer[len-1] == '\n' || buffer[len-1] == '\r')
+ buffer[len-1] = '\0'; /* hack */
+ else
+ buffer[sizeof(buffer)-1] = '\0'; /* hack */
+ }
+ LYTrimTail(buffer);
+ LYTrimHead(buffer);
+ if (buffer[0] != '#' && (len = strlen(buffer)) > 0)
+ HStyle_addStyle(buffer);
+ }
+ /* the default styles are added after the user styles in order
+ ** that they come before them <grin> RP
+ */
+ /* style_defaultStyleSheet(); */
+
+ fclose (fh);
+ if (LYCursesON)
+ parse_userstyles();
+ return 0;
+}
+#endif /* USE_COLOR_STYLE */
diff --git a/gnu/usr.bin/lynx/src/LYStyle.h b/gnu/usr.bin/lynx/src/LYStyle.h
new file mode 100644
index 00000000000..8ec3c52c81a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYStyle.h
@@ -0,0 +1,32 @@
+#ifndef LYSTYLE_H
+#define LYSTYLE_H
+
+#ifdef USE_COLOR_STYLE
+
+#include "AttrList.h"
+
+/* list of elements */
+extern CONST SGML_dtd HTML_dtd;
+
+/* array of currently set styles */
+extern HTCharStyle displayStyles[DSTYLE_ELEMENTS];
+
+/* Can we do colour? - RP */
+extern int lynx_has_color;
+
+/* Set all the buckets in the hash table to be empty */
+extern void style_initialiseHashTable NOPARAMS;
+
+extern void parse_userstyles NOPARAMS;
+
+extern void HStyle_addStyle PARAMS((char* buffer));
+
+extern void style_deleteStyleList NOPARAMS;
+
+extern void style_defaultStyleSheet NOPARAMS;
+
+extern int style_readFromFile PARAMS((char* file));
+
+#endif /* USE_COLOR_STYLE */
+
+#endif /* LYSTYLE_H */
diff --git a/gnu/usr.bin/lynx/src/LYSystem.h b/gnu/usr.bin/lynx/src/LYSystem.h
new file mode 100644
index 00000000000..6acd02b30e0
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYSystem.h
@@ -0,0 +1,10 @@
+
+#ifndef LYSYSTEM_H
+#define LYSYSTEM_H
+
+#ifdef VMS
+extern int DCLsystem PARAMS((char *command));
+#define system(a) DCLsystem(a) /* use LYCurses.c routines for spawns */
+#endif /* VMS */
+
+#endif /* LYSYSTEM_H */
diff --git a/gnu/usr.bin/lynx/src/LYTraversal.c b/gnu/usr.bin/lynx/src/LYTraversal.c
new file mode 100644
index 00000000000..44853908009
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYTraversal.c
@@ -0,0 +1,194 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYSignal.h"
+#include "LYTraversal.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+/* routines to handle special traversal feature */
+
+PUBLIC BOOLEAN lookup ARGS1(char *,target)
+{
+ FILE *ifp;
+ char buffer[200], line[200];
+
+ if ((ifp = fopen(TRAVERSE_FILE,"r")) == NULL) {
+ if ((ifp = LYNewTxtFile(TRAVERSE_FILE)) == NULL) {
+ perror("unable to open or create a traversal file");
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ } else {
+ fclose(ifp);
+ return(FALSE);
+ }
+ }
+
+ sprintf(line,"%s\n",target);
+
+ while(fgets(buffer, 200, ifp) != NULL) {
+ if (STREQ(line,buffer)) {
+ fclose(ifp);
+ return(TRUE);
+ }
+ } /* end while */
+
+ fclose(ifp);
+ return(FALSE);
+}
+
+PUBLIC void add_to_table ARGS1(char *,target)
+{
+
+ FILE *ifp;
+
+ if ((ifp = LYAppendToTxtFile(TRAVERSE_FILE)) == NULL) {
+ perror("unable to open traversal file");
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ fprintf(ifp,"%s\n",target);
+
+ fclose(ifp);
+}
+
+PUBLIC void add_to_traverse_list ARGS2(char *,fname, char *,prev_link_name)
+{
+
+ FILE *ifp;
+
+ if ((ifp = LYAppendToTxtFile(TRAVERSE_FOUND_FILE)) == NULL) {
+ perror("unable to open traversal found file");
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ fprintf(ifp,"%s\t%s\n",fname, prev_link_name);
+
+ fclose(ifp);
+}
+
+PUBLIC void dump_traversal_history NOARGS
+{
+ int x;
+ FILE *ifp;
+
+ if (nhist <= 0)
+ return;
+
+ if ((ifp = LYAppendToTxtFile(TRAVERSE_FILE)) == NULL) {
+ perror("unable to open traversal file");
+ return;
+ }
+
+ fprintf(ifp, "\n\nTRAVERSAL WAS INTERUPTED\n\n\
+\t here is a list of the history stack so that you may rebuild\n\n");
+
+ for (x = nhist-1; x >= 0; x--) {
+ fprintf(ifp,"%s\t%s\n", history[x].title, history[x].address);
+ }
+
+ fclose(ifp);
+}
+
+PUBLIC void add_to_reject_list ARGS1(char *,target)
+{
+
+ FILE *ifp;
+
+ if ((ifp = LYAppendToTxtFile(TRAVERSE_REJECT_FILE)) == NULL) {
+ perror("unable to open reject file");
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_DFL);
+#endif /* NOSIGHUP */
+ (void) signal(SIGTERM, SIG_DFL);
+#ifndef VMS
+ (void) signal(SIGINT, SIG_DFL);
+#endif /* !VMS */
+#ifdef SIGTSTP
+ if (no_suspend)
+ (void) signal(SIGTSTP,SIG_DFL);
+#endif /* SIGTSTP */
+ exit(-1);
+ }
+
+ fprintf(ifp,"%s\n",target);
+
+ fclose(ifp);
+}
+
+/* there need not be a reject file, so if it doesn't open, just return
+ FALSE, meaning "target not in reject file" If the last character in
+ a line in a reject file is "*", then also reject if target matches up to
+ that point in the string
+ Blank lines are ignored
+ Lines that contain just a * are allowed, but since they mean "reject
+ everything" it shouldn't come up much!
+ */
+
+PUBLIC BOOLEAN lookup_reject ARGS1(char *,target)
+{
+ FILE *ifp;
+ char buffer[200], line[200], ch;
+ int frag;
+
+ if ((ifp = fopen(TRAVERSE_REJECT_FILE,"r")) == NULL){
+ return(FALSE);
+ }
+
+ sprintf(line,"%s\n",target);
+
+ while (fgets(buffer, 200, ifp) != NULL) {
+ frag = strlen(buffer) - 1; /* real length, minus trailing null */
+ ch = buffer[frag - 1]; /* last character in buffer */
+ if (frag > 0) { /* if not an empty line */
+ if (ch == '*') {
+ if (frag == 1 || ((strncmp(line,buffer,frag - 1)) == 0)) {
+ fclose(ifp);
+ return(TRUE);
+ }
+ } else { /* last character = "*" test */
+ if (STREQ(line,buffer)) {
+ fclose(ifp);
+ return(TRUE);
+ }
+ } /* last character = "*" test */
+ } /* frag >= 0 */
+ } /* end while */
+
+ fclose(ifp);
+ return(FALSE);
+}
diff --git a/gnu/usr.bin/lynx/src/LYTraversal.h b/gnu/usr.bin/lynx/src/LYTraversal.h
new file mode 100644
index 00000000000..1d97ce5fe17
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYTraversal.h
@@ -0,0 +1,15 @@
+/* traversal.c function declarations
+*/
+#ifndef TRAVERSAL_H
+#define TRAVERSAL_H
+
+#include "HTUtils.h" /* BOOL, PARAMS, ARGS */
+
+extern BOOLEAN lookup PARAMS((char * target));
+extern void add_to_table PARAMS((char * target));
+extern void add_to_traverse_list PARAMS((char * fname, char * prev_link_name));
+extern void dump_traversal_history NOPARAMS;
+extern void add_to_reject_list PARAMS((char * target));
+extern BOOLEAN lookup_reject PARAMS((char * target));
+
+#endif /* TRAVERSAL_H */
diff --git a/gnu/usr.bin/lynx/src/LYUpload.c b/gnu/usr.bin/lynx/src/LYUpload.c
new file mode 100644
index 00000000000..dba75c5670a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYUpload.c
@@ -0,0 +1,316 @@
+/*
+** Routines to upload files to the local filesystem.
+** Created by: Rick Mallett, Carleton University
+** Report problems to rmallett@ccs.carleton.ca
+** Modified 15-Dec-95 George Lindholm (lindholm@ucs.ubc.ca):
+** Reread the upload menu page every time, in case the "upload" directory
+** has changed (make the current directory that for the upload process).
+** Prompt for the upload file name if there is no "%s" in the command
+** string. Most protocols allow the user to specify the file name
+** from the client side. Xmodem appears to be the only that can't
+** figure out the filename from the transfer data so it needs the
+** information from lynx (or an upload script which prompts for it).
+** On the other hand, zmodem aborts when you give it a filename on
+** the command line (great way of bypassing the nodotfile code :=( ).
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTParse.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "LYStrings.h"
+#include "LYClean.h"
+#include "LYGetFile.h"
+#include "LYUpload.h"
+#include "LYSystem.h"
+#include "LYLocal.h"
+
+#include "LYexit.h"
+#include "LYLeaks.h"
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+PUBLIC char LYUploadFileURL[256] = "\0";
+
+/*
+ * LYUpload uploads a file to a given location using a
+ * specified upload method. It parses an incoming link
+ * that looks like:
+ * LYNXDIRED://UPLOAD=<#>/TO=<STRING>
+ */
+PUBLIC int LYUpload ARGS1(
+ char *, line)
+{
+ char *method, *directory, *dir;
+ int method_number;
+ int count;
+ char tmpbuf[256];
+ char buffer[256];
+ lynx_html_item_type *upload_command = 0;
+ int c;
+ char *cp;
+ FILE *fp;
+ char cmd[512];
+#ifdef VMS
+ extern BOOLEAN HadVMSInterrupt;
+#endif /* VMS */
+
+ /*
+ * Use configured upload commands.
+ */
+ if((directory = (char *)strstr(line, "TO=")) == NULL)
+ goto failed;
+ *(directory - 1) = '\0';
+ /* go past "Directory=" */
+ directory+=3;
+
+ if((method = (char *)strstr(line, "UPLOAD=")) == NULL)
+ goto failed;
+ /*
+ * Go past "Method=".
+ */
+ method += 7;
+ method_number = atoi(method);
+
+ for (count = 0, upload_command = uploaders; count < method_number;
+ count++, upload_command = upload_command->next)
+ ; /* null body */
+
+ /*
+ * Parsed out the Method and the Location?
+ */
+ if (upload_command->command == NULL) {
+ _statusline("ERROR! - upload command is misconfigured");
+ sleep(AlertSecs);
+ goto failed;
+ }
+
+ /*
+ * Care about the local name?
+ */
+ if (strstr(upload_command->command, "%s")) {
+ /*
+ * Commands have the form "command %s [etc]"
+ * where %s is the filename.
+ */
+ _statusline("Enter a filename: ");
+retry:
+ *tmpbuf = '\0';
+ if (LYgetstr(tmpbuf, VISIBLE, sizeof(tmpbuf), NORECALL) < 0)
+ goto cancelled;
+
+ if (*tmpbuf == '\0')
+ goto cancelled;
+
+ if (strstr(tmpbuf, "../") != NULL) {
+ _statusline(
+ "Illegal redirection \"../\" found! Request ignored.");
+ sleep(AlertSecs);
+ goto cancelled;
+ } else if (strchr(tmpbuf, '/') != NULL) {
+ _statusline("Illegal character \"/\" found! Request ignored.");
+ sleep(AlertSecs);
+ goto cancelled;
+ } else if (tmpbuf[0] == '~') {
+ _statusline(
+ "Illegal redirection using \"~\" found! Request ignored.");
+ sleep(AlertSecs);
+ goto cancelled;
+ }
+ sprintf(buffer, "%s/%s", directory, tmpbuf);
+
+ if (no_dotfiles || !show_dotfiles) {
+ if (*buffer == '.' ||
+#ifdef VMS
+ ((cp = strrchr(buffer, ':')) && *(cp+1) == '.') ||
+ ((cp = strrchr(buffer, ']')) && *(cp+1) == '.') ||
+#endif /* VMS */
+ ((cp = strrchr(buffer, '/')) && *(cp+1) == '.')) {
+ _statusline(
+ "File name may not begin with dot. Enter a new filename: ");
+ goto retry;
+ }
+ }
+
+ /*
+ * See if it already exists.
+ */
+ if ((fp = fopen(buffer, "r")) != NULL) {
+ fclose(fp);
+
+#ifdef VMS
+ _statusline("File exists. Create higher version? (y/n)");
+#else
+ _statusline("File exists. Overwrite? (y/n)");
+#endif /* VMS */
+ c = 0;
+ while (TOUPPER(c) != 'Y' && TOUPPER(c) != 'N' && c != 7 && c != 3)
+ c = LYgetch();
+#ifdef VMS
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ goto cancelled;
+ }
+#endif /* VMS */
+
+ if (c == 7 || c == 3) { /* Control-G or Control-C */
+ goto cancelled;
+ }
+
+ if (TOUPPER(c) == 'N') {
+ _statusline("Enter a filename: ");
+ goto retry;
+ }
+ }
+
+ /*
+ * See if we can write to it.
+ */
+ if ((fp = fopen(buffer, "w")) != NULL) {
+ fclose(fp);
+ remove(buffer);
+ } else {
+ _statusline("Cannot write to file. Enter a new filename: ");
+ goto retry;
+ }
+
+#ifdef VMS
+ sprintf(tmpbuf, upload_command->command, buffer, "", "", "", "", "");
+#else
+ cp = quote_pathname(buffer); /* to prevent spoofing of the shell */
+ sprintf(tmpbuf, upload_command->command, cp, "", "", "", "", "");
+ FREE(cp);
+#endif /* VMS */
+ } else { /* No substitution, no changes */
+ strcpy(tmpbuf, upload_command->command);
+ }
+
+ dir = quote_pathname(directory);
+ sprintf(cmd, "cd %s ; %s", dir, tmpbuf);
+ FREE(dir);
+ stop_curses();
+ if (TRACE)
+ fprintf(stderr, "command: %s\n", cmd);
+ system(cmd);
+ fflush(stdout);
+ start_curses();
+#ifdef UNIX
+ chmod(buffer, HIDE_CHMOD);
+#endif /* UNIX */
+ /* don't remove(file); */
+
+ return 1;
+
+failed:
+ _statusline("Unable to upload file.");
+ sleep(AlertSecs);
+ return 0;
+
+cancelled:
+ _statusline("Cancelling.");
+ sleep(InfoSecs);
+ return 0;
+}
+
+/*
+ * LYUpload_options writes out the current upload choices to a
+ * file so that the user can select printers in the same way that
+ * they select all other links. Upload links look like:
+ * LYNXDIRED://UPLOAD=<#>/TO=<STRING>
+ */
+PUBLIC int LYUpload_options ARGS2(
+ char **, newfile,
+ char *, directory)
+{
+ static char tempfile[256];
+ static BOOLEAN first = TRUE;
+ FILE *fp0;
+ lynx_html_item_type *cur_upload;
+ int count;
+ static char curloc[256];
+ char *cp;
+
+ if (first) {
+ /*
+ * Get an unused tempfile name. - FM
+ */
+ tempname(tempfile, NEW_FILE);
+#ifdef VMS
+ } else {
+ remove(tempfile); /* Remove duplicates on VMS. */
+#endif /* VMS */
+ }
+
+ /*
+ * Open the tempfile for writing and set it's
+ * protection in case this wasn't done via an
+ * external umask. - FM
+ */
+ if ((fp0 = LYNewTxtFile(tempfile)) == NULL) {
+ HTAlert(CANNOT_OPEN_TEMP);
+ return(-1);
+ }
+
+#ifdef VMS
+ strcpy(curloc, "/sys$login");
+#else
+ cp = directory;
+ if (!strncmp(cp, "file://localhost", 16))
+ cp += 16;
+ else if (!strncmp(cp, "file:", 5))
+ cp += 5;
+ strcpy(curloc,cp);
+ HTUnEscape(curloc);
+ if (curloc[strlen(curloc) - 1] == '/')
+ curloc[strlen(curloc) - 1] = '\0';
+#endif /* VMS */
+
+ if (first) {
+ /*
+ * Make the tempfile a URL.
+ */
+#if defined (VMS) || defined (DOSPATH)
+ sprintf(LYUploadFileURL, "file://localhost/%s", tempfile);
+#else
+ sprintf(LYUploadFileURL, "file://localhost%s", tempfile);
+#endif /* VMS */
+ first = FALSE;
+ }
+ StrAllocCopy(*newfile, LYUploadFileURL);
+
+ fprintf(fp0, "<head>\n<title>%s</title>\n</head>\n<body>\n",
+ UPLOAD_OPTIONS_TITLE);
+
+ fprintf(fp0, "<h1>Upload Options (%s Version %s)</h1>\n",
+ LYNX_NAME, LYNX_VERSION);
+
+ fputs("You have the following upload choices.<br>\n", fp0);
+ fputs("Please select one:<br>\n<pre>\n", fp0);
+
+ if (uploaders != NULL) {
+ for (count = 0, cur_upload = uploaders;
+ cur_upload != NULL;
+ cur_upload = cur_upload->next, count++) {
+ fprintf(fp0, " <a href=\"LYNXDIRED://UPLOAD=%d/TO=%s\">",
+ count, curloc);
+ fprintf(fp0, (cur_upload->name ?
+ cur_upload->name : "No Name Given"));
+ fprintf(fp0, "</a>\n");
+ }
+ } else {
+ fprintf(fp0, "\n \
+No other upload methods have been defined yet. You may define\n \
+an unlimited number of upload methods using the lynx.cfg file.\n");
+
+ }
+ fprintf(fp0, "</pre>\n</body>\n");
+ fclose(fp0);
+
+ LYforce_no_cache = TRUE;
+
+ return(0);
+}
diff --git a/gnu/usr.bin/lynx/src/LYUpload.h b/gnu/usr.bin/lynx/src/LYUpload.h
new file mode 100644
index 00000000000..9f74edf6709
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYUpload.h
@@ -0,0 +1,15 @@
+
+#ifndef LYUPLOAD_H
+#define LYUPLOAD_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern int LYUpload PARAMS((char *line));
+extern int LYUpload_options PARAMS((char **newfile, char *directory));
+
+#define UPLOAD_OPTIONS_TITLE "Lynx Upload Options"
+
+#endif /* LYUPLOAD_H */
+
diff --git a/gnu/usr.bin/lynx/src/LYUtils.c b/gnu/usr.bin/lynx/src/LYUtils.c
new file mode 100644
index 00000000000..c0d9ebc89a1
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYUtils.c
@@ -0,0 +1,5691 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include <ctype.h>
+#include "HTParse.h"
+#include "HTAccess.h"
+#include "HTCJK.h"
+#include "HTAlert.h"
+#include "LYCurses.h"
+#include "LYUtils.h"
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "LYSignal.h"
+#include "GridText.h"
+#include "LYCharSets.h"
+
+#ifdef DOSPATH
+#include "HTDOS.h"
+#endif
+#ifdef VMS
+#include <descrip.h>
+#include <libclidef.h>
+#include <lib$routines.h>
+#include "HTVMSUtils.h"
+#endif /* VMS */
+
+#if HAVE_UTMP
+#include <pwd.h>
+#ifdef UTMPX_FOR_UTMP
+#include <utmpx.h>
+#define utmp utmpx
+#ifdef UTMP_FILE
+#undef UTMP_FILE
+#endif /* UTMP_FILE */
+#define UTMP_FILE UTMPX_FILE
+#else
+#include <utmp.h>
+#endif /* UTMPX_FOR_UTMP */
+#endif /* HAVE_UTMP */
+
+#if NEED_PTEM_H
+/* they neglected to define struct winsize in termios.h -- it's only in
+ * termio.h and ptem.h (the former conflicts with other definitions).
+ */
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#endif
+
+#include "LYLeaks.h"
+
+#ifdef USE_COLOR_STYLE
+#include "AttrList.h"
+#include "LYHash.h"
+#include "LYStyle.h"
+#endif
+
+#undef hline /* FIXME: this is a curses feature used as a variable here */
+
+#ifdef SVR4_BSDSELECT
+extern int BSDselect PARAMS((int nfds, fd_set * readfds, fd_set * writefds,
+ fd_set * exceptfds, struct timeval * timeout));
+#ifdef select
+#undef select
+#endif /* select */
+#define select BSDselect
+#ifdef SOCKS
+#ifdef Rselect
+#undef Rselect
+#endif /* Rselect */
+#define Rselect BSDselect
+#endif /* SOCKS */
+#endif /* SVR4_BSDSELECT */
+
+#ifndef FD_SETSIZE
+#define FD_SETSIZE 256
+#endif /* !FD_SETSIZE */
+
+#ifndef UTMP_FILE
+#if defined(__FreeBSD__) || defined(__bsdi__)
+#define UTMP_FILE _PATH_UTMP
+#else
+#define UTMP_FILE "/etc/utmp"
+#endif /* __FreeBSD__ || __bsdi__ */
+#endif /* !UTMP_FILE */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+extern HTkcode kanji_code;
+extern BOOLEAN LYHaveCJKCharacterSet;
+extern HTCJKlang HTCJK;
+
+PRIVATE HTList * localhost_aliases = NULL; /* Hosts to treat as local */
+PRIVATE char *HomeDir = NULL; /* HOME directory */
+PUBLIC HTList * sug_filenames = NULL; /* Suggested filenames */
+
+/*
+ * Highlight (or unhighlight) a given link.
+ */
+PUBLIC void highlight ARGS3(
+ int, flag,
+ int, cur,
+ char *, target)
+{
+ char buffer[200];
+ int i;
+ char tmp[7], *cp;
+ char *theData = NULL;
+ char *Data = NULL;
+ int Offset, HitOffset, tLen;
+ int LenNeeded;
+ BOOL TargetEmphasisON = FALSE;
+ BOOL utf_flag = (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8);
+
+ tmp[0] = tmp[1] = tmp[2] = '\0';
+
+ /*
+ * Bugs in the history code might cause -1 to be sent for cur, which
+ * yields a crash when LYstrncpy() is called with a nonsense pointer.
+ * As far as I know, such bugs have been squashed, but if they should
+ * reappear, this works around them. - FM
+ */
+ if (cur < 0)
+ cur = 0;
+
+ if (nlinks > 0) {
+#ifdef USE_COLOR_STYLE
+#define LXP (links[cur].lx)
+#define LYP (links[cur].ly)
+#endif
+ move(links[cur].ly, links[cur].lx);
+#ifndef USE_COLOR_STYLE
+ lynx_start_link_color (flag == ON, links[cur].inUnderline);
+#else
+ if (flag == ON) {
+ LynxChangeStyle(s_alink, ABS_ON, 0);
+ } else {
+ /* the logic is flawed here - no provision is made for links that
+ ** aren't coloured as [s_a] by default - rjp
+ */
+ if (LYP >= 0 && LYP < CACHEH && LXP >= 0 && LXP < CACHEW &&
+ cached_styles[LYP][LXP]) {
+ LynxChangeStyle(cached_styles[LYP][LXP], ABS_ON, 0);
+ }
+ else {
+ LynxChangeStyle(s_a, ABS_ON, 0);
+ }
+ }
+#endif
+
+ if (links[cur].type == WWW_FORM_LINK_TYPE) {
+ int len;
+ int avail_space = (LYcols - links[cur].lx) - 1;
+
+ LYstrncpy(buffer,
+ (links[cur].hightext ?
+ links[cur].hightext : ""),
+ (avail_space > links[cur].form->size ?
+ links[cur].form->size : avail_space));
+ addstr(buffer);
+
+ len = strlen(buffer);
+ for (; len < links[cur].form->size && len < avail_space; len++)
+ addch('_');
+
+ } else {
+ /*
+ * Copy into the buffer only what will fit
+ * within the width of the screen.
+ */
+ LYmbcsstrncpy(buffer,
+ (links[cur].hightext ?
+ links[cur].hightext : ""),
+ (sizeof(buffer) - 1),
+ ((LYcols - 1) - links[cur].lx),
+ utf_flag);
+ addstr(buffer);
+ }
+
+ /*
+ * Display a second line as well.
+ */
+ if (links[cur].hightext2 && links[cur].ly < display_lines) {
+ lynx_stop_link_color (flag == ON, links[cur].inUnderline);
+ move((links[cur].ly + 1), links[cur].hightext2_offset);
+#ifndef USE_COLOR_STYLE
+ lynx_start_link_color (flag == ON, links[cur].inUnderline);
+#else
+ LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_ON, 0);
+#endif
+
+ for (i = 0; (tmp[0] = links[cur].hightext2[i]) != '\0' &&
+ i+links[cur].hightext2_offset < LYcols; i++) {
+ if (!IsSpecialAttrChar(links[cur].hightext2[i])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ tmp[1] = links[cur].hightext2[++i];
+ addstr(tmp);
+ tmp[1] = '\0';
+ } else {
+ addstr(tmp);
+ }
+ }
+ }
+ }
+ lynx_stop_link_color (flag == ON, links[cur].inUnderline);
+
+#if defined(FANCY_CURSES) || defined(USE_SLANG)
+ /*
+ * If we have an emphasized WHEREIS hit in the highlighted
+ * text, restore the emphasis. Note that we never emphasize
+ * the first and last characters of the highlighted text when
+ * we are making the link current, so the link attributes for
+ * the current link will persist at the beginning and end,
+ * providing an indication to the user that it has been made
+ * current. Also note that we use HText_getFirstTargetInLine()
+ * to determine if there's a hit in the HText structure line
+ * containing the link, and if so, get back a copy of the line
+ * starting at that first hit (which might be before or after
+ * our link), and with all IsSpecial characters stripped, so we
+ * don't need to deal with them here. - FM
+ */
+ if (target && *target && (links[cur].type & WWW_LINK_TYPE) &&
+ links[cur].hightext && *links[cur].hightext &&
+ HText_getFirstTargetInLine(HTMainText,
+ links[cur].anchor_line_num,
+ utf_flag,
+ (int *)&Offset,
+ (int *)&tLen,
+ (char **)&theData,
+ target)) {
+ int itmp, written, len, y, offset;
+ char *data;
+ int tlen = strlen(target);
+ int hlen, hLen;
+ int hLine = links[cur].ly, hoffset = links[cur].lx;
+ size_t utf_extra = 0;
+
+ /*
+ * Copy into the buffer only what will fit
+ * up to the right border of the screen. - FM
+ */
+ LYmbcsstrncpy(buffer,
+ (links[cur].hightext ?
+ links[cur].hightext : ""),
+ (sizeof(buffer) - 1),
+ ((LYcols - 1) - links[cur].lx),
+ utf_flag);
+ hlen = strlen(buffer);
+ hLen = ((HTCJK != NOCJK || utf_flag) ?
+ LYmbcsstrlen(buffer, utf_flag) : hlen);
+
+ /*
+ * Break out if the first hit in the line
+ * starts after this link. - FM
+ */
+ if (Offset >= (hoffset + hLen)) {
+ goto highlight_search_hightext2;
+ }
+
+ /*
+ * Recursively skip hits that end before this link, and
+ * break out if there is no hit beyond those. - FM
+ */
+ Data = theData;
+ while ((Offset < hoffset) &&
+ ((Offset + tLen) <= hoffset)) {
+ data = (Data + tlen);
+ offset = (Offset + tLen);
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ Data = cp;
+ Offset = (offset + HitOffset);
+ } else {
+ goto highlight_search_hightext2;
+ }
+ }
+ data = buffer;
+ offset = hoffset;
+
+ /*
+ * If the hit starts before the hightext, and ends
+ * in or beyond the hightext, restore the emphasis,
+ * skipping the first and last characters of the
+ * hightext if we're making the link current. - FM
+ */
+ if ((Offset < offset) &&
+ ((Offset + tLen) > offset)) {
+ itmp = 0;
+ written = 0;
+ len = (tlen - (offset - Offset));
+
+ /*
+ * Go to the start of the hightext and
+ * handle its first character. - FM
+ */
+ move(hLine, offset);
+ tmp[0] = data[itmp];
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Start emphasis immediately if we are
+ * making the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Start emphasis immediately if we are
+ * making the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ written++;
+ }
+ itmp++;
+ /*
+ * Start emphasis after the first character
+ * if we are making the link current and this
+ * is not the last character. - FM
+ */
+ if (!TargetEmphasisON &&
+ data[itmp] != '\0') {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ }
+
+ /*
+ * Handle the remaining characters. - FM
+ */
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+
+ /*
+ * Stop the emphasis if we haven't already, then
+ * reset the offset to our current position in
+ * the line, and if that is beyond the link, or
+ * or we are making the link current and it is
+ * the last character of the hightext, we are
+ * done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ }
+ LYGetYX(y, offset);
+ if (offset >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_hightext2;
+ }
+
+ /*
+ * See if we have another hit that starts
+ * within the hightext. - FM
+ */
+ data = (Data + (offset - Offset));
+ if (!utf_flag) {
+ data = Data + (offset - Offset);
+ } else {
+ data = LYmbcs_skip_glyphs(Data,
+ (offset - Offset),
+ utf_flag);
+ }
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ /*
+ * If the hit starts after the end of the hightext,
+ * or we are making the link current and the hit
+ * starts at its last character, we are done. - FM
+ */
+ if ((HitOffset + offset) >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_hightext2;
+ }
+
+ /*
+ * Set up the data and offset for the hit, and let
+ * the code for within hightext hits handle it. - FM
+ */
+ Data = cp;
+ Offset = (offset + HitOffset);
+ data = buffer;
+ offset = hoffset;
+ goto highlight_hit_within_hightext;
+ }
+ goto highlight_search_hightext2;
+ }
+
+highlight_hit_within_hightext:
+ /*
+ * If we get to here, the hit starts within the
+ * hightext. If we are making the link current
+ * and it's the last character in the hightext,
+ * we are done. Otherwise, move there and start
+ * restoring the emphasis. - FM
+ */
+ if ((Offset - offset) >
+ (flag == ON ? (hLen - 1) : hLen)) {
+ goto highlight_search_hightext2;
+ }
+ if (!utf_flag) {
+ data += (Offset - offset);
+ } else {
+ refresh();
+ data = LYmbcs_skip_glyphs(data,
+ (Offset - offset),
+ utf_flag);
+ }
+ offset = Offset;
+ itmp = 0;
+ written = 0;
+ len = tlen;
+
+ /*
+ * Go to the start of the hit and
+ * handle its first character. - FM
+ */
+ move(hLine, offset);
+ tmp[0] = data[itmp];
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ written++;
+ }
+ itmp++;
+ /*
+ * Start emphasis after the first character
+ * if we are making the link current and this
+ * is not the last character. - FM
+ */
+ if (!TargetEmphasisON &&
+ data[itmp] != '\0') {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ }
+
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+
+ /*
+ * Stop the emphasis if we haven't already, then reset
+ * the offset to our current position in the line, and
+ * if that is beyond the link, or we are making the link
+ * current and it is the last character in the hightext,
+ * we are done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ }
+ LYGetYX(y, offset);
+ if (offset >=
+ (hoffset + (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_hightext2;
+ }
+
+ /*
+ * See if we have another hit that starts
+ * within the hightext. - FM
+ */
+ if (!utf_flag) {
+ data = Data + (offset - Offset);
+ } else {
+ data = LYmbcs_skip_glyphs(Data,
+ (offset - Offset),
+ utf_flag);
+ }
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ /*
+ * If the hit starts after the end of the hightext,
+ * or we are making the link current and the hit
+ * starts at its last character, we are done. - FM
+ */
+ if ((HitOffset + offset) >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_hightext2;
+ }
+
+ /*
+ * If the target extends beyond our buffer, emphasize
+ * everything in the hightext starting at this hit.
+ * Otherwise, set up the data and offsets, and loop
+ * back. - FM
+ */
+ if ((HitOffset + (offset + tLen)) >=
+ (hoffset + hLen)) {
+ offset = (HitOffset + offset);
+ if (!utf_flag) {
+ data = buffer + (offset - hoffset);
+ } else {
+ refresh();
+ data = LYmbcs_skip_glyphs(buffer,
+ (offset - hoffset),
+ utf_flag);
+ }
+ move(hLine, offset);
+ itmp = 0;
+ written = 0;
+ len = strlen(data);
+
+ /*
+ * Turn the emphasis back on. - FM
+ */
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+ /*
+ * Turn off the emphasis if we haven't already,
+ * and then we're done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ }
+ goto highlight_search_hightext2;
+ } else {
+ Data = cp;
+ Offset = (offset + HitOffset);
+ data = buffer;
+ offset = hoffset;
+ goto highlight_hit_within_hightext;
+ }
+ }
+ goto highlight_search_hightext2;
+ }
+highlight_search_hightext2:
+ if (target && *target && (links[cur].type & WWW_LINK_TYPE) &&
+ links[cur].hightext2 && *links[cur].hightext2 &&
+ links[cur].ly < display_lines &&
+ HText_getFirstTargetInLine(HTMainText,
+ (links[cur].anchor_line_num + 1),
+ utf_flag,
+ (int *)&Offset,
+ (int *)&tLen,
+ (char **)&theData,
+ target)) {
+ int itmp, written, len, y, offset;
+ char *data;
+ int tlen = strlen(target);
+ int hlen, hLen;
+ int hLine = (links[cur].ly + 1);
+ int hoffset = links[cur].hightext2_offset;
+ size_t utf_extra = 0;
+
+ /*
+ * Copy into the buffer only what will fit
+ * up to the right border of the screen. - FM
+ */
+ LYmbcsstrncpy(buffer,
+ (links[cur].hightext2 ?
+ links[cur].hightext2 : ""),
+ (sizeof(buffer) - 1),
+ ((LYcols - 1) - links[cur].hightext2_offset),
+ utf_flag);
+ hlen = strlen(buffer);
+ hLen = ((HTCJK != NOCJK || utf_flag) ?
+ LYmbcsstrlen(buffer, utf_flag) : hlen);
+
+ /*
+ * Break out if the first hit in the line
+ * starts after this link. - FM
+ */
+ if (Offset >= (hoffset + hLen)) {
+ goto highlight_search_done;
+ }
+
+ /*
+ * Recursively skip hits that end before this link, and
+ * break out if there is no hit beyond those. - FM
+ */
+ Data = theData;
+ while ((Offset < hoffset) &&
+ ((Offset + tLen) <= hoffset)) {
+ data = (Data + tlen);
+ offset = (Offset + tLen);
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ Data = cp;
+ Offset = (offset + HitOffset);
+ } else {
+ goto highlight_search_done;
+ }
+ }
+ data = buffer;
+ offset = hoffset;
+
+ /*
+ * If the hit starts before the hightext2, and ends
+ * in or beyond the hightext2, restore the emphasis,
+ * skipping the first and last characters of the
+ * hightext2 if we're making the link current. - FM
+ */
+ if ((Offset < offset) &&
+ ((Offset + tLen) > offset)) {
+ itmp = 0;
+ written = 0;
+ len = (tlen - (offset - Offset));
+
+ /*
+ * Go to the start of the hightext2 and
+ * handle its first character. - FM
+ */
+ move(hLine, offset);
+ tmp[0] = data[itmp];
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Start emphasis immediately if we are
+ * making the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Start emphasis immediately if we are
+ * making the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current. - FM
+ */
+ if (flag != ON) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ written++;
+ }
+ itmp++;
+ /*
+ * Start emphasis after the first character
+ * if we are making the link current and this
+ * is not the last character. - FM
+ */
+ if (!TargetEmphasisON &&
+ data[itmp] != '\0') {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ }
+
+ /*
+ * Handle the remaining characters. - FM
+ */
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext2 and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+
+ /*
+ * Stop the emphasis if we haven't already, then
+ * reset the offset to our current position in
+ * the line, and if that is beyond the link, or
+ * or we are making the link current and it is
+ * the last character of the hightext2, we are
+ * done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ }
+ LYGetYX(y, offset);
+ if (offset >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_done;
+ }
+
+ /*
+ * See if we have another hit that starts
+ * within the hightext2. - FM
+ */
+ if (!utf_flag) {
+ data = Data + (offset - Offset);
+ } else {
+ data = LYmbcs_skip_glyphs(Data,
+ (offset - Offset),
+ utf_flag);
+ }
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ /*
+ * If the hit starts after the end of the hightext2,
+ * or we are making the link current and the hit
+ * starts at its last character, we are done. - FM
+ */
+ if ((HitOffset + offset) >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_done;
+ }
+
+ /*
+ * Set up the data and offset for the hit, and let
+ * the code for within hightext2 hits handle it. - FM
+ */
+ Data = cp;
+ Offset = (offset + HitOffset);
+ data = buffer;
+ offset = hoffset;
+ goto highlight_hit_within_hightext2;
+ }
+ goto highlight_search_done;
+ }
+
+highlight_hit_within_hightext2:
+ /*
+ * If we get to here, the hit starts within the
+ * hightext2. If we are making the link current
+ * and it's the last character in the hightext2,
+ * we are done. Otherwise, move there and start
+ * restoring the emphasis. - FM
+ */
+ if ((Offset - offset) >
+ (flag == ON ? (hLen - 1) : hLen)) {
+ goto highlight_search_done;
+ }
+ if (!utf_flag) {
+ data += (Offset - offset);
+ } else {
+ refresh();
+ data = LYmbcs_skip_glyphs(data,
+ (Offset - offset),
+ utf_flag);
+ }
+ offset = Offset;
+ itmp = 0;
+ written = 0;
+ len = tlen;
+
+ /*
+ * Go to the start of the hit and
+ * handle its first character. - FM
+ */
+ move(hLine, offset);
+ tmp[0] = data[itmp];
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext2. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext2. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Start emphasis immediately if we are making
+ * the link non-current, or we are making it
+ * current but this is not the first or last
+ * character of the hightext2. - FM
+ */
+ if (flag != ON ||
+ (offset > hoffset && data[itmp+1] != '\0')) {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ addstr(tmp);
+ } else {
+ move(hLine, (offset + 1));
+ }
+ written++;
+ }
+ itmp++;
+ /*
+ * Start emphasis after the first character
+ * if we are making the link current and this
+ * is not the last character. - FM
+ */
+ if (!TargetEmphasisON &&
+ data[itmp] != '\0') {
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ }
+
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext2 and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+
+ /*
+ * Stop the emphasis if we haven't already, then reset
+ * the offset to our current position in the line, and
+ * if that is beyond the link, or we are making the link
+ * current and it is the last character in the hightext2,
+ * we are done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ }
+ LYGetYX(y, offset);
+ if (offset >=
+ (hoffset + (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_done;
+ }
+
+ /*
+ * See if we have another hit that starts
+ * within the hightext2. - FM
+ */
+ if (!utf_flag) {
+ data = (Data + (offset - Offset));
+ } else {
+ data = LYmbcs_skip_glyphs(Data,
+ (offset - Offset),
+ utf_flag);
+ }
+ if ((case_sensitive ?
+ (cp = LYno_attr_mbcs_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL :
+ (cp = LYno_attr_mbcs_case_strstr(data,
+ target,
+ utf_flag,
+ &HitOffset,
+ &LenNeeded)) != NULL) &&
+ (offset + LenNeeded) < LYcols) {
+ /*
+ * If the hit starts after the end of the hightext2,
+ * or we are making the link current and the hit
+ * starts at its last character, we are done. - FM
+ */
+ if ((HitOffset + offset) >=
+ (hoffset +
+ (flag == ON ? (hLen - 1) : hLen))) {
+ goto highlight_search_done;
+ }
+
+ /*
+ * If the target extends beyond our buffer, emphasize
+ * everything in the hightext2 starting at this hit.
+ * Otherwise, set up the data and offsets, and loop
+ * back. - FM
+ */
+ if ((HitOffset + (offset + tLen)) >=
+ (hoffset + hLen)) {
+ offset = (HitOffset + offset);
+ if (!utf_flag) {
+ data = buffer + (offset - hoffset);
+ } else {
+ refresh();
+ data = LYmbcs_skip_glyphs(buffer,
+ (offset - hoffset),
+ utf_flag);
+ }
+ move(hLine, offset);
+ itmp = 0;
+ written = 0;
+ len = strlen(data);
+
+ /*
+ * Turn the emphasis back on. - FM
+ */
+ LYstartTargetEmphasis();
+ TargetEmphasisON = TRUE;
+ for (;
+ written < len && (tmp[0] = data[itmp]) != '\0';
+ itmp++) {
+ /*
+ * Print all the other target chars, except
+ * the last character if it is also the last
+ * character of hightext2 and we are making
+ * the link current. - FM
+ */
+ if (utf_flag && !isascii(tmp[0])) {
+ if ((*tmp & 0xe0) == 0xc0) {
+ utf_extra = 1;
+ } else if ((*tmp & 0xf0) == 0xe0) {
+ utf_extra = 2;
+ } else if ((*tmp & 0xf8) == 0xf0) {
+ utf_extra = 3;
+ } else if ((*tmp & 0xfc) == 0xf8) {
+ utf_extra = 4;
+ } else if ((*tmp & 0xfe) == 0xfc) {
+ utf_extra = 5;
+ } else {
+ /*
+ * Garbage.
+ */
+ utf_extra = 0;
+ }
+ if (strlen(&data[itmp+1]) < utf_extra) {
+ /*
+ * Shouldn't happen.
+ */
+ utf_extra = 0;
+ }
+ }
+ if (utf_extra) {
+ LYstrncpy(&tmp[1], &data[itmp+1], utf_extra);
+ itmp += utf_extra;
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ LYGetYX(y, offset);
+ move(hLine, (offset + 1));
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += (utf_extra + 1);
+ utf_extra = 0;
+ } else if (HTCJK != NOCJK && !isascii(tmp[0])) {
+ /*
+ * For CJK strings, by Masanobu Kimura.
+ */
+ tmp[1] = data[++itmp];
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ } else {
+ addstr(tmp);
+ }
+ tmp[1] = '\0';
+ written += 2;
+ } else {
+ /*
+ * Make sure we don't restore emphasis to
+ * the last character of hightext2 if we
+ * are making the link current. - FM
+ */
+ if (flag == ON && data[(itmp + 1)] == '\0') {
+ LYstopTargetEmphasis();
+ TargetEmphasisON = FALSE;
+ } else {
+ addstr(tmp);
+ }
+ written++;
+ }
+ }
+ /*
+ * Turn off the emphasis if we haven't already,
+ * and then we're done. - FM
+ */
+ if (TargetEmphasisON) {
+ LYstopTargetEmphasis();
+ }
+ goto highlight_search_done;
+ } else {
+ Data = cp;
+ Offset = (offset + HitOffset);
+ data = buffer;
+ offset = hoffset;
+ goto highlight_hit_within_hightext2;
+ }
+ }
+ goto highlight_search_done;
+ }
+highlight_search_done:
+ FREE(theData);
+
+ if (!LYShowCursor)
+ /*
+ * Get cursor out of the way.
+ */
+ move((LYlines - 1), (LYcols - 1));
+ else
+#endif /* FANCY CURSES || USE_SLANG */
+ /*
+ * Never hide the cursor if there's no FANCY CURSES or SLANG.
+ */
+ move(links[cur].ly,
+ ((links[cur].lx > 0) ? (links[cur].lx - 1) : 0));
+
+ if (flag)
+ refresh();
+ }
+ return;
+}
+
+/*
+ * free_and_clear will free a pointer if it
+ * is non-zero and then set it to zero.
+ */
+PUBLIC void free_and_clear ARGS1(
+ char **, pointer)
+{
+ if (*pointer) {
+ free(*pointer);
+ *pointer = 0;
+ }
+ return;
+}
+
+/*
+ * Collapse (REMOVE) all spaces in the string.
+ */
+PUBLIC void collapse_spaces ARGS1(
+ char *, string)
+{
+ int i=0;
+ int j=0;
+
+ if (!string)
+ return;
+
+ for (; string[i] != '\0'; i++)
+ if (!isspace((unsigned char)string[i]))
+ string[j++] = string[i];
+
+ string[j] = '\0'; /* terminate */
+ return;
+}
+
+/*
+ * Convert single or serial newlines to single spaces throughout a string
+ * (ignore newlines if the preceding character is a space) and convert
+ * tabs to single spaces. Don't ignore any explicit tabs or spaces if
+ * the condense argument is FALSE, otherwise, condense any serial spaces
+ * or tabs to one space. - FM
+ */
+PUBLIC void convert_to_spaces ARGS2(
+ char *, string,
+ BOOL, condense)
+{
+ char *s = string;
+ char *ns = string;
+ BOOL last_is_space = FALSE;
+
+ if (!string)
+ return;
+
+ while (*s) {
+ switch (*s) {
+ case ' ':
+ case '\t':
+ if (!(condense && last_is_space))
+ *(ns++) = ' ';
+ last_is_space = TRUE;
+ break;
+
+ case '\r':
+ case '\n':
+ if (!last_is_space) {
+ *(ns++) = ' ';
+ last_is_space = TRUE;
+ }
+ break;
+
+ default:
+ *(ns++) = *s;
+ last_is_space = FALSE;
+ break;
+ }
+ s++;
+ }
+ *ns = '\0';
+ return;
+}
+
+/*
+ * Strip trailing slashes from directory paths.
+ */
+PUBLIC char * strip_trailing_slash ARGS1(
+ char *, dirname)
+{
+ int i;
+
+ i = strlen(dirname) - 1;
+ while (i >= 0 && dirname[i] == '/')
+ dirname[i--] = '\0';
+ return(dirname);
+}
+
+/*
+ * Display (or hide) the status line.
+ */
+BOOLEAN mustshow = FALSE;
+
+PUBLIC void statusline ARGS1(
+ CONST char *, text)
+{
+ char buffer[256];
+ unsigned char *temp = NULL;
+ int max_length, len, i, j;
+ unsigned char k;
+
+ if (text == NULL)
+ return;
+
+ /*
+ * Don't print statusline messages if dumping to stdout.
+ */
+ if (dump_output_immediately)
+ return;
+
+ /*
+ * Don't print statusline message if turned off.
+ */
+ if (mustshow != TRUE) {
+ if (no_statusline == TRUE) {
+ return;
+ }
+ }
+ mustshow = FALSE;
+
+ /*
+ * Deal with any CJK escape sequences and Kanji if we have a CJK
+ * character set selected, otherwise, strip any escapes. Also,
+ * make sure text is not longer than the statusline window. - FM
+ */
+ max_length = ((LYcols - 2) < 256) ? (LYcols - 2) : 255;
+ if ((text[0] != '\0') &&
+ (LYHaveCJKCharacterSet)) {
+ /*
+ * Translate or filter any escape sequences. - FM
+ */
+ if ((temp = (unsigned char *)calloc(1, strlen(text) + 1)) == NULL)
+ outofmem(__FILE__, "statusline");
+ if (kanji_code == EUC) {
+ TO_EUC((unsigned char *)text, temp);
+ } else if (kanji_code == SJIS) {
+ TO_SJIS((unsigned char *)text, temp);
+ } else {
+ for (i = 0, j = 0; text[i]; i++) {
+ if (text[i] != '\033') {
+ temp[j++] = text[i];
+ }
+ }
+ temp[j] = '\0';
+ }
+
+ /*
+ * Deal with any newlines or tabs in the string. - FM
+ */
+ convert_to_spaces((char *)temp, FALSE);
+
+ /*
+ * Handle the Kanji, making sure the text is not
+ * longer than the statusline window. - FM
+ */
+ for (i = 0, j = 0, len = 0, k = '\0';
+ temp[i] != '\0' && len < max_length; i++) {
+ if (k != '\0') {
+ buffer[j++] = k;
+ buffer[j++] = temp[i];
+ k = '\0';
+ len += 2;
+ } else if ((temp[i] & 0200) != 0) {
+ k = temp[i];
+ } else {
+ buffer[j++] = temp[i];
+ len++;
+ }
+ }
+ buffer[j] = '\0';
+ FREE(temp);
+ } else {
+ /*
+ * Strip any escapes, and shorten text if necessary. Note
+ * that we don't deal with the possibility of UTF-8 characters
+ * in the string. This is unlikely, but if strings with such
+ * characters are used in LYMessages_en.h, a compilation
+ * symbol of HAVE_UTF8_STATUSLINES could be added there, and
+ * code added here for determining the displayed string length,
+ * as we do above for CJK. - FM
+ */
+ for (i = 0, len = 0; text[i] != '\0' && len < max_length; i++) {
+ if (text[i] != '\033') {
+ buffer[len++] = text[i];
+ }
+ }
+ buffer[len] = '\0';
+ /*
+ * Deal with any newlines or tabs in the string. - FM
+ */
+ convert_to_spaces(buffer, FALSE);
+ }
+
+ /*
+ * Move to the desired statusline window and
+ * output the text highlighted. - FM
+ */
+ if (LYStatusLine >= 0) {
+ if (LYStatusLine < LYlines-1) {
+ move(LYStatusLine, 0);
+ } else {
+ move(LYlines-1, 0);
+ }
+ } else if (user_mode == NOVICE_MODE) {
+ move(LYlines-3, 0);
+ } else {
+ move(LYlines-1, 0);
+ }
+ clrtoeol();
+ if (text != NULL && text[0] != '\0') {
+#ifdef HAVE_UTF8_STATUSLINES
+ if (LYCharSet_UC[current_char_set].enc == UCT_ENC_UTF8) {
+ refresh();
+ }
+#endif /* HAVE_UTF8_STATUSLINES */
+#ifndef USE_COLOR_STYLE
+ lynx_start_status_color ();
+ addstr (buffer);
+ lynx_stop_status_color ();
+#else
+ /* draw the status bar in the STATUS style */
+ {
+ int a=(strncmp(buffer, "Alert", 5) || !hashStyles[s_alert].name ? s_status : s_alert);
+ LynxChangeStyle (a, ABS_ON, 1);
+ addstr(buffer);
+ wbkgdset(stdscr,
+ ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ ? hashStyles[a].color
+ :A_NORMAL) | ' ');
+ clrtoeol();
+ if (s_normal != NOSTYLE)
+ wbkgdset(stdscr, hashStyles[s_normal].color | ' ');
+ else
+ wbkgdset(stdscr,
+ ((lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
+ ? displayStyles[DSTYLE_NORMAL].color
+ : A_NORMAL) | ' ');
+ LynxChangeStyle (a, ABS_OFF, 0);
+ }
+#endif
+ }
+ refresh();
+
+ return;
+}
+
+static char *novice_lines[] = {
+#ifndef NOVICE_LINE_TWO_A
+#define NOVICE_LINE_TWO_A NOVICE_LINE_TWO
+#define NOVICE_LINE_TWO_B ""
+#define NOVICE_LINE_TWO_C ""
+#endif /* !NOVICE_LINE_TWO_A */
+ NOVICE_LINE_TWO_A,
+ NOVICE_LINE_TWO_B,
+ NOVICE_LINE_TWO_C,
+ ""
+};
+static int lineno = 0;
+
+PUBLIC void toggle_novice_line NOARGS
+{
+ lineno++;
+ if (*novice_lines[lineno] == '\0')
+ lineno = 0;
+ return;
+}
+
+PUBLIC void noviceline ARGS1(
+ int, more_flag GCC_UNUSED)
+{
+
+ if (dump_output_immediately)
+ return;
+
+ move(LYlines-2,0);
+ /* stop_reverse(); */
+ clrtoeol();
+ addstr(NOVICE_LINE_ONE);
+ clrtoeol();
+
+#if defined(DIRED_SUPPORT ) && defined(OK_OVERRIDE)
+ if (lynx_edit_mode && !no_dired_support)
+ addstr(DIRED_NOVICELINE);
+ else
+#endif /* DIRED_SUPPORT && OK_OVERRIDE */
+
+ if (LYUseNoviceLineTwo)
+ addstr(NOVICE_LINE_TWO);
+ else
+ addstr(novice_lines[lineno]);
+
+#ifdef NOTDEFINED
+ if (is_www_index && more_flag) {
+ addstr("This is a searchable index. Use ");
+ addstr(key_for_func(LYK_INDEX_SEARCH));
+ addstr(" to search:");
+ stop_reverse();
+ addstr(" ");
+ start_reverse();
+ addstr("space for more");
+
+ } else if (is_www_index) {
+ addstr("This is a searchable index. Use ");
+ addstr(key_for_func(LYK_INDEX_SEARCH));
+ addstr(" to search:");
+ } else {
+ addstr("Type a command or ? for help:");
+
+ if (more_flag) {
+ stop_reverse();
+ addstr(" ");
+ start_reverse();
+ addstr("Press space for next page");
+ }
+ }
+
+#endif /* NOTDEFINED */
+
+ refresh();
+ return;
+}
+
+PRIVATE int fake_zap = 0;
+
+PUBLIC void LYFakeZap ARGS1(
+ BOOL, set)
+{
+ if (set && fake_zap < 1) {
+ if (TRACE) {
+ fprintf(stderr, "\r *** Set simulated 'Z'");
+ if (fake_zap)
+ fprintf(stderr, ", %d pending", fake_zap);
+ fprintf(stderr, " ***\n");
+ }
+ fake_zap++;
+ } else if (!set && fake_zap) {
+ if (TRACE) {
+ fprintf(stderr, "\r *** Unset simulated 'Z'");
+ fprintf(stderr, ", %d pending", fake_zap);
+ fprintf(stderr, " ***\n");
+ }
+ fake_zap = 0;
+ }
+
+}
+
+PUBLIC int HTCheckForInterrupt NOARGS
+{
+#ifndef VMS /* UNIX stuff: */
+ int c;
+#ifndef USE_SLANG
+ struct timeval socket_timeout;
+ int ret = 0;
+ fd_set readfds;
+#endif /* !USE_SLANG */
+
+ if (fake_zap > 0) {
+ fake_zap--;
+ if (TRACE) {
+ fprintf(stderr, "\r *** Got simulated 'Z' ***\n");
+ fflush(stderr);
+ if (!LYTraceLogFP)
+ sleep(AlertSecs);
+ }
+ return((int)TRUE);
+ }
+
+ /** Curses or slang setup was not invoked **/
+ if (dump_output_immediately)
+ return((int)FALSE);
+
+#ifdef USE_SLANG
+ /** No keystroke was entered
+ Note that this isn't taking possible SOCKSification
+ and the socks_flag into account, and may fail on the
+ slang library's select() when SOCKSified. - FM **/
+ if (0 == SLang_input_pending(0))
+ return(FALSE);
+
+#else /* Unix curses: */
+
+ socket_timeout.tv_sec = 0;
+ socket_timeout.tv_usec = 100;
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+#ifdef SOCKS
+ if (socks_flag)
+ ret = Rselect(FD_SETSIZE, (void *)&readfds, NULL, NULL,
+ &socket_timeout);
+ else
+#endif /* SOCKS */
+ ret = select(FD_SETSIZE, (void *)&readfds, NULL, NULL,
+ &socket_timeout);
+
+ /** Suspended? **/
+ if ((ret == -1) && (errno == EINTR))
+ return((int)FALSE);
+
+ /** No keystroke was entered? **/
+ if (!FD_ISSET(0,&readfds))
+ return((int)FALSE);
+#endif /* USE_SLANG */
+
+ /** Keyboard 'Z' or 'z', or Control-G or Control-C **/
+#if defined (DOSPATH) && defined (NCURSES)
+ nodelay(stdscr,TRUE);
+#endif /* DOSPATH */
+ c = LYgetch();
+#if defined (DOSPATH) && defined (NCURSES)
+ nodelay(stdscr,FALSE);
+#endif /* DOSPATH */
+ if (TOUPPER(c) == 'Z' || c == 7 || c == 3)
+ return((int)TRUE);
+
+ /** Other keystrokes **/
+ return((int)FALSE);
+
+#else /* VMS: */
+
+ int c;
+ extern BOOLEAN HadVMSInterrupt;
+ extern int typeahead();
+
+ if (fake_zap > 0) {
+ fake_zap--;
+ if (TRACE) {
+ fprintf(stderr, "\r *** Got simulated 'Z' ***\n");
+ fflush(stderr);
+ if (!LYTraceLogFP)
+ sleep(AlertSecs);
+ }
+ return((int)TRUE);
+ }
+
+ /** Curses or slang setup was not invoked **/
+ if (dump_output_immediately)
+ return((int)FALSE);
+
+ /** Control-C or Control-Y and a 'N'o reply to exit query **/
+ if (HadVMSInterrupt) {
+ HadVMSInterrupt = FALSE;
+ return((int)TRUE);
+ }
+
+ /** Keyboard 'Z' or 'z', or Control-G or Control-C **/
+ c = typeahead();
+ if (TOUPPER(c) == 'Z' || c == 7 || c == 3)
+ return((int)TRUE);
+
+ /** Other or no keystrokes **/
+ return((int)FALSE);
+#endif /* !VMS */
+}
+
+/*
+ * A file URL for a remote host is an obsolete ftp URL.
+ * Return YES only if we're certain it's a local file. - FM
+ */
+PUBLIC BOOLEAN LYisLocalFile ARGS1(
+ char *, filename)
+{
+ char *host = NULL;
+ char *acc_method = NULL;
+ char *cp;
+
+ if (!filename)
+ return NO;
+ if (!(host = HTParse(filename, "", PARSE_HOST)))
+ return NO;
+ if (!*host) {
+ FREE(host);
+ return NO;
+ }
+
+ if ((cp=strchr(host, ':')) != NULL)
+ *cp = '\0';
+
+ if ((acc_method = HTParse(filename, "", PARSE_ACCESS))) {
+ if (0==strcmp("file", acc_method) &&
+ (0==strcmp(host, "localhost") ||
+#ifdef VMS
+ 0==strcasecomp(host, HTHostName())))
+#else
+ 0==strcmp(host, HTHostName())))
+#endif /* VMS */
+ {
+ FREE(host);
+ FREE(acc_method);
+ return YES;
+ }
+ }
+
+ FREE(host);
+ FREE(acc_method);
+ return NO;
+}
+
+/*
+ * Utility for checking URLs with a host field.
+ * Return YES only if we're certain it's the local host. - FM
+ */
+PUBLIC BOOLEAN LYisLocalHost ARGS1(
+ char *, filename)
+{
+ char *host = NULL;
+ char *cp;
+
+ if (!filename)
+ return NO;
+ if (!(host = HTParse(filename, "", PARSE_HOST)))
+ return NO;
+ if (!*host) {
+ FREE(host);
+ return NO;
+ }
+
+ if ((cp = strchr(host, ':')) != NULL)
+ *cp = '\0';
+
+#ifdef VMS
+ if ((0==strcasecomp(host, "localhost") ||
+ 0==strcasecomp(host, LYHostName) ||
+ 0==strcasecomp(host, HTHostName()))) {
+#else
+ if ((0==strcmp(host, "localhost") ||
+ 0==strcmp(host, LYHostName) ||
+ 0==strcmp(host, HTHostName()))) {
+#endif /* VMS */
+ FREE(host);
+ return YES;
+ }
+
+ FREE(host);
+ return NO;
+}
+
+/*
+ * Utility for freeing the list of local host aliases. - FM
+ */
+PUBLIC void LYLocalhostAliases_free NOARGS
+{
+ char *alias;
+ HTList *cur = localhost_aliases;
+
+ if (!cur)
+ return;
+
+ while (NULL != (alias = (char *)HTList_nextObject(cur))) {
+ FREE(alias);
+ }
+ HTList_delete(localhost_aliases);
+ localhost_aliases = NULL;
+ return;
+}
+
+/*
+ * Utility for listing hosts to be treated as local aliases. - FM
+ */
+PUBLIC void LYAddLocalhostAlias ARGS1(
+ char *, alias)
+{
+ char *LocalAlias;
+
+ if (!(alias && *alias))
+ return;
+
+ if (!localhost_aliases) {
+ localhost_aliases = HTList_new();
+ atexit(LYLocalhostAliases_free);
+ }
+
+ if ((LocalAlias = (char *)calloc(1, (strlen(alias) + 1))) == NULL)
+ outofmem(__FILE__, "HTAddLocalhosAlias");
+ strcpy(LocalAlias, alias);
+ HTList_addObject(localhost_aliases, LocalAlias);
+
+ return;
+}
+
+/*
+ * Utility for checking URLs with a host field.
+ * Return YES only if we've listed the host as a local alias. - FM
+ */
+PUBLIC BOOLEAN LYisLocalAlias ARGS1(
+ char *, filename)
+{
+ char *host = NULL;
+ char *alias;
+ char *cp;
+ HTList *cur = localhost_aliases;
+
+ if (!cur || !filename)
+ return NO;
+ if (!(host = HTParse(filename, "", PARSE_HOST)))
+ return NO;
+ if (!(*host)) {
+ FREE(host);
+ return NO;
+ }
+
+ if ((cp = strchr(host, ':')) != NULL)
+ *cp = '\0';
+
+ while (NULL != (alias = (char *)HTList_nextObject(cur))) {
+#ifdef VMS
+ if (0==strcasecomp(host, alias)) {
+#else
+ if (0==strcmp(host, alias)) {
+#endif /* VMS */
+ FREE(host);
+ return YES;
+ }
+ }
+
+ FREE(host);
+ return NO;
+}
+
+/*
+** This function checks for a URL with an unknown scheme,
+** but for which proxying has been set up, and if so,
+** returns PROXY_URL_TYPE. - FM
+**
+** If a colon is present but the string segment which
+** precedes it is not being proxied, and we can rule
+** out that what follows the colon is not a port field,
+** it returns UNKNOWN_URL_TYPE. Otherwise, it returns
+** 0 (not a URL). - FM
+*/
+PUBLIC int LYCheckForProxyURL ARGS1(
+ char *, filename)
+{
+ char *cp = filename;
+ char *cp1;
+ char *cp2 = NULL;
+
+ /*
+ * Don't crash on an empty argument.
+ */
+ if (cp == NULL || *cp == '\0')
+ return(0);
+
+ /* kill beginning spaces */
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ /*
+ * Check for a colon, and if present,
+ * see if we have proxying set up.
+ */
+ if ((cp1 = strchr((cp+1), ':')) != NULL) {
+ *cp1 = '\0';
+ StrAllocCopy(cp2, cp);
+ *cp1 = ':';
+ StrAllocCat(cp2, "_proxy");
+ if (getenv(cp2) != NULL) {
+ FREE(cp2);
+ return(PROXY_URL_TYPE);
+ }
+ FREE(cp2);
+ cp1++;
+ if (isdigit((unsigned char)*cp1)) {
+ while (*cp1 && isdigit((unsigned char)*cp1))
+ cp1++;
+ if (*cp1 && *cp1 != '/')
+ return(UNKNOWN_URL_TYPE);
+ }
+ }
+
+ return(0);
+}
+
+/*
+** Must recognize a URL and return the type.
+** If recognized, based on a case-insensitive
+** analyis of the scheme field, ensures that
+** the scheme field has the expected case.
+**
+** Returns 0 (not a URL) for a NULL argument,
+** one which lacks a colon.
+**
+** Chains to LYCheckForProxyURL() if a colon
+** is present but the type is not recognized.
+*/
+PUBLIC int is_url ARGS1(
+ char *, filename)
+{
+ char *cp = filename;
+ char *cp1;
+ int i;
+
+ /*
+ * Don't crash on an empty argument.
+ */
+ if (cp == NULL || *cp == '\0')
+ return(0);
+
+ /*
+ * Can't be a URL if it lacks a colon.
+ */
+ if (NULL == strchr(cp, ':'))
+ return(0);
+
+ /*
+ * Kill beginning spaces.
+ */
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ /*
+ * Can't be a URL if it starts with a slash.
+ * So return immediately for this common case,
+ * also to avoid false positives if there was
+ * a colon later in the string. - KW
+ */
+ if (*cp == '/')
+ return(0);
+
+#ifdef DOSPATH /* sorry! */
+ if (strncmp(cp, "file:///", 8) && strlen(cp) == 19 &&
+ cp[strlen(cp)-1] == ':')
+ StrAllocCat(cp,"/");
+#endif
+
+ if (!strncasecomp(cp, "news:", 5)) {
+ if (strncmp(cp, "news", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NEWS_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "nntp:", 5)) {
+ if (strncmp(cp, "nntp", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NNTP_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "snews:", 6)) {
+ if (strncmp(cp, "snews", 5)) {
+ for (i = 0; i < 5; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(SNEWS_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "newspost:", 9)) {
+ /*
+ * Special Lynx type to handle news posts.
+ */
+ if (strncmp(cp, "newspost", 8)) {
+ for (i = 0; i < 8; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NEWSPOST_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "newsreply:", 10)) {
+ /*
+ * Special Lynx type to handle news replies (followups).
+ */
+ if (strncmp(cp, "newsreply", 9)) {
+ for (i = 0; i < 9; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NEWSREPLY_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "snewspost:", 10)) {
+ /*
+ * Special Lynx type to handle snews posts.
+ */
+ if (strncmp(cp, "snewspost", 9)) {
+ for (i = 0; i < 9; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NEWSPOST_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "snewsreply:", 11)) {
+ /*
+ * Special Lynx type to handle snews replies (followups).
+ */
+ if (strncmp(cp, "snewsreply", 10)) {
+ for (i = 0; i < 10; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(NEWSREPLY_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "mailto:", 7)) {
+ if (strncmp(cp, "mailto", 6)) {
+ for (i = 0; i < 6; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(MAILTO_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "file:", 5)) {
+ if (strncmp(cp, "file", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ if (LYisLocalFile(cp)) {
+ return(FILE_URL_TYPE);
+ } else if (cp[5] == '/' && cp[6] == '/') {
+ return(FTP_URL_TYPE);
+ } else {
+ return(0);
+ }
+
+ } else if (!strncasecomp(cp, "data:", 5)) {
+ if (strncmp(cp, "data", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(DATA_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "lynxexec:", 9)) {
+ /*
+ * Special External Lynx type to handle execution
+ * of commands or scripts which require a pause to
+ * read the screen upon completion.
+ */
+ if (strncmp(cp, "lynxexec", 8)) {
+ for (i = 0; i < 8; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(LYNXEXEC_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "lynxprog:", 9)) {
+ /*
+ * Special External Lynx type to handle execution
+ * of commans, sriptis or programs with do not
+ * require a pause to read screen upon completion.
+ */
+ if (strncmp(cp, "lynxprog", 8)) {
+ for (i = 0; i < 8; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(LYNXPROG_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "lynxcgi:", 8)) {
+ /*
+ * Special External Lynx type to handle cgi scripts.
+ */
+ if (strncmp(cp, "lynxcgi", 7)) {
+ for (i = 0; i < 7; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(LYNXCGI_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXPRINT:", 10)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXPRINT", 9)) {
+ for (i = 0; i < 9; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXPRINT_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXDOWNLOAD:", 13)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYDOWNLOAD", 12)) {
+ for (i = 0; i < 12; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXDOWNLOAD_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXDIRED:", 10)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXDIRED", 9)) {
+ for (i = 0; i < 9; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXDIRED_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXHIST:", 9)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXHIST", 8)) {
+ for (i = 0; i < 8; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXHIST_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXKEYMAP:", 11)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXKEYMAP", 10)) {
+ for (i = 0; i < 10; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXKEYMAP_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXIMGMAP:", 11)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXIMGMAP", 10)) {
+ for (i = 0; i < 10; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ (void)is_url(&cp[11]);
+ return(LYNXIMGMAP_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "LYNXCOOKIE:", 11)) {
+ /*
+ * Special Internal Lynx type.
+ */
+ if (strncmp(cp, "LYNXCOOKIE", 10)) {
+ for (i = 0; i < 10; i++)
+ cp[i] = TOUPPER(cp[i]);
+ }
+ return(LYNXCOOKIE_URL_TYPE);
+
+ } else if (strstr((cp+3), "://") == NULL) {
+ /*
+ * If it doesn't contain "://", and it's not one of the
+ * the above, it can't be a URL with a scheme we know,
+ * so check if it's an unknown scheme for which proxying
+ * has been set up. - FM
+ */
+ return(LYCheckForProxyURL(filename));
+
+ } else if (!strncasecomp(cp, "http:", 5)) {
+ if (strncmp(cp, "http", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(HTTP_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "https:", 6)) {
+ if (strncmp(cp, "https", 5)) {
+ for (i = 0; i < 5; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(HTTPS_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "gopher:", 7)) {
+ if (strncmp(cp, "gopher", 6)) {
+ for (i = 0; i < 6; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ if ((cp1 = strchr(cp+11,'/')) != NULL) {
+
+ if (TOUPPER(*(cp1+1)) == 'H' || *(cp1+1) == 'w')
+ /* if this is a gopher html type */
+ return(HTML_GOPHER_URL_TYPE);
+ else if (*(cp1+1) == 'T' || *(cp1+1) == '8')
+ return(TELNET_GOPHER_URL_TYPE);
+ else if (*(cp1+1) == '7')
+ return(INDEX_GOPHER_URL_TYPE);
+ else
+ return(GOPHER_URL_TYPE);
+ } else {
+ return(GOPHER_URL_TYPE);
+ }
+
+ } else if (!strncasecomp(cp, "ftp:", 4)) {
+ if (strncmp(cp, "ftp", 3)) {
+ for (i = 0; i < 3; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(FTP_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "wais:", 5)) {
+ if (strncmp(cp, "wais", 4)) {
+ for (i = 0; i < 4; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(WAIS_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "telnet:", 7)) {
+ if (strncmp(cp, "telnet", 6)) {
+ for (i = 0; i < 6; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(TELNET_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "tn3270:", 7)) {
+ if (strncmp(cp, "tn", 2)) {
+ for (i = 0; i < 2; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(TN3270_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "rlogin:", 7)) {
+ if (strncmp(cp, "rlogin", 6)) {
+ for (i = 0; i < 6; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(RLOGIN_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "cso:", 4)) {
+ if (strncmp(cp, "cso", 3)) {
+ for (i = 0; i < 3; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(CSO_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "finger:", 7)) {
+ if (strncmp(cp, "finger", 6)) {
+ for (i = 0; i < 6; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(FINGER_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "afs:", 4)) {
+ if (strncmp(cp, "afs", 3)) {
+ for (i = 0; i < 3; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(AFS_URL_TYPE);
+
+ } else if (!strncasecomp(cp, "prospero:", 9)) {
+ if (strncmp(cp, "prospero", 8)) {
+ for (i = 0; i < 8; i++)
+ cp[i] = TOLOWER(cp[i]);
+ }
+ return(PROSPERO_URL_TYPE);
+
+ } else {
+ /*
+ * Check if it's an unknown scheme for which
+ * proxying has been set up. - FM
+ */
+ return(LYCheckForProxyURL(filename));
+ }
+}
+
+/*
+ * Determine whether we allow HEAD and related flags for a URL. - kw
+ */
+PUBLIC BOOLEAN LYCanDoHEAD ARGS1(
+ CONST char *, address
+ )
+{
+ char *temp0 = NULL;
+ int isurl;
+ if (!(address && *address))
+ return FALSE;
+ if (!strncmp(address, "http", 4))
+ return TRUE;
+ /* Make copy for is_url() since caller may not care for case changes */
+ StrAllocCopy(temp0, address);
+ isurl = is_url(temp0);
+ FREE(temp0);
+ if (!isurl)
+ return FALSE;
+ if (isurl == LYNXCGI_URL_TYPE) {
+#if defined(LYNXCGI_LINKS) && !defined(VMS)
+ return TRUE;
+#else
+ return FALSE;
+#endif
+ }
+ if (isurl == NEWS_URL_TYPE || isurl == NNTP_URL_TYPE) {
+ char *temp = HTParse(address, "", PARSE_PATH);
+ char *cp = strrchr(temp, '/');
+ if (strchr((cp ? cp : temp), '@') != NULL) {
+ FREE(temp);
+ return TRUE;
+ }
+ if (cp && isdigit(cp[1]) && strchr(cp, '-') == NULL) {
+ FREE(temp);
+ return TRUE;
+ }
+ FREE(temp);
+ }
+ return FALSE;
+}
+
+/*
+ * Remove backslashes from any string.
+ */
+PUBLIC void remove_backslashes ARGS1(
+ char *, buf)
+{
+ char *cp;
+
+ for (cp = buf; *cp != '\0' ; cp++) {
+
+ if (*cp != '\\') { /* don't print slashes */
+ *buf = *cp;
+ buf++;
+ } else if (*cp == '\\' && /* print one slash if there */
+ *(cp+1) == '\\') { /* are two in a row */
+ *buf = *cp;
+ buf++;
+ }
+ }
+ *buf = '\0';
+ return;
+}
+
+/*
+ * Quote the path to make it safe for shell command processing.
+ *
+ * We use a simple technique which involves quoting the entire
+ * string using single quotes, escaping the real single quotes
+ * with double quotes. This may be gross but it seems to work.
+ */
+PUBLIC char * quote_pathname ARGS1(
+ char *, pathname)
+{
+ size_t i, n = 0;
+ char * result;
+
+ for (i=0; i < strlen(pathname); ++i)
+ if (pathname[i] == '\'') ++n;
+
+ result = (char *)malloc(strlen(pathname) + 5*n + 3);
+ if (result == NULL)
+ outofmem(__FILE__, "quote_pathname");
+
+ result[0] = '\'';
+ for (i = 0, n = 1; i < strlen(pathname); i++)
+ if (pathname[i] == '\'') {
+ result[n++] = '\'';
+ result[n++] = '"';
+ result[n++] = '\'';
+ result[n++] = '"';
+ result[n++] = '\'';
+ } else {
+ result[n++] = pathname[i];
+ }
+ result[n++] = '\'';
+ result[n] = '\0';
+ return result;
+}
+
+#if HAVE_UTMP
+extern char *ttyname PARAMS((int fd));
+#endif
+
+/*
+ * Checks to see if the current process is attached
+ * via a terminal in the local domain.
+ *
+ */
+PUBLIC BOOLEAN inlocaldomain NOARGS
+{
+#if ! HAVE_UTMP
+ return(TRUE);
+#else
+ int n;
+ FILE *fp;
+ struct utmp me;
+ char *cp, *mytty = NULL;
+
+ if ((cp=ttyname(0)))
+ mytty = strrchr(cp, '/');
+
+ if (mytty && (fp=fopen(UTMP_FILE, "r")) != NULL) {
+ mytty++;
+ do {
+ n = fread((char *) &me, sizeof(struct utmp), 1, fp);
+ } while (n>0 && !STREQ(me.ut_line,mytty));
+ (void) fclose(fp);
+
+ if (n > 0 &&
+ strlen(me.ut_host) > strlen(LYLocalDomain) &&
+ STREQ(LYLocalDomain,
+ me.ut_host+strlen(me.ut_host)-strlen(LYLocalDomain)) )
+ return(TRUE);
+#ifdef LINUX
+/* Linux fix to check for local user. J.Cullen 11Jul94 */
+ if ((n > 0) && (strlen(me.ut_host) == 0))
+ return(TRUE);
+#endif /* LINUX */
+
+ } else {
+ if (TRACE)
+ fprintf(stderr,"Could not get ttyname or open UTMP file");
+ }
+
+ return(FALSE);
+#endif /* !HAVE_UTMP */
+}
+
+/**************
+** This bit of code catches window size change signals
+**/
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
+/* For systems that have both, but both can't be included, duh */
+#ifdef TERMIO_AND_TERMIOS
+# include <termio.h>
+#else
+# ifdef HAVE_TERMIOS_H
+# include <termios.h>
+# else
+# ifdef HAVE_TERMIO_H
+# include <termio.h>
+# endif /* HAVE_TERMIO_H */
+# endif /* HAVE_TERMIOS_H */
+#endif /* TERMIO_AND_TERMIOS */
+
+PUBLIC void size_change ARGS1(
+ int, sig GCC_UNUSED)
+{
+ int old_lines = LYlines;
+ int old_cols = LYcols;
+
+#ifdef USE_SLANG
+ SLtt_get_screen_size();
+ LYlines = SLtt_Screen_Rows;
+ LYcols = SLtt_Screen_Cols;
+#ifdef SLANG_MBCS_HACK
+ PHYSICAL_SLtt_Screen_Cols = LYcols;
+ SLtt_Screen_Cols = (LYcols * 6);
+#endif /* SLANG_MBCS_HACK */
+ if (sig == 0)
+ /*
+ * Called from start_curses().
+ */
+ return;
+#else /* Curses: */
+#if HAVE_SIZECHANGE
+#ifdef TIOCGSIZE
+ struct ttysize win;
+#else
+#ifdef TIOCGWINSZ
+ struct winsize win;
+#endif /* TIOCGWINSZ */
+#endif /* TIOCGSIZE */
+
+#ifdef TIOCGSIZE
+ if (ioctl(0, TIOCGSIZE, &win) == 0) {
+ if (win.ts_lines != 0) {
+ LYlines = win.ts_lines;
+ }
+ if (win.ts_cols != 0) {
+ LYcols = win.ts_cols;
+ }
+ }
+#else
+#ifdef TIOCGWINSZ
+ if (ioctl(0, TIOCGWINSZ, &win) == 0) {
+ if (win.ws_row != 0) {
+ LYlines = win.ws_row;
+ }
+ if (win.ws_col != 0) {
+ LYcols = win.ws_col;
+ }
+ }
+#endif /* TIOCGWINSZ */
+#endif /* TIOCGSIZE */
+#endif /* HAVE_SIZECHANGE */
+
+ if (LYlines <= 0)
+ LYlines = 24;
+ if (LYcols <= 0)
+ LYcols = 80;
+#endif /* USE_SLANG */
+
+ /*
+ * Check if the screen size has actually changed. - AJL
+ */
+ if (LYlines != old_lines || LYcols != old_cols) {
+ recent_sizechange = TRUE;
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "Window size changed from (%d,%d) to (%d,%d)\n",
+ old_lines, old_cols, LYlines, LYcols);
+ }
+#ifdef SIGWINCH
+ (void)signal (SIGWINCH, size_change);
+#endif /* SIGWINCH */
+
+ return;
+}
+
+/*
+ * Utility for freeing the list of previous suggested filenames. - FM
+ */
+PUBLIC void HTSugFilenames_free NOARGS
+{
+ char *fname;
+ HTList *cur = sug_filenames;
+
+ if (!cur)
+ return;
+
+ while (NULL != (fname = (char *)HTList_nextObject(cur))) {
+ FREE(fname);
+ }
+ HTList_delete(sug_filenames);
+ sug_filenames = NULL;
+ return;
+}
+
+/*
+ * Utility for listing suggested filenames, making any
+ * repeated filenanmes the most current in the list. - FM
+ */
+PUBLIC void HTAddSugFilename ARGS1(
+ char *, fname)
+{
+ char *new;
+ char *old;
+ HTList *cur;
+
+ if (!(fname && *fname))
+ return;
+
+ if ((new = (char *)calloc(1, (strlen(fname) + 1))) == NULL)
+ outofmem(__FILE__, "HTAddSugFilename");
+ strcpy(new, fname);
+
+ if (!sug_filenames) {
+ sug_filenames = HTList_new();
+ atexit(HTSugFilenames_free);
+ HTList_addObject(sug_filenames, new);
+ return;
+ }
+
+ cur = sug_filenames;
+ while (NULL != (old = (char *)HTList_nextObject(cur))) {
+ if (!strcmp(old, new)) {
+ HTList_removeObject(sug_filenames, old);
+ FREE(old);
+ break;
+ }
+ }
+ HTList_addObject(sug_filenames, new);
+
+ return;
+}
+
+/*
+ * CHANGE_SUG_FILENAME -- Foteos Macrides 29-Dec-1993
+ * Upgraded for use with Lynx2.2 - FM 17-Jan-1994
+ */
+PUBLIC void change_sug_filename ARGS1(
+ char *, fname)
+{
+ char *temp, *cp, *cp1, *end;
+#ifdef VMS
+ char *dot;
+ int j, k;
+#endif /* VMS */
+
+ /*
+ * Establish the current end of fname.
+ */
+ end = fname + strlen(fname);
+
+ /*
+ * Unescape fname.
+ */
+ HTUnEscape(fname);
+
+ /*
+ * Rename any temporary files.
+ */
+ temp = (char *)calloc(1, (strlen(lynx_temp_space) + 60));
+#if defined(FNAMES_8_3) && defined(DOSPATH)
+ cp = HTDOS_wwwName(lynx_temp_space);
+#else
+ cp = lynx_temp_space;
+#endif
+ if (*cp == '/') {
+ sprintf(temp, "file://localhost%s%d", cp, (int)getpid());
+ } else {
+ sprintf(temp, "file://localhost/%s%d", cp, (int)getpid());
+ }
+ if (!strncmp(fname, temp, strlen(temp))) {
+ cp = strrchr(fname, '.');
+ if (strlen(cp) > (strlen(temp) - 4))
+ cp = NULL;
+ strcpy(temp, (cp ? cp : ""));
+ strcpy(fname, "temp");
+ strcat(fname, temp);
+ }
+ FREE(temp);
+
+ /*
+ * Remove everything up the the last_slash if there is one.
+ */
+ if ((cp = strrchr(fname,'/')) != NULL && strlen(cp) > 1) {
+ cp1 = fname;
+ /*
+ * Go past the slash.
+ */
+ cp++;
+ for (; *cp != '\0'; cp++, cp1++) {
+ *cp1 = *cp;
+ }
+ *cp1 = '\0';
+ }
+
+ /*
+ * Trim off date-size suffix, if present.
+ */
+ if ((*(end - 1) == ']') && ((cp = strrchr(fname, '[')) != NULL) &&
+ (cp > fname) && *(--cp) == ' ') {
+ while (*cp == ' ') {
+ *(cp--) = '\0';
+ }
+ }
+
+ /*
+ * Trim off VMS device and/or directory specs, if present.
+ */
+ if ((cp = strchr(fname,'[')) != NULL &&
+ (cp1 = strrchr(cp,']')) != NULL && strlen(cp1) > 1) {
+ cp1++;
+ for (cp=fname; *cp1 != '\0'; cp1++) {
+ *(cp++) = *cp1;
+ }
+ *cp = '\0';
+ }
+
+#ifdef VMS
+ /*
+ * Replace illegal or problem characters.
+ */
+ dot = fname + strlen(fname);
+ for (cp = fname; cp < dot; cp++) {
+ /*
+ * Replace with underscores.
+ */
+ if (*cp == ' ' || *cp == '/' || *cp == ':' ||
+ *cp == '[' || *cp == ']' || *cp == '&') {
+ *cp = '_';
+ /*
+ * Replace with dashes.
+ */
+ } else if (*cp == '!' || *cp == '?' || *cp == '\'' ||
+ *cp == ',' || *cp == ':' || *cp == '\"' ||
+ *cp == '+' || *cp == '@' || *cp == '\\' ||
+ *cp == '(' || *cp == ')' || *cp == '=' ||
+ *cp == '<' || *cp == '>' || *cp == '#' ||
+ *cp == '%' || *cp == '*' || *cp == '`' ||
+ *cp == '~' || *cp == '^' || *cp == '|' ||
+ *cp < ' ' || ((unsigned char)*cp) > 126) {
+ *cp = '-';
+ }
+ }
+
+ /*
+ * Collapse any serial underscores.
+ */
+ cp = fname + 1;
+ j = 0;
+ while (cp < dot) {
+ if (fname[j] == '_' && *cp == '_') {
+ cp++;
+ } else {
+ fname[++j] = *cp++;
+ }
+ }
+ fname[++j] = '\0';
+
+ /*
+ * Collapse any serial dashes.
+ */
+ dot = fname + (strlen(fname));
+ cp = fname + 1;
+ j = 0;
+ while (cp < dot) {
+ if (fname[j] == '-' && *cp == '-') {
+ cp++;
+ } else {
+ fname[++j] = *cp++;
+ }
+ }
+ fname[++j] = '\0';
+
+ /*
+ * Trim any trailing or leading
+ * underscrores or dashes.
+ */
+ cp = fname + (strlen(fname)) - 1;
+ while (*cp == '_' || *cp == '-') {
+ *cp-- = '\0';
+ }
+ if (fname[0] == '_' || fname[0] == '-') {
+ dot = fname + (strlen(fname));
+ cp = fname;
+ while ((*cp == '_' || *cp == '-') && cp < dot) {
+ cp++;
+ }
+ j = 0;
+ while (cp < dot) {
+ fname[j++] = *cp++;
+ }
+ fname[j] = '\0';
+ }
+
+ /*
+ * Replace all but the last period with _'s, or second
+ * to last if last is followed by a terminal Z or z,
+ * or GZ or gz,
+ * e.g., convert foo.tar.Z to
+ * foo.tar_Z
+ * or, convert foo.tar.gz to
+ * foo.tar-gz
+ */
+ j = strlen(fname) - 1;
+ if ((dot = strrchr(fname, '.')) != NULL) {
+ if (TOUPPER(fname[j]) == 'Z') {
+ if ((fname[j-1] == '.') &&
+ (((cp = strchr(fname, '.')) != NULL) && cp < dot)) {
+ *dot = '_';
+ dot = strrchr(fname, '.');
+ } else if (((TOUPPER(fname[j-1]) == 'G') &&
+ fname[j-2] == '.') &&
+ (((cp = strchr(fname, '.')) != NULL) && cp < dot)) {
+ *dot = '-';
+ dot = strrchr(fname, '.');
+ }
+ }
+ cp = fname;
+ while ((cp = strchr(cp, '.')) != NULL && cp < dot) {
+ *cp = '_';
+ }
+
+ /*
+ * But if the root is > 39 characters, move
+ * the period appropriately to the left.
+ */
+ while (dot - fname > 39) {
+ *dot = '\0';
+ if ((cp = strrchr(fname, '_')) != NULL) {
+ *cp = '.';
+ *dot = '_';
+ } else if ((cp = strrchr(fname, '-')) != NULL) {
+ *cp = '.';
+ *dot = '_';
+ } else if (*(dot + 1) == '\0') {
+ j = strlen(fname);
+ while (j > 39) {
+ fname[j] = fname[j-1];
+ j--;
+ }
+ fname[j] = '.';
+ } else {
+ *dot = '.';
+ j = 39;
+ k = 0;
+ while (dot[k] != '\0') {
+ fname[j++] = dot[k++];
+ }
+ fname[j] = '\0';
+ }
+ dot = strrchr(fname, '.');
+ }
+
+ /*
+ * Make sure the extension is < 40 characters.
+ */
+ if ((fname + strlen(fname) - dot) > 39) {
+ *(dot + 40) = '\0';
+ }
+
+ /*
+ * Trim trailing dashes or underscores.
+ */
+ j = (strlen(fname) - 1);
+ while (fname[j] == '_' || fname[j] == '-') {
+ fname[j--] = '\0';
+ }
+ } else {
+ /*
+ * No period, so put one on the end, or after
+ * the 39th character, trimming trailing dashes
+ * or underscrores.
+ */
+ if (strlen(fname) > 39) {
+ fname[39] = '\0';
+ }
+ j = (strlen(fname) - 1);
+ while ((fname[j] == '_') || (fname[j] == '-')) {
+ j--;
+ }
+ fname[++j] = '.';
+ fname[++j] = '\0';
+ }
+
+#else /* Not VMS (UNIX): */
+
+ /*
+ * Replace problem characters.
+ */
+ for (cp = fname; *cp != '\0'; cp++) {
+ switch (*cp) {
+ case '\'':
+ case '\"':
+ case '/':
+ case ' ':
+ *cp = '-';
+ }
+ }
+#endif /* VMS (UNIX) */
+
+ /*
+ * Make sure the rest of the original string in nulled.
+ */
+ cp = fname + strlen(fname);
+ while (cp < end) {
+ *cp++ = '\0';
+ }
+
+ return;
+}
+
+/*
+ * To create standard temporary file names.
+ */
+PUBLIC void tempname ARGS2(
+ char *, namebuffer,
+ int, action)
+{
+ static int counter = 0;
+ FILE *fp = NULL;
+#ifdef FNAMES_8_3
+ int LYMaxTempCount = 1000; /* Arbitrary limit. Make it configurable? */
+#else
+ int LYMaxTempCount = 10000; /* Arbitrary limit. Make it configurable? */
+#endif /* FNAMES_8_3 */
+
+ if (action == REMOVE_FILES) {
+ /*
+ * Remove all temporary files with .txt or .html suffixes. - FM
+ */
+ for (; counter > 0; counter--) {
+#ifdef FNAMES_8_3
+ sprintf(namebuffer,
+ "%s%d%u.txt",
+ lynx_temp_space, (int)getpid(), counter-1);
+ remove(namebuffer);
+ sprintf(namebuffer,
+ "%s%d%u%s",
+ lynx_temp_space, (int)getpid(), counter-1, HTML_SUFFIX);
+ remove(namebuffer);
+#else
+ sprintf(namebuffer,
+ "%sL%d-%uTMP.txt",
+ lynx_temp_space, (int)getpid(), counter-1);
+ remove(namebuffer);
+ sprintf(namebuffer,
+ "%sL%d-%uTMP%s",
+ lynx_temp_space, (int)getpid(), counter-1, HTML_SUFFIX);
+ remove(namebuffer);
+#endif /* FNAMES_8_3 */
+ }
+ } else {
+ /*
+ * Load a tentative temporary file name into namebuffer. - FM
+ */
+ while (counter < LYMaxTempCount) {
+ /*
+ * Create names with .txt, then .bin, then
+ * .html suffixes, and check for their prior
+ * existence. If any already exist, someone
+ * might be trying to spoof us, so increment
+ * the count and try again. Otherwise, return
+ * with the name which has the .html suffix
+ * loaded in namebuffer. - FM
+ *
+ * Some systems may use .htm instead of .html. This
+ * should be done consistently by always using HTML_SUFFIX
+ * where filenames are generated for new local files. - kw
+ */
+#ifdef FNAMES_8_3
+ sprintf(namebuffer,
+ "%s%d%u.txt",
+ lynx_temp_space, (int)getpid(), counter);
+#else
+ sprintf(namebuffer,
+ "%sL%d-%uTMP.txt",
+ lynx_temp_space, (int)getpid(), counter);
+#endif /* FNAMES_8_3 */
+ if ((fp = fopen(namebuffer, "r")) != NULL) {
+ fclose(fp);
+ if (TRACE)
+ fprintf(stderr,
+ "tempname: file '%s' already exists!\n",
+ namebuffer);
+ counter++;
+ continue;
+ }
+#ifdef FNAMES_8_3
+ sprintf(namebuffer,
+ "%s%d%u.bin",
+ lynx_temp_space, (int)getpid(), counter);
+#else
+ sprintf(namebuffer,
+ "%sL%d-%uTMP.bin",
+ lynx_temp_space, (int)getpid(), counter);
+#endif /* FNAMES_8_3 */
+ if ((fp = fopen(namebuffer, "r")) != NULL) {
+ fclose(fp);
+ if (TRACE)
+ fprintf(stderr,
+ "tempname: file '%s' already exists!\n",
+ namebuffer);
+ counter++;
+ continue;
+ }
+#ifdef FNAMES_8_3
+ sprintf(namebuffer,
+ "%s%d%u%s",
+ lynx_temp_space, (int)getpid(), counter++, HTML_SUFFIX);
+#else
+ sprintf(namebuffer,
+ "%sL%d-%uTMP%s",
+ lynx_temp_space, (int)getpid(), counter++, HTML_SUFFIX);
+#endif /* FNAMES_8_3 */
+ if ((fp = fopen(namebuffer, "r")) != NULL) {
+ fclose(fp);
+ if (TRACE)
+ fprintf(stderr,
+ "tempname: file '%s' already exists!\n",
+ namebuffer);
+ continue;
+ }
+ /*
+ * Return to the calling function, with the tentative
+ * temporary file name loaded in namebuffer. Note that
+ * if the calling function will use a suffix other than
+ * .txt, .bin, or .html, it similarly should do tests for
+ * a spoof. The file name can be reused if it is written
+ * to on receipt of this name, and thereafter accessed
+ * for reading. Note that if writing to a file is to
+ * be followed by reading it, as it the usual case for
+ * Lynx, the spoof attempt will be apparent, and the user
+ * can take appropriate action. - FM
+ */
+ return;
+ }
+ /*
+ * The tempfile maximum count has been reached.
+ * Issue a message and exit. - FM
+ */
+ _statusline(MAX_TEMPCOUNT_REACHED);
+ sleep(AlertSecs);
+ exit(-1);
+ }
+
+ /*
+ * We were called for a clean up, and have done it. - FM
+ */
+ return;
+}
+
+/*
+ * Convert 4, 6, 2, 8 to left, right, down, up, etc.
+ */
+PUBLIC int number2arrows ARGS1(
+ int, number)
+{
+ switch(number) {
+ case '1':
+ number=END;
+ break;
+ case '2':
+ number=DNARROW;
+ break;
+ case '3':
+ number=PGDOWN;
+ break;
+ case '4':
+ number=LTARROW;
+ break;
+ case '5':
+ number=DO_NOTHING;
+ break;
+ case '6':
+ number=RTARROW;
+ break;
+ case '7':
+ number=HOME;
+ break;
+ case '8':
+ number=UPARROW;
+ break;
+ case '9':
+ number=PGUP;
+ break;
+ }
+
+ return(number);
+}
+
+/*
+ * parse_restrictions takes a string of comma-separated restrictions
+ * and sets the corresponding flags to restrict the facilities available.
+ */
+PRIVATE char *restrict_name[] = {
+ "inside_telnet" ,
+ "outside_telnet",
+ "telnet_port" ,
+ "inside_ftp" ,
+ "outside_ftp" ,
+ "inside_rlogin" ,
+ "outside_rlogin",
+ "suspend" ,
+ "editor" ,
+ "shell" ,
+ "bookmark" ,
+ "multibook" ,
+ "bookmark_exec" ,
+ "option_save" ,
+ "print" ,
+ "download" ,
+ "disk_save" ,
+ "exec" ,
+ "lynxcgi" ,
+ "exec_frozen" ,
+ "goto" ,
+ "jump" ,
+ "file_url" ,
+ "news_post" ,
+ "inside_news" ,
+ "outside_news" ,
+ "mail" ,
+ "dotfiles" ,
+ "useragent" ,
+#ifdef DIRED_SUPPORT
+ "dired_support" ,
+#ifdef OK_PERMIT
+ "change_exec_perms",
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
+#ifdef USE_EXTERNALS
+ "externals" ,
+#endif
+ (char *) 0 };
+
+ /* restrict_name and restrict_flag structure order
+ * must be maintained exactly!
+ */
+
+PRIVATE BOOLEAN *restrict_flag[] = {
+ &no_inside_telnet,
+ &no_outside_telnet,
+ &no_telnet_port,
+ &no_inside_ftp,
+ &no_outside_ftp,
+ &no_inside_rlogin,
+ &no_outside_rlogin,
+ &no_suspend ,
+ &no_editor ,
+ &no_shell ,
+ &no_bookmark ,
+ &no_multibook ,
+ &no_bookmark_exec,
+ &no_option_save,
+ &no_print ,
+ &no_download ,
+ &no_disk_save,
+ &no_exec ,
+ &no_lynxcgi ,
+ &exec_frozen ,
+ &no_goto ,
+ &no_jump ,
+ &no_file_url ,
+ &no_newspost ,
+ &no_inside_news,
+ &no_outside_news,
+ &no_mail ,
+ &no_dotfiles ,
+ &no_useragent ,
+#ifdef DIRED_SUPPORT
+ &no_dired_support,
+#ifdef OK_PERMIT
+ &no_change_exec_perms,
+#endif /* OK_PERMIT */
+#endif /* DIRED_SUPPORT */
+#ifdef USE_EXTERNALS
+ &no_externals ,
+#endif
+ (BOOLEAN *) 0 };
+
+PUBLIC void parse_restrictions ARGS1(
+ char *, s)
+{
+ char *p;
+ char *word;
+ int i;
+
+ if (STREQ("all", s)) {
+ /* set all restrictions */
+ for (i=0; restrict_flag[i]; i++)
+ *restrict_flag[i] = TRUE;
+ return;
+ }
+
+ if (STREQ("default", s)) {
+ /* set all restrictions */
+ for (i=0; restrict_flag[i]; i++)
+ *restrict_flag[i] = TRUE;
+
+ /* reset these to defaults */
+ no_inside_telnet = !(CAN_ANONYMOUS_INSIDE_DOMAIN_TELNET);
+ no_outside_telnet = !(CAN_ANONYMOUS_OUTSIDE_DOMAIN_TELNET);
+ no_inside_news = !(CAN_ANONYMOUS_INSIDE_DOMAIN_READ_NEWS);
+ no_outside_news = !(CAN_ANONYMOUS_OUTSIDE_DOMAIN_READ_NEWS);
+ no_inside_ftp = !(CAN_ANONYMOUS_INSIDE_DOMAIN_FTP);
+ no_outside_ftp = !(CAN_ANONYMOUS_OUTSIDE_DOMAIN_FTP);
+ no_inside_rlogin = !(CAN_ANONYMOUS_INSIDE_DOMAIN_RLOGIN);
+ no_outside_rlogin = !(CAN_ANONYMOUS_OUTSIDE_DOMAIN_RLOGIN);
+ no_goto = !(CAN_ANONYMOUS_GOTO);
+ no_goto_cso = !(CAN_ANONYMOUS_GOTO_CSO);
+ no_goto_file = !(CAN_ANONYMOUS_GOTO_FILE);
+ no_goto_finger = !(CAN_ANONYMOUS_GOTO_FINGER);
+ no_goto_ftp = !(CAN_ANONYMOUS_GOTO_FTP);
+ no_goto_gopher = !(CAN_ANONYMOUS_GOTO_GOPHER);
+ no_goto_http = !(CAN_ANONYMOUS_GOTO_HTTP);
+ no_goto_https = !(CAN_ANONYMOUS_GOTO_HTTPS);
+ no_goto_lynxcgi = !(CAN_ANONYMOUS_GOTO_LYNXCGI);
+ no_goto_lynxexec = !(CAN_ANONYMOUS_GOTO_LYNXEXEC);
+ no_goto_lynxprog = !(CAN_ANONYMOUS_GOTO_LYNXPROG);
+ no_goto_mailto = !(CAN_ANONYMOUS_GOTO_MAILTO);
+ no_goto_news = !(CAN_ANONYMOUS_GOTO_NEWS);
+ no_goto_nntp = !(CAN_ANONYMOUS_GOTO_NNTP);
+ no_goto_rlogin = !(CAN_ANONYMOUS_GOTO_RLOGIN);
+ no_goto_snews = !(CAN_ANONYMOUS_GOTO_SNEWS);
+ no_goto_telnet = !(CAN_ANONYMOUS_GOTO_TELNET);
+ no_goto_tn3270 = !(CAN_ANONYMOUS_GOTO_TN3270);
+ no_goto_wais = !(CAN_ANONYMOUS_GOTO_WAIS);
+ no_telnet_port = !(CAN_ANONYMOUS_GOTO_TELNET_PORT);
+ no_jump = !(CAN_ANONYMOUS_JUMP);
+ no_mail = !(CAN_ANONYMOUS_MAIL);
+ no_print = !(CAN_ANONYMOUS_PRINT);
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ no_exec = LOCAL_EXECUTION_LINKS_ALWAYS_OFF_FOR_ANONYMOUS;
+#endif /* EXEC_LINKS || EXEC_SCRIPTS */
+ return;
+ }
+
+ p = s;
+ while (*p) {
+ while (isspace((unsigned char)*p))
+ p++;
+ if (*p == '\0')
+ break;
+ word = p;
+ while (*p != ',' && *p != '\0')
+ p++;
+ if (*p)
+ *p++ = '\0';
+
+ for (i=0; restrict_name[i]; i++)
+ if (STREQ(word, restrict_name[i])) {
+ *restrict_flag[i] = TRUE;
+ break;
+ }
+ }
+ return;
+}
+
+#ifdef VMS
+#include <jpidef.h>
+#include <maildef.h>
+#include <starlet.h>
+
+typedef struct _VMSMailItemList
+{
+ short buffer_length;
+ short item_code;
+ void *buffer_address;
+ long *return_length_address;
+} VMSMailItemList;
+
+PUBLIC int LYCheckMail NOARGS
+{
+ static BOOL firsttime = TRUE, failure = FALSE;
+ static char user[13], dir[252];
+ static long userlen = 0, dirlen;
+ static time_t lastcheck = 0;
+ time_t now;
+ static short new, lastcount;
+ long ucontext = 0, status;
+ short flags = MAIL$M_NEWMSG;
+ VMSMailItemList
+ null_list[] = {{0,0,0,0}},
+ jpi_list[] = {{sizeof(user) - 1,JPI$_USERNAME,(void *)user,&userlen},
+ {0,0,0,0}},
+ uilist[] = {{0,MAIL$_USER_USERNAME,0,0},
+ {0,0,0,0}},
+ uolist[] = {{sizeof(new),MAIL$_USER_NEW_MESSAGES,&new,0},
+ {sizeof(dir),MAIL$_USER_FULL_DIRECTORY,dir,&dirlen},
+ {0,0,0,0}};
+ extern long mail$user_begin();
+ extern long mail$user_get_info();
+ extern long mail$user_end();
+
+ if (failure)
+ return 0;
+
+ if (firsttime) {
+ firsttime = FALSE;
+ /* Get the username. */
+ status = sys$getjpiw(0,0,0,jpi_list,0,0,0);
+ if (!(status & 1)) {
+ failure = TRUE;
+ return 0;
+ }
+ user[userlen] = '\0';
+ while (user[0] &&
+ /*
+ * Suck up trailing spaces.
+ */
+ isspace((unsigned char)user[--userlen]))
+ user[userlen] = '\0';
+ }
+
+ /* Minimum report interval is 60 sec. */
+ time(&now);
+ if (now - lastcheck < 60)
+ return 0;
+ lastcheck = now;
+
+ /* Get the current newmail count. */
+ status = mail$user_begin(&ucontext,null_list,null_list);
+ if (!(status & 1)) {
+ failure = TRUE;
+ return 0;
+ }
+ uilist[0].buffer_length = strlen(user);
+ uilist[0].buffer_address = user;
+ status = mail$user_get_info(&ucontext,uilist,uolist);
+ if (!(status & 1)) {
+ failure = TRUE;
+ return 0;
+ }
+
+ /* Should we report anything to the user? */
+ if (new > 0) {
+ if (lastcount == 0)
+ /* Have newmail at startup of Lynx. */
+ _statusline(HAVE_UNREAD_MAIL_MSG);
+ else if (new > lastcount)
+ /* Have additional mail since last report. */
+ _statusline(HAVE_NEW_MAIL_MSG);
+ lastcount = new;
+ return 1;
+ }
+ lastcount = new;
+
+ /* Clear the context */
+ mail$user_end((long *)&ucontext,null_list,null_list);
+ return 0;
+}
+#else
+PUBLIC int LYCheckMail NOARGS
+{
+ static BOOL firsttime = TRUE;
+ static char *mf;
+ static time_t lastcheck;
+ static long lastsize;
+ time_t now;
+ struct stat st;
+
+ if (firsttime) {
+ mf = getenv("MAIL");
+ firsttime = FALSE;
+ }
+
+ if (mf == NULL)
+ return 0;
+
+ time(&now);
+ if (now - lastcheck < 60)
+ return 0;
+ lastcheck = now;
+
+ if (stat(mf,&st) < 0) {
+ mf = NULL;
+ return 0;
+ }
+
+ if (st.st_size > 0) {
+ if (st.st_mtime > st.st_atime ||
+ (lastsize && st.st_size > lastsize))
+ _statusline(HAVE_NEW_MAIL_MSG);
+ else if (lastsize == 0)
+ _statusline(HAVE_MAIL_MSG);
+ lastsize = st.st_size;
+ return 1;
+ }
+ lastsize = st.st_size;
+ return 0;
+}
+#endif /* VMS */
+
+/*
+** This function ensures that an href will be
+** converted to a fully resolved, absolute URL,
+** with guessing of the host or expansions of
+** lead tildes via LYConvertToURL() if needed,
+** and tweaking/simplifying via HTParse(). It
+** is used for LynxHome, startfile, homepage,
+** an 'g'oto entries, after they have been
+** passed to LYFillLocalFileURL(). - FM
+*/
+PUBLIC void LYEnsureAbsoluteURL ARGS2(
+ char **, href,
+ char *, name)
+{
+ char *temp = NULL;
+
+ if (!(*href && *(*href)))
+ return;
+
+ /*
+ * If it is not a URL then make it one.
+ */
+ if (!strcasecomp(*href, "news:")) {
+ StrAllocCat(*href, "*");
+ } else if (!strcasecomp(*href, "nntp:") ||
+ !strcasecomp(*href, "snews:")) {
+ StrAllocCat(*href, "/*");
+ }
+ if (!is_url(*href)) {
+ if (TRACE)
+ fprintf(stderr, "%s%s'%s' is not a URL\n",
+ (name ? name : ""), (name ? " " : ""), *href);
+ LYConvertToURL(href);
+ }
+ if ((temp = HTParse(*href, "", PARSE_ALL)) != NULL && *temp != '\0')
+ StrAllocCopy(*href, temp);
+ FREE(temp);
+}
+
+/*
+ * Rewrite and reallocate a previously allocated string
+ * as a file URL if the string resolves to a file or
+ * directory on the local system, otherwise as an
+ * http URL. - FM
+ */
+PUBLIC void LYConvertToURL ARGS1(
+ char **, AllocatedString)
+{
+ char *old_string = *AllocatedString;
+ char *temp = NULL;
+ char *cp = NULL;
+#ifndef VMS
+ struct stat st;
+ FILE *fptemp = NULL;
+#endif /* !VMS */
+
+ if (!old_string || *old_string == '\0')
+ return;
+
+#ifdef DOSPATH
+ {
+ char *cp_url = *AllocatedString;
+ for(; *cp_url != '\0'; cp_url++)
+ if(*cp_url == '\\') *cp_url = '/';
+ cp_url--;
+ if(*cp_url == ':')
+ StrAllocCat(*AllocatedString,"/");
+#ifdef NOTDEFINED
+ if(strlen(old_string) > 3 && *cp_url == '/')
+ *cp_url = '\0';
+#endif
+ }
+#endif /* DOSPATH */
+
+ *AllocatedString = NULL; /* so StrAllocCopy doesn't free it */
+ StrAllocCopy(*AllocatedString,"file://localhost");
+
+ if (*old_string != '/') {
+ char *fragment = NULL;
+#ifdef DOSPATH
+ StrAllocCat(*AllocatedString,"/");
+#endif /* DOSPATH */
+#ifdef VMS
+ /*
+ * Not a SHELL pathspec. Get the full VMS spec and convert it.
+ */
+ char *cur_dir = NULL;
+ static char url_file[256], file_name[256], dir_name[256];
+ unsigned long context = 0;
+ $DESCRIPTOR(url_file_dsc, url_file);
+ $DESCRIPTOR(file_name_dsc, file_name);
+ if (*old_string == '~') {
+ /*
+ * On VMS, we'll accept '~' on the command line as
+ * Home_Dir(), and assume the rest of the path, if
+ * any, has SHELL syntax.
+ */
+ StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir()));
+ if ((cp = strchr(old_string, '/')) != NULL) {
+ /*
+ * Append rest of path, if present, skipping "user" if
+ * "~user" was entered, simplifying, and eliminating
+ * any residual relative elements. - FM
+ */
+ StrAllocCopy(temp, cp);
+ LYTrimRelFromAbsPath(temp);
+ StrAllocCat(*AllocatedString, temp);
+ FREE(temp);
+ }
+ goto have_VMS_URL;
+ } else {
+ if ((fragment = strchr(old_string, '#')) != NULL)
+ *fragment = '\0';
+ strcpy(url_file, old_string);
+ }
+ url_file_dsc.dsc$w_length = (short) strlen(url_file);
+ if (1&lib$find_file(&url_file_dsc, &file_name_dsc, &context,
+ 0, 0, 0, 0)) {
+ /*
+ * We found the file. Convert to a URL pathspec.
+ */
+ if ((cp = strchr(file_name, ';')) != NULL) {
+ *cp = '\0';
+ }
+ for (cp = file_name; *cp; cp++) {
+ *cp = TOLOWER(*cp);
+ }
+ StrAllocCat(*AllocatedString, HTVMS_wwwName(file_name));
+ if ((cp = strchr(old_string, ';')) != NULL) {
+ StrAllocCat(*AllocatedString, cp);
+ }
+ if (fragment != NULL) {
+ *fragment = '#';
+ StrAllocCat(*AllocatedString, fragment);
+ fragment = NULL;
+ }
+ } else if ((NULL != getcwd(dir_name, 255, 0)) &&
+ 0 == chdir(old_string)) {
+ /*
+ * Probably a directory. Try converting that.
+ */
+ StrAllocCopy(cur_dir, dir_name);
+ if (fragment != NULL) {
+ *fragment = '#';
+ }
+ if (NULL != getcwd(dir_name, 255, 0)) {
+ /*
+ * Yup, we got it!
+ */
+ for (cp = dir_name; *cp; cp++) {
+ *cp = TOLOWER(*cp);
+ }
+ StrAllocCat(*AllocatedString, dir_name);
+ if (fragment != NULL) {
+ StrAllocCat(*AllocatedString, fragment);
+ fragment = NULL;
+ }
+ } else {
+ /*
+ * Nope. Assume it's an http URL with
+ * the "http://" defaulted, if we can't
+ * rule out a bad VMS path.
+ */
+ fragment = NULL;
+ if (strchr(old_string, '[') ||
+ ((cp = strchr(old_string, ':')) != NULL &&
+ !isdigit((unsigned char)cp[1])) ||
+ !LYExpandHostForURL((char **)&old_string,
+ URLDomainPrefixes,
+ URLDomainSuffixes)) {
+ /*
+ * Probably a bad VMS path (but can't be
+ * sure). Use original pathspec for the
+ * error message that will result.
+ */
+ strcpy(url_file, "/");
+ strcat(url_file, old_string);
+ if (TRACE) {
+ fprintf(stderr,
+ "Can't find '%s' Will assume it's a bad path.\n",
+ old_string);
+ }
+ StrAllocCat(*AllocatedString, url_file);
+ } else {
+ /*
+ * Assume a URL is wanted, so guess the
+ * scheme with "http://" as the default. - FM
+ */
+ if (!LYAddSchemeForURL((char **)&old_string, "http://")) {
+ StrAllocCopy(*AllocatedString, "http://");
+ StrAllocCat(*AllocatedString, old_string);
+ } else {
+ StrAllocCopy(*AllocatedString, old_string);
+ }
+ }
+ }
+ } else {
+ /*
+ * Nothing found. Assume it's an http URL
+ * with the "http://" defaulted, if we can't
+ * rule out a bad VMS path.
+ */
+ if (fragment != NULL) {
+ *fragment = '#';
+ fragment = NULL;
+ }
+ if (strchr(old_string, '[') ||
+ ((cp = strchr(old_string, ':')) != NULL &&
+ !isdigit((unsigned char)cp[1])) ||
+ !LYExpandHostForURL((char **)&old_string,
+ URLDomainPrefixes,
+ URLDomainSuffixes)) {
+ /*
+ * Probably a bad VMS path (but can't be
+ * sure). Use original pathspec for the
+ * error message that will result.
+ */
+ strcpy(url_file, "/");
+ strcat(url_file, old_string);
+ if (TRACE) {
+ fprintf(stderr,
+ "Can't find '%s' Will assume it's a bad path.\n",
+ old_string);
+ }
+ StrAllocCat(*AllocatedString, url_file);
+ } else {
+ /*
+ * Assume a URL is wanted, so guess the
+ * scheme with "http://" as the default. - FM
+ */
+ if (!LYAddSchemeForURL((char **)&old_string, "http://")) {
+ StrAllocCopy(*AllocatedString, "http://");
+ StrAllocCat(*AllocatedString, old_string);
+ } else {
+ StrAllocCopy(*AllocatedString, old_string);
+ }
+ }
+ }
+ lib$find_file_end(&context);
+ FREE(cur_dir);
+have_VMS_URL:
+ if (TRACE) {
+ fprintf(stderr, "Trying: '%s'\n", *AllocatedString);
+ }
+#else /* Unix: */
+#ifdef DOSPATH
+ if (strlen(old_string) == 1 && *old_string == '.') {
+ /*
+ * They want .
+ */
+ char curdir[DIRNAMESIZE];
+ getcwd (curdir, DIRNAMESIZE);
+ StrAllocCopy(temp, HTDOS_wwwName(curdir));
+ StrAllocCat(*AllocatedString, temp);
+ FREE(temp);
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+ } else
+#endif /* DOSPATH */
+ if (*old_string == '~') {
+ /*
+ * On Unix, covert '~' to Home_Dir().
+ */
+ StrAllocCat(*AllocatedString, Home_Dir());
+ if ((cp = strchr(old_string, '/')) != NULL) {
+ /*
+ * Append rest of path, if present, skipping "user" if
+ * "~user" was entered, simplifying, and eliminating
+ * any residual relative elements. - FM
+ */
+ StrAllocCopy(temp, cp);
+ LYTrimRelFromAbsPath(temp);
+ StrAllocCat(*AllocatedString, temp);
+ FREE(temp);
+ }
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+ } else {
+ /*
+ * Create a full path to the current default directory.
+ */
+ char curdir[DIRNAMESIZE];
+ char *temp2 = NULL;
+ BOOL is_local = FALSE;
+#if HAVE_GETCWD
+ getcwd (curdir, DIRNAMESIZE);
+#else
+ getwd (curdir);
+#endif /* NO_GETCWD */
+ /*
+ * Concatenate and simplify, trimming any
+ * residual relative elements. - FM
+ */
+#ifndef DOSPATH
+ StrAllocCopy(temp, curdir);
+ StrAllocCat(temp, "/");
+ StrAllocCat(temp, old_string);
+#else
+ if (old_string[1] != ':' && old_string[1] != '|') {
+ StrAllocCopy(temp, HTDOS_wwwName(curdir));
+ if(curdir[strlen(curdir)-1] != '/')
+ StrAllocCat(temp, "/");
+ LYstrncpy(curdir, temp, (DIRNAMESIZE - 1));
+ StrAllocCat(temp, old_string);
+ } else {
+ curdir[0] = '\0';
+ StrAllocCopy(temp, old_string);
+ }
+#endif /* DOSPATH */
+ LYTrimRelFromAbsPath(temp);
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n", old_string, temp);
+ }
+ if ((stat(temp, &st) > -1) ||
+ (fptemp = fopen(temp, "r")) != NULL) {
+ /*
+ * It is a subdirectory or file on the local system.
+ */
+#ifdef DOSPATH
+ /* Don't want to see DOS local paths like c: escaped */
+ /* especially when we really have file://localhost/ */
+ /* at the beginning. To avoid any confusion we allow */
+ /* escaping the path if URL specials % or # present. */
+ if (strchr(temp, '#') == NULL &&
+ strchr(temp, '%') == NULL)
+ StrAllocCopy(cp, temp);
+ else
+#endif /* DOSPATH */
+ cp = HTEscape(temp, URL_PATH);
+ StrAllocCat(*AllocatedString, cp);
+ FREE(cp);
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+ is_local = TRUE;
+ } else {
+ char *cp2 = NULL;
+ StrAllocCopy(temp2, curdir);
+ if (curdir[0] != '\0' && curdir[strlen(curdir)-1] != '/')
+ StrAllocCat(temp2, "/");
+ StrAllocCopy(cp, old_string);
+ if ((fragment = strchr(cp, '#')) != NULL)
+ *fragment = '\0'; /* keep as pointer into cp string */
+ HTUnEscape(cp); /* unescape given path without fragment */
+ StrAllocCat(temp2, cp); /* append to current dir */
+ StrAllocCopy(cp2, temp2); /* keep a copy in cp2 */
+ LYTrimRelFromAbsPath(temp2);
+
+ if (strcmp(temp2, temp) != 0 &&
+ ((stat(temp2, &st) > -1) ||
+ (fptemp = fopen(temp2, "r")) != NULL)) {
+ /*
+ * It is a subdirectory or file on the local system
+ * with escaped characters and/or a fragment to be
+ * appended to the URL. - FM
+ */
+
+ FREE(temp);
+ if (strcmp(cp2, temp2) == 0) {
+ /*
+ * LYTrimRelFromAbsPath did nothing, use
+ * old_string as given. - kw
+ */
+ temp = HTEscape(curdir, URL_PATH);
+ if (curdir[0] != '\0' && curdir[strlen(curdir)-1] != '/')
+ StrAllocCat(temp, "/");
+ StrAllocCat(temp, old_string);
+ } else {
+ temp = HTEscape(temp2, URL_PATH);
+ if (fragment != NULL) {
+ *fragment = '#';
+ StrAllocCat(temp, fragment);
+ }
+ }
+ StrAllocCat(*AllocatedString, temp);
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+ is_local = TRUE;
+
+ } else if (strchr(curdir, '#') != NULL ||
+ strchr(curdir, '%') != NULL) {
+ /*
+ * If PWD has some unusual characters, construct a
+ * filename in temp where those are escaped. This
+ * is mostly to prevent this function from returning
+ * with some weird URL if the LYExpandHostForURL tests
+ * further down fail. - kw
+ */
+ FREE(temp);
+ if (strcmp(cp2, temp2) == 0) {
+ /*
+ * LYTrimRelFromAbsPath did nothing, use
+ * old_string as given. - kw
+ */
+ temp = HTEscape(curdir, URL_PATH);
+ if (curdir[0] != '\0' && curdir[strlen(curdir)-1] != '/')
+ StrAllocCat(temp, "/");
+ StrAllocCat(temp, old_string);
+ } else {
+ temp = HTEscape(temp2, URL_PATH);
+ if (fragment != NULL) {
+ *fragment = '#';
+ StrAllocCat(temp, fragment);
+ }
+ }
+ }
+ FREE(cp);
+ FREE(cp2);
+ }
+ if (is_local == FALSE) {
+ /*
+ * It's not an accessible subdirectory or file on the
+ * local system, so assume it's a URL request and guess
+ * the scheme with "http://" as the default.
+ */
+ if (TRACE) {
+ fprintf(stderr, "Can't stat() or fopen() '%s'\n",
+ temp2 ? temp2 : temp);
+ }
+ if (LYExpandHostForURL((char **)&old_string,
+ URLDomainPrefixes,
+ URLDomainSuffixes)) {
+ if (!LYAddSchemeForURL((char **)&old_string, "http://")) {
+ StrAllocCopy(*AllocatedString, "http://");
+ StrAllocCat(*AllocatedString, old_string);
+ } else {
+ StrAllocCopy(*AllocatedString, old_string);
+ }
+ } else {
+ StrAllocCat(*AllocatedString, temp);
+ }
+ if (TRACE) {
+ fprintf(stderr, "Trying: '%s'\n", *AllocatedString);
+ }
+ }
+ FREE(temp);
+ FREE(temp2);
+ if (fptemp) {
+ fclose(fptemp);
+ fptemp = NULL;
+ }
+ }
+#endif /* VMS */
+ } else {
+ /*
+ * Path begins with a slash. Simplify and use it.
+ */
+ if (old_string[1] == '\0') {
+ /*
+ * Request for root. Respect it on Unix, but
+ * on VMS we treat that as a listing of the
+ * login directory. - FM
+ */
+#ifdef VMS
+ StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(*AllocatedString, "/");
+ } else if ((stat(old_string, &st) > -1) ||
+ (fptemp = fopen(old_string, "r")) != NULL) {
+ /*
+ * It is an absolute directory or file
+ * on the local system. - KW
+ */
+ StrAllocCopy(temp, old_string);
+ LYTrimRelFromAbsPath(temp);
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n", old_string, temp);
+ }
+ cp = HTEscape(temp, URL_PATH);
+ StrAllocCat(*AllocatedString, cp);
+ FREE(cp);
+ FREE(temp);
+ if (fptemp) {
+ fclose(fptemp);
+ fptemp = NULL;
+ }
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+#endif /* VMS */
+ } else if (old_string[1] == '~') {
+ /*
+ * Has a Home_Dir() reference. Handle it
+ * as if there weren't a lead slash. - FM
+ */
+#ifdef VMS
+ StrAllocCat(*AllocatedString, HTVMS_wwwName((char *)Home_Dir()));
+#else
+ StrAllocCat(*AllocatedString, Home_Dir());
+#endif /* VMS */
+ if ((cp = strchr((old_string + 1), '/')) != NULL) {
+ /*
+ * Append rest of path, if present, skipping "user" if
+ * "~user" was entered, simplifying, and eliminating
+ * any residual relative elements. - FM
+ */
+ StrAllocCopy(temp, cp);
+ LYTrimRelFromAbsPath(temp);
+ StrAllocCat(*AllocatedString, temp);
+ FREE(temp);
+ }
+ } else {
+ /*
+ * Normal absolute path. Simplify, trim any
+ * residual relative elements, and append it. - FM
+ */
+ StrAllocCopy(temp, old_string);
+ LYTrimRelFromAbsPath(temp);
+ StrAllocCat(*AllocatedString, temp);
+ FREE(temp);
+ }
+ if (TRACE) {
+ fprintf(stderr, "Converted '%s' to '%s'\n",
+ old_string, *AllocatedString);
+ }
+ }
+ FREE(old_string);
+ if (TRACE) {
+ /* Pause so we can read the messages before invoking curses */
+ if (!LYTraceLogFP)
+ sleep(AlertSecs);
+ }
+}
+
+/*
+ * This function rewrites and reallocates a previously allocated
+ * string so that the first element is a confirmed Internet host,
+ * and returns TRUE, otherwise it does not modify the string and
+ * returns FALSE. It first tries the element as is, then, if the
+ * element does not end with a dot, it adds prefixes from the
+ * (comma separated) prefix list arguement, and, if the element
+ * does not begin with a dot, suffixes from the (comma separated)
+ * suffix list arguments (e.g., www.host.com, then www.host,edu,
+ * then www.host.net, then www.host.org). The remaining path, if
+ * one is present, will be appended to the expanded host. It also
+ * takes into account whether a colon is in the element or suffix,
+ * and includes that and what follows as a port field for the
+ * expanded host field (e.g, wfbr:8002/dir/lynx should yield
+ * www.wfbr.edu:8002/dir/lynx). The calling function should
+ * prepend the scheme field (e.g., http://), or pass the string
+ * to LYAddSchemeForURL(), if this function returns TRUE. - FM
+ */
+PUBLIC BOOLEAN LYExpandHostForURL ARGS3(
+ char **, AllocatedString,
+ char *, prefix_list,
+ char *, suffix_list)
+{
+ char DomainPrefix[80], *StartP, *EndP;
+ char DomainSuffix[80], *StartS, *EndS;
+ char *Str = NULL, *StrColon = NULL, *MsgStr = NULL;
+ char *Host = NULL, *HostColon = NULL, *host = NULL;
+ char *Path = NULL;
+ char *Fragment = NULL;
+ struct hostent *phost;
+ BOOLEAN GotHost = FALSE;
+ BOOLEAN Startup = (helpfilepath == NULL);
+
+ /*
+ * If it's a NULL or zero-length string,
+ * or if it begins with a slash or hash,
+ * don't continue pointlessly. - FM
+ */
+ if (!(*AllocatedString) || *AllocatedString[0] == '\0' ||
+ *AllocatedString[0] == '/' || *AllocatedString[0] == '#') {
+ return GotHost;
+ }
+
+ /*
+ * If it's a partial or relative path,
+ * don't continue pointlessly. - FM
+ */
+ if (!strncmp(*AllocatedString, "..", 2) ||
+ !strncmp(*AllocatedString, "./", 2)) {
+ return GotHost;
+ }
+
+ /*
+ * Make a clean copy of the string, and trim off the
+ * path if one is present, but save the information
+ * so we can restore the path after filling in the
+ * Host[:port] field. - FM
+ */
+ StrAllocCopy(Str, *AllocatedString);
+ if ((Path = strchr(Str, '/')) != NULL) {
+ /*
+ * Have a path. Any fragment should
+ * already be included in Path. - FM
+ */
+ *Path = '\0';
+ } else if ((Fragment = strchr(Str, '#')) != NULL) {
+ /*
+ * No path, so check for a fragment and
+ * trim that, to be restored after filling
+ * in the Host[:port] field. - FM
+ */
+ *Fragment = '\0';
+ }
+
+ /*
+ * If the potential host string has a colon, assume it
+ * begins a port field, and trim it off, but save the
+ * information so we can restore the port field after
+ * filling in the host field. - FM
+ */
+ if ((StrColon = strrchr(Str, ':')) != NULL &&
+ isdigit((unsigned char)StrColon[1])) {
+ if (StrColon == Str) {
+ FREE(Str);
+ return GotHost;
+ }
+ *StrColon = '\0';
+ }
+
+ /*
+ * Do a DNS test on the potential host field
+ * as presently trimmed. - FM
+ */
+ StrAllocCopy(host, Str);
+ HTUnEscape(host);
+ if (LYCursesON) {
+ StrAllocCopy(MsgStr, "Looking up ");
+ StrAllocCat(MsgStr, host);
+ StrAllocCat(MsgStr, " first.");
+ HTProgress(MsgStr);
+ } else if (Startup && !dump_output_immediately) {
+ fprintf(stdout, "Looking up '%s' first.\n", host);
+ }
+#ifndef DJGPP
+ if ((phost = gethostbyname(host)) != NULL)
+#else
+ if (resolve(host) != 0)
+#endif /* DJGPP */
+ {
+ /*
+ * Clear any residual interrupt. - FM
+ */
+ if (LYCursesON && HTCheckForInterrupt()) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandHostForURL: Ignoring interrupt because '%s' resolved.\n",
+ host);
+ }
+ }
+
+ /*
+ * Return success. - FM
+ */
+ GotHost = TRUE;
+ FREE(host);
+ FREE(Str);
+ FREE(MsgStr);
+ return GotHost;
+ } else if (LYCursesON && HTCheckForInterrupt()) {
+ /*
+ * Give the user chance to interrupt lookup cycles. - KW & FM
+ */
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandHostForURL: Interrupted while '%s' failed to resolve.\n",
+ host);
+ }
+
+ /*
+ * Return failure. - FM
+ */
+ FREE(host);
+ FREE(Str);
+ FREE(MsgStr);
+ return FALSE;
+ }
+
+ /*
+ * Set the first prefix, making it a zero-length string
+ * if the list is NULL or if the potential host field
+ * ends with a dot. - FM
+ */
+ StartP = ((prefix_list && Str[strlen(Str)-1] != '.') ?
+ prefix_list : "");
+ /*
+ * If we have a prefix, but the allocated string is
+ * one of the common host prefixes, make our prefix
+ * a zero-length string. - FM
+ */
+ if (*StartP && *StartP != '.') {
+ if (!strncasecomp(*AllocatedString, "www.", 4) ||
+ !strncasecomp(*AllocatedString, "ftp.", 4) ||
+ !strncasecomp(*AllocatedString, "gopher.", 7) ||
+ !strncasecomp(*AllocatedString, "wais.", 5) ||
+ !strncasecomp(*AllocatedString, "cso.", 4) ||
+ !strncasecomp(*AllocatedString, "ns.", 3) ||
+ !strncasecomp(*AllocatedString, "ph.", 3) ||
+ !strncasecomp(*AllocatedString, "finger.", 7) ||
+ !strncasecomp(*AllocatedString, "news.", 5) ||
+ !strncasecomp(*AllocatedString, "nntp.", 5)) {
+ StartP = "";
+ }
+ }
+ while ((*StartP) && (WHITE(*StartP) || *StartP == ',')) {
+ StartP++; /* Skip whitespace and separators */
+ }
+ EndP = StartP;
+ while (*EndP && !WHITE(*EndP) && *EndP != ',') {
+ EndP++; /* Find separator */
+ }
+ LYstrncpy(DomainPrefix, StartP, (EndP - StartP));
+
+ /*
+ * Test each prefix with each suffix. - FM
+ */
+ do {
+ /*
+ * Set the first suffix, making it a zero-length string
+ * if the list is NULL or if the potential host field
+ * begins with a dot. - FM
+ */
+ StartS = ((suffix_list && *Str != '.') ?
+ suffix_list : "");
+ while ((*StartS) && (WHITE(*StartS) || *StartS == ',')) {
+ StartS++; /* Skip whitespace and separators */
+ }
+ EndS = StartS;
+ while (*EndS && !WHITE(*EndS) && *EndS != ',') {
+ EndS++; /* Find separator */
+ }
+ LYstrncpy(DomainSuffix, StartS, (EndS - StartS));
+
+ /*
+ * Create domain names and do DNS tests. - FM
+ */
+ do {
+ StrAllocCopy(Host, DomainPrefix);
+ StrAllocCat(Host, ((*Str == '.') ? (Str + 1) : Str));
+ if (Host[strlen(Host)-1] == '.') {
+ Host[strlen(Host)-1] = '\0';
+ }
+ StrAllocCat(Host, DomainSuffix);
+ if ((HostColon = strrchr(Host, ':')) != NULL &&
+ isdigit((unsigned char)HostColon[1])) {
+ *HostColon = '\0';
+ }
+ StrAllocCopy(host, Host);
+ HTUnEscape(host);
+ if (LYCursesON) {
+ StrAllocCopy(MsgStr, "Looking up ");
+ StrAllocCat(MsgStr, host);
+ StrAllocCat(MsgStr, ", guessing...");
+ HTProgress(MsgStr);
+ } else if (Startup && !dump_output_immediately) {
+ fprintf(stdout, "Looking up '%s', guessing...\n", host);
+ }
+#ifndef DJGPP
+ GotHost = ((phost = gethostbyname(host)) != NULL);
+#else
+ GotHost = (resolve(host) != 0);
+#endif /* DJGPP */
+ if (HostColon != NULL) {
+ *HostColon = ':';
+ }
+ if (GotHost == FALSE) {
+ /*
+ * Give the user chance to interrupt lookup cycles. - KW
+ */
+ if (LYCursesON && HTCheckForInterrupt()) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandHostForURL: Interrupted while '%s' failed to resolve.\n",
+ host);
+ }
+ FREE(Str);
+ FREE(MsgStr);
+ FREE(Host);
+ FREE(host);
+ return FALSE; /* We didn't find a valid name. */
+ }
+
+ /*
+ * Advance to the next suffix, or end of suffix list. - FM
+ */
+ StartS = ((*EndS == '\0') ? EndS : (EndS + 1));
+ while ((*StartS) && (WHITE(*StartS) || *StartS == ',')) {
+ StartS++; /* Skip whitespace and separators */
+ }
+ EndS = StartS;
+ while (*EndS && !WHITE(*EndS) && *EndS != ',') {
+ EndS++; /* Find separator */
+ }
+ LYstrncpy(DomainSuffix, StartS, (EndS - StartS));
+ }
+ } while ((GotHost == FALSE) && (*DomainSuffix != '\0'));
+
+ if (GotHost == FALSE) {
+ /*
+ * Advance to the next prefix, or end of prefix list. - FM
+ */
+ StartP = ((*EndP == '\0') ? EndP : (EndP + 1));
+ while ((*StartP) && (WHITE(*StartP) || *StartP == ',')) {
+ StartP++; /* Skip whitespace and separators */
+ }
+ EndP = StartP;
+ while (*EndP && !WHITE(*EndP) && *EndP != ',') {
+ EndP++; /* Find separator */
+ }
+ LYstrncpy(DomainPrefix, StartP, (EndP - StartP));
+ }
+ } while ((GotHost == FALSE) && (*DomainPrefix != '\0'));
+
+ /*
+ * If a test passed, restore the port field if we had one
+ * and there is no colon in the expanded host, and the path
+ * if we had one, and reallocate the original string with
+ * the expanded Host[:port] field included. - FM
+ */
+ if (GotHost) {
+ if (StrColon && strchr(Host, ':') == NULL) {
+ *StrColon = ':';
+ StrAllocCat(Host, StrColon);
+ }
+ if (Path) {
+ *Path = '/';
+ StrAllocCat(Host, Path);
+ } else if (Fragment) {
+ StrAllocCat(Host, "/");
+ *Fragment = '#';
+ StrAllocCat(Host, Fragment);
+ }
+ StrAllocCopy(*AllocatedString, Host);
+ }
+
+ /*
+ * Clear any residual interrupt. - FM
+ */
+ if (LYCursesON && HTCheckForInterrupt()) {
+ if (TRACE) {
+ fprintf(stderr,
+ "LYExpandHostForURL: Ignoring interrupt because '%s' %s.\n",
+ host,
+ (GotHost ? "resolved" : "timed out"));
+ }
+ }
+
+ /*
+ * Clean up and return the last test result. - FM
+ */
+ FREE(Str);
+ FREE(MsgStr);
+ FREE(Host);
+ FREE(host);
+ return GotHost;
+}
+
+/*
+ * This function rewrites and reallocates a previously allocated
+ * string that begins with an Internet host name so that the string
+ * begins with its guess of the scheme based on the first field of
+ * the host name, or the default scheme if no guess was made, and
+ * returns TRUE, otherwise it does not modify the string and returns
+ * FALSE. It also returns FALSE without modifying the string if the
+ * default_scheme argument was NULL or zero-length and no guess was
+ * made. - FM
+ */
+PUBLIC BOOLEAN LYAddSchemeForURL ARGS2(
+ char **, AllocatedString,
+ char *, default_scheme)
+{
+ char *Str = NULL;
+ BOOLEAN GotScheme = FALSE;
+
+ /*
+ * If we were passed a NULL or zero-length string,
+ * don't continue pointlessly. - FM
+ */
+ if (!(*AllocatedString) || *AllocatedString[0] == '\0') {
+ return GotScheme;
+ }
+
+ /*
+ * Try to guess the appropriate scheme. - FM
+ */
+ if (0 == strncasecomp(*AllocatedString, "www", 3)) {
+ /*
+ * This could be either http or https, so check
+ * the default and otherwise use "http". - FM
+ */
+ if (default_scheme != NULL &&
+ NULL != strstr(default_scheme, "http")) {
+ StrAllocCopy(Str, default_scheme);
+ } else {
+ StrAllocCopy(Str, "http://");
+ }
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "ftp", 3)) {
+ StrAllocCopy(Str, "ftp://");
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "gopher", 6)) {
+ StrAllocCopy(Str, "gopher://");
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "wais", 4)) {
+ StrAllocCopy(Str, "wais://");
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "cso", 3) ||
+ 0 == strncasecomp(*AllocatedString, "ns.", 3) ||
+ 0 == strncasecomp(*AllocatedString, "ph.", 3)) {
+ StrAllocCopy(Str, "cso://");
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "finger", 6)) {
+ StrAllocCopy(Str, "finger://");
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "news", 4)) {
+ /*
+ * This could be either news, snews, or nntp, so
+ * check the default, and otherwise use news. - FM
+ */
+ if ((default_scheme != NULL) &&
+ (NULL != strstr(default_scheme, "news") ||
+ NULL != strstr(default_scheme, "nntp"))) {
+ StrAllocCopy(Str, default_scheme);
+ } else {
+ StrAllocCopy(Str, "news://");
+ }
+ GotScheme = TRUE;
+
+ } else if (0 == strncasecomp(*AllocatedString, "nntp", 4)) {
+ StrAllocCopy(Str, "nntp://");
+ GotScheme = TRUE;
+
+ }
+
+ /*
+ * If we've make a guess, use it. Otherwise, if we
+ * were passed a default scheme prefix, use that. - FM
+ */
+ if (GotScheme == TRUE) {
+ StrAllocCat(Str, *AllocatedString);
+ StrAllocCopy(*AllocatedString, Str);
+ FREE(Str);
+ return GotScheme;
+
+ } else if (default_scheme != NULL && *default_scheme != '\0') {
+ StrAllocCopy(Str, default_scheme);
+ GotScheme = TRUE;
+ StrAllocCat(Str, *AllocatedString);
+ StrAllocCopy(*AllocatedString, Str);
+ FREE(Str);
+ return GotScheme;
+ }
+
+ return GotScheme;
+}
+
+/*
+ * This function expects an absolute Unix or VMS SHELL path
+ * spec as an allocated string, simplifies it, and trims out
+ * any residual relative elements. It also checks whether
+ * the path had a terminal slash, and if it didn't, makes
+ * sure that the simplified path doesn't either. If it's
+ * a directory, our convention is to exclude "Up to parent"
+ * links when a terminal slash is present. - FM
+ */
+PUBLIC void LYTrimRelFromAbsPath ARGS1(
+ char *, path)
+{
+ char *cp;
+ int i;
+ BOOL TerminalSlash;
+
+ /*
+ * Make sure we have a pointer to an absolute path. - FM
+ */
+ if (path == NULL || *path != '/')
+ return;
+
+ /*
+ * Check whether the path has a terminal slash. - FM
+ */
+ TerminalSlash = (path[(strlen(path) - 1)] == '/');
+
+ /*
+ * Simplify the path and then do any necessary trimming. - FM
+ */
+ HTSimplify(path);
+ cp = path;
+ while (cp[1] == '.') {
+ if (cp[2] == '\0') {
+ /*
+ * Eliminate trailing dot. - FM
+ */
+ cp[1] = '\0';
+ } else if (cp[2] == '/') {
+ /*
+ * Skip over the "/." of a "/./". - FM
+ */
+ cp += 2;
+ } else if (cp[2] == '.' && cp[3] == '\0') {
+ /*
+ * Eliminate trailing dotdot. - FM
+ */
+ cp[1] = '\0';
+ } else if (cp[2] == '.' && cp[3] == '/') {
+ /*
+ * Skip over the "/.." of a "/../". - FM
+ */
+ cp += 3;
+ } else {
+ /*
+ * Done trimming. - FM
+ */
+ break;
+ }
+ }
+
+ /*
+ * Load any shifts into path, and eliminate any
+ * terminal slash created by HTSimplify() or our
+ * walk, but not present originally. - FM
+ */
+ if (cp > path) {
+ for (i = 0; cp[i] != '\0'; i++)
+ path[i] = cp[i];
+ path[i] = '\0';
+ }
+ if (TerminalSlash == FALSE &&
+ path[(strlen(path) - 1)] == '/') {
+ path[(strlen(path) - 1)] = '\0';
+ }
+}
+
+/*
+ * Example Client-Side Include interface.
+ *
+ * This is called from SGML.c and simply returns markup for reporting
+ * the URL of the document being loaded if a comment begins with
+ * "<!--#lynxCSI". The markup will be included as if it were in the
+ * document. Move this function to a separate module for doing this
+ * kind of thing seriously, someday. - FM
+ */
+PUBLIC void LYDoCSI ARGS3(
+ char *, url,
+ CONST char *, comment,
+ char **, csi)
+{
+ CONST char *cp = comment;
+
+ if (cp == NULL)
+ return;
+
+ if (strncmp(cp, "!--#", 4))
+ return;
+
+ cp += 4;
+ if (!strncasecomp(cp, "lynxCSI", 7)) {
+ StrAllocCat(*csi, "\n<p align=\"center\">URL: ");
+ StrAllocCat(*csi, url);
+ StrAllocCat(*csi, "</p>\n\n");
+ }
+
+ return;
+}
+
+#ifdef VMS
+/*
+ * Define_VMSLogical -- Fote Macrides 04-Apr-1995
+ * Define VMS logicals in the process table.
+ */
+PUBLIC void Define_VMSLogical ARGS2(
+ char *, LogicalName,
+ char *, LogicalValue)
+{
+ $DESCRIPTOR(lname, "");
+ $DESCRIPTOR(lvalue, "");
+ $DESCRIPTOR(ltable, "LNM$PROCESS");
+
+ if (!LogicalName || *LogicalName == '\0')
+ return;
+
+ lname.dsc$w_length = strlen(LogicalName);
+ lname.dsc$a_pointer = LogicalName;
+
+ if (!LogicalValue || *LogicalValue == '\0') {
+ lib$delete_logical(&lname, &ltable);
+ return;
+ }
+
+ lvalue.dsc$w_length = strlen(LogicalValue);
+ lvalue.dsc$a_pointer = LogicalValue;
+ lib$set_logical(&lname, &lvalue, &ltable, 0, 0);
+ return;
+}
+#endif /* VMS */
+
+PRIVATE void LYHomeDir_free NOARGS
+{
+ FREE(HomeDir);
+}
+
+PUBLIC CONST char * Home_Dir NOARGS
+{
+ static CONST char *homedir = NULL;
+ char *cp = NULL;
+
+ if (homedir == NULL) {
+ if ((cp = getenv("HOME")) == NULL || *cp == '\0') {
+#ifdef DOSPATH /* BAD! WSB */
+ if ((cp = getenv("TEMP")) == NULL || *cp == '\0') {
+ if ((cp = getenv("TMP")) == NULL || *cp == '\0') {
+ StrAllocCopy(HomeDir, "C:\\");
+ } else {
+ StrAllocCopy(HomeDir, cp);
+ }
+ } else {
+ StrAllocCopy(HomeDir, cp);
+ }
+#else
+#ifdef VMS
+ if ((cp = getenv("SYS$LOGIN")) == NULL || *cp == '\0') {
+ if ((cp = getenv("SYS$SCRATCH")) == NULL || *cp == '\0') {
+ StrAllocCopy(HomeDir, "sys$scratch:");
+ } else {
+ StrAllocCopy(HomeDir, cp);
+ }
+ } else {
+ StrAllocCopy(HomeDir, cp);
+ }
+#else
+#if HAVE_UTMP
+ /*
+ * One could use getlogin() and getpwnam() here instead.
+ */
+ struct passwd *pw = getpwuid(geteuid());
+
+ if (pw && pw->pw_dir) {
+ StrAllocCopy(HomeDir, pw->pw_dir);
+ } else
+#endif
+ {
+ /*
+ * Use /tmp; it should be writable.
+ */
+ StrAllocCopy(HomeDir, "/tmp");
+ }
+#endif /* VMS */
+#endif /* DOSPATH */
+ } else {
+ StrAllocCopy(HomeDir, cp);
+ }
+ homedir = (CONST char *)HomeDir;
+ atexit(LYHomeDir_free);
+ }
+ return homedir;
+}
+
+/*
+ * This function checks the acceptability of file paths that
+ * are intended to be off the home directory. The file path
+ * should be passed in fbuffer, together with the size of the
+ * buffer. The function simplifies the file path, and if it
+ * is acceptible, loads it into fbuffer and returns TRUE.
+ * Otherwise, it does not modify fbuffer and returns FALSE.
+ * If a subdirectory is present and the path does not begin
+ * with "./", that is prefixed to make the situation clear. - FM
+ */
+PUBLIC BOOLEAN LYPathOffHomeOK ARGS2(
+ char *, fbuffer,
+ size_t, fbuffer_size)
+{
+ char *file = NULL;
+ char *cp, *cp1;
+
+ /*
+ * Make sure we have an fbuffer and a string in it. - FM
+ */
+ if (!fbuffer || fbuffer_size < 2 || fbuffer[0] == '\0') {
+ return(FALSE);
+ }
+ StrAllocCopy(file, fbuffer);
+ cp = file;
+
+ /*
+ * Check for an inappropriate reference to the
+ * home directory, and correct it if we can. - FM
+ */
+#ifdef VMS
+ if (!strncasecomp(cp, "sys$login", 9)) {
+ if (*(cp + 9) == '\0') {
+ /*
+ * Reject "sys$login". - FM
+ */
+ FREE(file);
+ return(FALSE);
+ }
+ if (*(cp + 9) == ':') {
+ cp += 10;
+ if (*cp == '\0') {
+ /*
+ * Reject "sys$login:". Otherwise, we have
+ * converted "sys$login:file" to "file", or
+ * have left a strange path for VMS as it
+ * was originally. - FM
+ */
+ FREE(file);
+ return(FALSE);
+ }
+ }
+ }
+#endif /* VMS */
+ if (*cp == '~') {
+ if (*(cp + 1) == '/') {
+ if (*(cp + 2) != '\0') {
+ if ((cp1 = strchr((cp + 2), '/')) != NULL) {
+ /*
+ * Convert "~/subdir(s)/file"
+ * to "./subdir(s)/file". - FM
+ */
+ *cp = '.';
+ } else {
+ /*
+ * Convert "~/file" to "file". - FM
+ */
+ cp += 2;
+ }
+ } else {
+ /*
+ * Reject "~/". - FM
+ */
+ FREE(file);
+ return(FALSE);
+ }
+ } else if ((*(cp + 1) != '\0') &&
+ (cp1 = strchr((cp + 1), '/')) != NULL) {
+ cp = (cp1 - 1) ;
+ if (*(cp + 2) != '\0') {
+ if ((cp1 = strchr((cp + 2), '/')) != NULL) {
+ /*
+ * Convert "~user/subdir(s)/file" to
+ * "./subdir(s)/file". If user is someone
+ * else, we covered a spoof. Otherwise,
+ * we simplified. - FM
+ */
+ *cp = '.';
+ } else {
+ /*
+ * Convert "~user/file" to "file". - FM
+ */
+ cp += 2;
+ }
+ } else {
+ /*
+ * Reject "~user/". - FM
+ */
+ FREE(file);
+ return(FALSE);
+ }
+ } else {
+ /*
+ * Reject "~user". - FM
+ */
+ FREE(file);
+ return(FALSE);
+ }
+ }
+
+#ifdef VMS
+ /*
+ * Check for VMS path specs, and reject if still present. - FM
+ */
+ if (strchr(cp, ':') != NULL || strchr(cp, ']') != NULL) {
+ FREE(file);
+ return(FALSE);
+ }
+#endif /* VMS */
+
+ /*
+ * Check for a URL or absolute path, and reject if present. - FM
+ */
+ if (is_url(cp) || *cp == '/') {
+ FREE(file);
+ return(FALSE);
+ }
+
+ /*
+ * Simplify it. - FM
+ */
+ HTSimplify(cp);
+
+ /*
+ * Check if it has a pointless "./". - FM
+ */
+ if (!strncmp(cp, "./", 2)) {
+ if ((cp1 = strchr((cp + 2), '/')) == NULL) {
+ cp += 2;
+ }
+ }
+
+ /*
+ * Check for spoofing. - FM
+ */
+ if (*cp == '\0' || *cp == '/' || cp[(strlen(cp) - 1)] == '/' ||
+ strstr(cp, "..") != NULL || !strcmp(cp, ".")) {
+ FREE(file);
+ return(FALSE);
+ }
+
+ /*
+ * Load what we have at this point into fbuffer,
+ * trimming if too long, and claim it's OK. - FM
+ */
+ if (fbuffer_size > 3 && strncmp(cp, "./", 2) && strchr(cp, '/')) {
+ /*
+ * We have a subdirectory and no lead "./", so
+ * prefix it to make the situation clear. - FM
+ */
+ strcpy(fbuffer, "./");
+ if (strlen(cp) > (fbuffer_size - 3))
+ cp[(fbuffer_size - 3)] = '\0';
+ strcat(fbuffer, cp);
+ } else {
+ if (strlen(cp) > (fbuffer_size - 1))
+ cp[(fbuffer_size - 1)] = '\0';
+ strcpy(fbuffer, cp);
+ }
+ FREE(file);
+ return(TRUE);
+}
+
+/*
+ * This function appends fname to the home path and returns
+ * the full path and filename. The fname string can be just
+ * a filename (e.g., "lynx_bookmarks.html"), or include a
+ * subdirectory off the home directory, in which case fname
+ * should begin with "./" (e.g., ./BM/lynx_bookmarks.html)
+ * Use LYPathOffHomeOK() to check and/or fix up fname before
+ * calling this function. On VMS, the resultant full path
+ * and filename are converted to VMS syntax. - FM
+ */
+PUBLIC void LYAddPathToHome ARGS3(
+ char *, fbuffer,
+ size_t, fbuffer_size,
+ char *, fname)
+{
+ char *home = NULL;
+ char *file = fname;
+ int len;
+
+ /*
+ * Make sure we have a buffer. - FM
+ */
+ if (!fbuffer)
+ return;
+ if (fbuffer_size < 2) {
+ fbuffer[0] = '\0';
+ return;
+ }
+ fbuffer[(fbuffer_size - 1)] = '\0';
+
+ /*
+ * Make sure we have a file name. - FM
+ */
+ if (!file)
+ file = "";
+
+ /*
+ * Set up home string and length. - FM
+ */
+ StrAllocCopy(home, Home_Dir());
+ if (!(home && *home))
+ /*
+ * Home_Dir() has a bug if this ever happens. - FM
+ */
+#ifdef VMS
+ StrAllocCopy(home, "Error:");
+#else
+ StrAllocCopy(home, "/error");
+#endif /* VMS */
+ len = fbuffer_size - (strlen(home) + 1);
+ if (len <= 0) {
+ /*
+ * Buffer is smaller than or only big enough for the home path.
+ * Load what fits of the home path and return. This will fail,
+ * but we need something in the buffer. - FM
+ */
+ LYstrncpy(fbuffer, home, (fbuffer_size - 1));
+ FREE(home);
+ return;
+ }
+
+#ifdef VMS
+ /*
+ * Check whether we have a subdirectory path or just a filename. - FM
+ */
+ if (!strncmp(file, "./", 2)) {
+ /*
+ * We have a subdirectory path. - FM
+ */
+ if (home[strlen(home)-1] == ']') {
+ /*
+ * We got the home directory, so convert it to
+ * SHELL syntax and append subdirectory path,
+ * then convert that to VMS syntax. - FM
+ */
+ char *temp = (char *)calloc(1,
+ (strlen(home) + strlen(file) + 10));
+ sprintf(temp, "%s%s", HTVMS_wwwName(home), (file + 1));
+ sprintf(fbuffer, "%.*s",
+ (fbuffer_size - 1), HTVMS_name("", temp));
+ FREE(temp);
+ } else {
+ /*
+ * This will fail, but we need something in the buffer. - FM
+ */
+ sprintf(fbuffer, "%s%.*s", home, len, file);
+ }
+ } else {
+ /*
+ * We have a file in the home directory. - FM
+ */
+ sprintf(fbuffer, "%s%.*s", home, len, file);
+ }
+#else
+ /*
+ * Check whether we have a subdirectory path or just a filename. - FM
+ */
+ sprintf(fbuffer, "%s/%.*s", home, len,
+ (strncmp(file, "./", 2) ? file : (file + 2)));
+#endif /* VMS */
+ FREE(home);
+}
+
+/*
+ * This function takes a string in the format
+ * "Mon, 01-Jan-96 13:45:35 GMT" or
+ * "Mon, 1 Jan 1996 13:45:35 GMT"" or
+ * "dd-mm-yyyy"
+ * as an argument, and returns its conversion to clock format
+ * (seconds since 00:00:00 Jan 1 1970), or 0 if the string
+ * doesn't match the expected pattern. It also returns 0 if
+ * the time is in the past and the "absolute" argument is FALSE.
+ * It is intended for handling 'expires' strings in Version 0
+ * cookies homologously to 'max-age' strings in Version 1 cookies,
+ * for which 0 is the minimum, and greater values are handled as
+ * '[max-age seconds] + time(NULL)'. If "absolute" if TRUE, we
+ * return the clock format value itself, but if anything goes wrong
+ * when parsing the expected patterns, we still return 0. - FM
+ */
+PUBLIC time_t LYmktime ARGS2(
+ char *, string,
+ BOOL, absolute)
+{
+ char *s;
+ time_t now, clock2;
+ int day, month, year, hour, minutes, seconds;
+ char *start;
+ char temp[8];
+
+ /*
+ * Make sure we have a string to parse. - FM
+ */
+ if (!(string && *string))
+ return(0);
+ s = string;
+ if (TRACE)
+ fprintf(stderr, "LYmktime: Parsing '%s'\n", s);
+
+ /*
+ * Skip any lead alphabetic "Day, " field and
+ * seek a numberic day field. - FM
+ */
+ while (*s != '\0' && !isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ return(0);
+
+ /*
+ * Get the numeric day and convert to an integer. - FM
+ */
+ start = s;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0' || (s - start) > 2)
+ return(0);
+ LYstrncpy(temp, start, (int)(s - start));
+ day = atoi(temp);
+ if (day < 1 || day > 31)
+ return(0);
+
+ /*
+ * Get the month string and convert to an integer. - FM
+ */
+ while (*s != '\0' && !isalnum((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ return(0);
+ start = s;
+ while (*s != '\0' && isalnum((unsigned char)*s))
+ s++;
+ if ((*s == '\0') ||
+ (s - start) < (isdigit((unsigned char)*(s - 1)) ? 2 : 3) ||
+ (s - start) > (isdigit((unsigned char)*(s - 1)) ? 2 : 9))
+ return(0);
+ LYstrncpy(temp, start, (isdigit((unsigned char)*(s - 1)) ? 2 : 3));
+ switch (TOUPPER(temp[0])) {
+ case '0':
+ case '1':
+ month = atoi(temp);
+ if (month < 1 || month > 12) {
+ return(0);
+ }
+ break;
+ case 'A':
+ if (!strcasecomp(temp, "Apr")) {
+ month = 4;
+ } else if (!strcasecomp(temp, "Aug")) {
+ month = 8;
+ } else {
+ return(0);
+ }
+ break;
+ case 'D':
+ if (!strcasecomp(temp, "Dec")) {
+ month = 12;
+ } else {
+ return(0);
+ }
+ break;
+ case 'F':
+ if (!strcasecomp(temp, "Feb")) {
+ month = 2;
+ } else {
+ return(0);
+ }
+ break;
+ case 'J':
+ if (!strcasecomp(temp, "Jan")) {
+ month = 1;
+ } else if (!strcasecomp(temp, "Jun")) {
+ month = 6;
+ } else if (!strcasecomp(temp, "Jul")) {
+ month = 7;
+ } else {
+ return(0);
+ }
+ break;
+ case 'M':
+ if (!strcasecomp(temp, "Mar")) {
+ month = 3;
+ } else if (!strcasecomp(temp, "May")) {
+ month = 5;
+ } else {
+ return(0);
+ }
+ break;
+ case 'N':
+ if (!strcasecomp(temp, "Nov")) {
+ month = 11;
+ } else {
+ return(0);
+ }
+ break;
+ case 'O':
+ if (!strcasecomp(temp, "Oct")) {
+ month = 10;
+ } else {
+ return(0);
+ }
+ break;
+ case 'S':
+ if (!strcasecomp(temp, "Sep")) {
+ month = 9;
+ } else {
+ return(0);
+ }
+ break;
+ default:
+ return(0);
+ }
+
+ /*
+ * Get the numeric year string and convert to an integer. - FM
+ */
+ while (*s != '\0' && !isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ return(0);
+ start = s;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ s++;
+ if ((s - start) == 4) {
+ LYstrncpy(temp, start, 4);
+ } else if ((s - start) == 2) {
+ now = time(NULL);
+ /*
+ * Assume that received 2-digit dates >= 70 are 19xx; others
+ * are 20xx. Only matters when dealing with broken software
+ * (HTTP server or web page) which is not Y2K compliant. The
+ * line is drawn on a best-guess basis; it is impossible for
+ * this to be completely accurate because it depends on what
+ * the broken sender software intends. (This totally breaks
+ * in 2100 -- setting up the next crisis...) - BL
+ */
+ if (atoi(start) >= 70)
+ LYstrncpy(temp, "19", 2);
+ else
+ LYstrncpy(temp, "20", 2);
+ strncat(temp, start, 2);
+ temp[4] = '\0';
+ } else {
+ return(0);
+ }
+ year = atoi(temp);
+
+ /*
+ * Get the numeric hour string and convert to an integer. - FM
+ */
+ while (*s != '\0' && !isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0') {
+ hour = 0;
+ minutes = 0;
+ seconds = 0;
+ } else {
+ start = s;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ s++;
+ if (*s != ':' || (s - start) > 2)
+ return(0);
+ LYstrncpy(temp, start, (int)(s - start));
+ hour = atoi(temp);
+
+ /*
+ * Get the numeric minutes string and convert to an integer. - FM
+ */
+ while (*s != '\0' && !isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ return(0);
+ start = s;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ s++;
+ if (*s != ':' || (s - start) > 2)
+ return(0);
+ LYstrncpy(temp, start, (int)(s - start));
+ minutes = atoi(temp);
+
+ /*
+ * Get the numeric seconds string and convert to an integer. - FM
+ */
+ while (*s != '\0' && !isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0')
+ return(0);
+ start = s;
+ while (*s != '\0' && isdigit((unsigned char)*s))
+ s++;
+ if (*s == '\0' || (s - start) > 2)
+ return(0);
+ LYstrncpy(temp, start, (int)(s - start));
+ seconds = atoi(temp);
+ }
+
+ /*
+ * Convert to clock format (seconds since 00:00:00 Jan 1 1970),
+ * but then zero it if it's in the past and "absolute" is not
+ * TRUE. - FM
+ */
+ month -= 3;
+ if (month < 0) {
+ month += 12;
+ year--;
+ }
+ day += (year - 1968)*1461/4;
+ day += ((((month*153) + 2)/5) - 672);
+ clock2 = (time_t)((day * 60 * 60 * 24) +
+ (hour * 60 * 60) +
+ (minutes * 60) +
+ seconds);
+ if (absolute == FALSE && clock2 <= time(NULL))
+ clock2 = (time_t)0;
+ if (TRACE && clock2 > 0)
+ fprintf(stderr,
+ "LYmktime: clock=%ld, ctime=%s", (long) clock2, ctime(&clock2));
+
+ return(clock2);
+}
+
+#if ! HAVE_PUTENV
+/*
+ * No putenv on the next so we use this code instead!
+ */
+
+/* Copyright (C) 1991 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <errno.h>
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+extern int errno;
+#endif /* STDC_HEADERS */
+
+#if defined(STDC_HEADERS) || defined(USG)
+#include <string.h>
+#ifdef NOTDEFINED
+#define index strchr
+#define bcopy(s, d, n) memcpy((d), (s), (n))
+#endif /* NOTDEFINED */
+#else /* Not (STDC_HEADERS or USG): */
+#include <strings.h>
+#endif /* STDC_HEADERS or USG */
+
+#ifndef NULL
+#define NULL 0
+#endif /* !NULL */
+
+#if !__STDC__
+#define const
+#endif /* !__STDC__ */
+
+extern char **environ;
+
+/*
+ * Put STRING, which is of the form "NAME=VALUE", in the environment.
+ */
+PUBLIC int putenv ARGS1(
+ CONST char *, string)
+{
+ char *name_end = strchr(string, '=');
+ register size_t size;
+ register char **ep;
+
+ if (name_end == NULL)
+ {
+ /* Remove the variable from the environment. */
+ size = strlen (string);
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp (*ep, string, size) && (*ep)[size] == '=')
+ {
+ while (ep[1] != NULL)
+ {
+ ep[0] = ep[1];
+ ++ep;
+ }
+ *ep = NULL;
+ return 0;
+ }
+ }
+
+ size = 0;
+ for (ep = environ; *ep != NULL; ++ep)
+ if (!strncmp (*ep, string, name_end - string) && (*ep)[name_end - string] == '=')
+ break;
+ else
+ ++size;
+
+ if (*ep == NULL)
+ {
+ static char **last_environ = NULL;
+ char **new_environ = (char **) malloc ((size + 2) * sizeof (char *));
+ if (new_environ == NULL)
+ return -1;
+ (void) memcpy((char *)new_environ, (char *)environ, size * sizeof(char *));
+ new_environ[size] = (char *) string;
+ new_environ[size + 1] = NULL;
+ if (last_environ != NULL)
+ free ((char *) last_environ);
+ last_environ = new_environ;
+ environ = new_environ;
+ }
+ else
+ *ep = (char *) string;
+
+ return 0;
+}
+#endif /* !HAVE_PUTENV */
+
+#ifdef NEED_REMOVE
+int remove ARGS1(char *, name)
+{
+ return unlink(name);
+}
+#endif
+
+#ifdef UNIX
+/*
+ * Open a file that we don't want other users to see. For new files, the umask
+ * will suffice; however if the file already exists we'll change permissions
+ * first, before opening it. If the chmod fails because of some reason other
+ * than a non-existent file, there's no point in trying to open it.
+ */
+PRIVATE FILE *OpenHiddenFile ARGS2(char *, name, char *, mode)
+{
+ int save = umask(HIDE_UMASK);
+ FILE *fp = 0;
+ if (chmod(name, HIDE_CHMOD) == 0 || errno == ENOENT)
+ fp = fopen(name, mode);
+ umask(save);
+ return fp;
+}
+#else
+# ifndef VMS
+# define OpenHiddenFile(name, mode) fopen(name, mode)
+# endif
+#endif
+
+PUBLIC FILE *LYNewBinFile ARGS1(char *, name)
+{
+#ifdef VMS
+ FILE *fp = fopen (name, "wb", "mbc=32");
+ chmod(name, HIDE_CHMOD);
+#else
+ FILE *fp = OpenHiddenFile(name, "wb");
+#endif
+ return fp;
+}
+
+PUBLIC FILE *LYNewTxtFile ARGS1(char *, name)
+{
+#ifdef VMS
+ FILE *fp = fopen (name, "w", "shr=get");
+ chmod(name, HIDE_CHMOD);
+#else
+ FILE *fp = OpenHiddenFile(name, "w");
+#endif
+ return fp;
+}
+
+PUBLIC FILE *LYAppendToTxtFile ARGS1(char *, name)
+{
+#ifdef VMS
+ FILE *fp = fopen (name, "a+", "shr=get");
+ chmod(name, HIDE_CHMOD);
+#else
+ FILE *fp = OpenHiddenFile(name, "a+");
+#endif
+ return fp;
+}
+
+#ifdef UNIX
+/*
+ * Restore normal permisions to a copy of a file that we have created
+ * with temp file restricted permissions. The normal umask should
+ * apply for user files. - kw
+ */
+PUBLIC void LYRelaxFilePermissions ARGS1(CONST char *, name)
+{
+ int mode;
+ struct stat stat_buf;
+ if (stat(name, &stat_buf) == 0 &&
+ S_ISREG(stat_buf.st_mode) &&
+ (mode = (stat_buf.st_mode & 0777)) == HIDE_CHMOD) {
+ /*
+ * It looks plausible that this is a file we created with
+ * temp file paranoid permissions (and the umask wasn't even
+ * more restrictive when it was copied). - kw
+ */
+ int save = umask(HIDE_UMASK);
+ mode = ((mode & 0700) | 0066) & ~save;
+ umask(save);
+ chmod(name, mode);
+ }
+}
+#endif
diff --git a/gnu/usr.bin/lynx/src/LYUtils.h b/gnu/usr.bin/lynx/src/LYUtils.h
new file mode 100644
index 00000000000..cfccb4be44f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYUtils.h
@@ -0,0 +1,145 @@
+
+#ifndef LYUTILS_H
+#define LYUTILS_H
+
+#include <stdio.h>
+
+#ifndef HTLIST_H
+#include "HTList.h"
+#endif /* HTLIST_H */
+
+extern void highlight PARAMS((int flag, int cur, char *target));
+extern void free_and_clear PARAMS((char **obj));
+extern void collapse_spaces PARAMS((char *string));
+extern void convert_to_spaces PARAMS((char *string, BOOL condense));
+extern char * strip_trailing_slash PARAMS((char * dirname));
+extern void statusline PARAMS((CONST char *text));
+extern void toggle_novice_line NOPARAMS;
+extern void noviceline PARAMS((int more_flag));
+extern void LYFakeZap PARAMS((BOOL set));
+extern int HTCheckForInterrupt NOPARAMS;
+extern BOOLEAN LYisLocalFile PARAMS((char *filename));
+extern BOOLEAN LYisLocalHost PARAMS((char *filename));
+extern void LYLocalhostAliases_free NOPARAMS;
+extern void LYAddLocalhostAlias PARAMS((char *alias));
+extern BOOLEAN LYisLocalAlias PARAMS((char *filename));
+extern int LYCheckForProxyURL PARAMS((char *filename));
+extern int is_url PARAMS((char *filename));
+extern BOOLEAN LYCanDoHEAD PARAMS((CONST char *address));
+extern void remove_backslashes PARAMS((char *buf));
+extern char *quote_pathname PARAMS((char *pathname));
+extern BOOLEAN inlocaldomain NOPARAMS;
+extern void size_change PARAMS((int sig));
+extern void HTSugFilenames_free NOPARAMS;
+extern void HTAddSugFilename PARAMS((char *fname));
+extern void change_sug_filename PARAMS((char *fname));
+extern void tempname PARAMS((char *namebuffer, int action));
+extern int number2arrows PARAMS((int number));
+extern void parse_restrictions PARAMS((char *s));
+extern void checkmail NOPARAMS;
+extern int LYCheckMail NOPARAMS;
+extern void LYEnsureAbsoluteURL PARAMS((char **href, char *name));
+extern void LYConvertToURL PARAMS((char **AllocatedString));
+extern BOOLEAN LYExpandHostForURL PARAMS((
+ char **AllocatedString, char *prefix_list, char *suffix_list));
+extern BOOLEAN LYAddSchemeForURL PARAMS((
+ char **AllocatedString, char *default_scheme));
+extern void LYTrimRelFromAbsPath PARAMS((char *path));
+extern void LYDoCSI PARAMS((char *url, CONST char *comment, char **csi));
+#ifdef VMS
+extern void Define_VMSLogical PARAMS((
+ char *LogicalName, char *LogicalValue));
+#endif /* VMS */
+extern CONST char *Home_Dir NOPARAMS;
+extern BOOLEAN LYPathOffHomeOK PARAMS((char *fbuffer, size_t fbuffer_size));
+extern void LYAddPathToHome PARAMS((
+ char *fbuffer, size_t fbuffer_size, char *fname));
+extern time_t LYmktime PARAMS((char *string, BOOL absolute));
+#if ! HAVE_PUTENV
+extern int putenv PARAMS((CONST char *string));
+#endif /* HAVE_PUTENV */
+
+FILE *LYNewBinFile PARAMS((char * name));
+FILE *LYNewTxtFile PARAMS((char * name));
+FILE *LYAppendToTxtFile PARAMS((char * name));
+#ifdef UNIX
+extern void LYRelaxFilePermissions PARAMS((CONST char * name));
+#endif
+/*
+ * Whether or not the status line must be shown.
+ */
+extern BOOLEAN mustshow;
+#define _statusline(msg) mustshow = TRUE, statusline(msg)
+
+/*
+ * For is_url().
+ *
+ * Universal document id types.
+ */
+#define HTTP_URL_TYPE 1
+#define FILE_URL_TYPE 2
+#define FTP_URL_TYPE 3
+#define WAIS_URL_TYPE 4
+#define NEWS_URL_TYPE 5
+#define NNTP_URL_TYPE 6
+#define TELNET_URL_TYPE 7
+#define TN3270_URL_TYPE 8
+#define RLOGIN_URL_TYPE 9
+#define GOPHER_URL_TYPE 10
+#define HTML_GOPHER_URL_TYPE 11
+#define TELNET_GOPHER_URL_TYPE 12
+#define INDEX_GOPHER_URL_TYPE 13
+#define MAILTO_URL_TYPE 14
+#define FINGER_URL_TYPE 15
+#define CSO_URL_TYPE 16
+#define HTTPS_URL_TYPE 17
+#define SNEWS_URL_TYPE 18
+#define PROSPERO_URL_TYPE 19
+#define AFS_URL_TYPE 20
+
+#define DATA_URL_TYPE 21
+
+#define LYNXEXEC_URL_TYPE 22
+#define LYNXPROG_URL_TYPE 23
+#define LYNXCGI_URL_TYPE 24
+
+#define NEWSPOST_URL_TYPE 25
+#define NEWSREPLY_URL_TYPE 26
+#define SNEWSPOST_URL_TYPE 27
+#define SNEWSREPLY_URL_TYPE 28
+
+#define LYNXPRINT_URL_TYPE 29
+#define LYNXHIST_URL_TYPE 30
+#define LYNXDOWNLOAD_URL_TYPE 31
+#define LYNXKEYMAP_URL_TYPE 32
+#define LYNXIMGMAP_URL_TYPE 33
+#define LYNXCOOKIE_URL_TYPE 34
+#define LYNXDIRED_URL_TYPE 35
+
+#define PROXY_URL_TYPE 36
+
+#define UNKNOWN_URL_TYPE 37
+
+/*
+ * For change_sug_filename().
+ */
+extern HTList *sug_filenames;
+
+/*
+ * For tempname().
+ */
+#define NEW_FILE 0
+#define REMOVE_FILES 1
+
+/*
+ * Miscellaneous.
+ */
+#define ON 1
+#define OFF 0
+#define STREQ(a,b) (strcmp(a,b) == 0)
+#define STRNEQ(a,b,c) (strncmp(a,b,c) == 0)
+
+#define HIDE_CHMOD 0600
+#define HIDE_UMASK 0077
+
+#endif /* LYUTILS_H */
diff --git a/gnu/usr.bin/lynx/src/LYVMSdef.h b/gnu/usr.bin/lynx/src/LYVMSdef.h
new file mode 100644
index 00000000000..35e3f577e75
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYVMSdef.h
@@ -0,0 +1,18 @@
+
+#ifndef LYVMSDEF_H
+#define LYVMSDEF_H
+
+/*
+** These are VMS system definitions which may not be in the headers
+** of old VMS compilers and contain non-ANSI extended tokens that
+** genterate warnings by some Unix compilers while looking for the
+** "#endif" which closes the outer "#ifdef VMS".
+*/
+#ifndef CLI$M_TRUSTED
+#define CLI$M_TRUSTED 64 /* May not be in the compiler's clidef.h */
+#endif /* !CLI$M_TRUSTED */
+#ifndef LIB$_INVARG
+#define LIB$_INVARG 1409588 /* May not be in the compiler's libdef.h */
+#endif /* !LIB$_INVARG */
+
+#endif /* LYVMSDEF_H */
diff --git a/gnu/usr.bin/lynx/src/LYexit.c b/gnu/usr.bin/lynx/src/LYexit.c
new file mode 100644
index 00000000000..c884bf58657
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYexit.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1994, University of Kansas, All Rights Reserved
+ */
+#include "HTUtils.h"
+#include "tcp.h"
+#include "LYexit.h"
+#ifndef VMS
+#include "LYGlobalDefs.h"
+#include "LYUtils.h"
+#include "LYSignal.h"
+#include "LYClean.h"
+#ifdef SYSLOG_REQUESTED_URLS
+#include <syslog.h>
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * Stack of functions to call upon exit.
+ */
+PRIVATE void (*callstack[ATEXITSIZE]) NOPARAMS;
+PRIVATE int topOfStack = 0;
+
+/*
+ * Flag for outofmem macro. - FM
+ */
+PUBLIC BOOL LYOutOfMemory = FALSE;
+
+/*
+ * Forward declarations.
+ */
+PRIVATE void LYCompleteExit NOPARAMS;
+
+/*
+ * Purpose: Terminates program.
+ * Arguments: status Exit code.
+ * Return Value: void
+ * Remarks/Portability/Dependencies/Restrictions:
+ * Function calls stdlib.h exit
+ * Revision History:
+ * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+PUBLIC void LYexit ARGS1(
+ int, status)
+{
+#ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */
+#ifdef _WINDOWS
+ WSACleanup();
+#endif
+ if (LYOutOfMemory == TRUE) {
+ /*
+ * Ignore further interrupts. - FM
+ */
+#ifndef NOSIGHUP
+ (void) signal(SIGHUP, SIG_IGN);
+#endif /* NOSIGHUP */
+ (void) signal (SIGTERM, SIG_IGN);
+ (void) signal (SIGINT, SIG_IGN);
+#ifndef __linux__
+#ifndef DOSPATH
+ (void) signal(SIGBUS, SIG_IGN);
+#endif /* DOSPATH */
+#endif /* !__linux__ */
+ (void) signal(SIGSEGV, SIG_IGN);
+ (void) signal(SIGILL, SIG_IGN);
+
+ /*
+ * Flush all messages. - FM
+ */
+ fflush(stderr);
+ fflush(stdout);
+
+ /*
+ * Deal with curses, if on, and clean up. - FM
+ */
+ if (LYCursesON) {
+ sleep(AlertSecs);
+ }
+ cleanup_sig(0);
+#ifndef __linux__
+#ifndef DOSPATH
+ signal(SIGBUS, SIG_DFL);
+#endif /* DOSPATH */
+#endif /* !__linux__ */
+ signal(SIGSEGV, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
+ }
+#endif /* !VMS */
+
+ /*
+ * Do functions registered with LYatexit. - GAB
+ */
+ LYCompleteExit();
+
+#ifndef VMS
+#ifdef SYSLOG_REQUESTED_URLS
+ syslog(LOG_INFO, "Session over");
+ closelog();
+#endif /* SYSLOG_REQUESTED_URLS */
+#endif /* !VMS */
+
+#ifdef exit
+/* Make sure we use stdlib exit and not LYexit. - GAB
+*/
+#undef exit
+#endif /* exit */
+
+#ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */
+ fflush(stderr);
+ if (LYOutOfMemory == TRUE) {
+ LYOutOfMemory = FALSE;
+ printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
+ fflush(stdout);
+ }
+ if (LYTraceLogFP != NULL) {
+ fflush(stdout);
+ fflush(stderr);
+ fclose(LYTraceLogFP);
+ LYTraceLogFP = NULL;
+ *stderr = LYOrigStderr;
+ }
+#endif /* !VMS */
+ exit(status);
+}
+
+/*
+ * Purpose: Registers termination function.
+ * Arguments: function The function to register.
+ * Return Value: int 0 registered
+ * !0 no more space to register
+ * Remarks/Portability/Dependencies/Restrictions:
+ * Revision History:
+ * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+#ifdef __STDC__
+PUBLIC int LYatexit(void (*function)(void))
+#else /* Not ANSI, ugh! */
+PUBLIC int LYatexit(function)
+void (*function)();
+#endif /* __STDC__ */
+{
+ /*
+ * Check for available space.
+ */
+ if (topOfStack == ATEXITSIZE) {
+ if (TRACE)
+ fprintf(stderr, "(LY)atexit: Too many functions, ignoring one!\n");
+ return(-1);
+ }
+
+ /*
+ * Register the function.
+ */
+ callstack[topOfStack] = function;
+ topOfStack++;
+ return(0);
+}
+
+/*
+ * Purpose: Call the functions registered with LYatexit
+ * Arguments: void
+ * Return Value: void
+ * Remarks/Portability/Dependencies/Restrictions:
+ * Revision History:
+ * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
+ */
+PRIVATE void LYCompleteExit NOPARAMS
+{
+ /*
+ * Just loop through registered functions.
+ * This is reentrant if more exits occur in the registered functions.
+ */
+ while (--topOfStack >= 0) {
+ callstack[topOfStack]();
+ }
+}
diff --git a/gnu/usr.bin/lynx/src/LYrcFile.c b/gnu/usr.bin/lynx/src/LYrcFile.c
new file mode 100644
index 00000000000..92ec977ed8c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYrcFile.c
@@ -0,0 +1,924 @@
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTFTP.h"
+#include "LYUtils.h"
+#include "LYrcFile.h"
+#include "LYStrings.h"
+#include "LYGlobalDefs.h"
+#include "LYCharSets.h"
+#include "LYBookmark.h"
+
+#include "LYLeaks.h"
+
+PUBLIC void read_rc NOPARAMS
+{
+ char line_buffer[256];
+ char rcfile[256];
+ FILE *fp;
+ char *cp, *cp2;
+ int number_sign;
+ char MBM_line[256];
+ int MBM_counter;
+ char *MBM_cp2, *MBM_cp1;
+ int MBM_i2;
+
+ /*
+ * Make an RC file name.
+ */
+#ifdef DJGPP
+ sprintf(rcfile, "%s/lynx.rc", Home_Dir());
+#else
+#ifdef VMS
+ sprintf(rcfile, "sys$login:.lynxrc");
+#else
+ sprintf(rcfile, "%s/.lynxrc", Home_Dir());
+#endif /* VMS */
+#endif /* DJGPP */
+
+ /*
+ * Open the RC file for reading.
+ */
+ if ((fp = fopen(rcfile, "r")) == NULL) {
+ return;
+ }
+
+ /*
+ * Process the entries.
+ */
+ while (fgets(line_buffer, 256, fp) != NULL) {
+ /*
+ * Remove the /n from the end of the line.
+ */
+ if (line_buffer[0] && line_buffer[strlen(line_buffer)-1] == '\n')
+ line_buffer[strlen(line_buffer)-1] = '\0';
+
+ /*
+ * Remove any trailing white space.
+ */
+ while (line_buffer[0] && isspace(line_buffer[strlen(line_buffer)-1]))
+ line_buffer[strlen(line_buffer)-1] = '\0';
+
+ /*
+ * Skip any comment or blank lines.
+ */
+ if (line_buffer[0] == '\0' || line_buffer[0] == '#')
+ continue;
+
+ /*
+ * Find the line position of the number sign if there is one.
+ */
+ if ((cp = (char *)strchr(line_buffer, '#')) == NULL)
+ number_sign = 999;
+ else
+ number_sign = cp - line_buffer;
+
+ /*
+ * File editor.
+ */
+ if (!system_editor &&
+ (cp = LYstrstr(line_buffer, "file_editor")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ StrAllocCopy(editor, cp);
+
+ /*
+ * Default bookmark file.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "bookmark_file")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp,'=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+
+ /*
+ * Since this is the "Default Bookmark File", we save it
+ * as a globals, and as the first MBM_A_subbookmark entry.
+ */
+ StrAllocCopy(bookmark_page, cp);
+ StrAllocCopy(BookmarkPage, cp);
+ StrAllocCopy(MBM_A_subbookmark[0], cp);
+ StrAllocCopy(MBM_A_subdescript[0], MULTIBOOKMARKS_DEFAULT);
+
+ /*
+ * Multiple (sub)bookmark support settings.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "sub_bookmarks")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = (cp2 + 1);
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "standard", 8)) {
+ LYMultiBookmarks = TRUE;
+ LYMBMAdvanced = FALSE;
+ } else if (!strncasecomp(cp, "advanced", 8)) {
+ LYMultiBookmarks = TRUE;
+ LYMBMAdvanced = TRUE;
+ } else {
+ LYMultiBookmarks = FALSE;
+ }
+
+ /*
+ * Multiple (sub)bookmark definitions and descriptions.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "multi_bookmark")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ /*
+ * Found the root, now cycle through all the
+ * possible spaces and match specific ones.
+ */
+ for (MBM_counter = 1;
+ MBM_counter <= MBM_V_MAXFILES; MBM_counter++) {
+ sprintf(MBM_line, "multi_bookmark%c", (MBM_counter + 'A'));
+
+ if ((cp = LYstrstr(line_buffer, MBM_line)) != NULL &&
+ cp-line_buffer < number_sign) {
+ if ((MBM_cp1 = (char *)strchr(cp, '=')) == NULL) {
+ break;
+ } else {
+ if ((MBM_cp2 = (char *)strchr(cp, ',')) == NULL) {
+ break;
+ } else {
+ MBM_i2 = 0;
+ /*
+ * skip over the '='.
+ */
+ MBM_cp1++;
+ while (MBM_cp1 && MBM_cp1 != MBM_cp2) {
+ /*
+ * Skip spaces.
+ */
+ if (isspace(*MBM_cp1)) {
+ MBM_cp1++;
+ continue;
+ } else {
+ MBM_line[MBM_i2++] = *MBM_cp1++;
+ }
+ }
+ MBM_line[MBM_i2++] = '\0';
+
+ StrAllocCopy(MBM_A_subbookmark[MBM_counter],
+ MBM_line);
+
+ /*
+ * Now get the description ',' and ->.
+ */
+ MBM_cp1 = (char *)strchr(cp, ',');
+
+ MBM_i2 = 0;
+ /*
+ * Skip over the ','.
+ */
+ MBM_cp1++;
+ /*
+ * Eat spaces in front of description.
+ */
+ while (isspace(*MBM_cp1))
+ MBM_cp1++;
+ while (*MBM_cp1)
+ MBM_line[MBM_i2++] = *MBM_cp1++;
+ MBM_line[MBM_i2++] = '\0';
+
+ StrAllocCopy(MBM_A_subdescript[MBM_counter],
+ MBM_line);
+
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * FTP/file sorting method.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "file_sorting_method")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "BY_FILENAME", 11))
+ HTfileSortMethod = FILE_BY_NAME;
+ else if (!strncasecomp(cp, "BY_TYPE", 7))
+ HTfileSortMethod = FILE_BY_TYPE;
+ else if (!strncasecomp(cp, "BY_SIZE", 7))
+ HTfileSortMethod = FILE_BY_SIZE;
+ else if (!strncasecomp(cp, "BY_DATE", 7))
+ HTfileSortMethod = FILE_BY_DATE;
+
+ /*
+ * Personal mail address.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "personal_mail_address")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ StrAllocCopy(personal_mail_address, cp);
+
+ /*
+ * Searching type.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "case_sensitive_searching")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "on", 2))
+ case_sensitive = TRUE;
+ else
+ case_sensitive = FALSE;
+
+ /*
+ * Character set.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "character_set")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ int i = 0;
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ for (; LYchar_set_names[i]; i++) {
+ if (!strncmp(cp, LYchar_set_names[i], strlen(cp))) {
+ current_char_set=i;
+ HTMLSetRawModeDefault(i);
+ break;
+ }
+ }
+
+ /*
+ * Preferred language.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "preferred_language")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ StrAllocCopy(language, cp);
+
+ /*
+ * Preferred charset.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "preferred_charset")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ StrAllocCopy(pref_charset, cp);
+
+ /*
+ * VI keys.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "vi_keys")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char * )strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "on", 2))
+ vi_keys = TRUE;
+ else
+ vi_keys = FALSE;
+
+ /*
+ * EMACS keys.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "emacs_keys")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "on", 2))
+ emacs_keys = TRUE;
+ else
+ emacs_keys=FALSE;
+
+ /*
+ * Show dot files.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "show_dotfiles")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char * )strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "on", 2))
+ show_dotfiles = TRUE;
+ else
+ show_dotfiles = FALSE;
+
+ /*
+ * Show color.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "show_color")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char * )strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "always", 6)) {
+ LYrcShowColor = SHOW_COLOR_ALWAYS;
+#if defined(USE_SLANG) || defined(COLOR_CURSES)
+ if (LYShowColor != SHOW_COLOR_NEVER)
+ LYShowColor = SHOW_COLOR_ALWAYS;
+#endif /* USE_SLANG || COLOR_CURSES */
+ } else if (!strncasecomp(cp, "never", 5)) {
+ LYrcShowColor = SHOW_COLOR_NEVER;
+#if defined(COLOR_CURSES)
+ if (LYShowColor == SHOW_COLOR_ON)
+ LYShowColor = SHOW_COLOR_OFF;
+#endif /* COLOR_CURSES */
+ }
+
+ /*
+ * Select popups.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "select_popups")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char * )strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "off", 3))
+ LYSelectPopups = FALSE;
+ else
+ LYSelectPopups = TRUE;
+
+ /*
+ * Show cursor.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "show_cursor")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char * )strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "off", 3))
+ LYShowCursor = FALSE;
+ else
+ LYShowCursor = TRUE;
+
+ /*
+ * Keypad mode.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "keypad_mode")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (LYstrstr(cp, "LINKS_ARE_NUMBERED"))
+ keypad_mode = LINKS_ARE_NUMBERED;
+ else if (LYstrstr(cp, "LINKS_AND_FORM_FIELDS_ARE_NUMBERED"))
+ keypad_mode = LINKS_AND_FORM_FIELDS_ARE_NUMBERED;
+ else
+ keypad_mode = NUMBERS_AS_ARROWS;
+
+ /*
+ * Linedit mode.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "lineedit_mode")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ int i = 0;
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ for (; LYLineeditNames[i]; i++) {
+ if (!strncmp(cp, LYLineeditNames[i], strlen(cp))) {
+ current_lineedit = i;
+ break;
+ }
+ }
+
+#ifdef DIRED_SUPPORT
+ /*
+ * List directory style.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "dir_list_style")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp,'=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (LYstrstr(cp, "FILES_FIRST") != NULL) {
+ dir_list_style = FILES_FIRST;
+ } else if (LYstrstr(cp,"DIRECTORIES_FIRST") != NULL) {
+ dir_list_style = 0;
+ } else {
+ dir_list_style = MIXED_STYLE;
+ }
+#endif /* DIRED_SUPPORT */
+
+ /*
+ * User mode.
+ */
+ } else if ((cp = LYstrstr(line_buffer, "user_mode")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (LYstrstr(cp, "ADVANCED") != NULL) {
+ user_mode = ADVANCED_MODE;
+ } else if (LYstrstr(cp,"INTERMEDIATE") != NULL) {
+ user_mode = INTERMEDIATE_MODE;
+ } else {
+ user_mode = NOVICE_MODE;
+ }
+
+#ifdef ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ /*
+ * Local execution mode - all links.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "run_all_execution_links")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+
+ if (!strncasecomp(cp, "on", 2))
+ local_exec = TRUE;
+ else
+ local_exec = FALSE;
+
+ /*
+ * Local execution mode - only links in local files.
+ */
+ } else if ((cp = LYstrstr(line_buffer,
+ "run_execution_links_on_local_files")) != NULL &&
+ cp-line_buffer < number_sign) {
+
+ if ((cp2 = (char *)strchr(cp, '=')) != NULL)
+ cp = cp2 + 1;
+ while (isspace(*cp))
+ cp++; /* get rid of spaces */
+ if (!strncasecomp(cp, "on", 2))
+ local_exec_on_local_files = TRUE;
+ else
+ local_exec_on_local_files=FALSE;
+#endif /* ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+
+ } /* end of if */
+
+ } /* end of while */
+
+ fclose(fp);
+} /* big end */
+
+PUBLIC int save_rc NOPARAMS
+{
+ char rcfile[256];
+ FILE *fp;
+ int i;
+ int MBM_c;
+
+ /*
+ * Make a name.
+ */
+#ifdef DJGPP
+ sprintf(rcfile, "%s/lynx.rc", Home_Dir());
+#else
+#ifdef VMS
+ sprintf(rcfile, "sys$login:.lynxrc");
+#else
+ sprintf(rcfile, "%s/.lynxrc", Home_Dir());
+#endif /* VMS */
+#endif /* DJGPP */
+
+ /*
+ * Open the file for write.
+ */
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_TEXT;
+#endif /* __DJGPP__ or _WINDOWS */
+ if ((fp = LYNewTxtFile(rcfile)) == NULL) {
+ return FALSE;
+ }
+
+ /*
+ * Header.
+ */
+ fprintf(fp, "# Lynx User Defaults File\n#\n\
+# This file contains options saved from the Lynx Options Screen (normally\n\
+# with the '>' key). There is normally no need to edit this file manually,\n\
+# since the defaults here can be controlled from the Options Screen, and the\n\
+# next time options are saved from the Options Screen this file will be\n\
+# completely rewritten. You have been warned...\n\
+# If you are looking for the general configuration file - it is normally\n\
+# called lynx.cfg, and it has different content and a different format.\n\
+# It is not this file.\n\n");
+
+ /*
+ * File editor
+ */
+ fprintf(fp, "\
+# file_editor specifies the editor to be invoked when editing local files\n\
+# or sending mail. If no editor is specified, then file editing is disabled\n\
+# unless it is activated from the command line, and the built-in line editor\n\
+# will be used for sending mail.\n");
+ fprintf(fp, "file_editor=%s\n\n", (editor ? editor : ""));
+
+ /*
+ * Default bookmark file.
+ */
+ fprintf(fp, "\
+# bookmark_file specifies the name and location of the default bookmark\n\
+# file into which the user can paste links for easy access at a later\n\
+# date.\n");
+ fprintf(fp, "bookmark_file=%s\n\n", (bookmark_page ? bookmark_page : ""));
+
+ /*
+ * Multiple (sub)bookmark support settings.
+ */
+ fprintf(fp, "\
+# If sub_bookmarks is not turned \"off\", and multiple bookmarks have\n\
+# been defined (see below), then all bookmark operations will first\n\
+# prompt the user to select an active sub-bookmark file. If the default\n\
+# Lynx bookmark_file is defined (see above), it will be used as the\n\
+# default selection. When this option is set to \"advanced\", and the\n\
+# user mode is advanced, the 'v'iew bookmark command will invoke a\n\
+# statusline prompt instead of the menu seen in novice and intermediate\n\
+# user modes. When this option is set to \"standard\", the menu will be\n\
+# presented regardless of user mode.\n");
+ fprintf(fp, "sub_bookmarks=%s\n\n", (LYMultiBookmarks ?
+ (LYMBMAdvanced ?
+ "advanced" : "standard")
+ : "off"));
+
+ /*
+ * Multiple (sub)bookmark definitions and descriptions.
+ */
+ fprintf(fp, "\
+# The following allow you to define sub-bookmark files and descriptions.\n\
+# The format is multi_bookmark<capital_letter>=<filename>,<description>\n\
+# Up to 26 bookmark files (for the English capital letters) are allowed.\n\
+# We start with \"multi_bookmarkB\" since 'A' is the default (see above).\n");
+ for (MBM_c = 1; MBM_c <= MBM_V_MAXFILES; MBM_c++)
+ fprintf(fp, "multi_bookmark%c=%s%s%s\n",
+ (MBM_c + 'A'),
+ (MBM_A_subbookmark[MBM_c] ?
+ MBM_A_subbookmark[MBM_c] : ""),
+ (MBM_A_subbookmark[MBM_c] ?
+ "," : ""),
+ (MBM_A_subdescript[MBM_c] ?
+ MBM_A_subdescript[MBM_c] : ""));
+ fprintf(fp, "\n");
+
+ /*
+ * FTP/file sorting method.
+ */
+ fprintf(fp, "\
+# The file_sorting_method specifies which value to sort on when viewing\n\
+# file lists such as FTP directories. The options are:\n\
+# BY_FILENAME -- sorts on the name of the file\n\
+# BY_TYPE -- sorts on the type of the file\n\
+# BY_SIZE -- sorts on the size of the file\n\
+# BY_DATE -- sorts on the date of the file\n");
+ fprintf(fp, "file_sorting_method=%s\n\n",
+ (HTfileSortMethod == FILE_BY_NAME ? "BY_FILENAME"
+ :
+ (HTfileSortMethod == FILE_BY_SIZE ? "BY_SIZE"
+ :
+ (HTfileSortMethod == FILE_BY_TYPE ? "BY_TYPE"
+ : "BY_DATE"))));
+
+ /*
+ * Personal mail address.
+ */
+ fprintf(fp, "\
+# personal_mail_address specifies your personal mail address. The\n\
+# address will be sent during HTTP file transfers for authorization and\n\
+# logging purposes, and for mailed comments.\n\
+# If you do not want this information given out, set the NO_FROM_HEADER\n\
+# to TRUE in lynx.cfg, or use the -nofrom command line switch. You also\n\
+# could leave this field blank, but then you won't have it included in\n\
+# your mailed comments.\n");
+ fprintf(fp, "personal_mail_address=%s\n\n",
+ (personal_mail_address ? personal_mail_address : ""));
+
+ /*
+ * Searching type.
+ */
+ fprintf(fp, "\
+# If case_sensitive_searching is \"on\" then when the user invokes a search\n\
+# using the 's' or '/' keys, the search performed will be case sensitive\n\
+# instead of case INsensitive. The default is usually \"off\".\n");
+ fprintf(fp, "case_sensitive_searching=%s\n\n",
+ (case_sensitive ? "on" : "off"));
+
+ /*
+ * Character set.
+ */
+ fprintf(fp, "\
+# The character_set definition controls the representation of 8 bit\n\
+# characters for your terminal. If 8 bit characters do not show up\n\
+# correctly on your screen you may try changing to a different 8 bit\n\
+# set or using the 7 bit character approximations.\n\
+# Current valid characters sets are:\n");
+ for (i = 0; LYchar_set_names[i]; i++)
+ fprintf(fp, "# %s\n", LYchar_set_names[i]);
+ fprintf(fp, "character_set=%s\n\n", LYchar_set_names[current_char_set]);
+
+
+ /*
+ * Preferred language.
+ */
+ fprintf(fp, "\
+# preferred_language specifies the language in MIME notation (e.g., en,\n\
+# fr, may be a comma-separated list in decreasing preference)\n\
+# which Lynx will indicate you prefer in requests to http servers.\n\
+# If a file in that language is available, the server will send it.\n\
+# Otherwise, the server will send the file in it's default language.\n");
+ fprintf(fp, "preferred_language=%s\n\n", (language ? language : ""));
+
+ /*
+ * Preferred charset.
+ */
+ fprintf(fp, "\
+# preferred_charset specifies the character set in MIME notation (e.g.,\n\
+# ISO-8859-2, ISO-8859-5) which Lynx will indicate you prefer in requests\n\
+# to http servers using an Accept-Charset header. The value should NOT\n\
+# include ISO-8859-1 or US-ASCII, since those values are always assumed\n\
+# by default. May be a comma-separated list.\n\
+# If a file in that character set is available, the server will send it.\n\
+# If no Accept-Charset header is present, the default is that any\n\
+# character set is acceptable. If an Accept-Charset header is present,\n\
+# and if the server cannot send a response which is acceptable\n\
+# according to the Accept-Charset header, then the server SHOULD send\n\
+# an error response, though the sending of an unacceptable response\n\
+# is also allowed.\n");
+ fprintf(fp, "preferred_charset=%s\n\n",
+ (pref_charset ? pref_charset : ""));
+
+ /*
+ * Show color.
+ */
+ if (LYChosenShowColor != SHOW_COLOR_UNKNOWN) {
+ fprintf(fp, "\
+# show_color specifies how to set the color mode at startup. A value of\n\
+# \"never\" will force color mode off (treat the terminal as monochrome)\n\
+# at startup even if the terminal appears to be color capable. A value of\n\
+# \"always\" will force color mode on even if the terminal appears to be\n\
+# monochrome, if this is supported by the library used to build lynx.\n\
+# A value of \"default\" will yield the behavior of assuming\n\
+# a monochrome terminal unless color capability is inferred at startup\n\
+# based on the terminal type, or the -color command line switch is used, or\n\
+# the COLORTERM environment variable is set. The default behavior always is\n\
+# used in anonymous accounts or if the \"option_save\" restriction is set.\n\
+# The effect of the saved value can be overridden via\n\
+# the -color and -nocolor command line switches.\n\
+# The mode set at startup can be changed via the \"show color\" option in\n\
+# the 'o'ptions menu. If the option settings are saved, the \"on\" and\n\
+# \"off\" \"show color\" settings will be treated as \"default\".\n");
+ fprintf(fp, "show_color=%s\n\n",
+ ((LYChosenShowColor == SHOW_COLOR_NEVER ? "never" :
+ (LYChosenShowColor == SHOW_COLOR_ALWAYS ? "always" :
+ "default"))));
+ }
+
+ /*
+ * VI keys.
+ */
+ fprintf(fp, "\
+# If vi_keys is set to \"on\", then the normal VI movement keys:\n\
+# j = down k = up\n\
+# h = left l = right\n\
+# will be enabled. These keys are only lower case.\n\
+# Capital 'H', 'J' and 'K will still activate help, jump shortcuts,\n\
+# and the keymap display, respectively.\n");
+ fprintf(fp, "vi_keys=%s\n\n", (vi_keys ? "on" : "off"));
+
+ /*
+ * EMACS keys.
+ */
+ fprintf(fp, "\
+# If emacs_keys is to \"on\" then the normal EMACS movement keys:\n\
+# ^N = down ^P = up\n\
+# ^B = left ^F = right\n\
+# will be enabled.\n");
+ fprintf(fp, "emacs_keys=%s\n\n", (emacs_keys ? "on" : "off"));
+
+ /*
+ * Show dot files.
+ */
+ fprintf(fp, "\
+# show_dotfiles specifies that the directory listing should include\n\
+# \"hidden\" (dot) files/directories. If set \"on\", this will be\n\
+# honored only if enabled via userdefs.h and/or lynx.cfg, and not\n\
+# restricted via a command line switch. If display of hidden files\n\
+# is disabled, creation of such files via Lynx also is disabled.\n");
+ fprintf(fp, "show_dotfiles=%s\n\n", (show_dotfiles ? "on" : "off"));
+
+ /*
+ * Select popups.
+ */
+ fprintf(fp, "\
+# select_popups specifies whether the OPTIONs in a SELECT block which\n\
+# lacks a MULTIPLE attribute are presented as a vertical list of radio\n\
+# buttons or via a popup menu. Note that if the MULTIPLE attribute is\n\
+# present in the SELECT start tag, Lynx always will create a vertical list\n\
+# of checkboxes for the OPTIONs. A value of \"on\" will set popup menus\n\
+# as the default while a value of \"off\" will set use of radio boxes.\n\
+# The default can be overridden via the -popup command line toggle.\n");
+ fprintf(fp, "select_popups=%s\n\n", (LYSelectPopups ? "on" : "off"));
+
+ /*
+ * Show cursor.
+ */
+ fprintf(fp, "\
+# show_cursor specifies whether to 'hide' the cursor to the right (and\n\
+# bottom, if possible) of the screen, or to place it to the left of the\n\
+# current link in documents, or current option in select popup windows.\n\
+# Positioning the cursor to the left of the current link or option is\n\
+# helpful for speech or braille interfaces, and when the terminal is\n\
+# one which does not distingish the current link based on highlighting\n\
+# or color. A value of \"on\" will set positioning to the left as the\n\
+# default while a value of \"off\" will set 'hiding' of the cursor.\n\
+# The default can be overridden via the -show_cursor command line toggle.\n");
+ fprintf(fp, "show_cursor=%s\n\n", (LYShowCursor ? "on" : "off"));
+
+ /*
+ * Keypad mode.
+ */
+ fprintf(fp, "\
+# If keypad_mode is set to \"NUMBERS_AS_ARROWS\", then the numbers on\n\
+# your keypad when the numlock is on will act as arrow keys:\n\
+# 8 = Up Arrow\n\
+# 4 = Left Arrow 6 = Right Arrow\n\
+# 2 = Down Arrow\n\
+# and the corresponding keyboard numbers will act as arrow keys,\n\
+# regardless of whether numlock is on.\n");
+ fprintf(fp, "\
+# If keypad_mode is set to \"LINKS_ARE_NUMBERED\", then numbers will\n\
+# appear next to each link and numbers are used to select links.\n");
+ fprintf(fp, "\
+# If keypad_mode is set to \"LINKS_AND_FORM_FIELDS_ARE_NUMBERED\", then\n\
+# numbers will appear next to each link and visible form input field.\n\
+# Numbers are used to select links, or to move the \"current link\" to a\n\
+# form input field or button. In addition, options in popup menus are\n\
+# indexed so that the user may type an option number to select an option in\n\
+# a popup menu, even if the option isn't visible on the screen. Reference\n\
+# lists and output from the list command also enumerate form inputs.\n");
+ fprintf(fp, "\
+# NOTE: Some fixed format documents may look disfigured when\n\
+# \"LINKS_ARE_NUMBERED\" or \"LINKS_AND_FORM_FIELDS_ARE_NUMBERED\" are\n\
+# enabled.\n");
+ fprintf(fp, "keypad_mode=%s\n\n",
+ ((keypad_mode == NUMBERS_AS_ARROWS) ? "NUMBERS_AS_ARROWS" :
+ ((keypad_mode == LINKS_ARE_NUMBERED) ? "LINKS_ARE_NUMBERED" :
+ "LINKS_AND_FORM_FIELDS_ARE_NUMBERED")));
+
+ /*
+ * Lineedit mode.
+ */
+ fprintf(fp, "\
+# linedit_mode specifies the key binding used for inputting strings in\n\
+# prompts and forms. If lineedit_mode is set to \"Default Binding\" then\n\
+# the following control characters are used for moving and deleting:\n\
+#\n\
+# Prev Next Enter = Accept input\n\
+# Move char: <- -> ^G = Cancel input\n\
+# Move word: ^P ^N ^U = Erase line\n\
+# Delete char: ^H ^R ^A = Beginning of line\n\
+# Delete word: ^B ^F ^E = End of line\n\
+#\n\
+# Current lineedit modes are:\n");
+ {
+ char **bindings = LYLineeditNames;
+ while (*bindings) {
+ fprintf(fp, "# %s\n", *bindings);
+ bindings++;
+ }
+ }
+ fprintf(fp, "lineedit_mode=%s\n\n", LYLineeditNames[current_lineedit]);
+
+#ifdef DIRED_SUPPORT
+ /*
+ * List directory style.
+ */
+ fprintf(fp, "\
+# dir_list_styles specifies the directory list style under DIRED_SUPPORT\n\
+# (if implemented). The default is \"MIXED_STYLE\", which sorts both\n\
+# files and directories together. \"FILES_FIRST\" lists files first and\n\
+# \"DIRECTORIES_FIRST\" lists directories first.\n");
+ fprintf(fp, "dir_list_style=%s\n\n",
+ (dir_list_style==FILES_FIRST ? "FILES_FIRST"
+ :
+ (dir_list_style==MIXED_STYLE ? "MIXED_STYLE"
+ : "DIRECTORIES_FIRST")));
+#endif /* DIRED_SUPPORT */
+
+ /*
+ * User mode.
+ */
+ fprintf(fp, "\
+# user_mode specifies the users level of knowledge with Lynx. The\n\
+# default is \"NOVICE\" which displays two extra lines of help at the\n\
+# bottom of the screen to aid the user in learning the basic Lynx\n\
+# commands. Set user_mode to \"INTERMEDIATE\" to turn off the extra info.\n\
+# Use \"ADVANCED\" to see the URL of the currently selected link at the\n\
+# bottom of the screen.\n");
+ fprintf(fp, "user_mode=%s\n\n",
+ (user_mode == NOVICE_MODE ? "NOVICE" :
+ (user_mode == ADVANCED_MODE ?
+ "ADVANCED" : "INTERMEDIATE")));
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+ /*
+ * Local execution mode - all links.
+ */
+ fprintf(fp, "\
+# If run_all_execution_links is set \"on\" then all local exection links\n\
+# will be executed when they are selected.\n\
+#\n\
+# WARNING - This is potentially VERY dangerous. Since you may view\n\
+# information that is written by unknown and untrusted sources\n\
+# there exists the possibility that Trojan horse links could be\n\
+# written. Trojan horse links could be written to erase files\n\
+# or compromise security. This should only be set to \"on\" if\n\
+# you are viewing trusted source information.\n");
+ fprintf(fp, "run_all_execution_links=%s\n\n",
+ (local_exec ? "on" : "off"));
+
+ /*
+ * Local execution mode - only links in local files.
+ */
+ fprintf(fp, "\
+# If run_execution_links_on_local_files is set \"on\" then all local\n\
+# execution links that are found in LOCAL files will be executed when they\n\
+# are selected. This is different from run_all_execution_links in that\n\
+# only files that reside on the local system will have execution link\n\
+# permissions.\n\
+#\n\
+# WARNING - This is potentially dangerous. Since you may view\n\
+# information that is written by unknown and untrusted sources\n\
+# there exists the possibility that Trojan horse links could be\n\
+# written. Trojan horse links could be written to erase files\n\
+# or compromise security. This should only be set to \"on\" if\n\
+# you are viewing trusted source information.\n");
+ fprintf(fp, "run_execution_links_on_local_files=%s\n\n",
+ (local_exec_on_local_files ? "on" : "off"));
+#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */
+
+ /*
+ * Close the RC file.
+ */
+ fclose(fp);
+#if defined(__DJGPP__) || defined(_WINDOWS)
+ _fmode = O_BINARY;
+#endif /* __DJGPP__ or _WINDOWS */
+
+#ifdef VMS
+ /*
+ * Get rid of any copies of the .lynxrc file that VMS creates.
+ */
+ while (remove("sys$login:.lynxrc;-1") == 0) ;
+ /*
+ * Reset version number.
+ */
+ rename("sys$login:.lynxrc", "sys$login:.lynxrc;1");
+#endif /* VMS */
+
+ return TRUE;
+}
diff --git a/gnu/usr.bin/lynx/src/LYrcFile.h b/gnu/usr.bin/lynx/src/LYrcFile.h
new file mode 100644
index 00000000000..fedc927a7d6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/LYrcFile.h
@@ -0,0 +1,13 @@
+
+#ifndef LYRCFILE_H
+#define LYRCFILE_H
+
+#ifndef LYSTRUCTS_H
+#include "LYStructs.h"
+#endif /* LYSTRUCTS_H */
+
+extern void read_rc NOPARAMS;
+extern int save_rc NOPARAMS;
+
+#endif /* LYRCFILE_H */
+
diff --git a/gnu/usr.bin/lynx/src/UCAuto.c b/gnu/usr.bin/lynx/src/UCAuto.c
new file mode 100644
index 00000000000..e0c95f4d7b6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/UCAuto.c
@@ -0,0 +1,362 @@
+/*
+** This file contains code for changing the Linux console mode.
+** Currently some names for font files are hardwired in here.
+** You have to change this code if it needs accomodation for your
+** system (or get the required files...).
+**
+** Depending on the Display Character Set switched to, and the previous
+** one as far as it is known, system("setfont ...") and/or output of
+** escape sequences to switch console mode are done. Curses will be
+** temporarily suspended while that happens.
+**
+** NOTE that the setfont calls will also affect all other virtual consoles.
+**
+** Any ideas how to do this for other systems?
+*/
+
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "UCAuto.h"
+#include "LYGlobalDefs.h"
+#include "LYClean.h"
+#include "LYUtils.h"
+
+#ifdef EXP_CHARTRANS_AUTOSWITCH
+
+#ifdef VMS
+#define DISPLAY "DECW$DISPLAY"
+#else
+#define DISPLAY "DISPLAY"
+#endif /* VMS */
+
+#ifdef LINUX
+typedef enum {
+ Is_Unset, Is_Set, Dunno, Dont_Care
+} TGen_state_t;
+typedef enum {
+ G0, G1
+} TGNstate_t;
+typedef enum {
+ GN_Blat1, GN_0decgraf, GN_Ucp437, GN_Kuser, GN_dunno, GN_dontCare
+} TTransT_t;
+
+static char T_font_fn[100] = "\0";
+static char T_umap_fn[100] = "\0";
+static char T_setfont_cmd[200] = "\0";
+#define SETFONT "setfont"
+#define NOOUTPUT "2>/dev/null >/dev/null"
+
+PRIVATE void call_setfont ARGS3(
+ char *, font,
+ char *, fnsuffix,
+ char *, umap)
+{
+ if (font && *font && umap && *umap &&
+ !strcmp(font, T_font_fn) && !strcmp(umap, T_umap_fn)) {
+ /*
+ * No need to repeat.
+ */
+ return;
+ }
+ if (font)
+ strcpy(T_font_fn, font);
+ if (umap)
+ strcpy(T_umap_fn, umap);
+
+ if (!*fnsuffix)
+ fnsuffix = "";
+
+ if (umap &&*umap && font && *font) {
+ sprintf(T_setfont_cmd, "%s %s%s -u %s %s",
+ SETFONT, font, fnsuffix, umap, NOOUTPUT);
+ } else if (font && *font) {
+ sprintf(T_setfont_cmd, "%s %s%s %s",
+ SETFONT, font, fnsuffix, NOOUTPUT);
+ } else if (umap && *umap) {
+ sprintf(T_setfont_cmd, "%s -u %s %s",
+ SETFONT, umap, NOOUTPUT);
+ } else {
+ *T_setfont_cmd = '\0';
+ }
+
+ if (*T_setfont_cmd) {
+ if (TRACE) {
+ fprintf(stderr, "Executing setfont: '%s'\n", T_setfont_cmd);
+ }
+ system(T_setfont_cmd);
+ }
+}
+
+PRIVATE void write_esc ARGS1(
+ CONST char *, p)
+{
+ int fd = open("/dev/tty", O_WRONLY);
+
+ if (fd >= 0) {
+ write(fd, p, strlen(p));
+ close(fd);
+ }
+}
+
+PRIVATE int nonempty_file ARGS1(
+ CONST char *, p)
+{
+ struct stat sb;
+
+ return (stat(p, &sb) == 0 &&
+ (sb.st_mode & S_IFMT) == S_IFREG &&
+ (sb.st_size != 0));
+}
+
+/*
+ * This is the thing that actually gets called from display_page().
+ */
+PUBLIC void UCChangeTerminalCodepage ARGS2(
+ int, newcs,
+ LYUCcharset *, p)
+{
+ static int lastcs = -1;
+ static CONST char * lastname = NULL;
+ static TTransT_t lastTransT = GN_dunno;
+ static TGen_state_t lastUtf = Dunno;
+ static TGen_state_t lastHasUmap = Dunno;
+
+ static char *old_font;
+ static char *old_umap;
+
+ CONST char * name;
+ TTransT_t TransT = GN_dunno;
+ TGen_state_t Utf = Dunno;
+ TGen_state_t HasUmap = Dunno;
+
+ char tmpbuf1[100], tmpbuf2[20];
+ char *cp;
+
+ /*
+ * Restore the original character set.
+ */
+ if (newcs < 0 || p == 0) {
+ if (old_font && *old_font &&
+ old_umap && *old_umap) {
+ int have_font = nonempty_file(old_font);
+ int have_umap = nonempty_file(old_umap);
+
+ if (have_font) {
+ if (have_umap) {
+ sprintf(tmpbuf1, "%s %s -u %s %s",
+ SETFONT, old_font, old_umap, NOOUTPUT);
+ } else {
+ sprintf(tmpbuf1, "%s %s %s",
+ SETFONT, old_font, NOOUTPUT);
+ }
+ system(tmpbuf1);
+ }
+
+ remove(old_font);
+ free(old_font);
+ old_font = 0;
+
+ remove(old_umap);
+ free(old_umap);
+ old_umap = 0;
+ }
+ return;
+ } else if (lastcs < 0 && old_umap == 0 && old_font == 0) {
+ old_umap = tempnam((char *)0, "umap");
+ old_font = tempnam((char *)0, "font");
+ sprintf(tmpbuf1, "%s -o %s -ou %s %s",
+ SETFONT, old_font, old_umap, NOOUTPUT);
+ system(tmpbuf1);
+ }
+
+ name = p->MIMEname;
+
+ /*
+ * Font sizes are currently hardwired here.
+ */
+#define SUFF1 ".f16"
+#define SUFF2 "-16.psf"
+#define SUFF3 "-8x16"
+#define SUFF4 "8x16"
+
+ /*
+ * Use this for output of escape sequences.
+ */
+ if ((display != NULL) ||
+ ((cp = getenv(DISPLAY)) != NULL && *cp != '\0')) {
+ /*
+ * We won't do anything in an xterm. Better that way...
+ */
+ return;
+ }
+
+ if (!strcmp(name, "iso-8859-10")) {
+ call_setfont("iso10", SUFF1, "iso10.uni");
+ TransT = GN_Kuser;
+ HasUmap = Is_Set;
+ Utf = Is_Unset;
+ } else if (!strncmp(name, "iso-8859-1", 10)) {
+ if ((lastHasUmap == Is_Set) && !strcmp(lastname, "cp850")) {
+ /*
+ * cp850 already contains all latin1 characters.
+ */
+ if (lastTransT != GN_Blat1) {
+ TransT = GN_Blat1;
+ }
+ } else {
+ /*
+ * "setfont lat1u-16.psf -u lat1u.uni"
+ */
+ call_setfont("lat1u", SUFF2, "lat1u.uni");
+ HasUmap = Is_Set;
+ if (lastTransT != GN_Blat1) {
+ TransT = GN_Blat1;
+ }
+ }
+ Utf = Is_Unset;
+ } else if (!strcmp(name, "iso-8859-2")) {
+#ifdef NOTDEFINED
+ /*
+ * "setfont lat2-16.psf -u lat2.uni"
+ */
+ call_setfont("lat2", SUFF2, "lat2.uni"); */
+#endif /* NOTDEFINED */
+ /*
+ * "setfont iso02.f16 -u iso02.uni"
+ */
+ call_setfont("iso02", SUFF1, "iso02.uni");
+ TransT = GN_Kuser;
+ HasUmap = Is_Set;
+ Utf = Is_Unset;
+ } else if (!strncmp(name, "iso-8859-", 9)) {
+ sprintf(tmpbuf1, "iso0%s", &name[9]);
+ sprintf(tmpbuf2, "iso0%s%s", &name[9],".uni");
+ /*
+ * "setfont iso0N.f16 -u iso0N.uni"
+ */
+ call_setfont(tmpbuf1, SUFF1, tmpbuf2);
+ TransT = GN_Kuser;
+ HasUmap = Is_Set;
+ Utf = Is_Unset;
+ } else if (!strcmp(name, "koi8-r")) {
+ /*
+ * "setfont koi8-8x16"
+ */
+ call_setfont("koi8", SUFF3, NULL);
+ TransT = GN_Kuser;
+ HasUmap = Is_Unset;
+ Utf = Is_Unset;
+ } else if (!strcmp(name, "cp437")) {
+ /*
+ * "setfont default8x16 -u cp437.uni"
+ */
+ call_setfont("default", SUFF4, "cp437.uni");
+ if (TransT == GN_Kuser || TransT == GN_Ucp437)
+ TransT = GN_dontCare;
+ else
+ TransT = GN_Ucp437;
+ HasUmap = Is_Set;
+ Utf = Is_Unset;
+ } else if (!strcmp(name, "cp850")) {
+ /*
+ * "setfont cp850-8x16 -u cp850.uni"
+ */
+ call_setfont("cp850", SUFF3, "cp850.uni");
+ TransT = GN_Kuser;
+ HasUmap = Is_Set;
+ Utf = Is_Unset;
+ } else if (!strcmp(name, "x-transparent")) {
+ Utf = Dont_Care;
+ } else if (!strcmp(name, "us-ascii")) {
+ Utf = Dont_Care;
+ } else if (!strncmp(name, "mnem", 4)) {
+ Utf = Dont_Care;
+ }
+
+ if (TransT != lastTransT) {
+ if (TransT == GN_Blat1) {
+ /*
+ * Switch Linux console to lat1 table.
+ */
+ write_esc("\033(B");
+ } else if (TransT == GN_0decgraf) {
+ write_esc("\033(0");
+ } else if (TransT == GN_Ucp437) {
+ /*
+ * Switch Linux console to 437 table?
+ */
+ write_esc("\033(U");
+ } else if (TransT == GN_Kuser) {
+ /*
+ * Switch Linux console to user table.
+ */
+ write_esc("\033(K");
+ }
+ if (TransT != GN_dunno && TransT != GN_dontCare) {
+ lastTransT = TransT;
+ } else {
+ TransT = lastTransT;
+ }
+ }
+
+ if (HasUmap != Dont_Care && HasUmap != Dunno)
+ lastHasUmap = HasUmap;
+
+ if (p->enc == UCT_ENC_UTF8) {
+ if (lastUtf != Is_Set) {
+ Utf = Is_Set;
+ /*
+ * Turn Linux console UTF8 mode ON.
+ */
+ write_esc("\033%G");
+ lastUtf = Utf;
+ }
+ return;
+ } else if (lastUtf == Is_Set && Utf != Dont_Care) {
+ Utf = Is_Unset;
+ /*
+ * Turn Linux console UTF8 mode OFF.
+ */
+ write_esc("\033%@");
+ lastUtf = Utf;
+ }
+
+ if (Utf != Dont_Care && Utf != Dunno)
+ lastUtf = Utf;
+
+ lastcs = newcs;
+ lastname = name;
+}
+
+#else /* Not LINUX: */
+/*
+ * This is the thing that actually gets called from display_page().
+ */
+PUBLIC void UCChangeTerminalCodepage ARGS2(
+ int, newcs,
+ LYUCcharset *, p)
+{
+ if (TRACE) {
+ fprintf(stderr,
+ "UCChangeTerminalCodepage: Called, but not implemented!");
+ }
+}
+#endif /* LINUX */
+
+#else /* EXP_CHARTRANS_AUTOSWITCH not defined: */
+/*
+ * This is the thing that actually gets called from display_page().
+ */
+PUBLIC void UCChangeTerminalCodepage ARGS2(
+ int, newcs GCC_UNUSED,
+ LYUCcharset *, p GCC_UNUSED)
+{
+ if (TRACE) {
+ fprintf(stderr,
+ "UCChangeTerminalCodepage: Called, but not implemented!");
+ }
+}
+#endif /* EXP_CHARTRANS_AUTOSWITCH */
diff --git a/gnu/usr.bin/lynx/src/UCAuto.h b/gnu/usr.bin/lynx/src/UCAuto.h
new file mode 100644
index 00000000000..b4d582c343d
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/UCAuto.h
@@ -0,0 +1,7 @@
+
+#ifndef UCAUTO_H
+#define UCAUTO_H
+
+extern void UCChangeTerminalCodepage PARAMS((int newcs, LYUCcharset *p));
+
+#endif /* UCAUTO_H */
diff --git a/gnu/usr.bin/lynx/src/UCAux.c b/gnu/usr.bin/lynx/src/UCAux.c
new file mode 100644
index 00000000000..13685036435
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/UCAux.c
@@ -0,0 +1,451 @@
+#include "HTUtils.h"
+#include "tcp.h"
+
+#include "HTCJK.h"
+#include "UCDefs.h"
+#include "HTStream.h"
+#include "UCAux.h"
+
+extern HTCJKlang HTCJK;
+extern LYUCcharset LYCharSet_UC[];
+
+PUBLIC BOOL UCCanUniTranslateFrom ARGS1(
+ int, from)
+{
+ if (from < 0)
+ return NO;
+ if (LYCharSet_UC[from].enc == UCT_ENC_7BIT ||
+ LYCharSet_UC[from].enc == UCT_ENC_UTF8)
+ return YES;
+ if (LYCharSet_UC[from].codepoints & (UCT_CP_SUBSETOF_LAT1))
+ return YES;
+ return (LYCharSet_UC[from].UChndl >= 0);
+}
+
+PUBLIC BOOL UCCanTranslateUniTo ARGS1(
+ int, to)
+{
+ if (to < 0)
+ return NO;
+ return YES; /* well at least some characters... */
+}
+
+PUBLIC BOOL UCCanTranslateFromTo ARGS2(
+ int, from,
+ int, to)
+{
+ if (from == to)
+ return YES;
+ if (from < 0 || to < 0)
+ return NO;
+ if (from == 0)
+ return UCCanTranslateUniTo(to);
+ if (to == 0 || LYCharSet_UC[to].enc == UCT_ENC_UTF8)
+ return UCCanUniTranslateFrom(from);
+ {
+ CONST char * fromname = LYCharSet_UC[from].MIMEname;
+ CONST char * toname = LYCharSet_UC[to].MIMEname;
+ if (!strcmp(fromname, "x-transparent") ||
+ !strcmp(toname, "x-transparent")) {
+ return YES;
+ } else if (!strcmp(fromname, "us-ascii")) {
+ return YES;
+ }
+ if (LYCharSet_UC[from].enc == UCT_ENC_CJK) {
+ /*
+ ** CJK mode may be off (i.e., HTCJK == NOCJK) because
+ ** the current document is not CJK, but the check may
+ ** be for capability in relation to another document,
+ ** for which CJK mode might be turned on when retrieved.
+ ** Thus, when the from charset is CJK, check if the to
+ ** charset is CJK, and return NO or YES in relation to
+ ** that. - FM
+ */
+ if (LYCharSet_UC[to].enc != UCT_ENC_CJK)
+ return NO;
+ if ((!strcmp(toname, "euc-jp") ||
+ !strcmp(toname, "shift_jis")) &&
+ (!strcmp(fromname, "euc-jp") ||
+ !strcmp(fromname, "shift_jis")))
+ return YES;
+ /*
+ ** The euc-cn and euc-kr charsets were handled
+ ** by the (from == to) above, so we need not
+ ** check those. - FM
+ **/
+ return NO;
+ }
+ }
+ return (LYCharSet_UC[from].UChndl >= 0);
+}
+
+/*
+** Returns YES if no translation necessary (because
+** charsets are equal, are equivalent, etc.).
+*/
+PUBLIC BOOL UCNeedNotTranslate ARGS2(
+ int, from,
+ int, to)
+{
+ CONST char *fromname;
+ CONST char *toname;
+ if (from == to)
+ return YES;
+ if (from < 0)
+ return NO; /* ??? */
+ if (LYCharSet_UC[from].enc == UCT_ENC_7BIT) {
+ return YES; /* Only 7bit chars. */
+ }
+ fromname = LYCharSet_UC[from].MIMEname;
+ if (!strcmp(fromname, "x-transparent") ||
+ !strcmp(fromname, "us-ascii")) {
+ return YES;
+ }
+ if (to < 0)
+ return NO; /* ??? */
+ if (to == 0) {
+ if (LYCharSet_UC[from].codepoints & (UCT_CP_SUBSETOF_LAT1))
+ return YES;
+ }
+ toname = LYCharSet_UC[to].MIMEname;
+ if (!strcmp(toname, "x-transparent")) {
+ return YES;
+ }
+ if (LYCharSet_UC[to].enc == UCT_ENC_UTF8) {
+ return NO;
+ }
+ if (from == 0) {
+ if (LYCharSet_UC[from].codepoints & (UCT_CP_SUPERSETOF_LAT1))
+ return YES;
+ }
+ if (LYCharSet_UC[from].enc == UCT_ENC_CJK) {
+ if (HTCJK == NOCJK) /* Use that global flag, for now. */
+ return NO;
+ if (HTCJK == JAPANESE &&
+ /*
+ ** Always strip the "x-" from "x-euc-jp",
+ ** or convert "x-shift-jis" to "shift_jis",
+ ** before calling this function, and so
+ ** don't check for them here. - FM
+ */
+ (!strcmp(fromname, "euc-jp") ||
+ !strncmp(fromname, "iso-2022-jp",11) ||
+ !strcmp(fromname, "shift_jis")))
+ return YES; /* ??? */
+ return NO; /* If not handled by (from == to) above. */
+ }
+ return NO;
+}
+
+/*
+** The idea here is that any stage of the stream pipe which is interested
+** in some charset dependent processing will call this function.
+** Given input and output charsets, this function will set various flags
+** in a UCTransParams structure that _suggest_ to the caller what to do.
+**
+** Should be called once when a stage starts processing text (and the
+** input and output charsets are known), or whenever one of input or
+** output charsets has changed (e.g. by SGML.c stage after HTML.c stage
+** has processed a META tag).
+** The global flags (LYRawMode, HTPassEightBitRaw etc.) are currently
+** not taken into account here (except for HTCJK, somewhat), it's still
+** up to the caller to do something about them. - KW
+*/
+PUBLIC void UCSetTransParams ARGS5(
+ UCTransParams *, pT,
+ int, cs_in,
+ CONST LYUCcharset*, p_in,
+ int, cs_out,
+ CONST LYUCcharset*, p_out)
+{
+ /*
+ ** Initialize this element to FALSE, and set it TRUE
+ ** below if we're dealing with VISCII. - FM
+ */
+ pT->trans_C0_to_uni = FALSE;
+
+ /*
+ ** The "transparent" display character set is a
+ ** "super raw mode". - FM
+ */
+ pT->transp = (!strcmp(p_in->MIMEname, "x-transparent") ||
+ !strcmp(p_out->MIMEname, "x-transparent"));
+
+ if (pT->transp) {
+ /*
+ ** Set up the structure for "transparent". - FM
+ */
+ pT->do_cjk = FALSE;
+ pT->decode_utf8 = FALSE;
+ pT->output_utf8 = FALSE; /* We may, but won't know about it. - KW */
+ pT->do_8bitraw = TRUE;
+ pT->use_raw_char_in = TRUE;
+ pT->strip_raw_char_in = FALSE;
+ pT->pass_160_173_raw = TRUE;
+ pT->repl_translated_C0 = (p_out->enc == UCT_ENC_8BIT_C0);
+ pT->trans_C0_to_uni = (p_in->enc == UCT_ENC_8BIT_C0 ||
+ p_out->enc == UCT_ENC_8BIT_C0);
+ } else {
+ /*
+ ** Initialize local flags. - FM
+ */
+ BOOL intm_ucs = FALSE;
+ BOOL use_ucs = FALSE;
+ /*
+ ** Set this element if we want to treat
+ ** the input as CJK. - FM
+ */
+ pT->do_cjk = ((p_in->enc == UCT_ENC_CJK) && (HTCJK != NOCJK));
+ /*
+ ** Set these elements based on whether
+ ** we are dealing with UTF-8. - FM
+ */
+ pT->decode_utf8 = (p_in->enc == UCT_ENC_UTF8);
+ pT->output_utf8 = (p_out->enc == UCT_ENC_UTF8);
+ if (pT->do_cjk) {
+ /*
+ ** Set up the structure for a CJK input with
+ ** a CJK output (HTCJK != NOCJK). - FM
+ */
+ intm_ucs = FALSE;
+ pT->trans_to_uni = FALSE;
+ use_ucs = FALSE;
+ pT->do_8bitraw = FALSE;
+ pT->pass_160_173_raw = TRUE;
+ pT->use_raw_char_in = FALSE; /* Not used for CJK. - KW */
+ pT->repl_translated_C0 = FALSE;
+ pT->trans_from_uni = FALSE; /* Not used for CJK. - KW */
+ } else {
+ /*
+ ** Set up for all other charset combinations.
+ ** The intm_ucs flag is set TRUE if the input
+ ** charset is iso-8859-1 or UTF-8, or largely
+ ** equivalent to them, i.e. if we have UCS without
+ ** having to do a table translation.
+ */
+ intm_ucs = (cs_in == 0 || pT->decode_utf8 ||
+ (p_in->codepoints &
+ (UCT_CP_SUBSETOF_LAT1|UCT_CP_SUBSETOF_UCS2)));
+ /*
+ ** pT->trans_to_uni is set TRUE if we do not have that as
+ ** input already, and we can translate to Unicode. Note
+ ** that UTF-8 always is converted to Unicode in functions
+ ** that use the transformation structure, so it is
+ ** treated as already Unicode here.
+ */
+ pT->trans_to_uni = (!intm_ucs &&
+ UCCanUniTranslateFrom(cs_in));
+ /*
+ ** We set this if we are translating to Unicode and
+ ** what normally are low value control characters in
+ ** fact are encoding octets for the input charset
+ ** (presently, this applies to VISCII). - FM
+ */
+ pT->trans_C0_to_uni = (pT->trans_to_uni &&
+ p_in->enc == UCT_ENC_8BIT_C0);
+ /*
+ ** We set this, presently, for VISCII. - FM
+ */
+ pT->repl_translated_C0 = (p_out->enc == UCT_ENC_8BIT_C0);
+ /*
+ ** Currently unused for any charset combination.
+ ** Should always be FALSE
+ */
+ pT->strip_raw_char_in = FALSE;
+ /*
+ ** use_ucs should be set TRUE if we have or will create
+ ** Unicode values for input octets or UTF multibytes. - FM
+ */
+ use_ucs = (intm_ucs || pT->trans_to_uni);
+ /*
+ ** This is set TRUE if use_ucs was set FALSE. It is
+ ** complementary to the HTPassEightBitRaw flag, which
+ ** is set TRUE or FALSE elsewhere based on the raw mode
+ ** setting in relation to the current Display Character
+ ** Set. - FM
+ */
+ pT->do_8bitraw = (!use_ucs);
+ /*
+ ** This is set TRUE when 160 and 173 should not be
+ ** treated as nbsp and shy, respectively. - FM
+ */
+ pT->pass_160_173_raw = (!use_ucs &&
+ !(p_in->like8859 & UCT_R_8859SPECL));
+ /*
+ ** This is set when the input and output charsets match,
+ ** and they are not ones which should go through a Unicode
+ ** translation process anyway. - FM
+ */
+ pT->use_raw_char_in = (!pT->output_utf8 &&
+ cs_in == cs_out &&
+ !pT->trans_C0_to_uni);
+ /*
+ ** This should be set TRUE when we expect to have
+ ** done translation to Unicode or had the equivalent
+ ** as input, can translate it to our output charset,
+ ** and normally want to do so. The latter depends on
+ ** the pT->do_8bitraw and pT->use_raw_char_in values set
+ ** above, but also on HTPassEightBitRaw in any functions
+ ** which use the transformation structure.. - FM
+ */
+ pT->trans_from_uni = (use_ucs && !pT->do_8bitraw &&
+ !pT->use_raw_char_in &&
+ UCCanTranslateUniTo(cs_out));
+ }
+ }
+}
+
+/*
+** This function initializes the transformation
+** structure by setting all its elements to
+** FALSE. - KW
+*/
+PUBLIC void UCTransParams_clear ARGS1(
+ UCTransParams *, pT)
+{
+ pT->transp = FALSE;
+ pT->do_cjk = FALSE;
+ pT->decode_utf8 = FALSE;
+ pT->output_utf8 = FALSE;
+ pT->do_8bitraw = FALSE;
+ pT->use_raw_char_in = FALSE;
+ pT->strip_raw_char_in = FALSE;
+ pT->pass_160_173_raw = FALSE;
+ pT->trans_to_uni = FALSE;
+ pT->trans_C0_to_uni = FALSE;
+ pT->repl_translated_C0 = FALSE;
+ pT->trans_from_uni = FALSE;
+}
+
+/*
+** If terminal is in UTF-8 mode, it probably cannot understand
+** box drawing chars as (n)curses handles them. (This may also
+** be true for other display character sets, but isn't currently
+** checked.) In that case set the chars for hori and vert drawing
+** chars to displayable ASCII chars if '0' was requested. They'll
+** stay as they are otherwise. - kw
+*/
+PUBLIC void UCSetBoxChars ARGS5(
+ int, cset,
+ int *, pvert_out,
+ int *, phori_out,
+ int, vert_in,
+ int, hori_in)
+{
+ if (cset >= -1 && LYCharSet_UC[cset].enc == UCT_ENC_UTF8) {
+ *pvert_out = (vert_in ? vert_in : '|');
+ *phori_out = (hori_in ? hori_in : '-');
+ } else {
+ *pvert_out = vert_in;
+ *phori_out = hori_in;
+ }
+}
+
+/*
+** Given an output target HTStream* (can also be a HTStructured* via
+** typecast), the target stream's put_character method, and a Unicode
+** character, CPutUtf8_charstring() will either output the UTF8
+** encoding of the Unicode and return YES, or do nothing and return
+** NO (if conversion would be unnecessary or the Unicode character is
+** considered invalid).
+**
+** [Could be used more generally, but is currently only used for &#nnnnn
+** stuff - generation of UTF8 from 8-bit encoded charsets not yet done
+** by SGML.c etc.]
+*/
+#define PUTC(ch) ((*myPutc)(target, (char)(ch)))
+#define PUTC2(ch) ((*myPutc)(target,(char)(0x80|(0x3f &(ch)))))
+
+PUBLIC BOOL UCPutUtf8_charstring ARGS3(
+ HTStream *, target,
+ putc_func_t *, myPutc,
+ long, code)
+{
+ if (code < 128)
+ return NO; /* indicate to caller we didn't handle it */
+ else if (code < 0x800L) {
+ PUTC(0xc0 | (code>>6));
+ PUTC2(code);
+ } else if (code < 0x10000L) {
+ PUTC(0xe0 | (code>>12));
+ PUTC2(code>>6);
+ PUTC2(code);
+ } else if (code < 0x200000L) {
+ PUTC(0xf0 | (code>>18));
+ PUTC2(code>>12);
+ PUTC2(code>>6);
+ PUTC2(code);
+ } else if (code < 0x4000000L) {
+ PUTC(0xf8 | (code>>24));
+ PUTC2(code>>18);
+ PUTC2(code>>12);
+ PUTC2(code>>6);
+ PUTC2(code);
+ } else if (code <= 0x7fffffffL) {
+ PUTC(0xfc | (code>>30));
+ PUTC2(code>>24);
+ PUTC2(code>>18);
+ PUTC2(code>>12);
+ PUTC2(code>>6);
+ PUTC2(code);
+ } else
+ return NO;
+ return YES;
+}
+
+/*
+** This function converts a Unicode (UCode_t) value
+** to a multibyte UTF-8 character, which is loaded
+** into the buffer received as an argument. The
+** buffer should be large enough to hold at least
+** seven characters (but should be declared as 8
+** to minimize byte alignment problems with some
+** compilers). - FM
+*/
+PUBLIC BOOL UCConvertUniToUtf8 ARGS2(
+ UCode_t, code,
+ char *, buffer)
+{
+ char *ch = buffer;
+
+ if (!ch)
+ return NO;
+
+ if (code <= 0 || code > 0x7fffffffL) {
+ *ch = '\0';
+ return NO;
+ }
+
+ if (code < 0x800L) {
+ *ch++ = (char)(0xc0 | (code>>6));
+ *ch++ = (char)(0x80 | (0x3f & (code)));
+ *ch = '\0';
+ } else if (code < 0x10000L) {
+ *ch++ = (char)(0xe0 | (code>>12));
+ *ch++ = (char)(0x80 | (0x3f & (code>>6)));
+ *ch++ = (char)(0x80 | (0x3f & (code)));
+ *ch = '\0';
+ } else if (code < 0x200000L) {
+ *ch++ = (char)(0xf0 | (code>>18));
+ *ch++ = (char)(0x80 | (0x3f & (code>>12)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>6)));
+ *ch++ = (char)(0x80 | (0x3f & (code)));
+ *ch = '\0';
+ } else if (code < 0x4000000L) {
+ *ch++ = (char)(0xf8 | (code>>24));
+ *ch++ = (char)(0x80 | (0x3f & (code>>18)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>12)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>6)));
+ *ch++ = (char)(0x80 | (0x3f & (code)));
+ *ch = '\0';
+ } else {
+ *ch++ = (char)(0xfc | (code>>30));
+ *ch++ = (char)(0x80 | (0x3f & (code>>24)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>18)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>12)));
+ *ch++ = (char)(0x80 | (0x3f & (code>>6)));
+ *ch++ = (char)(0x80 | (0x3f & (code)));
+ *ch = '\0';
+ }
+ return YES;
+}
diff --git a/gnu/usr.bin/lynx/src/UCdomap.c b/gnu/usr.bin/lynx/src/UCdomap.c
new file mode 100644
index 00000000000..c5b3cd834ee
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/UCdomap.c
@@ -0,0 +1,2068 @@
+/*
+ * UCdomap.c
+ * =========
+ *
+ * Derived from code in the Linux kernel console driver.
+ * The GNU Public Licence therefore applies, see
+ * the file COPYING in the top-level directory
+ * which should come with every Lynx distribution.
+ *
+ * [ original comment: - KW ]
+ *
+ * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
+ * to font positions.
+ *
+ * aeb, 950210
+ */
+#include "HTUtils.h"
+#include "tcp.h"
+#include "HTMLDTD.h"
+
+#include "LYGlobalDefs.h"
+#include "UCkd.h"
+#include "UCdomap.h"
+#include "UCMap.h"
+#include "UCDefs.h"
+#include "LYCharSets.h"
+
+/*
+ * Include tables & parameters.
+ */
+#include "cp1250_uni.h" /* WinLatin2 (cp1250) */
+#include "cp1251_uni.h" /* WinCyrillic (cp1251) */
+#include "cp1252_uni.h" /* WinLatin1 (cp1252) */
+#include "cp1253_uni.h" /* WinGreek (cp1253) */
+#include "cp1255_uni.h" /* WinHebrew (cp1255) */
+#include "cp1256_uni.h" /* WinArabic (cp1256) */
+#include "cp1257_uni.h" /* WinBaltRim (cp1257) */
+#include "cp437_uni.h" /* DosLatinUS (cp437) */
+#include "cp737_uni.h" /* DosGreek (cp737) */
+#include "cp775_uni.h" /* DosBaltRim (cp775) */
+#include "cp850_uni.h" /* DosLatin1 (cp850) */
+#include "cp852_uni.h" /* DosLatin2 (cp852) */
+#include "cp862_uni.h" /* DosHebrew (cp862) */
+#include "cp864_uni.h" /* DosArabic (cp864) */
+#include "cp866_uni.h" /* DosCyrillic (cp866) */
+#include "cp869_uni.h" /* DosGreek2 (cp869) */
+#include "def7_uni.h" /* 7 bit approximations */
+#include "dmcs_uni.h" /* DEC Multinational */
+#include "iso01_uni.h" /* ISO Latin 1 */
+#include "iso02_uni.h" /* ISO Latin 2 */
+#include "iso03_uni.h" /* ISO Latin 3 */
+#include "iso04_uni.h" /* ISO Latin 4 */
+#include "iso05_uni.h" /* ISO 8859-5 Cyrillic */
+#include "iso06_uni.h" /* ISO 8859-6 Arabic */
+#include "iso07_uni.h" /* ISO 8859-7 Greek */
+#include "iso08_uni.h" /* ISO 8859-8 Hebrew */
+#include "iso09_uni.h" /* ISO 8859-9 (Latin 5) */
+#include "iso10_uni.h" /* ISO 8859-10 */
+#include "koi8r_uni.h" /* KOI8-R Cyrillic */
+#include "mac_uni.h" /* Macintosh (8 bit) */
+#include "mnem2_suni.h" /* RFC 1345 Mnemonic */
+#include "next_uni.h" /* NeXT character set */
+#include "rfc_suni.h" /* RFC 1345 w/o Intro */
+#include "utf8_uni.h" /* UNICODE UTF 8 */
+#include "viscii_uni.h" /* Vietnamese (VISCII) */
+#ifdef NOTDEFINED
+#include "mnem_suni.h"
+#endif /* NOTDEFINED */
+
+#define FREE(x) if (x) {free(x); x = NULL;}
+
+/*
+ * Some of the code below, and some of the comments, are left in for
+ * historical reasons. Not all those tables below are currently
+ * really needed (and what with all those hardwired codepoints),
+ * but let's keep them around for now. They may come in handy if we
+ * decide to make more extended use of the mechanisms (including e.g.
+ * for chars < 127...). - KW
+ */
+
+PRIVATE u16 translations[][256] = {
+ /*
+ * 8-bit Latin-1 mapped to Unicode -- trivial mapping.
+ */
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+ },
+ /*
+ * VT100 graphics mapped to Unicode.
+ */
+ {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
+ 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
+ 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
+ 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
+ 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0xf800,
+ 0xf801, 0x2500, 0xf803, 0xf804, 0x251c, 0x2524, 0x2534, 0x252c,
+ 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
+ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
+ 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
+ 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
+ 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
+ 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
+ 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
+ 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+ 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
+ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
+ 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
+ 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
+ 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
+ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
+ 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
+ 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
+ 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
+ },
+ /*
+ * IBM Codepage 437 mapped to Unicode.
+ */
+ {
+ 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
+ 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
+ 0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
+ 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
+ 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
+ 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
+ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+ 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
+ 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+ 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
+ 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
+ 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
+ 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+ 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
+ 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
+ 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+ 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
+ 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+ 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
+ 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
+ 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
+ },
+ /*
+ * User mapping -- default to codes for direct font mapping.
+ */
+ {
+ 0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
+ 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
+ 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
+ 0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
+ 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
+ 0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
+ 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
+ 0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
+ 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
+ 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
+ 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
+ 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
+ 0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
+ 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
+ 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
+ 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
+ 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
+ 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
+ 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
+ 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
+ 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
+ 0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
+ 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
+ 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
+ 0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
+ 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
+ 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
+ 0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
+ 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
+ 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
+ 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
+ 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
+ }
+};
+PRIVATE u16 *UC_translate = NULL;
+
+PRIVATE struct UC_charset UCInfo[MAXCHARSETS];
+
+/*
+ * The standard kernel character-to-font mappings are not invertible
+ * -- this is just a best effort.
+ */
+#define MAX_GLYPH 512 /* Max possible glyph value */
+
+PRIVATE unsigned char * inv_translate = NULL;
+PRIVATE unsigned char inv_norm_transl[MAX_GLYPH];
+PRIVATE unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
+
+PRIVATE void set_inverse_transl PARAMS((
+ int i));
+PRIVATE u16 *set_translate PARAMS((
+ int m));
+#ifdef NOTDEFINED
+PRIVATE unsigned char inverse_translate PARAMS((int glyph));
+PRIVATE int con_set_trans_old PARAMS((unsigned char *arg));
+PRIVATE int con_get_trans_old PARAMS((unsigned char *arg));
+PRIVATE int con_set_trans_new PARAMS((u16 *arg));
+PRIVATE int con_get_trans_new PARAMS((u16 *arg));
+#endif /* NOTDEFINED */
+PRIVATE int UC_valid_UC_charset PARAMS((
+ int UC_charset_hndl));
+PRIVATE void UC_con_set_trans PARAMS((
+ int UC_charset_in_hndl,
+ int Gn,
+ int update_flag));
+PRIVATE int con_insert_unipair PARAMS((
+ u16 unicode,
+ u16 fontpos,
+ int fordefault));
+PRIVATE int con_insert_unipair_str PARAMS((
+ u16 unicode,
+ char * replace_str,
+ int fordefault));
+PRIVATE void con_clear_unimap PARAMS((
+ int fordefault));
+PRIVATE void con_clear_unimap_str PARAMS((
+ int fordefault));
+#ifdef NOTDEFINED
+PRIVATE int con_set_unimap PARAMS((
+ u16 ct,
+ struct unipair * list));
+#endif /* NOTDEFINED */
+PRIVATE void con_set_default_unimap NOPARAMS;
+PRIVATE int UC_con_set_unimap PARAMS((
+ int UC_charset_out_hndl,
+ int update_flag));
+PRIVATE int UC_con_set_unimap_str PARAMS((
+ u16 ct,
+ struct unipair_str * list,
+ int fordefault));
+#ifdef NOTDEFINED
+PRIVATE int con_get_unimap PARAMS((
+ u16 ct,
+ u16 * uct,
+ struct unipair * list));
+#endif /* NOTDEFINED */
+PRIVATE int conv_uni_to_pc PARAMS((
+ long ucs,
+ int usedefault));
+PRIVATE int conv_uni_to_str PARAMS((
+ char* outbuf,
+ int buflen,
+ long ucs,
+ int usedefault));
+PRIVATE void UCconsole_map_init NOPARAMS;
+PRIVATE int UC_MapGN PARAMS((
+ int UChndl,
+ int update_flag));
+PRIVATE int UC_FindGN_byMIME PARAMS((
+ CONST char * UC_MIMEcharset));
+PRIVATE void UCreset_allocated_LYCharSets NOPARAMS;
+PRIVATE void UCfree_allocated_LYCharSets NOPARAMS;
+PRIVATE char ** UC_setup_LYCharSets_repl PARAMS((
+ int UC_charset_in_hndl,
+ unsigned lowest8));
+PRIVATE int UC_Register_with_LYCharSets PARAMS((
+ int s,
+ CONST char * UC_MIMEcharset,
+ CONST char * UC_LYNXcharset,
+ int lowest_eightbit));
+PRIVATE void UCcleanup_mem NOPARAMS;
+
+PRIVATE int default_UChndl = -1;
+
+PRIVATE void set_inverse_transl ARGS1(
+ int, i)
+{
+ int j, glyph;
+ u16 *p = translations[i];
+ unsigned char *q = inverse_translations[i];
+
+ if (!q) {
+ /*
+ * Slightly messy to avoid calling kmalloc too early.
+ */
+ q = inverse_translations[i] = ((i == LAT1_MAP) ?
+ inv_norm_transl :
+ (unsigned char *)malloc(MAX_GLYPH));
+ if (!q)
+ return;
+ }
+ for (j = 0; j < MAX_GLYPH; j++)
+ q[j] = 0;
+
+ for (j = 0; j < E_TABSZ; j++) {
+ glyph = conv_uni_to_pc(p[j], 0);
+ if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
+ /*
+ * Prefer '-' above SHY etc.
+ */
+ q[glyph] = j;
+ }
+ }
+}
+
+PRIVATE u16 *set_translate ARGS1(
+ int, m)
+{
+ if (!inverse_translations[m])
+ set_inverse_transl(m);
+ inv_translate = inverse_translations[m];
+ return translations[m];
+}
+
+#ifdef NOTDEFINED
+/*
+ * Inverse translation is impossible for several reasons:
+ * 1. The font<->character maps are not 1-1.
+ * 2. The text may have been written while a different translation map
+ * was active, or using Unicode.
+ * Still, it is now possible to a certain extent to cut and paste non-ASCII.
+ */
+PRIVATE unsigned char inverse_translate ARGS1(
+ int, glyph)
+{
+ if (glyph < 0 || glyph >= MAX_GLYPH) {
+ return 0;
+ } else {
+ return ((inv_translate && inv_translate[glyph]) ?
+ inv_translate[glyph] :
+ (unsigned char)(glyph & 0xff));
+ }
+}
+
+/*
+ * Load customizable translation table.
+ * 'arg' points to a 256 byte translation table.
+ *
+ * The "old" variants are for translation directly to font (using the
+ * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
+ * Unicodes explicitly.
+ */
+PRIVATE int con_set_trans_old ARGS1(
+ unsigned char *, arg)
+{
+ int i;
+ u16 *p = translations[USER_MAP];
+#if(0)
+ i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
+ if (i)
+ return i;
+#endif
+ for (i = 0; i < E_TABSZ; i++)
+ p[i] = UNI_DIRECT_BASE | (u16)arg[i];
+
+ set_inverse_transl(USER_MAP);
+ return 0;
+}
+
+PRIVATE int con_get_trans_old ARGS1(
+ unsigned char *, arg)
+{
+ int i, ch;
+ u16 *p = translations[USER_MAP];
+#if(0)
+ i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
+ if (i)
+ return i;
+#endif
+ for (i = 0; i < E_TABSZ; i++) {
+ ch = conv_uni_to_pc(p[i]);
+#ifdef NOTDEFINED
+ put_user((ch & ~0xff) ? 0 : ch, arg+i);
+#endif /* NOTDEFINED */
+ arg[i] = (unsigned char)((ch & ~0xff) ? 0 : ch);
+ }
+ return 0;
+}
+
+PRIVATE int con_set_trans_new ARGS1(
+ u16 *, arg)
+{
+ int i;
+ u16 *p = translations[USER_MAP];
+#if(0)
+ i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ*sizeof(u16));
+ if (i)
+ return i;
+#endif
+ for (i = 0; i < E_TABSZ; i++)
+ p[i] = arg[i];
+
+ set_inverse_transl(USER_MAP);
+ return 0;
+}
+
+PRIVATE int con_get_trans_new ARGS1(
+ u16 * arg)
+{
+ int i;
+ u16 *p = translations[USER_MAP];
+#if(0)
+ i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ*sizeof(u16));
+ if (i)
+ return i;
+#endif
+ for (i = 0; i < E_TABSZ; i++)
+ arg[i] = p[i];
+
+ return 0;
+}
+#endif /* NOTDEFINED */
+
+PRIVATE int UC_valid_UC_charset ARGS1(
+ int, UC_charset_hndl)
+{
+ return (UC_charset_hndl >= 0 && UC_charset_hndl < UCNumCharsets);
+}
+
+PRIVATE void UC_con_set_trans ARGS3(
+ int, UC_charset_in_hndl,
+ int, Gn,
+ int, update_flag)
+{
+ int i, j;
+ u16 *p;
+ u16 *ptrans;
+
+ if (!UC_valid_UC_charset(UC_charset_in_hndl)) {
+ if (TRACE)
+ fprintf(stderr, "UC_con_set_trans: Invalid charset handle %d.\n",
+ UC_charset_in_hndl);
+ return;
+ }
+ ptrans = translations[Gn];
+ p = UCInfo[UC_charset_in_hndl].unitable;
+#if(0)
+ if (p == UC_current_unitable) { /* test whether pointers are equal */
+ return; /* nothing to be done */
+ }
+ /*
+ * The font is always 256 characters - so far.
+ */
+ con_clear_unimap();
+#endif
+ for (i = 0; i < 256; i++) {
+ if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
+ ptrans[i] = *p;
+ for (; j; j--) {
+ p++;
+ }
+ } else {
+ ptrans[i] = 0xfffd;
+ }
+ }
+ if (update_flag) {
+ set_inverse_transl(Gn); /* Update inverse translation for this one */
+ }
+}
+
+/*
+ * Unicode -> current font conversion
+ *
+ * A font has at most 512 chars, usually 256.
+ * But one font position may represent several Unicode chars.
+ * A hashtable is somewhat of a pain to deal with, so use a
+ * "paged table" instead. Simulation has shown the memory cost of
+ * this 3-level paged table scheme to be comparable to a hash table.
+ */
+PRIVATE int hashtable_contents_valid = 0; /* Use ASCII-only mode for bootup*/
+PRIVATE int hashtable_str_contents_valid = 0;
+
+PRIVATE u16 **uni_pagedir[32] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+PRIVATE char* **uni_pagedir_str[32] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+PRIVATE u16 * UC_current_unitable = NULL;
+PRIVATE struct unimapdesc_str *UC_current_unitable_str = NULL;
+
+/*
+ * Keep a second set of structures for the translation designated
+ * as "default" - kw
+ */
+PRIVATE int unidefault_contents_valid = 0; /* Use ASCII-only mode for bootup*/
+PRIVATE int unidefault_str_contents_valid = 0;
+
+static u16 **unidefault_pagedir[32] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+static char* **unidefault_pagedir_str[32] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+PRIVATE u16 * UC_default_unitable = NULL;
+PRIVATE struct unimapdesc_str *UC_default_unitable_str = NULL;
+
+PRIVATE int con_insert_unipair ARGS3(
+ u16, unicode,
+ u16, fontpos,
+ int, fordefault)
+{
+ int i, n;
+ u16 **p1, *p2;
+
+ if(fordefault)
+ p1 = unidefault_pagedir[n = unicode >> 11];
+ else
+ p1 = uni_pagedir[n = unicode >> 11];
+ if (!p1) {
+ p1 = (u16* *)malloc(32*sizeof(u16 *));
+ if (fordefault)
+ unidefault_pagedir[n] = p1;
+ else
+ uni_pagedir[n] = p1;
+ if ( !p1 )
+ return -ENOMEM;
+
+ for (i = 0; i < 32; i++) {
+ p1[i] = NULL;
+ }
+ }
+
+ if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
+ p2 = p1[n] = (u16 *)malloc(64*sizeof(u16));
+ if (!p2)
+ return -ENOMEM;
+
+ for (i = 0; i < 64; i++) {
+ p2[i] = 0xffff; /* No glyph for this character (yet) */
+ }
+ }
+
+ p2[unicode & 0x3f] = fontpos;
+
+ return 0;
+}
+
+PRIVATE int con_insert_unipair_str ARGS3(
+ u16, unicode,
+ char *, replace_str,
+ int, fordefault)
+{
+ int i, n;
+ char ***p1, **p2;
+
+ if(fordefault)
+ p1 = unidefault_pagedir_str[n = unicode >> 11];
+ else
+ p1 = uni_pagedir_str[n = unicode >> 11];
+ if (!p1) {
+ p1 = (char** *)malloc(32*sizeof(char **));
+ if (fordefault)
+ unidefault_pagedir_str[n] = p1;
+ else
+ uni_pagedir_str[n] = p1;
+ if ( !p1 )
+ return -ENOMEM;
+
+ for (i = 0; i < 32; i++) {
+ p1[i] = NULL;
+ }
+ }
+
+ if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
+ p2 = p1[n] = (char* *)malloc(64*sizeof(char *));
+ if (!p2)
+ return -ENOMEM;
+
+ for (i = 0; i < 64; i++) {
+ p2[i] = NULL; /* No replace string this character (yet) */
+ }
+ }
+
+ p2[unicode & 0x3f] = replace_str;
+
+ return 0;
+}
+
+/*
+ * ui arg was a leftover, deleted. - KW
+ */
+PRIVATE void con_clear_unimap ARGS1(
+ int, fordefault)
+{
+ int i, j;
+ u16 **p1;
+
+ if (fordefault) {
+ for (i = 0; i < 32; i++) {
+ if ((p1 = unidefault_pagedir[i]) != NULL) {
+ for (j = 0; j < 32; j++) {
+ FREE(p1[j]);
+ }
+ FREE(p1);
+ }
+ unidefault_pagedir[i] = NULL;
+ }
+
+ unidefault_contents_valid = 1;
+ } else {
+ for (i = 0; i < 32; i++) {
+ if ((p1 = uni_pagedir[i]) != NULL) {
+ for (j = 0; j < 32; j++) {
+ FREE(p1[j]);
+ }
+ FREE(p1);
+ }
+ uni_pagedir[i] = NULL;
+ }
+
+ hashtable_contents_valid = 1;
+ }
+}
+
+PRIVATE void con_clear_unimap_str ARGS1(int, fordefault)
+{
+ int i, j;
+ char ***p1;
+
+ if (fordefault) {
+ for (i = 0; i < 32; i++) {
+ if ((p1 = unidefault_pagedir_str[i]) != NULL) {
+ for (j = 0; j < 32; j++) {
+ FREE(p1[j]);
+ }
+ FREE(p1);
+ }
+ unidefault_pagedir_str[i] = NULL;
+ }
+
+ unidefault_str_contents_valid = 1; /* ??? probably no use... */
+ } else {
+ for (i = 0; i < 32; i++) {
+ if ((p1 = uni_pagedir_str[i]) != NULL) {
+ for (j = 0; j < 32; j++) {
+ FREE(p1[j]);
+ }
+ FREE(p1);
+ }
+ uni_pagedir_str[i] = NULL;
+ }
+
+ hashtable_str_contents_valid = 1; /* ??? probably no use... */
+ }
+}
+
+#ifdef NOTDEFINED
+PRIVATE int con_set_unimap ARGS2(
+ u16, ct,
+ struct unipair *, list)
+{
+ int err = 0, err1, i;
+
+ while (ct--) {
+ if ((err1 = con_insert_unipair(list->unicode, list->fontpos)) != 0) {
+ err = err1;
+ }
+ list++;
+ }
+
+ for (i = 0; i <= 3; i++) {
+ set_inverse_transl(i); /* Update all inverse translations */
+ }
+ return err;
+}
+#endif /* NOTDEFINED */
+
+/*
+ * Loads the unimap for the hardware font, as defined in uni_hash.tbl.
+ * The representation used was the most compact I could come up
+ * with. This routine is executed at sys_setup time, and when the
+ * PIO_FONTRESET ioctl is called.
+ */
+PRIVATE void con_set_default_unimap NOARGS
+{
+ int i, j;
+ u16 *p;
+
+ /*
+ * The default font is always 256 characters.
+ */
+ con_clear_unimap(1);
+
+ p = dfont_unitable;
+ for (i = 0; i < 256; i++) {
+ for (j = dfont_unicount[i]; j; j--) {
+ con_insert_unipair(*(p++), i, 1);
+ }
+ }
+
+#if 0
+ for (i = 0; i <= 3; i++) {
+ set_inverse_transl(i); /* Update all inverse translations */
+ }
+#endif
+
+ UC_default_unitable = dfont_unitable;
+
+ con_clear_unimap_str(1);
+ UC_con_set_unimap_str(dfont_replacedesc.entry_ct, repl_map, 1);
+ UC_default_unitable_str = &dfont_replacedesc;
+}
+
+PUBLIC int UCNumCharsets = 0;
+
+PUBLIC int UCLYhndl_HTFile_for_unspec = -1;
+PUBLIC int UCLYhndl_HTFile_for_unrec = -1;
+PUBLIC int UCLYhndl_for_unspec = -1;
+PUBLIC int UCLYhndl_for_unrec = -1;
+
+PRIVATE int UC_con_set_unimap ARGS2(
+ int, UC_charset_out_hndl,
+ int, update_flag)
+{
+ int i, j;
+ u16 *p;
+
+ if (!UC_valid_UC_charset(UC_charset_out_hndl)) {
+ if (TRACE)
+ fprintf(stderr, "UC_con_set_unimap: Invalid charset handle %d.\n",
+ UC_charset_out_hndl);
+ return -1;
+ }
+
+ p = UCInfo[UC_charset_out_hndl].unitable;
+ if (p == UC_current_unitable) { /* test whether pointers are equal */
+ return update_flag; /* nothing to be done */
+ }
+ UC_current_unitable = p;
+
+ /*
+ * The font is always 256 characters - so far.
+ */
+ con_clear_unimap(0);
+
+ for (i = 0; i < 256; i++) {
+ for (j = UCInfo[UC_charset_out_hndl].unicount[i]; j; j--) {
+ con_insert_unipair(*(p++), i, 0);
+ }
+ }
+
+ if (update_flag) {
+ for (i = 0; i <= 3; i++) {
+ set_inverse_transl(i); /* Update all inverse translations */
+ }
+ }
+
+ return 0;
+}
+
+PRIVATE int UC_con_set_unimap_str ARGS3(
+ u16, ct,
+ struct unipair_str *, list,
+ int, fordefault)
+{
+ int err = 0, err1;
+
+ while (ct--) {
+ if ((err1 = con_insert_unipair_str(list->unicode,
+ list->replace_str,
+ fordefault)) != 0) {
+ err = err1;
+ }
+ list++;
+ }
+
+ /*
+ * No inverse translations for replacement strings!
+ */
+ if (!err) {
+ if (fordefault)
+ unidefault_str_contents_valid = 1;
+ else
+ hashtable_str_contents_valid = 1;
+ }
+
+ return err;
+}
+
+#ifdef NOTDEFINED
+PRIVATE int con_get_unimap ARGS3(
+ u16, ct,
+ u16 *, uct,
+ struct unipair *, list)
+{
+ int i, j, k, ect;
+ u16 **p1, *p2;
+
+ ect = 0;
+ if (hashtable_contents_valid) {
+ for (i = 0; i < 32; i++) {
+ if ((p1 = uni_pagedir[i]) != NULL) {
+ for (j = 0; j < 32; j++) {
+ if ((p2 = *(p1++)) != NULL) {
+ for (k = 0; k < 64; k++) {
+ if (*p2 < MAX_GLYPH && ect++ < ct) {
+ list->unicode = (u16) ((i<<11)+(j<<6)+k);
+ list->fontpos = (u16) *p2;
+ list++;
+ }
+ p2++;
+ }
+ }
+ }
+ }
+ }
+ }
+ *uct = ect;
+ return ((ect <= ct) ? 0 : -ENOMEM);
+}
+#endif /* NOTDEFINED */
+
+PRIVATE int conv_uni_to_pc ARGS2(
+ long, ucs,
+ int, usedefault)
+{
+ int h;
+ u16 **p1, *p2;
+
+ /*
+ * Only 16-bit codes supported at this time.
+ */
+ if (ucs > 0xffff) {
+ /*
+ * U+FFFD: REPLACEMENT CHARACTER.
+ */
+ ucs = 0xfffd;
+ } else if (ucs < 0x20 || ucs >= 0xfffe) {
+ /*
+ * Not a printable character.
+ */
+ return -1;
+ } else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) {
+ /*
+ * Zero-width space.
+ */
+ return -2;
+ } else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE) {
+ /*
+ * UNI_DIRECT_BASE indicates the start of the region in the
+ * User Zone which always has a 1:1 mapping to the currently
+ * loaded font. The UNI_DIRECT_MASK indicates the bit span
+ * of the region.
+ */
+ return (ucs & UNI_DIRECT_MASK);
+ }
+
+ if (usedefault) {
+ if (!unidefault_contents_valid)
+ return -3;
+ p1 = unidefault_pagedir[ucs >> 11];
+ } else {
+ if (!hashtable_contents_valid)
+ return -3;
+ p1 = uni_pagedir[ucs >> 11];
+ }
+
+ if (p1 &&
+ (p2 = p1[(ucs >> 6) & 0x1f]) &&
+ (h = p2[ucs & 0x3f]) < MAX_GLYPH) {
+ return h;
+ }
+
+ /*
+ * Not found.
+ */
+ return -4;
+}
+
+/*
+ * Note: contents of outbuf is not changes for negative return value!
+ */
+PRIVATE int conv_uni_to_str ARGS4(
+ char*, outbuf,
+ int, buflen,
+ long, ucs,
+ int, usedefault)
+{
+ char *h;
+ char ***p1, **p2;
+
+ /*
+ * Only 16-bit codes supported at this time.
+ */
+ if (ucs > 0xffff) {
+ /*
+ * U+FFFD: REPLACEMENT CHARACTER.
+ */
+ ucs = 0xfffd;
+ /*
+ * Maybe the following two cases should be allowed here?? - KW
+ */
+ } else if (ucs < 0x20 || ucs >= 0xfffe) {
+ /*
+ * Not a printable character.
+ */
+ return -1;
+ } else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) {
+ /*
+ * Zero-width space.
+ */
+ return -2;
+#ifdef NOTDEFINED /* We don't handle the following here: */
+ } else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE) {
+ /*
+ * UNI_DIRECT_BASE indicates the start of the region in the
+ * User Zone which always has a 1:1 mapping to the currently
+ * loaded font. The UNI_DIRECT_MASK indicates the bit span
+ * of the region.
+ */
+ return ucs & UNI_DIRECT_MASK;
+#endif /* NOTDEFINED */
+ }
+
+ if (usedefault) {
+ if (!unidefault_str_contents_valid)
+ return -3;
+ p1 = unidefault_pagedir_str[ucs >> 11];
+ } else {
+ if (!hashtable_str_contents_valid)
+ return -3;
+ p1 = uni_pagedir_str[ucs >> 11];
+ }
+
+ if (p1 &&
+ (p2 = p1[(ucs >> 6) & 0x1f]) &&
+ (h = p2[ucs & 0x3f])) {
+ strncpy (outbuf,h,(size_t) (buflen-1));
+ return 1; /* ok ! */
+ }
+
+ /*
+ * Not found.
+ */
+ return -4;
+}
+
+PUBLIC int UCInitialized = 0;
+/*
+ * [ original comment: - KW ]
+ * This is called at sys_setup time, after memory and the console are
+ * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
+ * from this function, hence the call from sys_setup.
+ */
+PRIVATE void UCconsole_map_init NOARGS
+{
+ con_set_default_unimap();
+ UCInitialized = 1;
+}
+
+/*
+ * OK now, finally, some stuff that is more specifically for Lynx: - KW
+ */
+#ifdef NOTDEFINED
+PUBLIC int UCGetcharset_byMIMEname PARAMS((CONST char * UC_MIMEcharset));
+PUBLIC int UCGetcharset_byLYNXname PARAMS((CONST char * UC_LYNXcharset));
+#endif /* NOTDEFINED */
+
+PUBLIC int UCTransUniChar ARGS2(
+ long, unicode,
+ int, charset_out)
+{
+ int rc = 0;
+ int UChndl_out;
+ int isdefault, trydefault = 0;
+ u16 * ut;
+
+ if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+ if ((UChndl_out = default_UChndl) < 0)
+ return -12;
+ isdefault = 1;
+ } else {
+ isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+ trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+ }
+
+ if (!isdefault) {
+ ut = UCInfo[UChndl_out].unitable;
+ if (ut != UC_current_unitable) {
+ rc = UC_con_set_unimap(UChndl_out, 1);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ rc = conv_uni_to_pc(unicode, 0);
+ if (rc >= 0)
+ return rc;
+ }
+ if (isdefault || trydefault) {
+ rc = conv_uni_to_pc(unicode, 1);
+ if (rc >= 0)
+ return rc;
+ }
+ if (!isdefault && (rc == -4)) {
+ rc = conv_uni_to_pc(0xfffd, 0);
+ }
+ if ((isdefault || trydefault) && (rc == -4)) {
+ rc = conv_uni_to_pc(0xfffd, 1);
+ }
+ return rc;
+}
+
+/*
+ * Returns string length, or negative value for error.
+ */
+PUBLIC int UCTransUniCharStr ARGS5(
+ char *, outbuf,
+ int, buflen,
+ long, unicode,
+ int, charset_out,
+ int, chk_single_flag)
+{
+ int rc = -14, src = 0, ignore_err;
+ int UChndl_out;
+ int isdefault, trydefault = 0;
+ struct unimapdesc_str * repl;
+ u16 * ut;
+
+ if (buflen < 2)
+ return -13;
+
+ if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+ if ((UChndl_out = default_UChndl) < 0)
+ return -12;
+ isdefault = 1;
+ } else {
+ isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+ trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+ }
+
+ if (chk_single_flag) {
+ if (!isdefault) {
+ ut = UCInfo[UChndl_out].unitable;
+ if (ut != UC_current_unitable) {
+ src = UC_con_set_unimap(UChndl_out, 1);
+ if (src < 0) {
+ return src;
+ }
+ }
+ }
+ src = conv_uni_to_pc(unicode, isdefault);
+ if (src >= 32) {
+ outbuf[0] = src; outbuf[1] = '\0';
+ return 1;
+ }
+ }
+
+ repl = &(UCInfo[UChndl_out].replacedesc);
+ if (!isdefault) {
+ if (repl != UC_current_unitable_str) {
+ con_clear_unimap_str(0);
+ ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
+ UC_current_unitable_str = repl;
+ }
+ rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (trydefault && chk_single_flag) {
+ src = conv_uni_to_pc(unicode, 1);
+ if (src >= 32) {
+ outbuf[0] = src; outbuf[1] = '\0';
+ return 1;
+ }
+ }
+ if (isdefault || trydefault) {
+ rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (rc == -4) {
+ if (!isdefault)
+ rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
+ if ((rc == -4) && (isdefault || trydefault))
+ rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (chk_single_flag && src == -4) {
+ if (!isdefault)
+ rc = conv_uni_to_pc(0xfffd, 0);
+ if ((rc == -4) && (isdefault || trydefault))
+ rc = conv_uni_to_pc(0xfffd, 1);
+ if (rc >= 32) {
+ outbuf[0] = rc; outbuf[1] = '\0';
+ return 1;
+ }
+ return rc;
+ }
+ return -4;
+}
+
+PRIVATE int UC_lastautoGN = 0;
+
+PRIVATE int UC_MapGN ARGS2(
+ int, UChndl,
+ int, update_flag)
+{
+ int i, Gn, found, lasthndl;
+ found = 0;
+ Gn = -1;
+ for (i = 0; i < 4 && Gn < 0; i++) {
+ if (UC_GNhandles[i] < 0) {
+ Gn = i;
+ } else if (UC_GNhandles[i] == UChndl) {
+ Gn = i;
+ found = 1;
+ }
+ }
+ if (found)
+ return Gn;
+ if (Gn >= 0) {
+ UCInfo[UChndl].GN = Gn;
+ UC_GNhandles[Gn] = UChndl;
+ } else {
+ if (UC_lastautoGN == GRAF_MAP) {
+ Gn = IBMPC_MAP;
+ } else {
+ Gn = GRAF_MAP;
+ }
+ UC_lastautoGN = Gn;
+ lasthndl = UC_GNhandles[Gn];
+ UCInfo[lasthndl].GN = -1;
+ UCInfo[UChndl].GN = Gn;
+ UC_GNhandles[Gn] = UChndl;
+ }
+ if (TRACE) {
+ fprintf(stderr,
+ "UC_MapGN: Using %d <- %d (%s)\n",
+ Gn, UChndl, UCInfo[UChndl].MIMEname);
+ }
+ UC_con_set_trans(UChndl,Gn,update_flag);
+ return Gn;
+}
+
+PUBLIC int UCTransChar ARGS3(
+ char, ch_in,
+ int, charset_in,
+ int, charset_out)
+{
+ int unicode, Gn;
+ int rc = -4;
+ int UChndl_in, UChndl_out;
+ int isdefault, trydefault = 0;
+ u16 * ut;
+ int upd = 0;
+
+#ifndef UC_NO_SHORTCUTS
+ if (charset_in == charset_out)
+ return (unsigned char)ch_in;
+#endif /* UC_NO_SHORTCUTS */
+ if (charset_in < 0)
+ return -11;
+ if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+ return -11;
+ if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+ if ((UChndl_out = default_UChndl) < 0)
+ return -12;
+ isdefault = 1;
+ } else {
+ isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+ trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+ }
+ if (!UCInfo[UChndl_in].num_uni)
+ return -11;
+ if ((Gn = UCInfo[UChndl_in].GN) < 0) {
+ Gn = UC_MapGN(UChndl_in,0);
+ upd = 1;
+ }
+
+ ut = UCInfo[UChndl_out].unitable;
+ if (!isdefault) {
+ if (ut == UC_current_unitable) {
+ if (upd) {
+ set_inverse_transl(Gn);
+ }
+ } else {
+ rc = UC_con_set_unimap(UChndl_out, 1);
+ if (rc > 0) {
+ set_inverse_transl(Gn);
+ } else if (rc < 0) {
+ return rc;
+ }
+ }
+ }
+ UC_translate = set_translate(Gn);
+ unicode = UC_translate[(unsigned char)ch_in];
+ if (!isdefault) {
+ rc = conv_uni_to_pc(unicode, 0);
+ if (rc >= 0)
+ return rc;
+ }
+ if ((rc == -4) && (isdefault || trydefault)) {
+ rc = conv_uni_to_pc(unicode, 1);
+ }
+ if ((rc == -4) && !isdefault) {
+ rc = conv_uni_to_pc(0xfffd, 0);
+ }
+ if ((rc == -4) && (isdefault || trydefault)) {
+ rc = conv_uni_to_pc(0xfffd, 1);
+ }
+ return rc;
+}
+
+PUBLIC long int UCTransToUni ARGS2(
+ char, ch_in,
+ int, charset_in)
+{
+ int unicode, Gn;
+ unsigned char ch_iu;
+ int UChndl_in;
+
+ ch_iu = (unsigned char)ch_in;
+#ifndef UC_NO_SHORTCUTS
+ if (charset_in == 0)
+ return ch_iu;
+ if ((unsigned char)ch_in < 128 && (unsigned char)ch_in >= 32)
+ return ch_iu;
+#endif /* UC_NO_SHORTCUTS */
+ if (charset_in < 0)
+ return -11;
+ if ((unsigned char)ch_in < 32 &&
+ LYCharSet_UC[charset_in].enc != UCT_ENC_8BIT_C0)
+ /*
+ * Don't translate C0 chars except for specific charsets.
+ */
+ return ch_iu;
+ if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+ return -11;
+ if (!UCInfo[UChndl_in].num_uni)
+ return -11;
+ if ((Gn = UCInfo[UChndl_in].GN) < 0) {
+ Gn = UC_MapGN(UChndl_in,1);
+ }
+
+ UC_translate = set_translate(Gn);
+ unicode = UC_translate[(unsigned char)ch_in];
+
+ return unicode;
+}
+
+PUBLIC int UCReverseTransChar ARGS3(
+ char, ch_out,
+ int, charset_in,
+ int, charset_out)
+{
+ int Gn;
+ int rc;
+ int UChndl_in, UChndl_out;
+ int isdefault;
+ int i_ch = (unsigned char)ch_out;
+ u16 * ut;
+
+#ifndef UC_NO_SHORTCUTS
+ if (charset_in == charset_out)
+ return ch_out;
+#endif /* UC_NO_SHORTCUTS */
+ if (charset_in < 0)
+ return -11;
+ if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+ return -11;
+ if (!UCInfo[UChndl_in].num_uni)
+ return -11;
+ if (charset_out < 0)
+ return -12;
+ if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+ if ((UChndl_out = default_UChndl) < 0)
+ return -12;
+ isdefault = 1;
+ } else {
+ isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+ }
+
+ if (!isdefault) {
+ /*
+ * Try to use the inverse table if charset_out is not equivalent
+ * to using just the default table. If it is, it should have
+ * just ASCII chars and trying to back-translate those should
+ * not give anything but themselves. - kw
+ */
+ ut = UCInfo[UChndl_out].unitable;
+ if (ut == UC_current_unitable) {
+ if ((Gn = UCInfo[UChndl_in].GN) >= 0) {
+ UC_translate = set_translate(Gn);
+ rc = inv_translate[i_ch];
+ if (rc >= 32) {
+ return rc;
+ }
+ } else {
+ Gn = UC_MapGN(UChndl_in,1);
+ UC_translate = set_translate(Gn);
+ rc = inv_translate[i_ch];
+ if (rc >= 32) {
+ return rc;
+ }
+ }
+ }
+ }
+ return UCTransChar(ch_out, charset_out, charset_in);
+}
+
+/*
+ * Returns string length, or negative value for error.
+ */
+PUBLIC int UCTransCharStr ARGS6(
+ char *, outbuf,
+ int, buflen,
+ char, ch_in,
+ int, charset_in,
+ int, charset_out,
+ int, chk_single_flag)
+{
+ int unicode, Gn;
+ int rc = -14, src = 0, ignore_err;
+ int UChndl_in, UChndl_out;
+ int isdefault, trydefault = 0;
+ struct unimapdesc_str * repl;
+ u16 * ut;
+ int upd = 0;
+
+ if (buflen < 2)
+ return -13;
+#ifndef UC_NO_SHORTCUTS
+ if (chk_single_flag && charset_in == charset_out) {
+ outbuf[0] = ch_in;
+ outbuf[1] = '\0';
+ return 1;
+ }
+#endif /* UC_NO_SHORTCUTS */
+ if (charset_in < 0)
+ return -11;
+ if ((UChndl_in = LYCharSet_UC[charset_in].UChndl) < 0)
+ return -11;
+ if (!UCInfo[UChndl_in].num_uni)
+ return -11;
+ if ((UChndl_out = LYCharSet_UC[charset_out].UChndl) < 0) {
+ if ((UChndl_out = default_UChndl) < 0)
+ return -12;
+ isdefault = 1;
+ } else {
+ isdefault = UCInfo[UChndl_out].replacedesc.isdefault;
+ trydefault = UCInfo[UChndl_out].replacedesc.trydefault;
+ }
+ if ((Gn = UCInfo[UChndl_in].GN) < 0) {
+ Gn = UC_MapGN(UChndl_in, !chk_single_flag);
+ upd = chk_single_flag;
+ }
+
+ UC_translate = set_translate(Gn);
+ unicode = UC_translate[(unsigned char)ch_in];
+
+ if (chk_single_flag) {
+ if (!isdefault) {
+ ut = UCInfo[UChndl_out].unitable;
+ if (ut == UC_current_unitable) {
+ if (upd) set_inverse_transl(Gn);
+ } else {
+ src = UC_con_set_unimap(UChndl_out, 1);
+ if (src > 0) {
+ set_inverse_transl(Gn);
+ } else if (src < 0) {
+ return src;
+ }
+ }
+ }
+ src = conv_uni_to_pc(unicode, isdefault);
+ if (src >= 32) {
+ outbuf[0] = src; outbuf[1] = '\0';
+ return 1;
+ }
+ }
+
+ repl = &(UCInfo[UChndl_out].replacedesc);
+ if (!isdefault) {
+ if (repl != UC_current_unitable_str) {
+ con_clear_unimap_str(0);
+ ignore_err = UC_con_set_unimap_str(repl->entry_ct, repl->entries, 0);
+ UC_current_unitable_str = repl;
+ }
+ rc = conv_uni_to_str(outbuf, buflen, unicode, 0);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (trydefault && chk_single_flag) {
+ src = conv_uni_to_pc(unicode, 1);
+ if (src >= 32) {
+ outbuf[0] = src; outbuf[1] = '\0';
+ return 1;
+ }
+ }
+ if (isdefault || trydefault) {
+ rc = conv_uni_to_str(outbuf, buflen, unicode, 1);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (rc == -4) {
+ if (!isdefault)
+ rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 0);
+ if ((rc == -4) && (isdefault || trydefault))
+ rc = conv_uni_to_str(outbuf, buflen, 0xfffd, 1);
+ if (rc >= 0)
+ return (strlen(outbuf));
+ }
+ if (chk_single_flag && src == -4) {
+ if (!isdefault)
+ rc = conv_uni_to_pc(0xfffd, 0);
+ if ((rc == -4) && (isdefault || trydefault))
+ rc = conv_uni_to_pc(0xfffd, 1);
+ if (rc >= 32) {
+ outbuf[0] = rc; outbuf[1] = '\0';
+ return 1;
+ } else if (rc <= 0) {
+ outbuf[0] = '\0';
+ return rc;
+ }
+ return rc;
+ }
+ return -4;
+}
+
+PRIVATE int UC_FindGN_byMIME ARGS1(
+ CONST char *, UC_MIMEcharset)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (!strcmp(UC_MIMEcharset,UC_GNsetMIMEnames[i])) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+PUBLIC int UCGetRawUniMode_byLYhndl ARGS1(
+ int, i)
+{
+ if (i < 0)
+ return 0;
+ return LYCharSet_UC[i].enc;
+}
+
+/*
+ * Currently the charset name has to match exactly -- not substring
+ * matching as was done before (see HTMIME.c, HTML.c).
+ */
+PUBLIC int UCGetLYhndl_byMIME ARGS1(
+ CONST char *, UC_MIMEcharset)
+{
+ int i;
+ int LYhndl = -1;
+
+ if (!UC_MIMEcharset || !(*UC_MIMEcharset))
+ return -1;
+
+ for (i = 0;
+ (i < MAXCHARSETS && i < LYNumCharsets &&
+ LYchar_set_names[i] && LYhndl < 0); i++) {
+ if (LYCharSet_UC[i].MIMEname &&
+ !strcmp(UC_MIMEcharset, LYCharSet_UC[i].MIMEname)) {
+ LYhndl = i;
+ }
+ }
+ if (LYhndl < 0) {
+ /*
+ * Not yet found, try synonyms. - FM
+ */
+ if (!strcmp(UC_MIMEcharset, "unicode-1-1-utf-8") ||
+ !strcmp(UC_MIMEcharset, "utf8")) {
+ /*
+ * Treat these as synonyms for the IANA registered name. - FM
+ */
+ return UCGetLYhndl_byMIME("utf-8");
+ }
+ if (!strncmp(UC_MIMEcharset, "iso-2022-jp", 11) ||
+ !strcmp(UC_MIMEcharset, "x-euc-jp")) {
+ return UCGetLYhndl_byMIME("euc-jp");
+ }
+ if (!strcmp(UC_MIMEcharset, "x-shift-jis")) {
+ return UCGetLYhndl_byMIME("shift_jis");
+ }
+ if (!strcmp(UC_MIMEcharset, "iso-2022-kr")) {
+ return UCGetLYhndl_byMIME("euc-kr");
+ }
+ if (!strcmp(UC_MIMEcharset, "gb2312") ||
+ !strncmp(UC_MIMEcharset, "cn-gb", 5) ||
+ !strcmp(UC_MIMEcharset, "iso-2022-cn")) {
+ return UCGetLYhndl_byMIME("euc-cn");
+ }
+ if (!strcmp(UC_MIMEcharset, "cn-big5")) {
+ return UCGetLYhndl_byMIME("big5");
+ }
+ if (!strcmp(UC_MIMEcharset, "x-mac-roman") ||
+ !strcmp(UC_MIMEcharset, "mac-roman")) {
+ return UCGetLYhndl_byMIME("macintosh");
+ }
+ if (!strcmp(UC_MIMEcharset, "x-next") ||
+ !strcmp(UC_MIMEcharset, "nextstep") ||
+ !strcmp(UC_MIMEcharset, "x-nextstep")) {
+ return UCGetLYhndl_byMIME("next");
+ }
+ if (!strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.1-latin-1") ||
+ !strcmp(UC_MIMEcharset, "cp1252") ||
+ !strcmp(UC_MIMEcharset, "cp-1252") ||
+ !strcmp(UC_MIMEcharset, "ibm1252") ||
+ !strcmp(UC_MIMEcharset, "iso-8859-1-windows-3.0-latin-1")) {
+ /*
+ * Treat these as synonyms for windows-1252, which is more
+ * commonly used than the IANA registered name. - FM
+ */
+ return UCGetLYhndl_byMIME("windows-1252");
+ }
+ if (!strcmp(UC_MIMEcharset, "iso-8859-2-windows-latin-2") ||
+ !strcmp(UC_MIMEcharset, "cp1250") ||
+ !strcmp(UC_MIMEcharset, "cp-1250") ||
+ !strcmp(UC_MIMEcharset, "ibm1250")) {
+ /*
+ * Treat these as synonyms for windows-1250. - FM
+ */
+ return UCGetLYhndl_byMIME("windows-1250");
+ }
+ if ((!strncmp(UC_MIMEcharset, "ibm", 3) ||
+ !strncmp(UC_MIMEcharset, "cp-", 3)) &&
+ isdigit((unsigned char)UC_MIMEcharset[3]) &&
+ isdigit((unsigned char)UC_MIMEcharset[4]) &&
+ isdigit((unsigned char)UC_MIMEcharset[5])) {
+ /*
+ * For "ibmNNN<...>" or "cp-NNN", try "cpNNN<...>"
+ * if not yet found. - KW & FM
+ */
+ char * cptmp = NULL;
+
+ StrAllocCopy(cptmp, (UC_MIMEcharset + 1));
+ cptmp[0] = 'c';
+ cptmp[1] = 'p';
+ if ((LYhndl = UCGetLYhndl_byMIME(cptmp)) >= 0) {
+ FREE(cptmp);
+ return LYhndl;
+ }
+ /*
+ * Try windows-NNN<...> if not yet found. - FM
+ */
+ StrAllocCopy(cptmp, "windows-");
+ StrAllocCat(cptmp, (UC_MIMEcharset + 3));
+ LYhndl = UCGetLYhndl_byMIME(cptmp);
+ FREE(cptmp);
+ return LYhndl;
+ }
+ if (!strncmp(UC_MIMEcharset, "windows-", 8) &&
+ isdigit((unsigned char)UC_MIMEcharset[8]) &&
+ isdigit((unsigned char)UC_MIMEcharset[9]) &&
+ isdigit((unsigned char)UC_MIMEcharset[10])) {
+ /*
+ * For "windows-NNN<...>", try "cpNNN<...>" - FM
+ */
+ char * cptmp = NULL;
+
+ StrAllocCopy(cptmp, (UC_MIMEcharset + 6));
+ cptmp[0] = 'c';
+ cptmp[1] = 'p';
+ LYhndl = UCGetLYhndl_byMIME(cptmp);
+ FREE(cptmp);
+ return LYhndl;
+ }
+ if (!strcmp(UC_MIMEcharset, "koi-8")) { /* accentsoft bugosity */
+ return UCGetLYhndl_byMIME("koi8-r");
+ }
+ }
+ return LYhndl; /* returns -1 if no charset found by that MIME name */
+}
+
+/*
+ * Function UC_setup_LYCharSets_repl() tries to set up a subtable in
+ * LYCharSets[] appropriate for this new charset, for compatibility
+ * with the "old method". Maybe not nice (maybe not even necessary
+ * any more), but it works (as far as it goes..).
+ *
+ * We try to be conservative and only allocate new memory for this
+ * if needed. If not needed, just point to SevenBitApproximations[i].
+ * [Could do the same for ISO_Latin1[] if it's identical to that, but
+ * would make it even *more* messy than it already is...]
+ * This the only function in this file that knows, or cares, about the
+ * HTMLDTD or details of LYCharSets[] subtables (and therefore somewhat
+ * violates the idea that this file should be independent of those).
+ * As in other places, we rely on ISO_Latin1 being the *first* table
+ * in LYCharSets. - KW
+ */
+
+/*
+ * We need to remember which ones were allocated and which are static.
+ */
+PRIVATE char ** remember_allocated_LYCharSets[MAXCHARSETS];
+
+PRIVATE void UCreset_allocated_LYCharSets NOARGS
+{
+ int i = 0;
+
+ for (; i < MAXCHARSETS; i++) {
+ remember_allocated_LYCharSets[i] = NULL;
+ }
+}
+
+PRIVATE void UCfree_allocated_LYCharSets NOARGS
+{
+ int i = 0;
+
+ for (; i < MAXCHARSETS; i++) {
+ if (remember_allocated_LYCharSets[i] != NULL) {
+ FREE(remember_allocated_LYCharSets[i]);
+ }
+ }
+}
+
+PRIVATE char ** UC_setup_LYCharSets_repl ARGS2(
+ int, UC_charset_in_hndl,
+ unsigned, lowest8)
+{
+ char **ISO_Latin1 = LYCharSets[0];
+ char **p;
+ char **prepl;
+ u16 *pp;
+ char **tp;
+ char *s7;
+ char *s8;
+ size_t i;
+ int j, changed;
+ u16 k;
+ u8 *ti;
+
+ /*
+ * Create a temporary table for reverse lookup of latin1 codes:
+ */
+ tp = (char **)malloc(96 * sizeof(char *));
+ if (!tp)
+ return NULL;
+ for (i = 0; i < 96; i++)
+ tp[i] = NULL;
+ ti = (u8 *)malloc(96 * sizeof(u8));
+ if (!ti) {
+ FREE(tp);
+ return NULL;
+ }
+ for (i = 0; i < 96; i++)
+ ti[i] = 0;
+
+ pp = UCInfo[UC_charset_in_hndl].unitable;
+
+ /*
+ * Determine if we have any mapping of a Unicode in the range 160-255
+ * to an allowed code point > 0x80 in our new charset...
+ * Store any mappings found in ti[].
+ */
+ if (UCInfo[UC_charset_in_hndl].num_uni > 0) {
+ for (i = 0; i < 256; i++) {
+ if ((j = UCInfo[UC_charset_in_hndl].unicount[i])) {
+ if ((k = *pp) >= 160 && k < 256 && i >= lowest8) {
+ ti[k-160] = i;
+ }
+ for (; j; j--) {
+ pp++;
+ }
+ }
+ }
+ }
+ {
+ u16 ct;
+ struct unipair_str *list;
+
+ /*
+ * Determine if we have any mapping of a Unicode in the range
+ * 160-255 to a replacement string for our new charset...
+ * Store any mappings found in tp[].
+ */
+ ct = UCInfo[UC_charset_in_hndl].replacedesc.entry_ct;
+ list = UCInfo[UC_charset_in_hndl].replacedesc.entries;
+ while (ct--) {
+ if ((k = list->unicode) >= 160 && k < 256) {
+ tp[k-160] = list->replace_str;
+ }
+ list++;
+ }
+ }
+ /*
+ * Now allocate a new table compatible with LYCharSets[]
+ * and with the HTMLDTD for entities.
+ * We don't know yet whether we'll keep it around. */
+ p = prepl = (char **)malloc(HTML_dtd.number_of_entities * sizeof(char *));
+ if (!p) {
+ FREE(tp);
+ FREE(ti);
+ return NULL;
+ }
+ changed = 0;
+ for (i = 0; i < HTML_dtd.number_of_entities; i++, p++) {
+ /*
+ * For each of those entities, we check what the "old method"
+ * ISO_Latin1[] mapping does with them. If it is nothing we
+ * want to use, just point to the SevenBitApproximations[] string.
+ */
+ s7 = SevenBitApproximations[i];
+ s8 = ISO_Latin1[i];
+ *p = s7;
+ if (s8 && (unsigned char)(*s8) >= 160 && strlen(s8) == 1) {
+ /*
+ * We have an entity that is mapped to
+ * one valid eightbit latin1 char.
+ */
+ if (ti[(unsigned char)(*s8) - 160] >= lowest8 &&
+ !(s7[0] == ti[(unsigned char)(*s8) - 160] &&
+ s7[1] == '\0')) {
+ /*
+ * ...which in turn is mapped, by our "new method",
+ * to another valid eightbit char for this new
+ * charset: either to itself...
+ */
+ if (ti[(unsigned char)(*s8) - 160] == (unsigned char)(*s8)) {
+ *p = s8;
+ } else {
+ /*
+ * ...or another byte...
+ */
+#ifdef NOTDEFINED
+ *p = (char *)malloc(2*sizeof(char));
+ if (!*p) {
+ FREE(tp);
+ FREE(ti);
+ FREE(prepl);
+ return NULL;
+ }
+ (*p)[0] = ti[(unsigned char)(*s8) - 160];
+ (*p)[1] = '\0';
+#else
+ /*
+ * Use this instead... make those 1-char strings
+ * into HTAtoms, so they will be cleaned up
+ * at exit... all for the sake of preventing
+ * memory leaks, sigh.
+ */
+ static char dummy[2]; /* one char dummy string */
+
+ dummy[0] = ti[(unsigned char)(*s8) - 160];
+ *p = HTAtom_name(HTAtom_for(dummy));
+#endif /* NOTDEFINED */
+ }
+ changed = 1;
+ } else if (tp[(unsigned char)(*s8) - 160] &&
+ strcmp(s7, tp[(unsigned char)(*s8) - 160])) {
+ /*
+ * ...or which is mapped, by our "new method",
+ * to a replacement string for this new charset.
+ */
+ *p = tp[(unsigned char)(*s8) - 160];
+ changed = 1;
+ }
+ }
+ }
+ FREE(tp);
+ FREE(ti);
+ if (!changed) {
+ FREE(prepl);
+ return NULL;
+ }
+ return prepl;
+}
+
+/*
+ * "New method" meets "Old method" ...
+ */
+PRIVATE int UC_Register_with_LYCharSets ARGS4(
+ int, s,
+ CONST char *, UC_MIMEcharset,
+ CONST char *, UC_LYNXcharset,
+ int, lowest_eightbit)
+{
+ int i, LYhndl, found;
+ char **repl;
+
+ LYhndl = -1;
+ if (LYNumCharsets == 0) {
+ /*
+ * Initialize here; so whoever changes
+ * LYCharSets.c doesn't have to count...
+ */
+ for (i = 0; (i < MAXCHARSETS) && LYchar_set_names[i]; i++) {
+ LYNumCharsets = i+1;
+ }
+ }
+
+ /*
+ * Do different kinds of searches...
+ * Normally the first should find the match if there is one!
+ */
+ for (i = 0; i < MAXCHARSETS && LYchar_set_names[i] && LYhndl < 0; i++) {
+ if (!strcmp(UC_LYNXcharset, LYchar_set_names[i])) {
+ LYhndl = i;
+ }
+ }
+ for (i = 0; i < MAXCHARSETS && LYchar_set_names[i] && LYhndl < 0; i++) {
+ if (LYCharSet_UC[i].MIMEname &&
+ !strcmp(UC_MIMEcharset, LYCharSet_UC[i].MIMEname)) {
+ LYhndl = i;
+ }
+ }
+
+ if (LYhndl < 0) { /* not found */
+ found = 0;
+ if (LYNumCharsets >= MAXCHARSETS) {
+ if (TRACE) {
+ fprintf(stderr,
+ "UC_Register_with_LYCharSets: Too many. Ignoring %s/%s.",
+ UC_MIMEcharset, UC_LYNXcharset);
+ }
+ return -1;
+ }
+ /*
+ * Add to LYCharSets.c lists.
+ */
+ LYhndl = LYNumCharsets;
+ LYNumCharsets ++;
+ LYlowest_eightbit[LYhndl] = 999;
+ LYCharSets[LYhndl] = SevenBitApproximations;
+ /*
+ * Hmm, try to be conservative here.
+ */
+ LYchar_set_names[LYhndl] = UC_LYNXcharset;
+ LYchar_set_names[LYhndl+1] = NULL;
+ /*
+ * Terminating NULL may be looked for by Lynx code.
+ */
+ } else {
+ found = 1;
+ }
+ LYCharSet_UC[LYhndl].UChndl = s;
+ /*
+ * Can we just copy the pointer? Hope so...
+ */
+ LYCharSet_UC[LYhndl].MIMEname = UC_MIMEcharset;
+ LYCharSet_UC[LYhndl].enc = UCInfo[s].enc;
+
+ /*
+ * @@@ We really SHOULD get more info from the table files,
+ * and set relevant flags in the LYCharSet_UC[] entry with
+ * that info... For now, let's try it without. - KW
+ */
+ if (lowest_eightbit < LYlowest_eightbit[LYhndl]) {
+ LYlowest_eightbit[LYhndl] = lowest_eightbit;
+ } else if (lowest_eightbit > LYlowest_eightbit[LYhndl]) {
+ UCInfo[s].lowest_eight = LYlowest_eightbit[LYhndl];
+ }
+
+ if (!found && LYhndl > 0) {
+ repl = UC_setup_LYCharSets_repl(s,UCInfo[s].lowest_eight);
+ if (repl) {
+ LYCharSets[LYhndl] = repl;
+ /*
+ * Remember to FREE at exit.
+ */
+ remember_allocated_LYCharSets[LYhndl]=repl;
+ }
+ }
+ return LYhndl;
+}
+
+/*
+ * This only sets up the structure - no initialization of the tables
+ * is done here yet.
+ */
+PUBLIC void UC_Charset_Setup ARGS8(
+ CONST char *, UC_MIMEcharset,
+ CONST char *, UC_LYNXcharset,
+ u8 *, unicount,
+ u16 *, unitable,
+ int, nnuni,
+ struct unimapdesc_str, replacedesc,
+ int, lowest_eight,
+ int, UC_rawuni)
+{
+ int s, Gn;
+ int i, status = 0, found;
+
+ /*
+ * Get (new?) slot.
+ */
+ found = -1;
+ for (i = 0; i < UCNumCharsets && found < 0; i++) {
+ if (!strcmp(UCInfo[i].MIMEname, UC_MIMEcharset)) {
+ found = i;
+ }
+ }
+ if (found >= 0) {
+ s = found;
+ } else {
+ if (UCNumCharsets >= MAXCHARSETS) {
+ if (TRACE) {
+ fprintf(stderr, "UC_Charset_Setup: Too many. Ignoring %s/%s.",
+ UC_MIMEcharset, UC_LYNXcharset);
+ }
+ return;
+ }
+ s = UCNumCharsets;
+ UCInfo[s].MIMEname = UC_MIMEcharset;
+ }
+ UCInfo[s].LYNXname = UC_LYNXcharset;
+ UCInfo[s].unicount = unicount;
+ UCInfo[s].unitable = unitable;
+ UCInfo[s].num_uni = nnuni;
+ UCInfo[s].replacedesc = replacedesc;
+ if (replacedesc.isdefault) {
+ default_UChndl = s;
+ }
+ Gn = UC_FindGN_byMIME(UC_MIMEcharset);
+ if (Gn >= 0)
+ UC_GNhandles[Gn] = s;
+ UCInfo[s].GN = Gn;
+ if (UC_rawuni == UCT_ENC_UTF8)
+ lowest_eight = 128; /* cheat here */
+ UCInfo[s].lowest_eight = lowest_eight;
+ UCInfo[s].enc = UC_rawuni;
+ UCInfo[s].LYhndl = UC_Register_with_LYCharSets(s,
+ UC_MIMEcharset,
+ UC_LYNXcharset,
+ lowest_eight);
+ UCInfo[s].uc_status = status;
+ if (found < 0)
+ UCNumCharsets++;
+ return;
+}
+
+PRIVATE void UCcleanup_mem NOARGS
+{
+ int i;
+
+ UCfree_allocated_LYCharSets();
+ con_clear_unimap_str(0);
+ con_clear_unimap_str(1);
+ con_clear_unimap(0);
+ con_clear_unimap(1);
+ for (i = 1; i < 4; i++) { /* first one is static! */
+ FREE(inverse_translations[i]);
+ }
+}
+
+PUBLIC void UCInit NOARGS
+{
+ UCreset_allocated_LYCharSets();
+ atexit(UCcleanup_mem);
+ UCconsole_map_init();
+
+ UC_CHARSET_SETUP; /* us-ascii */ /* 7 bit approximations */
+
+/*
+ * The order of charset names visible in Lynx Options menu
+ * correspond to the order of lines below,
+ * except for CJK and others described in LYCharSet.c
+ */
+
+ UC_CHARSET_SETUP_iso_8859_1; /* ISO Latin 1 */
+ UC_CHARSET_SETUP_cp850; /* DosLatin1 (cp850) */
+ UC_CHARSET_SETUP_windows_1252; /* WinLatin1 (cp1252) */
+ UC_CHARSET_SETUP_cp437; /* DosLatinUS (cp437) */
+
+ UC_CHARSET_SETUP_dec_mcs; /* DEC Multinational */
+ UC_CHARSET_SETUP_macintosh; /* Macintosh (8 bit) */
+ UC_CHARSET_SETUP_next; /* NeXT character set */
+
+ UC_CHARSET_SETUP_viscii; /* Vietnamese (VISCII) */
+
+ UC_CHARSET_SETUP_iso_8859_2; /* ISO Latin 2 */
+ UC_CHARSET_SETUP_cp852; /* DosLatin2 (cp852) */
+ UC_CHARSET_SETUP_windows_1250; /* WinLatin2 (cp1250) */
+ UC_CHARSET_SETUP_iso_8859_3; /* ISO Latin 3 */
+ UC_CHARSET_SETUP_iso_8859_4; /* ISO Latin 4 */
+ UC_CHARSET_SETUP_cp775; /* DosBaltRim (cp775) */
+ UC_CHARSET_SETUP_windows_1257; /* WinBaltRim (cp1257) */
+ UC_CHARSET_SETUP_iso_8859_5; /* ISO 8859-5 Cyrillic */
+ UC_CHARSET_SETUP_cp866; /* DosCyrillic (cp866) */
+ UC_CHARSET_SETUP_windows_1251; /* WinCyrillic (cp1251) */
+ UC_CHARSET_SETUP_koi8_r; /* KOI8-R Cyrillic */
+ UC_CHARSET_SETUP_iso_8859_6; /* ISO 8869-6 Arabic */
+ UC_CHARSET_SETUP_cp864; /* DosArabic (cp864) */
+ UC_CHARSET_SETUP_windows_1256; /* WinArabic (cp1256) */
+ UC_CHARSET_SETUP_iso_8859_7; /* ISO 8859-7 Greek */
+ UC_CHARSET_SETUP_cp737; /* DosGreek (cp737) */
+ UC_CHARSET_SETUP_cp869; /* DosGreek2 (cp869) */
+ UC_CHARSET_SETUP_windows_1253; /* WinGreek (cp1253) */
+ UC_CHARSET_SETUP_iso_8859_8; /* ISO 8859-8 Hebrew */
+ UC_CHARSET_SETUP_cp862; /* DosHebrew (cp862) */
+ UC_CHARSET_SETUP_windows_1255; /* WinHebrew (cp1255) */
+ UC_CHARSET_SETUP_iso_8859_9; /* ISO 8859-9 (Latin 5) */
+ UC_CHARSET_SETUP_iso_8859_10; /* ISO 8859-10 */
+
+ UC_CHARSET_SETUP_utf_8; /* UNICODE UTF-8 */
+ UC_CHARSET_SETUP_mnemonic_ascii_0; /* RFC 1345 w/o Intro */
+ UC_CHARSET_SETUP_mnemonic; /* RFC 1345 Mnemonic */
+#ifdef NOTDEFINED
+ UC_CHARSET_SETUP_mnem;
+#endif /* NOTDEFINED */
+
+/*
+ * To add synonyms for any charset name
+ * check function UCGetLYhndl_byMIME in this file.
+ */
+}
diff --git a/gnu/usr.bin/lynx/src/UCdomap.h b/gnu/usr.bin/lynx/src/UCdomap.h
new file mode 100644
index 00000000000..a0ff36b38dc
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/UCdomap.h
@@ -0,0 +1,55 @@
+
+#ifndef UCDOMAP_H
+#define UCDOMAP_H
+
+/*
+ * [old comments: - KW ]
+ * consolemap.h
+ *
+ * Interface between console.c, selection.c and UCmap.c
+ */
+#define LAT1_MAP 0
+#define GRAF_MAP 1
+#define IBMPC_MAP 2
+#define USER_MAP 3
+
+/*
+ * Some conventions I try to follow (loosely):
+ * [a-z]* only internal, names from linux driver code.
+ * UC_* to be only known internally.
+ * UC[A-Z]* to be exported to other parts of Lynx. -KW
+ */
+extern void UC_Charset_Setup PARAMS((
+ CONST char * UC_MIMEcharset,
+ CONST char * UC_LYNXcharset,
+ u8 * unicount,
+ u16 * unitable,
+ int nnuni,
+ struct unimapdesc_str replacedesc,
+ int lowest_eight,
+ int UC_rawuni));
+
+char *UC_GNsetMIMEnames[4] =
+ {"iso-8859-1", "x-dec-graphics", "cp437", "x-transparent"};
+
+int UC_GNhandles[4] = {-1, -1, -1, -1};
+
+struct UC_charset {
+ CONST char *MIMEname;
+ CONST char *LYNXname;
+ u8* unicount;
+ u16* unitable;
+ int num_uni;
+ struct unimapdesc_str replacedesc;
+ int uc_status;
+ int LYhndl;
+ int GN;
+ int lowest_eight;
+ int enc;
+};
+
+extern int UCNumCharsets;
+
+extern void UCInit NOARGS;
+
+#endif /* UCDOMAP_H */
diff --git a/gnu/usr.bin/lynx/src/chrtrans/MAKEFILE.W32 b/gnu/usr.bin/lynx/src/chrtrans/MAKEFILE.W32
new file mode 100644
index 00000000000..4968995f3ab
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/MAKEFILE.W32
@@ -0,0 +1,129 @@
+#
+# Borland C++ IDE generated makefile
+#
+.AUTODEPEND
+
+
+#
+# Borland C++ tools
+#
+IMPLIB = Implib
+BCC32 = Bcc32 +BccW32.cfg
+TLINK32 = TLink32
+TLIB = TLib
+BRC32 = Brc32
+TASM32 = Tasm32
+#
+# IDE macros
+#
+
+
+#
+# Options
+#
+IDE_LFLAGS32 = -LD:\BC45\LIB
+LLATC32_dbmakeuctbdexe = -LCURSES;D:\BC45\LIB -Tpe -ap -c -wdpl -wdup
+RLATC32_dbmakeuctbdexe = -w32 -k
+BLATC32_dbmakeuctbdexe =
+CNIEAT_dbmakeuctbdexe = -I.\;..\..\CURSES;..;..\..\WWW\LIBRARY\IMPLEMENTATION;D:\BC45\INCLUDE -DNO_UNISTD_H;_WINDOWS;NCURSES;FANCY_CURSES;XMOSAIC_HACK;ACCESS_AUTH;NO_UTMP;NO_CUSERID;NO_TTYTYPE;NOSIGHUP;DOSPATH;NOUSERS
+LNIEAT_dbmakeuctbdexe = -x
+LEAT_dbmakeuctbdexe = $(LLATC32_dbmakeuctbdexe)
+REAT_dbmakeuctbdexe = $(RLATC32_dbmakeuctbdexe)
+BEAT_dbmakeuctbdexe = $(BLATC32_dbmakeuctbdexe)
+
+#
+# Dependency List
+#
+Dep_char = \
+ .\makeuctb.exe
+
+char : BccW32.cfg $(Dep_char)
+ echo MakeNode
+
+Dep_dbmakeuctbdexe = \
+ .\makeuctb.obj
+
+.\makeuctb.exe : $(Dep_dbmakeuctbdexe)
+ $(TLINK32) @&&|
+ /v $(IDE_LFLAGS32) $(LEAT_dbmakeuctbdexe) $(LNIEAT_dbmakeuctbdexe) +
+D:\BC45\LIB\c0x32.obj+
+.\makeuctb.obj
+$<,$*
+D:\BC45\LIB\bidsf.lib+
+D:\BC45\LIB\import32.lib+
+D:\BC45\LIB\cw32.lib
+
+|
+
+.\makeuctb.obj : makeuctb.c
+ $(BCC32) -P- -c @&&|
+ $(CEAT_dbmakeuctbdexe) $(CNIEAT_dbmakeuctbdexe) -o$@ makeuctb.c
+|
+
+# Compiler configuration file
+BccW32.cfg :
+ Copy &&|
+-R
+-v
+-vi
+-H
+-H=lynx.csm
+-w-
+-A-
+-wcpt
+-wrpt
+-wrng
+-w-voi
+-w-ret
+-w-sus
+-w-dup
+-w-big
+-w-ext
+-w-zdi
+-w-bei
+-w-obi
+-w-ofp
+-w-eas
+-w-hid
+-w-ncf
+-w-ibc
+-w-dsz
+-w-nst
+-w-mpc
+-w-mpd
+-w-ntd
+-w-nvf
+-w-hch
+-w-inl
+-w-lin
+-w-lvc
+-w-pia
+-w-def
+-w-nod
+-w-pro
+-w-rvl
+-w-ccc
+-w-aus
+-w-par
+-w-rch
+-w-eff
+-w-ill
+-w-ias
+-w-msg
+-WC
+-Ot
+-d-
+-K
+-a-
+-w-stu
+-wbbf
+-w-dpu
+-wcln
+-wsig
+-wucp
+-g200
+-H-
+-v-
+| $@
+
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/MAKEW32.BAT b/gnu/usr.bin/lynx/src/chrtrans/MAKEW32.BAT
new file mode 100644
index 00000000000..c8714cc424f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/MAKEW32.BAT
@@ -0,0 +1,40 @@
+@echo If .tbl files are added or removed you will need to hand edit
+@echo this batch file.
+@echo .
+make -f makefile.w32
+makeuctb cp1250_uni.tbl > cp1250_uni.h
+makeuctb cp1251_uni.tbl > cp1251_uni.h
+makeuctb cp1252_uni.tbl > cp1252_uni.h
+makeuctb cp1253_uni.tbl > cp1253_uni.h
+makeuctb cp1255_uni.tbl > cp1255_uni.h
+makeuctb cp1256_uni.tbl > cp1256_uni.h
+makeuctb cp1257_uni.tbl > cp1257_uni.h
+makeuctb cp437_uni.tbl > cp437_uni.h
+makeuctb cp737_uni.tbl > cp737_uni.h
+makeuctb cp775_uni.tbl > cp775_uni.h
+makeuctb cp850_uni.tbl > cp850_uni.h
+makeuctb cp852_uni.tbl > cp852_uni.h
+makeuctb cp862_uni.tbl > cp862_uni.h
+makeuctb cp864_uni.tbl > cp864_uni.h
+makeuctb cp866_uni.tbl > cp866_uni.h
+makeuctb cp869_uni.tbl > cp869_uni.h
+makeuctb def7_uni.tbl > def7_uni.h
+makeuctb dmcs_uni.tbl > dmcs_uni.h
+makeuctb iso01_uni.tbl > iso01_uni.h
+makeuctb iso02_uni.tbl > iso02_uni.h
+makeuctb iso03_uni.tbl > iso03_uni.h
+makeuctb iso04_uni.tbl > iso04_uni.h
+makeuctb iso05_uni.tbl > iso05_uni.h
+makeuctb iso06_uni.tbl > iso06_uni.h
+makeuctb iso07_uni.tbl > iso07_uni.h
+makeuctb iso08_uni.tbl > iso08_uni.h
+makeuctb iso09_uni.tbl > iso09_uni.h
+makeuctb iso10_uni.tbl > iso10_uni.h
+makeuctb koi8r_uni.tbl > koi8r_uni.h
+makeuctb mac_uni.tbl > mac_uni.h
+makeuctb mnem_suni.tbl > mnem_suni.h
+makeuctb mnem2_suni.tbl > mnem2_suni.h
+makeuctb next_uni.tbl > next_uni.h
+makeuctb rfc_suni.tbl > rfc_suni.h
+makeuctb utf8_uni.tbl > utf8_uni.h
+makeuctb viscii_uni.tbl > viscii_uni.h
diff --git a/gnu/usr.bin/lynx/src/chrtrans/README.format b/gnu/usr.bin/lynx/src/chrtrans/README.format
new file mode 100644
index 00000000000..4ced0a14cc2
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/README.format
@@ -0,0 +1,130 @@
+Some notes on the format of table files used here.
+(See README.tables for what to do with them.)
+
+The format is derived from stuff in the console driver of the
+Linux kernel (as are the guts of the chartrans machinery).
+THAT DOES NOT MEAN that anything here is Linux specific - it isn't.
+
+[Note that the format may change, this is still somewhat experimental.]
+
+There are four kinds of lines:
+
+Summary example:
+
+ # This line is a comment, the next line is a directive
+ O Brand new Charset!
+ 0x41 U+0041 U+0391
+ U+00cd:I'
+
+Description:
+
+a) comment lines start with a '#' character.
+ (trailing comments are allowed on some of the other lines, if in doubt
+ check the examples..)
+
+b) directives:
+ start with a keyword which may be abbreviated to one letter (first
+ letter must be capitalized), followed by space and a value.
+ Currently recognized:
+
+ OptionName
+ The name under which this should appear on the O)ptions screen
+ in the list for Display Character Set
+ MIMEName
+ The name for this charset in MIME syntax (one word with digits
+ and some other non-letters allowed, should be IANA registered)
+ Default
+ If "Y[es]" or "1", this is the default (fallback) translation table,
+ it will be used for Unicode -> 8bit (or 7bit) translation if no
+ translation is found in the specific table.
+ FallBack
+ Whether to use the default table if no translation is found in
+ this table. Normally fallback is used, "FallBack NO" or "FallBack 0"
+ disables it (actually, other values than "FallBack Y[es]" or
+ "FallBack 1" disable it).
+
+ RawOrEnc
+ a number which flags some special property (encoding) for this
+ charset [see utf8_uni.tbl for example, see UCDefs.h for details].
+
+c) character translation definitions:
+ they look like
+
+ 0x41 U+0041 U+0391 ...
+
+ and are used for "forward" translation (mapping this charset to Unicode)
+ AS WELL AS "back" translation (mapping Unicodes to an 8-bit
+ [incl. 7-bit ASCII] code).
+
+ For the "forward" direction, only the first Unicode is used; for
+ "back" translation, all listed Unicodes are mapped to the byte (i.e.
+ code point) on the left.
+
+ The above example line would tell the chartrans mechanism:
+ "For this charset, code position 65 [hex 0x41] contains Unicode
+ U+0041 (LATIN CAPITAL LETTER A). For translation of Unicodes to
+ this charset, use byte value 65 [hex 0x41] for U+0041 (LATIN CAPITAL
+ LETTER A) as well as for U+0391 (GREEK CAPITAL LETTER ALPHA)."
+
+ [Note that for bytes in the ASCII range 0x00-0x7F, the forward translations
+ will (probably) not be used by Lynx. It doesn't hurt to list those,
+ too, for completeness.]
+
+ Some other forms are also accepted:
+
+ * Syntax accepted:
+ * <fontpos> <unicode> <unicode> ...
+ * <fontpos> <unicode range> <unicode range> ...
+ * <fontpos> idem
+ * <range> idem
+ * <range> <unicode range>
+ *
+ * where <range> ::= <fontpos>-<fontpos>
+ * and <unicode> ::= U+<h><h><h><h>
+ * and <h> ::= <hexadecimal digit>
+
+d) string replacement definitions:
+
+ They look like
+
+ U+00cd:I'
+
+ which would mean "Replace Unicode U+00cd (LATIN CAPITAL LETTER I WITH
+ ACUTE" with the string (consisting of two character) I' (if no other
+ translation is available)." Please note that replacement definitions
+ in certnain charset table will override ones from Default table.
+
+ Note that everything after the ':' is currently taken VERBATIM, so
+ careful with trailing blanks etc.
+
+ * Syntax accepted:
+ * <unicode> :<replace>
+ * <unicode range> :<replace>
+ * <unicode> "<C replace>"
+ * <unicode range> "<C replace>"
+ *
+ * where <unicode range> ::= <unicode>-<unicode>
+ * and <unicode> ::= U+<h><h><h><h>
+ * and <h> ::= <hexadecimal digit>
+ * and <replace> any string not containing '\n' or '\0', taken verbatim
+ * and <C replace> any string, with backslash having the usual C meaning.
+
+Motivation:
+
+- It is an extention of the format already in use for Linux (kernel,
+ kbd package), those files can be used with some minimal editing.
+
+- It is easy to convert Unicode tables for other charsets, as they
+ are commonly found on ftp sites etc., to this format - the right
+ sed command should do 99% of the work.
+
+- The format is independent of details of other parts of the Lynx code,
+ unlike the "old" LYCharsets.c mechanism. The tables don't have to
+ be changed in synch when e.g. new entities are added to the entities.h.
+
+
+Note: the Default "7bit approximation" table can be used for
+case-insensitive search for non-ascii letters if no upper/lower case
+information provided by other means, e.g. locale. It is assumed that
+upper/lower case letters have their "7bit approximation" images
+in def7_uni.tbl matched case-insensitively.
diff --git a/gnu/usr.bin/lynx/src/chrtrans/README.tables b/gnu/usr.bin/lynx/src/chrtrans/README.tables
new file mode 100644
index 00000000000..be6dac6a534
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/README.tables
@@ -0,0 +1,59 @@
+The translation table files in this directory are _examples only_.
+They were collected from several sources (among them ftp://ftp.unicode.org,
+Linux kbd package, ftp://dkuug.dk/) and are believed to be correct
+in their mappings, but not checked in detail. The Unicode/UCS2 values
+for some of the RFC 1345 Mnemonic codes are out of date, a cleanup and
+update would be needed for serious use.
+
+More translation files can be easily provided (and new character entities
+added to entities.h), this set is just to test whether the system works
+in principle (and also how it behaves with incomplete data...)
+
+See the file README.format for a brief explanation of what's in the
+table files.
+
+The examples have names *_uni or *_suni with a .tbl suffix, but it
+doesn't really matter. The auxiliary program makeuctb (MAKE UniCode
+TaBle) is used to "compile" them into C header files, which can be
+included by UCdomap.c.
+
+Ideally, this should be taken care of by the Makefiles. On VMS, use
+build-chrtrans.com to compile and link makeuctb.exe and create the
+set of .h files from the current set of .tbl files. Thereafter, use
+build-header.com to update particular .h files.
+
+To make a new chartrans table available to Lynx (and thereby make a new
+charset known to Lynx) you currently have to manually edit UCdomap.c, in
+two places:
+
+a) Near the top, you will find a bunch of lines (some may be commented out)
+
+ #include "<fn>.h"
+
+Add or comment out as you wish. But it is probably safest to leave the
+commonly used ones, referring to "def7_uni.h" and "iso01_uni.h", in place.
+
+b) At the bottom, you will find a bunch of lines (again, some may be
+ commented out by default) of the form
+
+ UC_CHARSET_SETUP_<something>;
+
+which should correspond to the #include lines from a). Again,
+add or subtract as you wish (but preferably consistent with what you
+did under a)...) [The <something> is derived from the charset's MIME name.
+if in doubt, check the last lines of the corresponding ...uni.h file.]
+
+c) To let make automatically notice when you have changed one of the
+ table files, and automatically regenerate the *uni.h file(s),
+you also have to add any new tables to both src/Makefile *and*
+src/chrtrans/Makefile. Or, for auto-config, the equivalent files
+named makefile.in before running ./configure, or makefile after running
+./configure. (That may be inconvenient, but I didn't want to depend
+on features than not all makes may have.) Note that for recompiling
+Lynx, a `make clean' should not be necessary if you have *only* made
+changes to the files in src/chrtrans. On VMS, add entries for new
+tables to build-chrtrans.com, but you can update the particular file
+with build-header.com, then use the top directory's build.com and
+answer 'n' to it's prompts about whether to update the WWWlibrary
+and chrtrans modules.
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/UCkd.h b/gnu/usr.bin/lynx/src/chrtrans/UCkd.h
new file mode 100644
index 00000000000..1e55716e3c3
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/UCkd.h
@@ -0,0 +1,65 @@
+#ifndef _UC_KD_H
+#define _UC_KD_H
+#ifdef NOTDEFINED
+#include <sys/types.h> /* Included via tcp.h. */
+#endif /* NOTDEFINED */
+
+/*
+ * NOTE: THE FOLLOWING #define MAY NEED ADJUSTMENT.
+ * u16 should be an unsigned type of 16 bit length (two octets).
+ * u8 should be an unsigned type of 8 bit length (one octet).
+ */
+#ifndef u16
+#define u16 unsigned short
+#endif /* u16 */
+
+
+#ifndef u8
+#define u8 unsigned char
+#endif /* u8 */
+
+#ifdef NOTDEFINED
+struct consolefontdesc {
+ u_short charcount; /* characters in font (256 or 512) */
+ u_short charheight; /* scan lines per character (1-32) */
+ char *chardata; /* font data in expanded form */
+};
+#endif /* NOTDEFINED */
+typedef char scrnmap_t;
+#define E_TABSZ 256
+
+struct unipair {
+ u16 unicode;
+ u16 fontpos;
+};
+struct unipair_str {
+ u16 unicode;
+ char * replace_str;
+};
+struct unimapdesc {
+ u16 entry_ct;
+ struct unipair *entries;
+};
+struct unimapdesc_str {
+ u16 entry_ct;
+ struct unipair_str *entries;
+ int isdefault;
+ int trydefault;
+};
+
+
+#define UNI_DIRECT_BASE 0xF000 /* start of Direct Font Region */
+#define UNI_DIRECT_MASK 0x01FF /* Direct Font Region bitmask */
+
+#define UC_MAXLEN_ID_APPEND 20
+#define UC_MAXLEN_MIMECSNAME 40
+#define UC_MAXLEN_LYNXCSNAME 40
+#define UC_LEN_LYNXCSNAME 20
+
+#undef EX_OK /* may be defined in system headers */
+#define EX_OK 0 /* successful termination */
+#define EX_USAGE 64 /* command line usage error */
+#define EX_DATAERR 65 /* data format error */
+#define EX_NOINPUT 66 /* cannot open input */
+
+#endif /* _UC_KD_H */
diff --git a/gnu/usr.bin/lynx/src/chrtrans/build-chrtrans.com b/gnu/usr.bin/lynx/src/chrtrans/build-chrtrans.com
new file mode 100644
index 00000000000..b1dd4a71f92
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/build-chrtrans.com
@@ -0,0 +1,159 @@
+$ v = 'f$verify(0)'
+$! BUILD-CHRTRANS.COM
+$!
+$! Command file to build MAKEUCTB.EXE on VMS systems
+$! and then use it to create the chrtrans header files.
+$!
+$! 28-Jun-1997 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for Lynx v2.7.1+fotemods
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$ CHRproc = f$environment("PROCEDURE")
+$ CHRwhere = f$parse(CHRproc,,,"DEVICE") + f$parse(CHRproc,,,"DIRECTORY")
+$!
+$ if p1 .nes. ""
+$ then
+$ CHRcc_opts = "/DEBUG/NOOPT"
+$ CHRlink_opts = "/DEBUG"
+$ else
+$ CHRcc_opts = ""
+$ CHRlink_opts = ""
+$ endif
+$!
+$ Compile_makeuctb:
+$!================
+$ v1 = f$verify(1)
+$!
+$! Compile the Lynx [.SRC.CHRTRANS]makeuctb module.
+$!
+$ v1 = 'f$verify(0)'
+$ IF f$trnlnm("VAXCMSG") .eqs. "DECC$MSG" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/DECC" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/VAXC"
+$ THEN
+$ CHRcompiler := "DECC"
+$ v1 = f$verify(1)
+$! DECC:
+$ cc := cc/decc/prefix=all /nomember 'CHRcc_opts'-
+ /INCLUDE=([-],[--],[--.WWW.Library.Implementation])
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ IF f$search("gnu_cc:[000000]gcclib.olb") .nes. ""
+$ THEN
+$ CHRcompiler := "GNUC"
+$ v1 = f$verify(1)
+$! GNUC:
+$ cc := gcc 'CHRcc_opts'/INCLUDE=([-],[--],[--.WWW.Library.Implementation])
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ CHRcompiler := "VAXC"
+$ v1 = f$verify(1)
+$! VAXC:
+$ cc := cc 'CHRcc_opts'/INCLUDE=([-],[--],[--.WWW.Library.Implementation])
+$ v1 = 'f$verify(0)'
+$ ENDIF
+$ ENDIF
+$!
+$ v1 = f$verify(1)
+$ cc makeuctb
+$ v1 = 'f$verify(0)'
+$!
+$ Link_makeuctb:
+$!=============
+$ v1 = f$verify(1)
+$!
+$! Link the Lynx [.SRC.CHRTRANS]makeuctb module.
+$!
+$ link/exe=makeuctb.exe'CHRlink_opts' makeuctb, -
+sys$disk:[-]'CHRcompiler'.opt/opt
+$ v1 = 'f$verify(0)'
+$!
+$ Create_headers:
+$!==============
+$ v1 = f$verify(1)
+$!
+$! Create the Lynx [.SRC.CHRTRANS] header files.
+$!
+$ makeuctb := $'CHRwhere'makeuctb
+$ define/user sys$output 'CHRwhere'iso01_uni.h !ISO Latin 1
+$ makeuctb iso01_uni.tbl
+$ define/user sys$output 'CHRwhere'cp850_uni.h !DosLatin1 (cp850)
+$ makeuctb cp850_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1252_uni.h !WinLatin1 (cp1252)
+$ makeuctb cp1252_uni.tbl
+$ define/user sys$output 'CHRwhere'cp437_uni.h !DosLatinUS (cp437)
+$ makeuctb cp437_uni.tbl
+$ define/user sys$output 'CHRwhere'dmcs_uni.h !DEC Multinational
+$ makeuctb dmcs_uni.tbl
+$ define/user sys$output 'CHRwhere'mac_uni.h !Macintosh (8 bit)
+$ makeuctb mac_uni.tbl
+$ define/user sys$output 'CHRwhere'next_uni.h !NeXT character set
+$ makeuctb next_uni.tbl
+$ define/user sys$output 'CHRwhere'viscii_uni.h !Vietnamese (VISCII)
+$ makeuctb viscii_uni.tbl
+$ define/user sys$output 'CHRwhere'def7_uni.h !7 bit approximations
+$ makeuctb def7_uni.tbl
+$ define/user sys$output 'CHRwhere'iso02_uni.h !ISO Latin 2
+$ makeuctb iso02_uni.tbl
+$ define/user sys$output 'CHRwhere'cp852_uni.h !DosLatin2 (cp852)
+$ makeuctb cp852_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1250_uni.h !WinLatin2 (cp1250)
+$ makeuctb cp1250_uni.tbl
+$ define/user sys$output 'CHRwhere'iso03_uni.h !ISO Latin 3
+$ makeuctb iso03_uni.tbl
+$ define/user sys$output 'CHRwhere'iso04_uni.h !ISO Latin 4
+$ makeuctb iso04_uni.tbl
+$ define/user sys$output 'CHRwhere'cp775_uni.h !DosBlatRim (cp775)
+$ makeuctb cp775_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1257_uni.h !WinBlatRim (cp1257)
+$ makeuctb cp1257_uni.tbl
+$ define/user sys$output 'CHRwhere'iso05_uni.h !ISO 8859-5 Cyrillic
+$ makeuctb iso05_uni.tbl
+$ define/user sys$output 'CHRwhere'cp866_uni.h !DosCyrillic (cp866)
+$ makeuctb cp866_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1251_uni.h !WinCyrillic (cp1251)
+$ makeuctb cp1251_uni.tbl
+$ define/user sys$output 'CHRwhere'koi8r_uni.h !KOI8-R Cyrillic
+$ makeuctb koi8r_uni.tbl
+$ define/user sys$output 'CHRwhere'iso06_uni.h !ISO 8859-6 Arabic
+$ makeuctb iso06_uni.tbl
+$ define/user sys$output 'CHRwhere'cp864_uni.h !DosArabic (cp864)
+$ makeuctb cp864_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1256_uni.h !WinArabic (cp1256)
+$ makeuctb cp1256_uni.tbl
+$ define/user sys$output 'CHRwhere'iso07_uni.h !ISO 8859-7 Greek
+$ makeuctb iso07_uni.tbl
+$ define/user sys$output 'CHRwhere'cp737_uni.h !DosGreek (cp737)
+$ makeuctb cp737_uni.tbl
+$ define/user sys$output 'CHRwhere'cp869_uni.h !DosGreek2 (cp869)
+$ makeuctb cp869_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1253_uni.h !WinGreek (cp1253)
+$ makeuctb cp1253_uni.tbl
+$ define/user sys$output 'CHRwhere'iso08_uni.h !ISO 8859-8 Hebrew
+$ makeuctb iso08_uni.tbl
+$ define/user sys$output 'CHRwhere'cp862_uni.h !DosHebrew (cp862)
+$ makeuctb cp862_uni.tbl
+$ define/user sys$output 'CHRwhere'cp1255_uni.h !WinHebrew (cp1255)
+$ makeuctb cp1255_uni.tbl
+$ define/user sys$output 'CHRwhere'iso09_uni.h !ISO 8859-9 (Latin 5)
+$ makeuctb iso09_uni.tbl
+$ define/user sys$output 'CHRwhere'iso10_uni.h !ISO 8859-10
+$ makeuctb iso10_uni.tbl
+$ define/user sys$output 'CHRwhere'utf8_uni.h !UNICODE UTF-8
+$ makeuctb utf8_uni.tbl
+$ define/user sys$output 'CHRwhere'rfc_suni.h !RFC 1345 w/o Intro
+$ makeuctb rfc_suni.tbl
+$ define/user sys$output 'CHRwhere'mnem2_suni.h !RFC 1345 Mnemonic
+$ makeuctb mnem2_suni.tbl
+$ define/user sys$output 'CHRwhere'mnem_suni.h !(not used)
+$ makeuctb mnem_suni.tbl
+$ v1 = 'f$verify(0)'
+$ exit
+$!
+$ CLEANUP:
+$ v1 = 'f$verify(0)'
+$ write sys$output "Default directory:"
+$ show default
+$ v1 = f$verify(v)
+$ exit
diff --git a/gnu/usr.bin/lynx/src/chrtrans/build-header.com b/gnu/usr.bin/lynx/src/chrtrans/build-header.com
new file mode 100644
index 00000000000..963825ddc00
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/build-header.com
@@ -0,0 +1,37 @@
+$ v = 'f$verify(0)'
+$! BUILD-HEADER.COM
+$!
+$! Command file to use MAKEUCTB.EXE on VMS systems for creating
+$! a chrtrans header (foo.h) file from a table (foo.tbl) file.
+$! Use the file root as P1, e.g.:
+$!
+$! $ @build-header iso05_uni
+$!
+$! will create iso05_uni.h from iso05_uni.tbl.
+$!
+$! 28-Jun-1997 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for Lynx v2.7.1+fotemods
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$ CHRproc = f$environment("PROCEDURE")
+$ CHRwhere = f$parse(CHRproc,,,"DEVICE") + f$parse(CHRproc,,,"DIRECTORY")
+$!
+$ Create_header:
+$!=============
+$ v1 = f$verify(1)
+$!
+$! Create a Lynx [.SRC.CHRTRANS] header file.
+$!
+$ makeuctb := $'CHRwhere'makeuctb
+$ define/user sys$output 'CHRwhere''P1'.h
+$ makeuctb 'P1'.tbl
+$ v1 = 'f$verify(0)'
+$ exit
+$!
+$ CLEANUP:
+$ v1 = 'f$verify(0)'
+$ write sys$output "Default directory:"
+$ show default
+$ v1 = f$verify(v)
+$ exit
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1250_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1250_uni.tbl
new file mode 100644
index 00000000000..41e8581db04
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1250_uni.tbl
@@ -0,0 +1,281 @@
+#The MIME name of this charset.
+Mwindows-1250
+
+#Name as a Display Charset (used on Options screen)
+OWinLatin2 (cp1250)
+
+#
+# Name: cp1250_WinLatin2 to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1250_WinLatin2 code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1250_WinLatin2 order
+#
+#0x00 U+0000 #NULL
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0A U+000A #LINE FEED
+#0x0B U+000B #VERTICAL TABULATION
+#0x0C U+000C #FORM FEED
+#0x0D U+000D #CARRIAGE RETURN
+#0x0E U+000E #SHIFT OUT
+#0x0F U+000F #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1A U+001A #SUBSTITUTE
+#0x1B U+001B #ESCAPE
+#0x1C U+001C #FILE SEPARATOR
+#0x1D U+001D #GROUP SEPARATOR
+#0x1E U+001E #RECORD SEPARATOR
+#0x1F U+001F #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2A U+002A #ASTERISK
+0x2B U+002B #PLUS SIGN
+0x2C U+002C #COMMA
+0x2D U+002D #HYPHEN-MINUS
+0x2E U+002E #FULL STOP
+0x2F U+002F #SOLIDUS
+0x30 U+0030 #DIGIT ZERO
+0x31 U+0031 #DIGIT ONE
+0x32 U+0032 #DIGIT TWO
+0x33 U+0033 #DIGIT THREE
+0x34 U+0034 #DIGIT FOUR
+0x35 U+0035 #DIGIT FIVE
+0x36 U+0036 #DIGIT SIX
+0x37 U+0037 #DIGIT SEVEN
+0x38 U+0038 #DIGIT EIGHT
+0x39 U+0039 #DIGIT NINE
+0x3A U+003A #COLON
+0x3B U+003B #SEMICOLON
+0x3C U+003C #LESS-THAN SIGN
+0x3D U+003D #EQUALS SIGN
+0x3E U+003E #GREATER-THAN SIGN
+0x3F U+003F #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL LETTER A
+0x42 U+0042 #LATIN CAPITAL LETTER B
+0x43 U+0043 #LATIN CAPITAL LETTER C
+0x44 U+0044 #LATIN CAPITAL LETTER D
+0x45 U+0045 #LATIN CAPITAL LETTER E
+0x46 U+0046 #LATIN CAPITAL LETTER F
+0x47 U+0047 #LATIN CAPITAL LETTER G
+0x48 U+0048 #LATIN CAPITAL LETTER H
+0x49 U+0049 #LATIN CAPITAL LETTER I
+0x4A U+004A #LATIN CAPITAL LETTER J
+0x4B U+004B #LATIN CAPITAL LETTER K
+0x4C U+004C #LATIN CAPITAL LETTER L
+0x4D U+004D #LATIN CAPITAL LETTER M
+0x4E U+004E #LATIN CAPITAL LETTER N
+0x4F U+004F #LATIN CAPITAL LETTER O
+0x50 U+0050 #LATIN CAPITAL LETTER P
+0x51 U+0051 #LATIN CAPITAL LETTER Q
+0x52 U+0052 #LATIN CAPITAL LETTER R
+0x53 U+0053 #LATIN CAPITAL LETTER S
+0x54 U+0054 #LATIN CAPITAL LETTER T
+0x55 U+0055 #LATIN CAPITAL LETTER U
+0x56 U+0056 #LATIN CAPITAL LETTER V
+0x57 U+0057 #LATIN CAPITAL LETTER W
+0x58 U+0058 #LATIN CAPITAL LETTER X
+0x59 U+0059 #LATIN CAPITAL LETTER Y
+0x5A U+005A #LATIN CAPITAL LETTER Z
+0x5B U+005B #LEFT SQUARE BRACKET
+0x5C U+005C #REVERSE SOLIDUS
+0x5D U+005D #RIGHT SQUARE BRACKET
+0x5E U+005E #CIRCUMFLEX ACCENT
+0x5F U+005F #LOW LINE
+0x60 U+0060 #GRAVE ACCENT
+0x61 U+0061 #LATIN SMALL LETTER A
+0x62 U+0062 #LATIN SMALL LETTER B
+0x63 U+0063 #LATIN SMALL LETTER C
+0x64 U+0064 #LATIN SMALL LETTER D
+0x65 U+0065 #LATIN SMALL LETTER E
+0x66 U+0066 #LATIN SMALL LETTER F
+0x67 U+0067 #LATIN SMALL LETTER G
+0x68 U+0068 #LATIN SMALL LETTER H
+0x69 U+0069 #LATIN SMALL LETTER I
+0x6A U+006A #LATIN SMALL LETTER J
+0x6B U+006B #LATIN SMALL LETTER K
+0x6C U+006C #LATIN SMALL LETTER L
+0x6D U+006D #LATIN SMALL LETTER M
+0x6E U+006E #LATIN SMALL LETTER N
+0x6F U+006F #LATIN SMALL LETTER O
+0x70 U+0070 #LATIN SMALL LETTER P
+0x71 U+0071 #LATIN SMALL LETTER Q
+0x72 U+0072 #LATIN SMALL LETTER R
+0x73 U+0073 #LATIN SMALL LETTER S
+0x74 U+0074 #LATIN SMALL LETTER T
+0x75 U+0075 #LATIN SMALL LETTER U
+0x76 U+0076 #LATIN SMALL LETTER V
+0x77 U+0077 #LATIN SMALL LETTER W
+0x78 U+0078 #LATIN SMALL LETTER X
+0x79 U+0079 #LATIN SMALL LETTER Y
+0x7A U+007A #LATIN SMALL LETTER Z
+0x7B U+007B #LEFT CURLY BRACKET
+0x7C U+007C #VERTICAL LINE
+0x7D U+007D #RIGHT CURLY BRACKET
+0x7E U+007E #TILDE
+#0x7F U+007F #DELETE
+#0x80 #UNDEFINED
+#0x81 #UNDEFINED
+0x82 U+201A #SINGLE LOW-9 QUOTATION MARK
+#0x83 #UNDEFINED
+0x84 U+201E #DOUBLE LOW-9 QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+#0x88 #UNDEFINED
+0x89 U+2030 #PER MILLE SIGN
+0x8A U+0160 #LATIN CAPITAL LETTER S WITH CARON
+0x8B U+2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C U+015A #LATIN CAPITAL LETTER S WITH ACUTE
+0x8D U+0164 #LATIN CAPITAL LETTER T WITH CARON
+0x8E U+017D #LATIN CAPITAL LETTER Z WITH CARON
+0x8F U+0179 #LATIN CAPITAL LETTER Z WITH ACUTE
+#0x90 #UNDEFINED
+0x91 U+2018 #LEFT SINGLE QUOTATION MARK
+0x92 U+2019 #RIGHT SINGLE QUOTATION MARK
+0x93 U+201C #LEFT DOUBLE QUOTATION MARK
+0x94 U+201D #RIGHT DOUBLE QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+#0x98 #UNDEFINED
+0x99 U+2122 #TRADE MARK SIGN
+0x9A U+0161 #LATIN SMALL LETTER S WITH CARON
+0x9B U+203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C U+015B #LATIN SMALL LETTER S WITH ACUTE
+0x9D U+0165 #LATIN SMALL LETTER T WITH CARON
+0x9E U+017E #LATIN SMALL LETTER Z WITH CARON
+0x9F U+017A #LATIN SMALL LETTER Z WITH ACUTE
+0xA0 U+00A0 #NO-BREAK SPACE
+0xA1 U+02C7 #CARON
+0xA2 U+02D8 #BREVE
+0xA3 U+0141 #LATIN CAPITAL LETTER L WITH STROKE
+0xA4 U+00A4 #CURRENCY SIGN
+0xA5 U+0104 #LATIN CAPITAL LETTER A WITH OGONEK
+0xA6 U+00A6 #BROKEN BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+00A8 #DIAERESIS
+0xA9 U+00A9 #COPYRIGHT SIGN
+0xAA U+015E #LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB U+00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+#0xAC #UNDEFINED
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED SIGN
+0xAF U+017B #LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-MINUS SIGN
+0xB2 U+02DB #OGONEK
+0xB3 U+0142 #LATIN SMALL LETTER L WITH STROKE
+0xB4 U+00B4 #ACUTE ACCENT
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PILCROW SIGN
+0xB7 U+00B7 #MIDDLE DOT
+0xB8 U+00B8 #CEDILLA
+0xB9 U+0105 #LATIN SMALL LETTER A WITH OGONEK
+0xBA U+015F #LATIN SMALL LETTER S WITH CEDILLA
+0xBB U+00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+013D #LATIN CAPITAL LETTER L WITH CARON
+0xBD U+02DD #DOUBLE ACUTE ACCENT
+0xBE U+013E #LATIN SMALL LETTER L WITH CARON
+0xBF U+017C #LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 U+0154 #LATIN CAPITAL LETTER R WITH ACUTE
+0xC1 U+00C1 #LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 U+00C2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 U+0102 #LATIN CAPITAL LETTER A WITH BREVE
+0xC4 U+00C4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 U+0139 #LATIN CAPITAL LETTER L WITH ACUTE
+0xC6 U+0106 #LATIN CAPITAL LETTER C WITH ACUTE
+0xC7 U+00C7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 U+010C #LATIN CAPITAL LETTER C WITH CARON
+0xC9 U+00C9 #LATIN CAPITAL LETTER E WITH ACUTE
+0xCA U+0118 #LATIN CAPITAL LETTER E WITH OGONEK
+0xCB U+00CB #LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC U+011A #LATIN CAPITAL LETTER E WITH CARON
+0xCD U+00CD #LATIN CAPITAL LETTER I WITH ACUTE
+0xCE U+00CE #LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF U+010E #LATIN CAPITAL LETTER D WITH CARON
+0xD0 U+0110 #LATIN CAPITAL LETTER D WITH STROKE
+0xD1 U+0143 #LATIN CAPITAL LETTER N WITH ACUTE
+0xD2 U+0147 #LATIN CAPITAL LETTER N WITH CARON
+0xD3 U+00D3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 U+00D4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 U+0150 #LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6 U+00D6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 U+00D7 #MULTIPLICATION SIGN
+0xD8 U+0158 #LATIN CAPITAL LETTER R WITH CARON
+0xD9 U+016E #LATIN CAPITAL LETTER U WITH RING ABOVE
+0xDA U+00DA #LATIN CAPITAL LETTER U WITH ACUTE
+0xDB U+0170 #LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xDC U+00DC #LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD U+00DD #LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE U+0162 #LATIN CAPITAL LETTER T WITH CEDILLA
+0xDF U+00DF #LATIN SMALL LETTER SHARP S
+0xE0 U+0155 #LATIN SMALL LETTER R WITH ACUTE
+0xE1 U+00E1 #LATIN SMALL LETTER A WITH ACUTE
+0xE2 U+00E2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 U+0103 #LATIN SMALL LETTER A WITH BREVE
+0xE4 U+00E4 #LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 U+013A #LATIN SMALL LETTER L WITH ACUTE
+0xE6 U+0107 #LATIN SMALL LETTER C WITH ACUTE
+0xE7 U+00E7 #LATIN SMALL LETTER C WITH CEDILLA
+0xE8 U+010D #LATIN SMALL LETTER C WITH CARON
+0xE9 U+00E9 #LATIN SMALL LETTER E WITH ACUTE
+0xEA U+0119 #LATIN SMALL LETTER E WITH OGONEK
+0xEB U+00EB #LATIN SMALL LETTER E WITH DIAERESIS
+0xEC U+011B #LATIN SMALL LETTER E WITH CARON
+0xED U+00ED #LATIN SMALL LETTER I WITH ACUTE
+0xEE U+00EE #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF U+010F #LATIN SMALL LETTER D WITH CARON
+0xF0 U+0111 #LATIN SMALL LETTER D WITH STROKE
+0xF1 U+0144 #LATIN SMALL LETTER N WITH ACUTE
+0xF2 U+0148 #LATIN SMALL LETTER N WITH CARON
+0xF3 U+00F3 #LATIN SMALL LETTER O WITH ACUTE
+0xF4 U+00F4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 U+0151 #LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6 U+00F6 #LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 U+00F7 #DIVISION SIGN
+0xF8 U+0159 #LATIN SMALL LETTER R WITH CARON
+0xF9 U+016F #LATIN SMALL LETTER U WITH RING ABOVE
+0xFA U+00FA #LATIN SMALL LETTER U WITH ACUTE
+0xFB U+0171 #LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xFC U+00FC #LATIN SMALL LETTER U WITH DIAERESIS
+0xFD U+00FD #LATIN SMALL LETTER Y WITH ACUTE
+0xFE U+0163 #LATIN SMALL LETTER T WITH CEDILLA
+0xFF U+02D9 #DOT ABOVE
+
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1251_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1251_uni.tbl
new file mode 100644
index 00000000000..e9bb94606c2
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1251_uni.tbl
@@ -0,0 +1,154 @@
+#The MIME name of this charset.
+Mwindows-1251
+
+#Name as a Display Charset (used on Options screen)
+OWinCyrillic (cp1251)
+
+#
+# Name: cp1251_WinCyrillic to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1251_WinCyrillic code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1251_WinCyrillic order
+#
+#
+0x20-0x7f idem
+#
+0x80 U+0402 #CYRILLIC CAPITAL LETTER DJE
+0x81 U+0403 #CYRILLIC CAPITAL LETTER GJE
+0x82 U+201A #SINGLE LOW-9 QUOTATION MARK
+0x83 U+0453 #CYRILLIC SMALL LETTER GJE
+0x84 U+201E #DOUBLE LOW-9 QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+#0x88 #UNDEFINED
+0x89 U+2030 #PER MILLE SIGN
+0x8A U+0409 #CYRILLIC CAPITAL LETTER LJE
+0x8B U+2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8C U+040A #CYRILLIC CAPITAL LETTER NJE
+0x8D U+040C #CYRILLIC CAPITAL LETTER KJE
+0x8E U+040B #CYRILLIC CAPITAL LETTER TSHE
+0x8F U+040F #CYRILLIC CAPITAL LETTER DZHE
+0x90 U+0452 #CYRILLIC SMALL LETTER DJE
+0x91 U+2018 #LEFT SINGLE QUOTATION MARK
+0x92 U+2019 #RIGHT SINGLE QUOTATION MARK
+0x93 U+201C #LEFT DOUBLE QUOTATION MARK
+0x94 U+201D #RIGHT DOUBLE QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+#0x98 #UNDEFINED
+0x99 U+2122 #TRADE MARK SIGN
+0x9A U+0459 #CYRILLIC SMALL LETTER LJE
+0x9B U+203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9C U+045A #CYRILLIC SMALL LETTER NJE
+0x9D U+045C #CYRILLIC SMALL LETTER KJE
+0x9E U+045B #CYRILLIC SMALL LETTER TSHE
+0x9F U+045F #CYRILLIC SMALL LETTER DZHE
+0xA0 U+00A0 #NO-BREAK SPACE
+0xA1 U+040E #CYRILLIC CAPITAL LETTER SHORT U
+0xA2 U+045E #CYRILLIC SMALL LETTER SHORT U
+0xA3 U+0408 #CYRILLIC CAPITAL LETTER JE
+0xA4 U+00A4 #CURRENCY SIGN
+0xA5 U+0490 #CYRILLIC CAPITAL LETTER GHE WITH UPTURN
+0xA6 U+00A6 #BROKEN BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+0401 #CYRILLIC CAPITAL LETTER IO
+0xA9 U+00A9 #COPYRIGHT SIGN
+0xAA U+0404 #CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xAB U+00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC U+00AC #NOT SIGN
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED SIGN
+0xAF U+0407 #CYRILLIC CAPITAL LETTER YI
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-MINUS SIGN
+0xB2 U+0406 #CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB3 U+0456 #CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xB4 U+0491 #CYRILLIC SMALL LETTER GHE WITH UPTURN
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PILCROW SIGN
+0xB7 U+00B7 #MIDDLE DOT
+0xB8 U+0451 #CYRILLIC SMALL LETTER IO
+0xB9 U+2116 #NUMERO SIGN
+0xBA U+0454 #CYRILLIC SMALL LETTER UKRAINIAN IE
+0xBB U+00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+0458 #CYRILLIC SMALL LETTER JE
+0xBD U+0405 #CYRILLIC CAPITAL LETTER DZE
+0xBE U+0455 #CYRILLIC SMALL LETTER DZE
+0xBF U+0457 #CYRILLIC SMALL LETTER YI
+0xC0 U+0410 #CYRILLIC CAPITAL LETTER A
+0xC1 U+0411 #CYRILLIC CAPITAL LETTER BE
+0xC2 U+0412 #CYRILLIC CAPITAL LETTER VE
+0xC3 U+0413 #CYRILLIC CAPITAL LETTER GHE
+0xC4 U+0414 #CYRILLIC CAPITAL LETTER DE
+0xC5 U+0415 #CYRILLIC CAPITAL LETTER IE
+0xC6 U+0416 #CYRILLIC CAPITAL LETTER ZHE
+0xC7 U+0417 #CYRILLIC CAPITAL LETTER ZE
+0xC8 U+0418 #CYRILLIC CAPITAL LETTER I
+0xC9 U+0419 #CYRILLIC CAPITAL LETTER SHORT I
+0xCA U+041A #CYRILLIC CAPITAL LETTER KA
+0xCB U+041B #CYRILLIC CAPITAL LETTER EL
+0xCC U+041C #CYRILLIC CAPITAL LETTER EM
+0xCD U+041D #CYRILLIC CAPITAL LETTER EN
+0xCE U+041E #CYRILLIC CAPITAL LETTER O
+0xCF U+041F #CYRILLIC CAPITAL LETTER PE
+0xD0 U+0420 #CYRILLIC CAPITAL LETTER ER
+0xD1 U+0421 #CYRILLIC CAPITAL LETTER ES
+0xD2 U+0422 #CYRILLIC CAPITAL LETTER TE
+0xD3 U+0423 #CYRILLIC CAPITAL LETTER U
+0xD4 U+0424 #CYRILLIC CAPITAL LETTER EF
+0xD5 U+0425 #CYRILLIC CAPITAL LETTER HA
+0xD6 U+0426 #CYRILLIC CAPITAL LETTER TSE
+0xD7 U+0427 #CYRILLIC CAPITAL LETTER CHE
+0xD8 U+0428 #CYRILLIC CAPITAL LETTER SHA
+0xD9 U+0429 #CYRILLIC CAPITAL LETTER SHCHA
+0xDA U+042A #CYRILLIC CAPITAL LETTER HARD SIGN
+0xDB U+042B #CYRILLIC CAPITAL LETTER YERU
+0xDC U+042C #CYRILLIC CAPITAL LETTER SOFT SIGN
+0xDD U+042D #CYRILLIC CAPITAL LETTER E
+0xDE U+042E #CYRILLIC CAPITAL LETTER YU
+0xDF U+042F #CYRILLIC CAPITAL LETTER YA
+0xE0 U+0430 #CYRILLIC SMALL LETTER A
+0xE1 U+0431 #CYRILLIC SMALL LETTER BE
+0xE2 U+0432 #CYRILLIC SMALL LETTER VE
+0xE3 U+0433 #CYRILLIC SMALL LETTER GHE
+0xE4 U+0434 #CYRILLIC SMALL LETTER DE
+0xE5 U+0435 #CYRILLIC SMALL LETTER IE
+0xE6 U+0436 #CYRILLIC SMALL LETTER ZHE
+0xE7 U+0437 #CYRILLIC SMALL LETTER ZE
+0xE8 U+0438 #CYRILLIC SMALL LETTER I
+0xE9 U+0439 #CYRILLIC SMALL LETTER SHORT I
+0xEA U+043A #CYRILLIC SMALL LETTER KA
+0xEB U+043B #CYRILLIC SMALL LETTER EL
+0xEC U+043C #CYRILLIC SMALL LETTER EM
+0xED U+043D #CYRILLIC SMALL LETTER EN
+0xEE U+043E #CYRILLIC SMALL LETTER O
+0xEF U+043F #CYRILLIC SMALL LETTER PE
+0xF0 U+0440 #CYRILLIC SMALL LETTER ER
+0xF1 U+0441 #CYRILLIC SMALL LETTER ES
+0xF2 U+0442 #CYRILLIC SMALL LETTER TE
+0xF3 U+0443 #CYRILLIC SMALL LETTER U
+0xF4 U+0444 #CYRILLIC SMALL LETTER EF
+0xF5 U+0445 #CYRILLIC SMALL LETTER HA
+0xF6 U+0446 #CYRILLIC SMALL LETTER TSE
+0xF7 U+0447 #CYRILLIC SMALL LETTER CHE
+0xF8 U+0448 #CYRILLIC SMALL LETTER SHA
+0xF9 U+0449 #CYRILLIC SMALL LETTER SHCHA
+0xFA U+044A #CYRILLIC SMALL LETTER HARD SIGN
+0xFB U+044B #CYRILLIC SMALL LETTER YERU
+0xFC U+044C #CYRILLIC SMALL LETTER SOFT SIGN
+0xFD U+044D #CYRILLIC SMALL LETTER E
+0xFE U+044E #CYRILLIC SMALL LETTER YU
+0xFF U+044F #CYRILLIC SMALL LETTER YA
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1252_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1252_uni.tbl
new file mode 100644
index 00000000000..d8adb2fa79e
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1252_uni.tbl
@@ -0,0 +1,285 @@
+#Shall this become the "default" translation?
+#There has to be exactly one table marked as "default".
+D0
+#
+#The MIME name of this charset.
+Mwindows-1252
+
+#Name as a Display Charset (used on Options screen)
+OWinLatin1 (cp1252)
+
+#
+# Name: cp1252_WinLatin1 to Unicode table
+# Unicode version: 1.1
+# Table version: 1.1
+# Table format: Format A
+# Date: 03/31/95
+# Authors: Michel Suignard <michelsu@microsoft.com>
+# Lori Hoerth <lorih@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1252_WinLatin1 code (in hex)
+# Column #2 is the Unicode (in hex as U+XXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1252_WinLatin1 order
+#
+#0x00 U+0000 #Null
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0a U+000a #LINE FEED
+#0x0b U+000b #VERTICAL TABULATION
+#0x0c U+000c #FORM FEED
+#0x0d U+000d #CARRIAGE RETURN
+#0x0e U+000e #SHIFT OUT
+#0x0f U+000f #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1a U+001a #SUBSTITUTE
+#0x1b U+001b #ESCAPE
+#0x1c U+001c #FILE SEPARATOR
+#0x1d U+001d #GROUP SEPARATOR
+#0x1e U+001e #RECORD SEPARATOR
+#0x1f U+001f #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2a U+002a #ASTERISK
+0x2b U+002b #PLUS SIGN
+0x2c U+002c #COMMA
+0x2d U+002d #HYPHEN-MINUS
+0x2e U+002e #FULL STOP
+0x2f U+002f #SOLIDUS
+0x30 U+0030 #DIGIT ZERO
+0x31 U+0031 #DIGIT ONE
+0x32 U+0032 #DIGIT TWO
+0x33 U+0033 #DIGIT THREE
+0x34 U+0034 #DIGIT FOUR
+0x35 U+0035 #DIGIT FIVE
+0x36 U+0036 #DIGIT SIX
+0x37 U+0037 #DIGIT SEVEN
+0x38 U+0038 #DIGIT EIGHT
+0x39 U+0039 #DIGIT NINE
+0x3a U+003a #COLON
+0x3b U+003b #SEMICOLON
+0x3c U+003c #LESS-THAN SIGN
+0x3d U+003d #EQUALS SIGN
+0x3e U+003e #GREATER-THAN SIGN
+0x3f U+003f #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL LETTER A
+0x42 U+0042 #LATIN CAPITAL LETTER B
+0x43 U+0043 #LATIN CAPITAL LETTER C
+0x44 U+0044 #LATIN CAPITAL LETTER D
+0x45 U+0045 #LATIN CAPITAL LETTER E
+0x46 U+0046 #LATIN CAPITAL LETTER F
+0x47 U+0047 #LATIN CAPITAL LETTER G
+0x48 U+0048 #LATIN CAPITAL LETTER H
+0x49 U+0049 #LATIN CAPITAL LETTER I
+0x4a U+004a #LATIN CAPITAL LETTER J
+0x4b U+004b #LATIN CAPITAL LETTER K
+0x4c U+004c #LATIN CAPITAL LETTER L
+0x4d U+004d #LATIN CAPITAL LETTER M
+0x4e U+004e #LATIN CAPITAL LETTER N
+0x4f U+004f #LATIN CAPITAL LETTER O
+0x50 U+0050 #LATIN CAPITAL LETTER P
+0x51 U+0051 #LATIN CAPITAL LETTER Q
+0x52 U+0052 #LATIN CAPITAL LETTER R
+0x53 U+0053 #LATIN CAPITAL LETTER S
+0x54 U+0054 #LATIN CAPITAL LETTER T
+0x55 U+0055 #LATIN CAPITAL LETTER U
+0x56 U+0056 #LATIN CAPITAL LETTER V
+0x57 U+0057 #LATIN CAPITAL LETTER W
+0x58 U+0058 #LATIN CAPITAL LETTER X
+0x59 U+0059 #LATIN CAPITAL LETTER Y
+0x5a U+005a #LATIN CAPITAL LETTER Z
+0x5b U+005b #LEFT SQUARE BRACKET
+0x5c U+005c #REVERSE SOLIDUS
+0x5d U+005d #RIGHT SQUARE BRACKET
+0x5e U+005e #CIRCUMFLEX ACCENT
+0x5f U+005f #LOW LINE
+0x60 U+0060 #GRAVE ACCENT
+0x61 U+0061 #LATIN SMALL LETTER A
+0x62 U+0062 #LATIN SMALL LETTER B
+0x63 U+0063 #LATIN SMALL LETTER C
+0x64 U+0064 #LATIN SMALL LETTER D
+0x65 U+0065 #LATIN SMALL LETTER E
+0x66 U+0066 #LATIN SMALL LETTER F
+0x67 U+0067 #LATIN SMALL LETTER G
+0x68 U+0068 #LATIN SMALL LETTER H
+0x69 U+0069 #LATIN SMALL LETTER I
+0x6a U+006a #LATIN SMALL LETTER J
+0x6b U+006b #LATIN SMALL LETTER K
+0x6c U+006c #LATIN SMALL LETTER L
+0x6d U+006d #LATIN SMALL LETTER M
+0x6e U+006e #LATIN SMALL LETTER N
+0x6f U+006f #LATIN SMALL LETTER O
+0x70 U+0070 #LATIN SMALL LETTER P
+0x71 U+0071 #LATIN SMALL LETTER Q
+0x72 U+0072 #LATIN SMALL LETTER R
+0x73 U+0073 #LATIN SMALL LETTER S
+0x74 U+0074 #LATIN SMALL LETTER T
+0x75 U+0075 #LATIN SMALL LETTER U
+0x76 U+0076 #LATIN SMALL LETTER V
+0x77 U+0077 #LATIN SMALL LETTER W
+0x78 U+0078 #LATIN SMALL LETTER X
+0x79 U+0079 #LATIN SMALL LETTER Y
+0x7a U+007a #LATIN SMALL LETTER Z
+0x7b U+007b #LEFT CURLY BRACKET
+0x7c U+007c #VERTICAL LINE
+0x7d U+007d #RIGHT CURLY BRACKET
+0x7e U+007e #TILDE
+0x7f U+007f #DELETE
+#0x80 U+0080 #NOT USED
+#0x81 U+0081 #NOT USED
+0x82 U+201a #SINGLE LOW-9 QUOTATION MARK
+0x83 U+0192 #LATIN SMALL LETTER F WITH HOOK
+0x84 U+201e #DOUBLE LOW-9 QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+0x88 U+02c6 #MODIFIER LETTER CIRCUMFLEX ACCENT
+0x89 U+2030 #PER MILLE SIGN
+0x8a U+0160 #LATIN CAPITAL LETTER S WITH CARON
+0x8b U+2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x8c U+0152 #LATIN CAPITAL LIGATURE OE
+#0x8d U+008d #NOT USED
+#0x8e U+008e #NOT USED
+#0x8f U+008f #NOT USED
+#0x90 U+0090 #NOT USED
+0x91 U+2018 #LEFT SINGLE QUOTATION MARK
+0x92 U+2019 #RIGHT SINGLE QUOTATION MARK
+0x93 U+201c #LEFT DOUBLE QUOTATION MARK
+0x94 U+201d #RIGHT DOUBLE QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+0x98 U+02dc #SMALL TILDE
+0x99 U+2122 #TRADE MARK SIGN
+0x9a U+0161 #LATIN SMALL LETTER S WITH CARON
+0x9b U+203a #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x9c U+0153 #LATIN SMALL LIGATURE OE
+#0x9d U+009d #NOT USED
+#0x9e U+009e #NOT USED
+0x9f U+0178 #LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xa0 U+00a0 #NO-BREAK SPACE
+0xa1 U+00a1 #INVERTED EXCLAMATION MARK
+0xa2 U+00a2 #CENT SIGN
+0xa3 U+00a3 #POUND SIGN
+0xa4 U+00a4 #CURRENCY SIGN
+0xa5 U+00a5 #YEN SIGN
+0xa6 U+00a6 #BROKEN BAR
+0xa7 U+00a7 #SECTION SIGN
+0xa8 U+00a8 #DIAERESIS
+0xa9 U+00a9 #COPYRIGHT SIGN
+0xaa U+00aa #FEMININE ORDINAL INDICATOR
+0xab U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xac U+00ac #NOT SIGN
+0xad U+00ad #SOFT HYPHEN
+0xae U+00ae #REGISTERED SIGN
+0xaf U+00af #MACRON
+0xb0 U+00b0 #DEGREE SIGN
+0xb1 U+00b1 #PLUS-MINUS SIGN
+0xb2 U+00b2 #SUPERSCRIPT TWO
+0xb3 U+00b3 #SUPERSCRIPT THREE
+0xb4 U+00b4 #ACUTE ACCENT
+0xb5 U+00b5 #MICRO SIGN
+0xb6 U+00b6 #PILCROW SIGN
+0xb7 U+00b7 #MIDDLE DOT
+0xb8 U+00b8 #CEDILLA
+0xb9 U+00b9 #SUPERSCRIPT ONE
+0xba U+00ba #MASCULINE ORDINAL INDICATOR
+0xbb U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xbc U+00bc #VULGAR FRACTION ONE QUARTER
+0xbd U+00bd #VULGAR FRACTION ONE HALF
+0xbe U+00be #VULGAR FRACTION THREE QUARTERS
+0xbf U+00bf #INVERTED QUESTION MARK
+0xc0 U+00c0 #LATIN CAPITAL LETTER A WITH GRAVE
+0xc1 U+00c1 #LATIN CAPITAL LETTER A WITH ACUTE
+0xc2 U+00c2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xc3 U+00c3 #LATIN CAPITAL LETTER A WITH TILDE
+0xc4 U+00c4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0xc5 U+00c5 #LATIN CAPITAL LETTER A WITH RING ABOVE
+0xc6 U+00c6 #LATIN CAPITAL LIGATURE AE
+0xc7 U+00c7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0xc8 U+00c8 #LATIN CAPITAL LETTER E WITH GRAVE
+0xc9 U+00c9 #LATIN CAPITAL LETTER E WITH ACUTE
+0xca U+00ca #LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xcb U+00cb #LATIN CAPITAL LETTER E WITH DIAERESIS
+0xcc U+00cc #LATIN CAPITAL LETTER I WITH GRAVE
+0xcd U+00cd #LATIN CAPITAL LETTER I WITH ACUTE
+0xce U+00ce #LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xcf U+00cf #LATIN CAPITAL LETTER I WITH DIAERESIS
+0xd0 U+00d0 #LATIN CAPITAL LETTER ETH
+0xd1 U+00d1 #LATIN CAPITAL LETTER N WITH TILDE
+0xd2 U+00d2 #LATIN CAPITAL LETTER O WITH GRAVE
+0xd3 U+00d3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xd4 U+00d4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xd5 U+00d5 #LATIN CAPITAL LETTER O WITH TILDE
+0xd6 U+00d6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0xd7 U+00d7 #MULTIPLICATION SIGN
+0xd8 U+00d8 #LATIN CAPITAL LETTER O WITH STROKE
+0xd9 U+00d9 #LATIN CAPITAL LETTER U WITH GRAVE
+0xda U+00da #LATIN CAPITAL LETTER U WITH ACUTE
+0xdb U+00db #LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xdc U+00dc #LATIN CAPITAL LETTER U WITH DIAERESIS
+0xdd U+00dd #LATIN CAPITAL LETTER Y WITH ACUTE
+0xde U+00de #LATIN CAPITAL LETTER THORN
+0xdf U+00df #LATIN SMALL LETTER SHARP S
+0xe0 U+00e0 #LATIN SMALL LETTER A WITH GRAVE
+0xe1 U+00e1 #LATIN SMALL LETTER A WITH ACUTE
+0xe2 U+00e2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xe3 U+00e3 #LATIN SMALL LETTER A WITH TILDE
+0xe4 U+00e4 #LATIN SMALL LETTER A WITH DIAERESIS
+0xe5 U+00e5 #LATIN SMALL LETTER A WITH RING ABOVE
+0xe6 U+00e6 #LATIN SMALL LIGATURE AE
+0xe7 U+00e7 #LATIN SMALL LETTER C WITH CEDILLA
+0xe8 U+00e8 #LATIN SMALL LETTER E WITH GRAVE
+0xe9 U+00e9 #LATIN SMALL LETTER E WITH ACUTE
+0xea U+00ea #LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xeb U+00eb #LATIN SMALL LETTER E WITH DIAERESIS
+0xec U+00ec #LATIN SMALL LETTER I WITH GRAVE
+0xed U+00ed #LATIN SMALL LETTER I WITH ACUTE
+0xee U+00ee #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xef U+00ef #LATIN SMALL LETTER I WITH DIAERESIS
+0xf0 U+00f0 #LATIN SMALL LETTER ETH
+0xf1 U+00f1 #LATIN SMALL LETTER N WITH TILDE
+0xf2 U+00f2 #LATIN SMALL LETTER O WITH GRAVE
+0xf3 U+00f3 #LATIN SMALL LETTER O WITH ACUTE
+0xf4 U+00f4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xf5 U+00f5 #LATIN SMALL LETTER O WITH TILDE
+0xf6 U+00f6 #LATIN SMALL LETTER O WITH DIAERESIS
+0xf7 U+00f7 #DIVISION SIGN
+0xf8 U+00f8 #LATIN SMALL LETTER O WITH STROKE
+0xf9 U+00f9 #LATIN SMALL LETTER U WITH GRAVE
+0xfa U+00fa #LATIN SMALL LETTER U WITH ACUTE
+0xfb U+00fb #LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xfc U+00fc #LATIN SMALL LETTER U WITH DIAERESIS
+0xfd U+00fd #LATIN SMALL LETTER Y WITH ACUTE
+0xfe U+00fe #LATIN SMALL LETTER THORN
+0xff U+00ff #LATIN SMALL LETTER Y WITH DIAERESIS
+
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1253_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1253_uni.tbl
new file mode 100644
index 00000000000..097dae2bb15
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1253_uni.tbl
@@ -0,0 +1,154 @@
+#The MIME name of this charset.
+Mwindows-1253
+
+#Name as a Display Charset (used on Options screen)
+OWinGreek (cp1253)
+
+# Name: cp1253_WinGreek to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1253_WinGreek code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1253_WinGreek order
+#
+##################
+
+0x20-0x7f idem
+#
+#0x80 #UNDEFINED
+#0x81 #UNDEFINED
+0x82 U+201A #SINGLE LOW-9 QUOTATION MARK
+0x83 U+0192 #LATIN SMALL LETTER F WITH HOOK
+0x84 U+201E #DOUBLE LOW-9 QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+#0x88 #UNDEFINED
+0x89 U+2030 #PER MILLE SIGN
+#0x8A #UNDEFINED
+0x8B U+2039 #SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+#0x8C #UNDEFINED
+#0x8D #UNDEFINED
+#0x8E #UNDEFINED
+#0x8F #UNDEFINED
+#0x90 #UNDEFINED
+0x91 U+2018 #LEFT SINGLE QUOTATION MARK
+0x92 U+2019 #RIGHT SINGLE QUOTATION MARK
+0x93 U+201C #LEFT DOUBLE QUOTATION MARK
+0x94 U+201D #RIGHT DOUBLE QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+#0x98 #UNDEFINED
+0x99 U+2122 #TRADE MARK SIGN
+#0x9A #UNDEFINED
+0x9B U+203A #SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+#0x9C #UNDEFINED
+#0x9D #UNDEFINED
+#0x9E #UNDEFINED
+#0x9F #UNDEFINED
+0xA0 U+00A0 #NO-BREAK SPACE
+0xA1 U+0385 #GREEK DIALYTIKA TONOS
+0xA2 U+0386 #GREEK CAPITAL LETTER ALPHA WITH TONOS
+0xA3 U+00A3 #POUND SIGN
+0xA4 U+00A4 #CURRENCY SIGN
+0xA5 U+00A5 #YEN SIGN
+0xA6 U+00A6 #BROKEN BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+00A8 #DIAERESIS
+0xA9 U+00A9 #COPYRIGHT SIGN
+#0xAA #UNDEFINED
+0xAB U+00AB #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC U+00AC #NOT SIGN
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED SIGN
+0xAF U+2015 #HORIZONTAL BAR
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-MINUS SIGN
+0xB2 U+00B2 #SUPERSCRIPT TWO
+0xB3 U+00B3 #SUPERSCRIPT THREE
+0xB4 U+0384 #GREEK TONOS
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PILCROW SIGN
+0xB7 U+00B7 #MIDDLE DOT
+0xB8 U+0388 #GREEK CAPITAL LETTER EPSILON WITH TONOS
+0xB9 U+0389 #GREEK CAPITAL LETTER ETA WITH TONOS
+0xBA U+038A #GREEK CAPITAL LETTER IOTA WITH TONOS
+0xBB U+00BB #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+038C #GREEK CAPITAL LETTER OMICRON WITH TONOS
+0xBD U+00BD #VULGAR FRACTION ONE HALF
+0xBE U+038E #GREEK CAPITAL LETTER UPSILON WITH TONOS
+0xBF U+038F #GREEK CAPITAL LETTER OMEGA WITH TONOS
+0xC0 U+0390 #GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0xC1 U+0391 #GREEK CAPITAL LETTER ALPHA
+0xC2 U+0392 #GREEK CAPITAL LETTER BETA
+0xC3 U+0393 #GREEK CAPITAL LETTER GAMMA
+0xC4 U+0394 #GREEK CAPITAL LETTER DELTA
+0xC5 U+0395 #GREEK CAPITAL LETTER EPSILON
+0xC6 U+0396 #GREEK CAPITAL LETTER ZETA
+0xC7 U+0397 #GREEK CAPITAL LETTER ETA
+0xC8 U+0398 #GREEK CAPITAL LETTER THETA
+0xC9 U+0399 #GREEK CAPITAL LETTER IOTA
+0xCA U+039A #GREEK CAPITAL LETTER KAPPA
+0xCB U+039B #GREEK CAPITAL LETTER LAMDA
+0xCC U+039C #GREEK CAPITAL LETTER MU
+0xCD U+039D #GREEK CAPITAL LETTER NU
+0xCE U+039E #GREEK CAPITAL LETTER XI
+0xCF U+039F #GREEK CAPITAL LETTER OMICRON
+0xD0 U+03A0 #GREEK CAPITAL LETTER PI
+0xD1 U+03A1 #GREEK CAPITAL LETTER RHO
+#0xD2 #UNDEFINED
+0xD3 U+03A3 #GREEK CAPITAL LETTER SIGMA
+0xD4 U+03A4 #GREEK CAPITAL LETTER TAU
+0xD5 U+03A5 #GREEK CAPITAL LETTER UPSILON
+0xD6 U+03A6 #GREEK CAPITAL LETTER PHI
+0xD7 U+03A7 #GREEK CAPITAL LETTER CHI
+0xD8 U+03A8 #GREEK CAPITAL LETTER PSI
+0xD9 U+03A9 #GREEK CAPITAL LETTER OMEGA
+0xDA U+03AA #GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0xDB U+03AB #GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0xDC U+03AC #GREEK SMALL LETTER ALPHA WITH TONOS
+0xDD U+03AD #GREEK SMALL LETTER EPSILON WITH TONOS
+0xDE U+03AE #GREEK SMALL LETTER ETA WITH TONOS
+0xDF U+03AF #GREEK SMALL LETTER IOTA WITH TONOS
+0xE0 U+03B0 #GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0xE1 U+03B1 #GREEK SMALL LETTER ALPHA
+0xE2 U+03B2 #GREEK SMALL LETTER BETA
+0xE3 U+03B3 #GREEK SMALL LETTER GAMMA
+0xE4 U+03B4 #GREEK SMALL LETTER DELTA
+0xE5 U+03B5 #GREEK SMALL LETTER EPSILON
+0xE6 U+03B6 #GREEK SMALL LETTER ZETA
+0xE7 U+03B7 #GREEK SMALL LETTER ETA
+0xE8 U+03B8 #GREEK SMALL LETTER THETA
+0xE9 U+03B9 #GREEK SMALL LETTER IOTA
+0xEA U+03BA #GREEK SMALL LETTER KAPPA
+0xEB U+03BB #GREEK SMALL LETTER LAMDA
+0xEC U+03BC #GREEK SMALL LETTER MU
+0xED U+03BD #GREEK SMALL LETTER NU
+0xEE U+03BE #GREEK SMALL LETTER XI
+0xEF U+03BF #GREEK SMALL LETTER OMICRON
+0xF0 U+03C0 #GREEK SMALL LETTER PI
+0xF1 U+03C1 #GREEK SMALL LETTER RHO
+0xF2 U+03C2 #GREEK SMALL LETTER FINAL SIGMA
+0xF3 U+03C3 #GREEK SMALL LETTER SIGMA
+0xF4 U+03C4 #GREEK SMALL LETTER TAU
+0xF5 U+03C5 #GREEK SMALL LETTER UPSILON
+0xF6 U+03C6 #GREEK SMALL LETTER PHI
+0xF7 U+03C7 #GREEK SMALL LETTER CHI
+0xF8 U+03C8 #GREEK SMALL LETTER PSI
+0xF9 U+03C9 #GREEK SMALL LETTER OMEGA
+0xFA U+03CA #GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xFB U+03CB #GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xFC U+03CC #GREEK SMALL LETTER OMICRON WITH TONOS
+0xFD U+03CD #GREEK SMALL LETTER UPSILON WITH TONOS
+0xFE U+03CE #GREEK SMALL LETTER OMEGA WITH TONOS
+#0xFF #UNDEFINED
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1255_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1255_uni.tbl
new file mode 100644
index 00000000000..5f4d761a68b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1255_uni.tbl
@@ -0,0 +1,154 @@
+#The MIME name of this charset.
+Mwindows-1255
+
+#Name as a Display Charset (used on Options screen).
+OWinHebrew (cp1255)
+
+# Name: cp1255_WinHebrew to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1255_WinHebrew code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1255_WinHebrew order
+#
+##################
+
+0x20-0x7f idem
+#
+#0x80 #UNDEFINED
+#0x81 #UNDEFINED
+0x82 U+201A #LOW SINGLE COMMA QUOTATION MARK
+0x83 U+0192 #LATIN SMALL LETTER SCRIPT F
+0x84 U+201E #LOW DOUBLE COMMA QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+0x88 U+02C6 #MODIFIER LETTER CIRCUMFLEX
+0x89 U+2030 #PER MILLE SIGN
+#0x8A #UNDEFINED
+0x8B U+2039 #LEFT POINTING SINGLE GUILLEMET
+#0x8C #UNDEFINED
+#0x8D #UNDEFINED
+#0x8E #UNDEFINED
+#0x8F #UNDEFINED
+#0x90 #UNDEFINED
+0x91 U+2018 #SINGLE TURNED COMMA QUOTATION MARK
+0x92 U+2019 #SINGLE COMMA QUOTATION MARK
+0x93 U+201C #DOUBLE TURNED COMMA QUOTATION MARK
+0x94 U+201D #DOUBLE COMMA QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+0x98 U+02DC #SPACING TILDE
+0x99 U+2122 #TRADEMARK
+#0x9A #UNDEFINED
+0x9B U+203A #RIGHT POINTING SINGLE GUILLEMET
+#0x9C #UNDEFINED
+#0x9D #UNDEFINED
+#0x9E #UNDEFINED
+#0x9F #UNDEFINED
+0xA0 U+00A0 #NON-BREAKING SPACE
+#0xA1 #UNDEFINED
+0xA2 U+00A2 #CENT SIGN
+0xA3 U+00A3 #POUND SIGN
+0xA4 U+20AA #NEW SHEQEL SIGN
+0xA5 U+00A5 #YEN SIGN
+0xA6 U+00A6 #BROKEN VERTICAL BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+00A8 #SPACING DIAERESIS
+0xA9 U+00A9 #COPYRIGHT SIGN
+#0xAA #UNDEFINED
+0xAB U+00AB #LEFT POINTING GUILLEMET
+0xAC U+00AC #NOT SIGN
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED TRADE MARK SIGN
+0xAF U+00AF #SPACING MACRON
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-OR-MINUS SIGN
+0xB2 U+00B2 #SUPERSCRIPT DIGIT TWO
+0xB3 U+00B3 #SUPERSCRIPT DIGIT THREE
+0xB4 U+00B4 #SPACING ACUTE
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PARAGRAPH SIGN
+0xB7 U+00B7 #MIDDLE DOT
+#0xB8 #UNDEFINED
+0xB9 U+00B9 #SUPERSCRIPT DIGIT ONE
+#0xBA #UNDEFINED
+0xBB U+00BB #RIGHT POINTING GUILLEMET
+0xBC U+00BC #FRACTION ONE QUARTER
+0xBD U+00BD #FRACTION ONE HALF
+0xBE U+00BE #FRACTION THREE QUARTERS
+#0xBF #UNDEFINED
+0xC0 U+05B0 #HEBREW POINT SHEVA
+0xC1 U+05B1 #HEBREW POINT HATAF SEGOL
+0xC2 U+05B2 #HEBREW POINT HATAF PATAH
+0xC3 U+05B3 #HEBREW POINT HATAF QAMATS
+0xC4 U+05B4 #HEBREW POINT HIRIQ
+0xC5 U+05B5 #HEBREW POINT TSERE
+0xC6 U+05B6 #HEBREW POINT SEGOL
+0xC7 U+05B7 #HEBREW POINT PATAH
+0xC8 U+05B8 #HEBREW POINT QAMATS
+0xC9 U+05B9 #HEBREW POINT HOLAM
+0xCA U+05BA #HEBREW POINT
+0xCB U+05BB #HEBREW POINT QUBUTS
+0xCC U+05BC #HEBREW POINT DAGESH
+0xCD U+05BD #HEBREW POINT METEG
+0xCE U+05BE #HEBREW PUNCTUATION MAQAF
+0xCF U+05BF #HEBREW POINT RAFE
+0xD0 U+05C0 #HEBREW POINT PASEQ
+0xD1 U+05C1 #HEBREW POINT SHIN DOT
+0xD2 U+05C2 #HEBREW POINT SIN DOT
+0xD3 U+05C3 #HEBREW PUNCTUATION SOF PASUQ
+0xD4 U+05F0 #HEBREW LETTER DOUBLE VAV
+0xD5 U+05F1 #HEBREW LETTER VAV YOD
+0xD6 U+05F2 #HEBREW LETTER DOUBLE YOD
+#0xD7 #UNDEFINED
+#0xD8 #UNDEFINED
+#0xD9 #UNDEFINED
+#0xDA #UNDEFINED
+#0xDB #UNDEFINED
+#0xDC #UNDEFINED
+#0xDD #UNDEFINED
+#0xDE #UNDEFINED
+#0xDF #UNDEFINED
+0xE0 U+05D0 #HEBREW LETTER ALEF
+0xE1 U+05D1 #HEBREW LETTER BET
+0xE2 U+05D2 #HEBREW LETTER GIMEL
+0xE3 U+05D3 #HEBREW LETTER DALET
+0xE4 U+05D4 #HEBREW LETTER HE
+0xE5 U+05D5 #HEBREW LETTER VAV
+0xE6 U+05D6 #HEBREW LETTER ZAYIN
+0xE7 U+05D7 #HEBREW LETTER HET
+0xE8 U+05D8 #HEBREW LETTER TET
+0xE9 U+05D9 #HEBREW LETTER YOD
+0xEA U+05DA #HEBREW LETTER FINAL KAF
+0xEB U+05DB #HEBREW LETTER KAF
+0xEC U+05DC #HEBREW LETTER LAMED
+0xED U+05DD #HEBREW LETTER FINAL MEM
+0xEE U+05DE #HEBREW LETTER MEM
+0xEF U+05DF #HEBREW LETTER FINAL NUN
+0xF0 U+05E0 #HEBREW LETTER NUN
+0xF1 U+05E1 #HEBREW LETTER SAMEKH
+0xF2 U+05E2 #HEBREW LETTER AYIN
+0xF3 U+05E3 #HEBREW LETTER FINAL PE
+0xF4 U+05E4 #HEBREW LETTER PE
+0xF5 U+05E5 #HEBREW LETTER FINAL TSADI
+0xF6 U+05E6 #HEBREW LETTER TSADI
+0xF7 U+05E7 #HEBREW LETTER QOF
+0xF8 U+05E8 #HEBREW LETTER RESH
+0xF9 U+05E9 #HEBREW LETTER SHIN
+0xFA U+05EA #HEBREW LETTER TAV
+#0xFB #UNDEFINED
+#0xFC #UNDEFINED
+0xFD U+200E #LEFT-TO-RIGHT MARK
+0xFE U+200F #RIGHT-TO-LEFT MARK
+#0xFF #UNDEFINED
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1256_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1256_uni.tbl
new file mode 100644
index 00000000000..6d85d22127f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1256_uni.tbl
@@ -0,0 +1,154 @@
+#The MIME name of this charset.
+Mwindows-1256
+
+#Name as a Display Charset (used on Options screen).
+OWinArabic (cp1256)
+
+# Name: cp1256_WinArabic to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1256_WinArabic code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1256_WinArabic order
+#
+##################
+
+0x20-0x7f idem
+#
+#0x80 #UNDEFINED
+0x81 U+067E #ARABIC TAA WITH THREE DOTS BELOW
+0x82 U+201A #LOW SINGLE COMMA QUOTATION MARK
+0x83 U+0192 #LATIN SMALL LETTER SCRIPT F
+0x84 U+201E #LOW DOUBLE COMMA QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+0x88 U+02C6 #MODIFIER LETTER CIRCUMFLEX
+0x89 U+2030 #PER MILLE SIGN
+#0x8A #UNDEFINED
+0x8B U+2039 #LEFT POINTING SINGLE GUILLEMET
+0x8C U+0152 #LATIN CAPITAL LETTER O E
+0x8D U+0686 #ARABIC HAA WITH MIDDLE THREE DOTS DOWNWARD
+0x8E U+0698 #ARABIC RA WITH THREE DOTS ABOVE
+#0x8F #UNDEFINED
+0x90 U+06AF #ARABIC GAF
+0x91 U+2018 #SINGLE TURNED COMMA QUOTATION MARK
+0x92 U+2019 #SINGLE COMMA QUOTATION MARK
+0x93 U+201C #DOUBLE TURNED COMMA QUOTATION MARK
+0x94 U+201D #DOUBLE COMMA QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+#0x98 #UNDEFINED
+0x99 U+2122 #TRADEMARK
+#0x9A #UNDEFINED
+0x9B U+203A #RIGHT POINTING SINGLE GUILLEMET
+0x9C U+0153 #LATIN SMALL LETTER O E
+0x9D U+200C #ZERO WIDTH NON-JOINER
+0x9E U+200D #ZERO WIDTH JOINER
+#0x9F #UNDEFINED
+0xA0 U+00A0 #NON-BREAKING SPACE
+0xA1 U+060C #ARABIC COMMA
+0xA2 U+00A2 #CENT SIGN
+0xA3 U+00A3 #POUND SIGN
+0xA4 U+00A4 #CURRENCY SIGN
+0xA5 U+00A5 #YEN SIGN
+0xA6 U+00A6 #BROKEN VERTICAL BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+00A8 #SPACING DIAERESIS
+0xA9 U+00A9 #COPYRIGHT SIGN
+#0xAA #UNDEFINED
+0xAB U+00AB #LEFT POINTING GUILLEMET
+0xAC U+00AC #NOT SIGN
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED TRADE MARK SIGN
+0xAF U+00AF #SPACING MACRON
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-OR-MINUS SIGN
+0xB2 U+00B2 #SUPERSCRIPT DIGIT TWO
+0xB3 U+00B3 #SUPERSCRIPT DIGIT THREE
+0xB4 U+00B4 #SPACING ACUTE
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PARAGRAPH SIGN
+0xB7 U+00B7 #MIDDLE DOT
+0xB8 U+00B8 #SPACING CEDILLA
+0xB9 U+00B9 #SUPERSCRIPT DIGIT ONE
+0xBA U+061B #ARABIC SEMICOLON
+0xBB U+00BB #RIGHT POINTING GUILLEMET
+0xBC U+00BC #FRACTION ONE QUARTER
+0xBD U+00BD #FRACTION ONE HALF
+0xBE U+00BE #FRACTION THREE QUARTERS
+0xBF U+061F #ARABIC QUESTION MARK
+#0xC0 #UNDEFINED
+0xC1 U+0621 #ARABIC LETTER HAMZAH
+0xC2 U+0622 #ARABIC LETTER MADDAH ON ALEF
+0xC3 U+0623 #ARABIC LETTER HAMZAH ON ALEF
+0xC4 U+0624 #ARABIC LETTER HAMZAH ON WAW
+0xC5 U+0625 #ARABIC LETTER HAMZAH UNDER ALEF
+0xC6 U+0626 #ARABIC LETTER HAMZAH ON YA
+0xC7 U+0627 #ARABIC LETTER ALEF
+0xC8 U+0628 #ARABIC LETTER BAA
+0xC9 U+0629 #ARABIC LETTER TAA MARBUTAH
+0xCA U+062A #ARABIC LETTER TAA
+0xCB U+062B #ARABIC LETTER THAA
+0xCC U+062C #ARABIC LETTER JEEM
+0xCD U+062D #ARABIC LETTER HAA
+0xCE U+062E #ARABIC LETTER KHAA
+0xCF U+062F #ARABIC LETTER DAL
+0xD0 U+0630 #ARABIC LETTER THAL
+0xD1 U+0631 #ARABIC LETTER RA
+0xD2 U+0632 #ARABIC LETTER ZAIN
+0xD3 U+0633 #ARABIC LETTER SEEN
+0xD4 U+0634 #ARABIC LETTER SHEEN
+0xD5 U+0635 #ARABIC LETTER SAD
+0xD6 U+0636 #ARABIC LETTER DAD
+0xD7 U+00D7 #MULTIPLICATION SIGN
+0xD8 U+0637 #ARABIC LETTER TAH
+0xD9 U+0638 #ARABIC LETTER DHAH
+0xDA U+0639 #ARABIC LETTER AIN
+0xDB U+063A #ARABIC LETTER GHAIN
+0xDC U+0640 #ARABIC TATWEEL
+0xDD U+0641 #ARABIC LETTER FA
+0xDE U+0642 #ARABIC LETTER QAF
+0xDF U+0643 #ARABIC LETTER CAF
+0xE0 U+00E0 #LATIN SMALL LETTER A GRAVE
+0xE1 U+0644 #ARABIC LETTER LAM
+0xE2 U+00E2 #LATIN SMALL LETTER A CIRCUMFLEX
+0xE3 U+0645 #ARABIC LETTER MEEM
+0xE4 U+0646 #ARABIC LETTER NOON
+0xE5 U+0647 #ARABIC LETTER HA
+0xE6 U+0648 #ARABIC LETTER WAW
+0xE7 U+00E7 #LATIN SMALL LETTER C CEDILLA
+0xE8 U+00E8 #LATIN SMALL LETTER E GRAVE
+0xE9 U+00E9 #LATIN SMALL LETTER E ACUTE
+0xEA U+00EA #LATIN SMALL LETTER E CIRCUMFLEX
+0xEB U+00EB #LATIN SMALL LETTER E DIAERESIS
+0xEC U+0649 #ARABIC LETTER ALEF MAQSURAH
+0xED U+064A #ARABIC LETTER YA
+0xEE U+00EE #LATIN SMALL LETTER I CIRCUMFLEX
+0xEF U+00EF #LATIN SMALL LETTER I DIAERESIS
+0xF0 U+064B #ARABIC FATHATAN
+0xF1 U+064C #ARABIC DAMMATAN
+0xF2 U+064D #ARABIC KASRATAN
+0xF3 U+064E #ARABIC FATHAH
+0xF4 U+00F4 #LATIN SMALL LETTER O CIRCUMFLEX
+0xF5 U+064F #ARABIC DAMMAH
+0xF6 U+0650 #ARABIC KASRAH
+0xF7 U+00F7 #DIVISION SIGN
+0xF8 U+0651 #ARABIC SHADDAH
+0xF9 U+00F9 #LATIN SMALL LETTER U GRAVE
+0xFA U+0652 #ARABIC SUKUN
+0xFB U+00FB #LATIN SMALL LETTER U CIRCUMFLEX
+0xFC U+00FC #LATIN SMALL LETTER U DIAERESIS
+0xFD U+200E #LEFT-TO-RIGHT MARK
+0xFE U+200F #RIGHT-TO-LEFT MARK
+#0xFF #UNDEFINED
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp1257_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp1257_uni.tbl
new file mode 100644
index 00000000000..794df717e95
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp1257_uni.tbl
@@ -0,0 +1,278 @@
+#The MIME name of this charset.
+Mwindows-1257
+
+#Name as a Display Charset (used on Options screen)
+OWinBaltRim (cp1257)
+
+# Name: cp1257_WinBaltic to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp1257_WinBaltic code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp1257_WinBaltic order
+#
+#0x00 U+0000 #NULL
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0A U+000A #LINE FEED
+#0x0B U+000B #VERTICAL TABULATION
+#0x0C U+000C #FORM FEED
+#0x0D U+000D #CARRIAGE RETURN
+#0x0E U+000E #SHIFT OUT
+#0x0F U+000F #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1A U+001A #SUBSTITUTE
+#0x1B U+001B #ESCAPE
+#0x1C U+001C #FILE SEPARATOR
+#0x1D U+001D #GROUP SEPARATOR
+#0x1E U+001E #RECORD SEPARATOR
+#0x1F U+001F #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2A U+002A #ASTERISK
+0x2B U+002B #PLUS SIGN
+0x2C U+002C #COMMA
+0x2D U+002D #HYPHEN-MINUS
+0x2E U+002E #FULL STOP
+0x2F U+002F #SOLIDUS
+0x30 U+0030 #DIGIT 0
+0x31 U+0031 #DIGIT 1
+0x32 U+0032 #DIGIT 2
+0x33 U+0033 #DIGIT 3
+0x34 U+0034 #DIGIT 4
+0x35 U+0035 #DIGIT 5
+0x36 U+0036 #DIGIT 6
+0x37 U+0037 #DIGIT 7
+0x38 U+0038 #DIGIT 8
+0x39 U+0039 #DIGIT 9
+0x3A U+003A #COLON
+0x3B U+003B #SEMICOLON
+0x3C U+003C #LESS-THAN SIGN
+0x3D U+003D #EQUALS SIGN
+0x3E U+003E #GREATER-THAN SIGN
+0x3F U+003F #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL A
+0x42 U+0042 #LATIN CAPITAL B
+0x43 U+0043 #LATIN CAPITAL C
+0x44 U+0044 #LATIN CAPITAL D
+0x45 U+0045 #LATIN CAPITAL E
+0x46 U+0046 #LATIN CAPITAL F
+0x47 U+0047 #LATIN CAPITAL G
+0x48 U+0048 #LATIN CAPITAL H
+0x49 U+0049 #LATIN CAPITAL I
+0x4A U+004A #LATIN CAPITAL J
+0x4B U+004B #LATIN CAPITAL K
+0x4C U+004C #LATIN CAPITAL L
+0x4D U+004D #LATIN CAPITAL M
+0x4E U+004E #LATIN CAPITAL N
+0x4F U+004F #LATIN CAPITAL O
+0x50 U+0050 #LATIN CAPITAL P
+0x51 U+0051 #LATIN CAPITAL Q
+0x52 U+0052 #LATIN CAPITAL R
+0x53 U+0053 #LATIN CAPITAL S
+0x54 U+0054 #LATIN CAPITAL T
+0x55 U+0055 #LATIN CAPITAL U
+0x56 U+0056 #LATIN CAPITAL V
+0x57 U+0057 #LATIN CAPITAL W
+0x58 U+0058 #LATIN CAPITAL X
+0x59 U+0059 #LATIN CAPITAL Y
+0x5A U+005A #LATIN CAPITAL Z
+0x5B U+005B #LEFT SQUARE BRACKET
+0x5C U+005C #BACKSLASH
+0x5D U+005D #RIGHT SQUARE BRACKET
+0x5E U+005E #CIRCUMFLEX
+0x5F U+005F #LOW LINE
+0x60 U+0060 #GRAVE
+0x61 U+0061 #LATIN SMALL A
+0x62 U+0062 #LATIN SMALL B
+0x63 U+0063 #LATIN SMALL C
+0x64 U+0064 #LATIN SMALL D
+0x65 U+0065 #LATIN SMALL E
+0x66 U+0066 #LATIN SMALL F
+0x67 U+0067 #LATIN SMALL G
+0x68 U+0068 #LATIN SMALL H
+0x69 U+0069 #LATIN SMALL I
+0x6A U+006A #LATIN SMALL J
+0x6B U+006B #LATIN SMALL K
+0x6C U+006C #LATIN SMALL L
+0x6D U+006D #LATIN SMALL M
+0x6E U+006E #LATIN SMALL N
+0x6F U+006F #LATIN SMALL O
+0x70 U+0070 #LATIN SMALL P
+0x71 U+0071 #LATIN SMALL Q
+0x72 U+0072 #LATIN SMALL R
+0x73 U+0073 #LATIN SMALL S
+0x74 U+0074 #LATIN SMALL T
+0x75 U+0075 #LATIN SMALL U
+0x76 U+0076 #LATIN SMALL V
+0x77 U+0077 #LATIN SMALL W
+0x78 U+0078 #LATIN SMALL X
+0x79 U+0079 #LATIN SMALL Y
+0x7A U+007A #LATIN SMALL Z
+0x7B U+007B #LEFT CURLY BRACKET
+0x7C U+007C #VERTICAL LINE
+0x7D U+007D #RIGHT CURLY BRACKET
+0x7E U+007E #TILDE
+#0x7F U+007F #DELETE
+#0x80 #UNDEFINED
+#0x81 #UNDEFINED
+0x82 U+201A #LOW SINGLE COMMA QUOTATION MARK
+#0x83 #UNDEFINED
+0x84 U+201E #LOW DOUBLE COMMA QUOTATION MARK
+0x85 U+2026 #HORIZONTAL ELLIPSIS
+0x86 U+2020 #DAGGER
+0x87 U+2021 #DOUBLE DAGGER
+#0x88 #UNDEFINED
+0x89 U+2030 #PER MILLE SIGN
+#0x8A #UNDEFINED
+0x8B U+2039 #LEFT POINTING SINGLE GUILLEMENT
+#0x8C #UNDEFINED
+0x8D U+00A8 #DIAERESIS
+0x8E U+02C7 #HACEK
+0x8F U+00B8 #CEDILLA
+#0x90 #UNDEFINED
+0x91 U+2018 #LEFT SINGLE QUOTATION MARK
+0x92 U+2019 #RIGHT SINGLE QUOTATION MARK
+0x93 U+201C #LEFT DOUBLE QUOTATION MARK
+0x94 U+201D #RIGHT DOUBLE QUOTATION MARK
+0x95 U+2022 #BULLET
+0x96 U+2013 #EN DASH
+0x97 U+2014 #EM DASH
+#0x98 #UNDEFINED
+0x99 U+2122 #TRADE MARK SIGN
+#0x9A #UNDEFINED
+0x9B U+203A #RIGHT POINTING SINGLE GUILLEMENT
+#0x9C #UNDEFINED
+0x9D U+00AF #MACRON
+0x9E U+02DB #OGONEK
+#0x9F #UNDEFINED
+0xA0 U+00A0 #NO-BREAK SPACE
+#0xA1 #UNDEFINED
+0xA2 U+00A2 #CENT SIGN
+0xA3 U+00A3 #POUND SIGN
+0xA4 U+00A4 #CURRENCY SIGN
+#0xA5 #UNDEFINED
+0xA6 U+00A6 #BROKEN BAR
+0xA7 U+00A7 #SECTION SIGN
+0xA8 U+00D8 #LATIN CAPITAL O STROKE
+0xA9 U+00A9 #COPYRIGHT SIGN
+0xAA U+0156 #LATIN CAPITAL R CEDILLA
+0xAB U+00AB #LEFT POINTING GUILLEMENT
+0xAC U+00AC #NOT SIGN
+0xAD U+00AD #SOFT HYPHEN
+0xAE U+00AE #REGISTERED SIGN
+0xAF U+00C6 #LATIN CAPITAL AE LIGATURE
+0xB0 U+00B0 #DEGREE SIGN
+0xB1 U+00B1 #PLUS-MINUS SIGN
+0xB2 U+00B2 #SUPERSCRIPT 2
+0xB3 U+00B3 #SUPERSCRIPT 3
+0xB4 U+00B4 #ACUTE
+0xB5 U+00B5 #MICRO SIGN
+0xB6 U+00B6 #PILCROW SIGN
+0xB7 U+00B7 #MIDDLE DOT
+0xB8 U+00F8 #LATIN SAMLL O STROKE
+0xB9 U+00B9 #SUPERSCRIPT ONE
+0xBA U+0157 #LATIN SMALL R CEDILLA
+0xBB U+00BB #RIGHT POINTING GUILLEMENT
+0xBC U+00BC #FRACTION 1/4
+0xBD U+00BD #FRACTION 1/2
+0xBE U+00BE #FRACTION 3/4
+0xBF U+00E6 #LATIN SMALL AE LIGATURE
+0xC0 U+0104 #LATIN CAPITAL A OGONEK
+0xC1 U+012E #LATIN CAPITAL I OGONEK
+0xC2 U+0100 #LATIN CAPITAL A MACRON
+0xC3 U+0106 #LATIN CAPITAL C ACUTE
+0xC4 U+00C4 #LATIN CAPITAL A DIAERESIS
+0xC5 U+00C5 #LATIN CAPITAL A RING ABOVE
+0xC6 U+0118 #LATIN CAPITAL E OGONEK
+0xC7 U+0112 #LATIN CAPITAL E MACRON
+0xC8 U+010C #LATIN CAPITAL C HACEK
+0xC9 U+00C9 #LATIN CAPITAL E ACUTE
+0xCA U+0179 #LATIN CAPITAL Z ACUTE
+0xCB U+0116 #LATIN CAPITAL E DOT ABOVE
+0xCC U+0122 #LATIN CAPITAL G CEDILLA
+0xCD U+0136 #LATIN CAPITAL K CEDILLA
+0xCE U+012A #LATIN CAPITAL I MACRON
+0xCF U+013B #LATIN CAPITAL L CEDILLA
+0xD0 U+0160 #LATIN CAPITAL S HACEK
+0xD1 U+0143 #LATIN CAPITAL N ACUTE
+0xD2 U+0145 #LATIN CAPITAL N CEDILLA
+0xD3 U+00D3 #LATIN CAPITAL O ACUTE
+0xD4 U+014C #LATIN CAPITAL O MACRON
+0xD5 U+00D5 #LATIN CAPITAL O TILDE
+0xD6 U+00D6 #LATIN CAPITAL O DIAERESIS
+0xD7 U+00D7 #MULTIPLICATION SIGN
+0xD8 U+0172 #LATIN CAPITAL U OGONEK
+0xD9 U+0141 #LATIN CAPITAL L STROKE
+0xDA U+015A #LATIN CAPITAL S ACUTE
+0xDB U+016A #LATIN CAPITAL U MACRON
+0xDC U+00DC #LATIN CAPITAL U DIAERESIS
+0xDD U+017B #LATIN CAPITAL Z DOT ABOVE
+0xDE U+017D #LATIN CAPITAL Z HACEK
+0xDF U+00DF #LATIN SMALL SHARP SS
+0xE0 U+0105 #LATIN SMALL A OGONEK
+0xE1 U+012F #LATIN SMALL I OGONEK
+0xE2 U+0101 #LATIN SMALL A MACRON
+0xE3 U+0107 #LATIN SMALL C ACUTE
+0xE4 U+00E4 #LATIN SMALL A DIAERESIS
+0xE5 U+00E5 #LATIN SMALL A RING ABOVE
+0xE6 U+0119 #LATIN SMALL E OGONEK
+0xE7 U+0113 #LATIN SMALL E MACRON
+0xE8 U+010D #LATIN SMALL C HACEK
+0xE9 U+00E9 #LATIN SMALL E ACUTE
+0xEA U+017A #LATIN SMALL Z ACUTE
+0xEB U+0117 #LATIN SMALL E DOT ABOVE
+0xEC U+0123 #LATIN SMALL G CEDILLA
+0xED U+0137 #LATIN SMALL K CEDILLA
+0xEE U+012B #LATIN SMALL I MACRON
+0xEF U+013C #LATIN SMALL L CEDILLA
+0xF0 U+0161 #LATIN SMALL S HACEK
+0xF1 U+0144 #LATIN SMALL N ACUTE
+0xF2 U+0146 #LATIN SMALL N CEDILLA
+0xF3 U+00F3 #LATIN SMALL O ACUTE
+0xF4 U+014D #LATIN SMALL O MACRON
+0xF5 U+00F5 #LATIN SMALL O TILDE
+0xF6 U+00F6 #LATIN SMALL O DIAERESIS
+0xF7 U+00F7 #DIVISION SIGN
+0xF8 U+0173 #LATIN SMALL U OGONEK
+0xF9 U+0142 #LATIN SMALL L STROKE
+0xFA U+015B #LATIN SMALL S ACUTE
+0xFB U+016B #LATIN SMALL U MACRON
+0xFC U+00FC #LATIN SMALL U DIAERESIS
+0xFD U+017C #LATIN SMALL Z DOT ABOVE
+0xFE U+017E #LATIN SMALL Z HACEK
+0xFF U+02D9 #DOT ABOVE
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp437_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp437_uni.tbl
new file mode 100644
index 00000000000..621e730e458
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp437_uni.tbl
@@ -0,0 +1,168 @@
+#Shall this become the "default" translation?
+#There has to be exactly one table marked as "default".
+D0
+#
+#The MIME name of this charset.
+Mcp437
+
+#Name as a Display Charset (used on Options screen)
+ODosLatinUS (cp437)
+#
+# Name: cp437_DOSLatinUS to Unicode table
+# Unicode version: 1.1
+# Table version: 1.1
+# Table format: Format A
+# Date: 03/31/95
+# Authors: Michel Suignard <michelsu@microsoft.com>
+# Lori Hoerth <lorih@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp437_DosLatinUS code (in hex)
+# Column #2 is the Unicode (in hex as U+XXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp437_DosLatinUS order
+#
+# some mapppings of greek letters to latin letters added,
+# just for fun.. - KW
+#
+0x20-0x7f idem
+#
+0x80 U+00c7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0x81 U+00fc U+03cb #LATIN SMALL LETTER U WITH DIAERESIS
+0x82 U+00e9 #LATIN SMALL LETTER E WITH ACUTE
+0x83 U+00e2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84 U+00e4 #LATIN SMALL LETTER A WITH DIAERESIS
+0x85 U+00e0 #LATIN SMALL LETTER A WITH GRAVE
+0x86 U+00e5 #LATIN SMALL LETTER A WITH RING ABOVE
+0x87 U+00e7 #LATIN SMALL LETTER C WITH CEDILLA
+0x88 U+00ea #LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x89 U+00eb #LATIN SMALL LETTER E WITH DIAERESIS
+0x8a U+00e8 #LATIN SMALL LETTER E WITH GRAVE
+0x8b U+00ef U+03ca #LATIN SMALL LETTER I WITH DIAERESIS
+0x8c U+00ee #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d U+00ec #LATIN SMALL LETTER I WITH GRAVE
+0x8e U+00c4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f U+00c5 #LATIN CAPITAL LETTER A WITH RING ABOVE
+0x90 U+00c9 #LATIN CAPITAL LETTER E WITH ACUTE
+0x91 U+00e6 #LATIN SMALL LIGATURE AE
+0x92 U+00c6 #LATIN CAPITAL LIGATURE AE
+0x93 U+00f4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94 U+00f6 #LATIN SMALL LETTER O WITH DIAERESIS
+0x95 U+00f2 #LATIN SMALL LETTER O WITH GRAVE
+0x96 U+00fb #LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x97 U+00f9 #LATIN SMALL LETTER U WITH GRAVE
+0x98 U+00ff #LATIN SMALL LETTER Y WITH DIAERESIS
+0x99 U+00d6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a U+00dc #LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b U+00a2 #CENT SIGN
+0x9c U+00a3 #POUND SIGN
+0x9d U+00a5 #YEN SIGN
+0x9e U+20a7 #PESETA SIGN
+0x9f U+0192 #LATIN SMALL LETTER F WITH HOOK
+0xa0 U+00e1 U+03ac #LATIN SMALL LETTER A WITH ACUTE
+0xa1 U+00ed U+03af #LATIN SMALL LETTER I WITH ACUTE
+0xa2 U+00f3 U+03cc #LATIN SMALL LETTER O WITH ACUTE
+0xa3 U+00fa U+03cd #LATIN SMALL LETTER U WITH ACUTE
+0xa4 U+00f1 #LATIN SMALL LETTER N WITH TILDE
+0xa5 U+00d1 #LATIN CAPITAL LETTER N WITH TILDE
+0xa6 U+00aa #FEMININE ORDINAL INDICATOR
+0xa7 U+00ba #MASCULINE ORDINAL INDICATOR
+0xa8 U+00bf #INVERTED QUESTION MARK
+0xa9 U+2310 #REVERSED NOT SIGN
+0xaa U+00ac #NOT SIGN
+0xab U+00bd #VULGAR FRACTION ONE HALF
+0xac U+00bc #VULGAR FRACTION ONE QUARTER
+0xad U+00a1 #INVERTED EXCLAMATION MARK
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+2561 #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6 U+2562 #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7 U+2556 #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8 U+2555 #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+255c #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe U+255b #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+255e #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7 U+255f #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+2567 #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0 U+2568 #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1 U+2564 #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2 U+2565 #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3 U+2559 #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4 U+2558 #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5 U+2552 #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6 U+2553 #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7 U+256b #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8 U+256a #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+258c #LEFT HALF BLOCK
+0xde U+2590 #RIGHT HALF BLOCK
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+03b1 #GREEK SMALL LETTER ALPHA
+0xe1 U+00df U+03b2 #LATIN SMALL LETTER SHARP S
+0xe2 U+0393 #GREEK CAPITAL LETTER GAMMA
+0xe3 U+03c0 #GREEK SMALL LETTER PI
+0xe4 U+03a3 #GREEK CAPITAL LETTER SIGMA
+0xe5 U+03c3 #GREEK SMALL LETTER SIGMA
+0xe6 U+00b5 U+03bc #MICRO SIGN
+0xe7 U+03c4 #GREEK SMALL LETTER TAU
+0xe8 U+03a6 #GREEK CAPITAL LETTER PHI
+0xe9 U+0398 U+03b8 #GREEK CAPITAL LETTER THETA
+0xea U+03a9 #GREEK CAPITAL LETTER OMEGA
+0xeb U+03b4 #GREEK SMALL LETTER DELTA
+0xec U+221e #INFINITY
+0xed U+03c6 #GREEK SMALL LETTER PHI
+0xee U+03b5 #GREEK SMALL LETTER EPSILON
+0xef U+2229 #INTERSECTION
+0xf0 U+2261 #IDENTICAL TO
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+2265 #GREATER-THAN OR EQUAL TO
+0xf3 U+2264 #LESS-THAN OR EQUAL TO
+0xf4 U+2320 #TOP HALF INTEGRAL
+0xf5 U+2321 #BOTTOM HALF INTEGRAL
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+2248 #ALMOST EQUAL TO
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+2219 #BULLET OPERATOR
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+221a #SQUARE ROOT
+0xfc U+207f #SUPERSCRIPT LATIN SMALL LETTER N
+0xfd U+00b2 #SUPERSCRIPT TWO
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
+U+03ac:a'
+U+03ad "\356'" #:î'
+U+03ae:h'
+U+03af:i'
+U+03cc:o'
+U+03cd:u'
+U+03ce:w'
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp737_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp737_uni.tbl
new file mode 100644
index 00000000000..32f01c8c5ba
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp737_uni.tbl
@@ -0,0 +1,155 @@
+#The MIME name of this charset.
+Mcp737
+
+#Name as a Display Charset (used on Options screen)
+ODosGreek (cp737)
+
+#
+# Name: cp737_DOSGreek to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp737_DOSGreek code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp737_DOSGreek order
+#
+##################
+
+0x20-0x7f idem
+#
+0x80 U+0391 #GREEK CAPITAL LETTER ALPHA
+0x81 U+0392 #GREEK CAPITAL LETTER BETA
+0x82 U+0393 #GREEK CAPITAL LETTER GAMMA
+0x83 U+0394 #GREEK CAPITAL LETTER DELTA
+0x84 U+0395 #GREEK CAPITAL LETTER EPSILON
+0x85 U+0396 #GREEK CAPITAL LETTER ZETA
+0x86 U+0397 #GREEK CAPITAL LETTER ETA
+0x87 U+0398 #GREEK CAPITAL LETTER THETA
+0x88 U+0399 #GREEK CAPITAL LETTER IOTA
+0x89 U+039a #GREEK CAPITAL LETTER KAPPA
+0x8a U+039b #GREEK CAPITAL LETTER LAMDA
+0x8b U+039c #GREEK CAPITAL LETTER MU
+0x8c U+039d #GREEK CAPITAL LETTER NU
+0x8d U+039e #GREEK CAPITAL LETTER XI
+0x8e U+039f #GREEK CAPITAL LETTER OMICRON
+0x8f U+03a0 #GREEK CAPITAL LETTER PI
+0x90 U+03a1 #GREEK CAPITAL LETTER RHO
+0x91 U+03a3 #GREEK CAPITAL LETTER SIGMA
+0x92 U+03a4 #GREEK CAPITAL LETTER TAU
+0x93 U+03a5 #GREEK CAPITAL LETTER UPSILON
+0x94 U+03a6 #GREEK CAPITAL LETTER PHI
+0x95 U+03a7 #GREEK CAPITAL LETTER CHI
+0x96 U+03a8 #GREEK CAPITAL LETTER PSI
+0x97 U+03a9 #GREEK CAPITAL LETTER OMEGA
+0x98 U+03b1 #GREEK SMALL LETTER ALPHA
+0x99 U+03b2 #GREEK SMALL LETTER BETA
+0x9a U+03b3 #GREEK SMALL LETTER GAMMA
+0x9b U+03b4 #GREEK SMALL LETTER DELTA
+0x9c U+03b5 #GREEK SMALL LETTER EPSILON
+0x9d U+03b6 #GREEK SMALL LETTER ZETA
+0x9e U+03b7 #GREEK SMALL LETTER ETA
+0x9f U+03b8 #GREEK SMALL LETTER THETA
+0xa0 U+03b9 #GREEK SMALL LETTER IOTA
+0xa1 U+03ba #GREEK SMALL LETTER KAPPA
+0xa2 U+03bb #GREEK SMALL LETTER LAMDA
+0xa3 U+03bc #GREEK SMALL LETTER MU
+0xa4 U+03bd #GREEK SMALL LETTER NU
+0xa5 U+03be #GREEK SMALL LETTER XI
+0xa6 U+03bf #GREEK SMALL LETTER OMICRON
+0xa7 U+03c0 #GREEK SMALL LETTER PI
+0xa8 U+03c1 #GREEK SMALL LETTER RHO
+0xa9 U+03c3 #GREEK SMALL LETTER SIGMA
+0xaa U+03c2 #GREEK SMALL LETTER FINAL SIGMA
+0xab U+03c4 #GREEK SMALL LETTER TAU
+0xac U+03c5 #GREEK SMALL LETTER UPSILON
+0xad U+03c6 #GREEK SMALL LETTER PHI
+0xae U+03c7 #GREEK SMALL LETTER CHI
+0xaf U+03c8 #GREEK SMALL LETTER PSI
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+2561 #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6 U+2562 #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7 U+2556 #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8 U+2555 #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+255c #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe U+255b #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+255e #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7 U+255f #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+2567 #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0 U+2568 #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1 U+2564 #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2 U+2565 #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3 U+2559 #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4 U+2558 #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5 U+2552 #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6 U+2553 #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7 U+256b #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8 U+256a #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+258c #LEFT HALF BLOCK
+0xde U+2590 #RIGHT HALF BLOCK
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+03c9 #GREEK SMALL LETTER OMEGA
+0xe1 U+03ac #GREEK SMALL LETTER ALPHA WITH TONOS
+0xe2 U+03ad #GREEK SMALL LETTER EPSILON WITH TONOS
+0xe3 U+03ae #GREEK SMALL LETTER ETA WITH TONOS
+0xe4 U+03ca #GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xe5 U+03af #GREEK SMALL LETTER IOTA WITH TONOS
+0xe6 U+03cc #GREEK SMALL LETTER OMICRON WITH TONOS
+0xe7 U+03cd #GREEK SMALL LETTER UPSILON WITH TONOS
+0xe8 U+03cb #GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xe9 U+03ce #GREEK SMALL LETTER OMEGA WITH TONOS
+0xea U+0386 #GREEK CAPITAL LETTER ALPHA WITH TONOS
+0xeb U+0388 #GREEK CAPITAL LETTER EPSILON WITH TONOS
+0xec U+0389 #GREEK CAPITAL LETTER ETA WITH TONOS
+0xed U+038a #GREEK CAPITAL LETTER IOTA WITH TONOS
+0xee U+038c #GREEK CAPITAL LETTER OMICRON WITH TONOS
+0xef U+038e #GREEK CAPITAL LETTER UPSILON WITH TONOS
+0xf0 U+038f #GREEK CAPITAL LETTER OMEGA WITH TONOS
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+2265 #GREATER-THAN OR EQUAL TO
+0xf3 U+2264 #LESS-THAN OR EQUAL TO
+0xf4 U+03aa #GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0xf5 U+03ab #GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+2248 #ALMOST EQUAL TO
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+2219 #BULLET OPERATOR
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+221a #SQUARE ROOT
+0xfc U+207f #SUPERSCRIPT LATIN SMALL LETTER N
+0xfd U+00b2 #SUPERSCRIPT TWO
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp775_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp775_uni.tbl
new file mode 100644
index 00000000000..02a8b61b230
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp775_uni.tbl
@@ -0,0 +1,278 @@
+#The MIME name of this charset.
+Mcp775
+
+#Name as a Display Charset (used on Options screen)
+ODosBaltRim (cp775)
+
+# Name: cp775_DOSBaltRim to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp775_DOSBaltRim code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp775_DOSBaltRim order
+#
+#0x00 U+0000 #NULL
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0a U+000a #LINE FEED
+#0x0b U+000b #VERTICAL TABULATION
+#0x0c U+000c #FORM FEED
+#0x0d U+000d #CARRIAGE RETURN
+#0x0e U+000e #SHIFT OUT
+#0x0f U+000f #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1a U+001a #SUBSTITUTE
+#0x1b U+001b #ESCAPE
+#0x1c U+001c #FILE SEPARATOR
+#0x1d U+001d #GROUP SEPARATOR
+#0x1e U+001e #RECORD SEPARATOR
+#0x1f U+001f #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2a U+002a #ASTERISK
+0x2b U+002b #PLUS SIGN
+0x2c U+002c #COMMA
+0x2d U+002d #HYPHEN-MINUS
+0x2e U+002e #FULL STOP
+0x2f U+002f #SOLIDUS
+0x30 U+0030 #DIGIT ZERO
+0x31 U+0031 #DIGIT ONE
+0x32 U+0032 #DIGIT TWO
+0x33 U+0033 #DIGIT THREE
+0x34 U+0034 #DIGIT FOUR
+0x35 U+0035 #DIGIT FIVE
+0x36 U+0036 #DIGIT SIX
+0x37 U+0037 #DIGIT SEVEN
+0x38 U+0038 #DIGIT EIGHT
+0x39 U+0039 #DIGIT NINE
+0x3a U+003a #COLON
+0x3b U+003b #SEMICOLON
+0x3c U+003c #LESS-THAN SIGN
+0x3d U+003d #EQUALS SIGN
+0x3e U+003e #GREATER-THAN SIGN
+0x3f U+003f #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL LETTER A
+0x42 U+0042 #LATIN CAPITAL LETTER B
+0x43 U+0043 #LATIN CAPITAL LETTER C
+0x44 U+0044 #LATIN CAPITAL LETTER D
+0x45 U+0045 #LATIN CAPITAL LETTER E
+0x46 U+0046 #LATIN CAPITAL LETTER F
+0x47 U+0047 #LATIN CAPITAL LETTER G
+0x48 U+0048 #LATIN CAPITAL LETTER H
+0x49 U+0049 #LATIN CAPITAL LETTER I
+0x4a U+004a #LATIN CAPITAL LETTER J
+0x4b U+004b #LATIN CAPITAL LETTER K
+0x4c U+004c #LATIN CAPITAL LETTER L
+0x4d U+004d #LATIN CAPITAL LETTER M
+0x4e U+004e #LATIN CAPITAL LETTER N
+0x4f U+004f #LATIN CAPITAL LETTER O
+0x50 U+0050 #LATIN CAPITAL LETTER P
+0x51 U+0051 #LATIN CAPITAL LETTER Q
+0x52 U+0052 #LATIN CAPITAL LETTER R
+0x53 U+0053 #LATIN CAPITAL LETTER S
+0x54 U+0054 #LATIN CAPITAL LETTER T
+0x55 U+0055 #LATIN CAPITAL LETTER U
+0x56 U+0056 #LATIN CAPITAL LETTER V
+0x57 U+0057 #LATIN CAPITAL LETTER W
+0x58 U+0058 #LATIN CAPITAL LETTER X
+0x59 U+0059 #LATIN CAPITAL LETTER Y
+0x5a U+005a #LATIN CAPITAL LETTER Z
+0x5b U+005b #LEFT SQUARE BRACKET
+0x5c U+005c #REVERSE SOLIDUS
+0x5d U+005d #RIGHT SQUARE BRACKET
+0x5e U+005e #CIRCUMFLEX ACCENT
+0x5f U+005f #LOW LINE
+0x60 U+0060 #GRAVE ACCENT
+0x61 U+0061 #LATIN SMALL LETTER A
+0x62 U+0062 #LATIN SMALL LETTER B
+0x63 U+0063 #LATIN SMALL LETTER C
+0x64 U+0064 #LATIN SMALL LETTER D
+0x65 U+0065 #LATIN SMALL LETTER E
+0x66 U+0066 #LATIN SMALL LETTER F
+0x67 U+0067 #LATIN SMALL LETTER G
+0x68 U+0068 #LATIN SMALL LETTER H
+0x69 U+0069 #LATIN SMALL LETTER I
+0x6a U+006a #LATIN SMALL LETTER J
+0x6b U+006b #LATIN SMALL LETTER K
+0x6c U+006c #LATIN SMALL LETTER L
+0x6d U+006d #LATIN SMALL LETTER M
+0x6e U+006e #LATIN SMALL LETTER N
+0x6f U+006f #LATIN SMALL LETTER O
+0x70 U+0070 #LATIN SMALL LETTER P
+0x71 U+0071 #LATIN SMALL LETTER Q
+0x72 U+0072 #LATIN SMALL LETTER R
+0x73 U+0073 #LATIN SMALL LETTER S
+0x74 U+0074 #LATIN SMALL LETTER T
+0x75 U+0075 #LATIN SMALL LETTER U
+0x76 U+0076 #LATIN SMALL LETTER V
+0x77 U+0077 #LATIN SMALL LETTER W
+0x78 U+0078 #LATIN SMALL LETTER X
+0x79 U+0079 #LATIN SMALL LETTER Y
+0x7a U+007a #LATIN SMALL LETTER Z
+0x7b U+007b #LEFT CURLY BRACKET
+0x7c U+007c #VERTICAL LINE
+0x7d U+007d #RIGHT CURLY BRACKET
+0x7e U+007e #TILDE
+#0x7f U+007f #DELETE
+0x80 U+0106 #LATIN CAPITAL LETTER C WITH ACUTE
+0x81 U+00fc #LATIN SMALL LETTER U WITH DIAERESIS
+0x82 U+00e9 #LATIN SMALL LETTER E WITH ACUTE
+0x83 U+0101 #LATIN SMALL LETTER A WITH MACRON
+0x84 U+00e4 #LATIN SMALL LETTER A WITH DIAERESIS
+0x85 U+0123 #LATIN SMALL LETTER G WITH CEDILLA
+0x86 U+00e5 #LATIN SMALL LETTER A WITH RING ABOVE
+0x87 U+0107 #LATIN SMALL LETTER C WITH ACUTE
+0x88 U+0142 #LATIN SMALL LETTER L WITH STROKE
+0x89 U+0113 #LATIN SMALL LETTER E WITH MACRON
+0x8a U+0156 #LATIN CAPITAL LETTER R WITH CEDILLA
+0x8b U+0157 #LATIN SMALL LETTER R WITH CEDILLA
+0x8c U+012b #LATIN SMALL LETTER I WITH MACRON
+0x8d U+0179 #LATIN CAPITAL LETTER Z WITH ACUTE
+0x8e U+00c4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f U+00c5 #LATIN CAPITAL LETTER A WITH RING ABOVE
+0x90 U+00c9 #LATIN CAPITAL LETTER E WITH ACUTE
+0x91 U+00e6 #LATIN SMALL LIGATURE AE
+0x92 U+00c6 #LATIN CAPITAL LIGATURE AE
+0x93 U+014d #LATIN SMALL LETTER O WITH MACRON
+0x94 U+00f6 #LATIN SMALL LETTER O WITH DIAERESIS
+0x95 U+0122 #LATIN CAPITAL LETTER G WITH CEDILLA
+0x96 U+00a2 #CENT SIGN
+0x97 U+015a #LATIN CAPITAL LETTER S WITH ACUTE
+0x98 U+015b #LATIN SMALL LETTER S WITH ACUTE
+0x99 U+00d6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a U+00dc #LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b U+00f8 #LATIN SMALL LETTER O WITH STROKE
+0x9c U+00a3 #POUND SIGN
+0x9d U+00d8 #LATIN CAPITAL LETTER O WITH STROKE
+0x9e U+00d7 #MULTIPLICATION SIGN
+0x9f U+00a4 #CURRENCY SIGN
+0xa0 U+0100 #LATIN CAPITAL LETTER A WITH MACRON
+0xa1 U+012a #LATIN CAPITAL LETTER I WITH MACRON
+0xa2 U+00f3 #LATIN SMALL LETTER O WITH ACUTE
+0xa3 U+017b #LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xa4 U+017c #LATIN SMALL LETTER Z WITH DOT ABOVE
+0xa5 U+017a #LATIN SMALL LETTER Z WITH ACUTE
+0xa6 U+201d #RIGHT DOUBLE QUOTATION MARK
+0xa7 U+00a6 #BROKEN BAR
+0xa8 U+00a9 #COPYRIGHT SIGN
+0xa9 U+00ae #REGISTERED SIGN
+0xaa U+00ac #NOT SIGN
+0xab U+00bd #VULGAR FRACTION ONE HALF
+0xac U+00bc #VULGAR FRACTION ONE QUARTER
+0xad U+0141 #LATIN CAPITAL LETTER L WITH STROKE
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+0104 #LATIN CAPITAL LETTER A WITH OGONEK
+0xb6 U+010c #LATIN CAPITAL LETTER C WITH CARON
+0xb7 U+0118 #LATIN CAPITAL LETTER E WITH OGONEK
+0xb8 U+0116 #LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+012e #LATIN CAPITAL LETTER I WITH OGONEK
+0xbe U+0160 #LATIN CAPITAL LETTER S WITH CARON
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+0172 #LATIN CAPITAL LETTER U WITH OGONEK
+0xc7 U+016a #LATIN CAPITAL LETTER U WITH MACRON
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+017d #LATIN CAPITAL LETTER Z WITH CARON
+0xd0 U+0105 #LATIN SMALL LETTER A WITH OGONEK
+0xd1 U+010d #LATIN SMALL LETTER C WITH CARON
+0xd2 U+0119 #LATIN SMALL LETTER E WITH OGONEK
+0xd3 U+0117 #LATIN SMALL LETTER E WITH DOT ABOVE
+0xd4 U+012f #LATIN SMALL LETTER I WITH OGONEK
+0xd5 U+0161 #LATIN SMALL LETTER S WITH CARON
+0xd6 U+0173 #LATIN SMALL LETTER U WITH OGONEK
+0xd7 U+016b #LATIN SMALL LETTER U WITH MACRON
+0xd8 U+017e #LATIN SMALL LETTER Z WITH CARON
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+258c #LEFT HALF BLOCK
+0xde U+2590 #RIGHT HALF BLOCK
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+00d3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xe1 U+00df #LATIN SMALL LETTER SHARP S (GERMAN)
+0xe2 U+014c #LATIN CAPITAL LETTER O WITH MACRON
+0xe3 U+0143 #LATIN CAPITAL LETTER N WITH ACUTE
+0xe4 U+00f5 #LATIN SMALL LETTER O WITH TILDE
+0xe5 U+00d5 #LATIN CAPITAL LETTER O WITH TILDE
+0xe6 U+00b5 #MICRO SIGN
+0xe7 U+0144 #LATIN SMALL LETTER N WITH ACUTE
+0xe8 U+0136 #LATIN CAPITAL LETTER K WITH CEDILLA
+0xe9 U+0137 #LATIN SMALL LETTER K WITH CEDILLA
+0xea U+013b #LATIN CAPITAL LETTER L WITH CEDILLA
+0xeb U+013c #LATIN SMALL LETTER L WITH CEDILLA
+0xec U+0146 #LATIN SMALL LETTER N WITH CEDILLA
+0xed U+0112 #LATIN CAPITAL LETTER E WITH MACRON
+0xee U+0145 #LATIN CAPITAL LETTER N WITH CEDILLA
+0xef U+2019 #RIGHT SINGLE QUOTATION MARK
+0xf0 U+00ad #SOFT HYPHEN
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+201c #LEFT DOUBLE QUOTATION MARK
+0xf3 U+00be #VULGAR FRACTION THREE QUARTERS
+0xf4 U+00b6 #PILCROW SIGN
+0xf5 U+00a7 #SECTION SIGN
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+201e #DOUBLE LOW-9 QUOTATION MARK
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+2219 #BULLET OPERATOR
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+00b9 #SUPERSCRIPT ONE
+0xfc U+00b3 #SUPERSCRIPT THREE
+0xfd U+00b2 #SUPERSCRIPT TWO
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp850_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp850_uni.tbl
new file mode 100644
index 00000000000..05685971d91
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp850_uni.tbl
@@ -0,0 +1,286 @@
+#Shall this become the "default" translation?
+#Meaning of that is currently unclear... It's different
+#from the default input or default output charset...
+#but there has to be exactly one table marked as "default".
+D0
+#
+#The MIME name of this charset.
+Mcp850
+
+#Name as a Display Charset (used on Options screen)
+ODosLatin1 (cp850)
+
+#
+# Name: cp850_DOSLatin1 to Unicode table
+# Unicode version: 1.1
+# Table version: 1.1
+# Table format: Format A
+# Date: 03/31/95
+# Authors: Michel Suignard <michelsu@microsoft.com>
+# Lori Hoerth <lorih@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp850_DOSLatin1 code (in hex)
+# Column #2 is the Unicode (in hex as U+XXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp850_DOSLatin1 order
+#
+#0x00 U+0000 #NULL
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0a U+000a #LINE FEED
+#0x0b U+000b #VERTICAL TABULATION
+#0x0c U+000c #FORM FEED
+#0x0d U+000d #CARRIAGE RETURN
+#0x0e U+000e #SHIFT OUT
+#0x0f U+000f #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1a U+001a #SUBSTITUTE
+#0x1b U+001b #ESCAPE
+#0x1c U+001c #FILE SEPARATOR
+#0x1d U+001d #GROUP SEPARATOR
+#0x1e U+001e #RECORD SEPARATOR
+#0x1f U+001f #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2a U+002a #ASTERISK
+0x2b U+002b #PLUS SIGN
+0x2c U+002c #COMMA
+0x2d U+002d #HYPHEN-MINUS
+0x2e U+002e #FULL STOP
+0x2f U+002f #SOLIDUS
+0x30 U+0030 #DIGIT ZERO
+0x31 U+0031 #DIGIT ONE
+0x32 U+0032 #DIGIT TWO
+0x33 U+0033 #DIGIT THREE
+0x34 U+0034 #DIGIT FOUR
+0x35 U+0035 #DIGIT FIVE
+0x36 U+0036 #DIGIT SIX
+0x37 U+0037 #DIGIT SEVEN
+0x38 U+0038 #DIGIT EIGHT
+0x39 U+0039 #DIGIT NINE
+0x3a U+003a #COLON
+0x3b U+003b #SEMICOLON
+0x3c U+003c #LESS-THAN SIGN
+0x3d U+003d #EQUALS SIGN
+0x3e U+003e #GREATER-THAN SIGN
+0x3f U+003f #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL LETTER A
+0x42 U+0042 #LATIN CAPITAL LETTER B
+0x43 U+0043 #LATIN CAPITAL LETTER C
+0x44 U+0044 #LATIN CAPITAL LETTER D
+0x45 U+0045 #LATIN CAPITAL LETTER E
+0x46 U+0046 #LATIN CAPITAL LETTER F
+0x47 U+0047 #LATIN CAPITAL LETTER G
+0x48 U+0048 #LATIN CAPITAL LETTER H
+0x49 U+0049 #LATIN CAPITAL LETTER I
+0x4a U+004a #LATIN CAPITAL LETTER J
+0x4b U+004b #LATIN CAPITAL LETTER K
+0x4c U+004c #LATIN CAPITAL LETTER L
+0x4d U+004d #LATIN CAPITAL LETTER M
+0x4e U+004e #LATIN CAPITAL LETTER N
+0x4f U+004f #LATIN CAPITAL LETTER O
+0x50 U+0050 #LATIN CAPITAL LETTER P
+0x51 U+0051 #LATIN CAPITAL LETTER Q
+0x52 U+0052 #LATIN CAPITAL LETTER R
+0x53 U+0053 #LATIN CAPITAL LETTER S
+0x54 U+0054 #LATIN CAPITAL LETTER T
+0x55 U+0055 #LATIN CAPITAL LETTER U
+0x56 U+0056 #LATIN CAPITAL LETTER V
+0x57 U+0057 #LATIN CAPITAL LETTER W
+0x58 U+0058 #LATIN CAPITAL LETTER X
+0x59 U+0059 #LATIN CAPITAL LETTER Y
+0x5a U+005a #LATIN CAPITAL LETTER Z
+0x5b U+005b #LEFT SQUARE BRACKET
+0x5c U+005c #REVERSE SOLIDUS
+0x5d U+005d #RIGHT SQUARE BRACKET
+0x5e U+005e #CIRCUMFLEX ACCENT
+0x5f U+005f #LOW LINE
+0x60 U+0060 #GRAVE ACCENT
+0x61 U+0061 #LATIN SMALL LETTER A
+0x62 U+0062 #LATIN SMALL LETTER B
+0x63 U+0063 #LATIN SMALL LETTER C
+0x64 U+0064 #LATIN SMALL LETTER D
+0x65 U+0065 #LATIN SMALL LETTER E
+0x66 U+0066 #LATIN SMALL LETTER F
+0x67 U+0067 #LATIN SMALL LETTER G
+0x68 U+0068 #LATIN SMALL LETTER H
+0x69 U+0069 #LATIN SMALL LETTER I
+0x6a U+006a #LATIN SMALL LETTER J
+0x6b U+006b #LATIN SMALL LETTER K
+0x6c U+006c #LATIN SMALL LETTER L
+0x6d U+006d #LATIN SMALL LETTER M
+0x6e U+006e #LATIN SMALL LETTER N
+0x6f U+006f #LATIN SMALL LETTER O
+0x70 U+0070 #LATIN SMALL LETTER P
+0x71 U+0071 #LATIN SMALL LETTER Q
+0x72 U+0072 #LATIN SMALL LETTER R
+0x73 U+0073 #LATIN SMALL LETTER S
+0x74 U+0074 #LATIN SMALL LETTER T
+0x75 U+0075 #LATIN SMALL LETTER U
+0x76 U+0076 #LATIN SMALL LETTER V
+0x77 U+0077 #LATIN SMALL LETTER W
+0x78 U+0078 #LATIN SMALL LETTER X
+0x79 U+0079 #LATIN SMALL LETTER Y
+0x7a U+007a #LATIN SMALL LETTER Z
+0x7b U+007b #LEFT CURLY BRACKET
+0x7c U+007c #VERTICAL LINE
+0x7d U+007d #RIGHT CURLY BRACKET
+0x7e U+007e #TILDE
+0x7f U+007f #DELETE
+0x80 U+00c7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0x81 U+00fc #LATIN SMALL LETTER U WITH DIAERESIS
+0x82 U+00e9 #LATIN SMALL LETTER E WITH ACUTE
+0x83 U+00e2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84 U+00e4 #LATIN SMALL LETTER A WITH DIAERESIS
+0x85 U+00e0 #LATIN SMALL LETTER A WITH GRAVE
+0x86 U+00e5 #LATIN SMALL LETTER A WITH RING ABOVE
+0x87 U+00e7 #LATIN SMALL LETTER C WITH CEDILLA
+0x88 U+00ea #LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x89 U+00eb #LATIN SMALL LETTER E WITH DIAERESIS
+0x8a U+00e8 #LATIN SMALL LETTER E WITH GRAVE
+0x8b U+00ef #LATIN SMALL LETTER I WITH DIAERESIS
+0x8c U+00ee #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d U+00ec #LATIN SMALL LETTER I WITH GRAVE
+0x8e U+00c4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f U+00c5 #LATIN CAPITAL LETTER A WITH RING ABOVE
+0x90 U+00c9 #LATIN CAPITAL LETTER E WITH ACUTE
+0x91 U+00e6 #LATIN SMALL LIGATURE AE
+0x92 U+00c6 #LATIN CAPITAL LIGATURE AE
+0x93 U+00f4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94 U+00f6 #LATIN SMALL LETTER O WITH DIAERESIS
+0x95 U+00f2 #LATIN SMALL LETTER O WITH GRAVE
+0x96 U+00fb #LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x97 U+00f9 #LATIN SMALL LETTER U WITH GRAVE
+0x98 U+00ff #LATIN SMALL LETTER Y WITH DIAERESIS
+0x99 U+00d6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a U+00dc #LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b U+00f8 #LATIN SMALL LETTER O WITH STROKE
+0x9c U+00a3 #POUND SIGN
+0x9d U+00d8 #LATIN CAPITAL LETTER O WITH STROKE
+0x9e U+00d7 #MULTIPLICATION SIGN
+0x9f U+0192 #LATIN SMALL LETTER F WITH HOOK
+0xa0 U+00e1 #LATIN SMALL LETTER A WITH ACUTE
+0xa1 U+00ed #LATIN SMALL LETTER I WITH ACUTE
+0xa2 U+00f3 #LATIN SMALL LETTER O WITH ACUTE
+0xa3 U+00fa #LATIN SMALL LETTER U WITH ACUTE
+0xa4 U+00f1 #LATIN SMALL LETTER N WITH TILDE
+0xa5 U+00d1 #LATIN CAPITAL LETTER N WITH TILDE
+0xa6 U+00aa #FEMININE ORDINAL INDICATOR
+0xa7 U+00ba #MASCULINE ORDINAL INDICATOR
+0xa8 U+00bf #INVERTED QUESTION MARK
+0xa9 U+00ae #REGISTERED SIGN
+0xaa U+00ac #NOT SIGN
+0xab U+00bd #VULGAR FRACTION ONE HALF
+0xac U+00bc #VULGAR FRACTION ONE QUARTER
+0xad U+00a1 #INVERTED EXCLAMATION MARK
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+00c1 #LATIN CAPITAL LETTER A WITH ACUTE
+0xb6 U+00c2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xb7 U+00c0 #LATIN CAPITAL LETTER A WITH GRAVE
+0xb8 U+00a9 #COPYRIGHT SIGN
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+00a2 #CENT SIGN
+0xbe U+00a5 #YEN SIGN
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+00e3 #LATIN SMALL LETTER A WITH TILDE
+0xc7 U+00c3 #LATIN CAPITAL LETTER A WITH TILDE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+00a4 #CURRENCY SIGN
+0xd0 U+00f0 #LATIN SMALL LETTER ETH
+0xd1 U+00d0 #LATIN CAPITAL LETTER ETH
+0xd2 U+00ca #LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xd3 U+00cb #LATIN CAPITAL LETTER E WITH DIAERESIS
+0xd4 U+00c8 #LATIN CAPITAL LETTER E WITH GRAVE
+0xd5 U+0131 #LATIN SMALL LETTER DOTLESS I
+0xd6 U+00cd #LATIN CAPITAL LETTER I WITH ACUTE
+0xd7 U+00ce #LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xd8 U+00cf #LATIN CAPITAL LETTER I WITH DIAERESIS
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+00a6 #BROKEN BAR
+0xde U+00cc #LATIN CAPITAL LETTER I WITH GRAVE
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+00d3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xe1 U+00df #LATIN SMALL LETTER SHARP S
+0xe2 U+00d4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xe3 U+00d2 #LATIN CAPITAL LETTER O WITH GRAVE
+0xe4 U+00f5 #LATIN SMALL LETTER O WITH TILDE
+0xe5 U+00d5 #LATIN CAPITAL LETTER O WITH TILDE
+0xe6 U+00b5 #MICRO SIGN
+0xe7 U+00fe #LATIN SMALL LETTER THORN
+0xe8 U+00de #LATIN CAPITAL LETTER THORN
+0xe9 U+00da #LATIN CAPITAL LETTER U WITH ACUTE
+0xea U+00db #LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xeb U+00d9 #LATIN CAPITAL LETTER U WITH GRAVE
+0xec U+00fd #LATIN SMALL LETTER Y WITH ACUTE
+0xed U+00dd #LATIN CAPITAL LETTER Y WITH ACUTE
+0xee U+00af #MACRON
+0xef U+00b4 #ACUTE ACCENT
+0xf0 U+00ad #SOFT HYPHEN
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+2017 #DOUBLE LOW LINE
+0xf3 U+00be #VULGAR FRACTION THREE QUARTERS
+0xf4 U+00b6 #PILCROW SIGN
+0xf5 U+00a7 #SECTION SIGN
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+00b8 #CEDILLA
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+00a8 #DIAERESIS
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+00b9 #SUPERSCRIPT ONE
+0xfc U+00b3 #SUPERSCRIPT THREE
+0xfd U+00b2 #SUPERSCRIPT TWO
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp852_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp852_uni.tbl
new file mode 100644
index 00000000000..0658d8934ba
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp852_uni.tbl
@@ -0,0 +1,280 @@
+#The MIME name of this charset.
+Mcp852
+
+#Name as a Display Charset (used on Options screen)
+ODosLatin2 (cp852)
+
+#
+# Name: cp852_DOSLatin2 to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp852_DOSLatin2 code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp852_DOSLatin2 order
+#
+#0x00 U+0000 #NULL
+#0x01 U+0001 #START OF HEADING
+#0x02 U+0002 #START OF TEXT
+#0x03 U+0003 #END OF TEXT
+#0x04 U+0004 #END OF TRANSMISSION
+#0x05 U+0005 #ENQUIRY
+#0x06 U+0006 #ACKNOWLEDGE
+#0x07 U+0007 #BELL
+#0x08 U+0008 #BACKSPACE
+#0x09 U+0009 #HORIZONTAL TABULATION
+#0x0a U+000a #LINE FEED
+#0x0b U+000b #VERTICAL TABULATION
+#0x0c U+000c #FORM FEED
+#0x0d U+000d #CARRIAGE RETURN
+#0x0e U+000e #SHIFT OUT
+#0x0f U+000f #SHIFT IN
+#0x10 U+0010 #DATA LINK ESCAPE
+#0x11 U+0011 #DEVICE CONTROL ONE
+#0x12 U+0012 #DEVICE CONTROL TWO
+#0x13 U+0013 #DEVICE CONTROL THREE
+#0x14 U+0014 #DEVICE CONTROL FOUR
+#0x15 U+0015 #NEGATIVE ACKNOWLEDGE
+#0x16 U+0016 #SYNCHRONOUS IDLE
+#0x17 U+0017 #END OF TRANSMISSION BLOCK
+#0x18 U+0018 #CANCEL
+#0x19 U+0019 #END OF MEDIUM
+#0x1a U+001a #SUBSTITUTE
+#0x1b U+001b #ESCAPE
+#0x1c U+001c #FILE SEPARATOR
+#0x1d U+001d #GROUP SEPARATOR
+#0x1e U+001e #RECORD SEPARATOR
+#0x1f U+001f #UNIT SEPARATOR
+0x20 U+0020 #SPACE
+0x21 U+0021 #EXCLAMATION MARK
+0x22 U+0022 #QUOTATION MARK
+0x23 U+0023 #NUMBER SIGN
+0x24 U+0024 #DOLLAR SIGN
+0x25 U+0025 #PERCENT SIGN
+0x26 U+0026 #AMPERSAND
+0x27 U+0027 #APOSTROPHE
+0x28 U+0028 #LEFT PARENTHESIS
+0x29 U+0029 #RIGHT PARENTHESIS
+0x2a U+002a #ASTERISK
+0x2b U+002b #PLUS SIGN
+0x2c U+002c #COMMA
+0x2d U+002d #HYPHEN-MINUS
+0x2e U+002e #FULL STOP
+0x2f U+002f #SOLIDUS
+0x30 U+0030 #DIGIT ZERO
+0x31 U+0031 #DIGIT ONE
+0x32 U+0032 #DIGIT TWO
+0x33 U+0033 #DIGIT THREE
+0x34 U+0034 #DIGIT FOUR
+0x35 U+0035 #DIGIT FIVE
+0x36 U+0036 #DIGIT SIX
+0x37 U+0037 #DIGIT SEVEN
+0x38 U+0038 #DIGIT EIGHT
+0x39 U+0039 #DIGIT NINE
+0x3a U+003a #COLON
+0x3b U+003b #SEMICOLON
+0x3c U+003c #LESS-THAN SIGN
+0x3d U+003d #EQUALS SIGN
+0x3e U+003e #GREATER-THAN SIGN
+0x3f U+003f #QUESTION MARK
+0x40 U+0040 #COMMERCIAL AT
+0x41 U+0041 #LATIN CAPITAL LETTER A
+0x42 U+0042 #LATIN CAPITAL LETTER B
+0x43 U+0043 #LATIN CAPITAL LETTER C
+0x44 U+0044 #LATIN CAPITAL LETTER D
+0x45 U+0045 #LATIN CAPITAL LETTER E
+0x46 U+0046 #LATIN CAPITAL LETTER F
+0x47 U+0047 #LATIN CAPITAL LETTER G
+0x48 U+0048 #LATIN CAPITAL LETTER H
+0x49 U+0049 #LATIN CAPITAL LETTER I
+0x4a U+004a #LATIN CAPITAL LETTER J
+0x4b U+004b #LATIN CAPITAL LETTER K
+0x4c U+004c #LATIN CAPITAL LETTER L
+0x4d U+004d #LATIN CAPITAL LETTER M
+0x4e U+004e #LATIN CAPITAL LETTER N
+0x4f U+004f #LATIN CAPITAL LETTER O
+0x50 U+0050 #LATIN CAPITAL LETTER P
+0x51 U+0051 #LATIN CAPITAL LETTER Q
+0x52 U+0052 #LATIN CAPITAL LETTER R
+0x53 U+0053 #LATIN CAPITAL LETTER S
+0x54 U+0054 #LATIN CAPITAL LETTER T
+0x55 U+0055 #LATIN CAPITAL LETTER U
+0x56 U+0056 #LATIN CAPITAL LETTER V
+0x57 U+0057 #LATIN CAPITAL LETTER W
+0x58 U+0058 #LATIN CAPITAL LETTER X
+0x59 U+0059 #LATIN CAPITAL LETTER Y
+0x5a U+005a #LATIN CAPITAL LETTER Z
+0x5b U+005b #LEFT SQUARE BRACKET
+0x5c U+005c #REVERSE SOLIDUS
+0x5d U+005d #RIGHT SQUARE BRACKET
+0x5e U+005e #CIRCUMFLEX ACCENT
+0x5f U+005f #LOW LINE
+0x60 U+0060 #GRAVE ACCENT
+0x61 U+0061 #LATIN SMALL LETTER A
+0x62 U+0062 #LATIN SMALL LETTER B
+0x63 U+0063 #LATIN SMALL LETTER C
+0x64 U+0064 #LATIN SMALL LETTER D
+0x65 U+0065 #LATIN SMALL LETTER E
+0x66 U+0066 #LATIN SMALL LETTER F
+0x67 U+0067 #LATIN SMALL LETTER G
+0x68 U+0068 #LATIN SMALL LETTER H
+0x69 U+0069 #LATIN SMALL LETTER I
+0x6a U+006a #LATIN SMALL LETTER J
+0x6b U+006b #LATIN SMALL LETTER K
+0x6c U+006c #LATIN SMALL LETTER L
+0x6d U+006d #LATIN SMALL LETTER M
+0x6e U+006e #LATIN SMALL LETTER N
+0x6f U+006f #LATIN SMALL LETTER O
+0x70 U+0070 #LATIN SMALL LETTER P
+0x71 U+0071 #LATIN SMALL LETTER Q
+0x72 U+0072 #LATIN SMALL LETTER R
+0x73 U+0073 #LATIN SMALL LETTER S
+0x74 U+0074 #LATIN SMALL LETTER T
+0x75 U+0075 #LATIN SMALL LETTER U
+0x76 U+0076 #LATIN SMALL LETTER V
+0x77 U+0077 #LATIN SMALL LETTER W
+0x78 U+0078 #LATIN SMALL LETTER X
+0x79 U+0079 #LATIN SMALL LETTER Y
+0x7a U+007a #LATIN SMALL LETTER Z
+0x7b U+007b #LEFT CURLY BRACKET
+0x7c U+007c #VERTICAL LINE
+0x7d U+007d #RIGHT CURLY BRACKET
+0x7e U+007e #TILDE
+#0x7f U+007f #DELETE
+0x80 U+00c7 #LATIN CAPITAL LETTER C WITH CEDILLA
+0x81 U+00fc #LATIN SMALL LETTER U WITH DIAERESIS
+0x82 U+00e9 #LATIN SMALL LETTER E WITH ACUTE
+0x83 U+00e2 #LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x84 U+00e4 #LATIN SMALL LETTER A WITH DIAERESIS
+0x85 U+016f #LATIN SMALL LETTER U WITH RING ABOVE
+0x86 U+0107 #LATIN SMALL LETTER C WITH ACUTE
+0x87 U+00e7 #LATIN SMALL LETTER C WITH CEDILLA
+0x88 U+0142 #LATIN SMALL LETTER L WITH STROKE
+0x89 U+00eb #LATIN SMALL LETTER E WITH DIAERESIS
+0x8a U+0150 #LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0x8b U+0151 #LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0x8c U+00ee #LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x8d U+0179 #LATIN CAPITAL LETTER Z WITH ACUTE
+0x8e U+00c4 #LATIN CAPITAL LETTER A WITH DIAERESIS
+0x8f U+0106 #LATIN CAPITAL LETTER C WITH ACUTE
+0x90 U+00c9 #LATIN CAPITAL LETTER E WITH ACUTE
+0x91 U+0139 #LATIN CAPITAL LETTER L WITH ACUTE
+0x92 U+013a #LATIN SMALL LETTER L WITH ACUTE
+0x93 U+00f4 #LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x94 U+00f6 #LATIN SMALL LETTER O WITH DIAERESIS
+0x95 U+013d #LATIN CAPITAL LETTER L WITH CARON
+0x96 U+013e #LATIN SMALL LETTER L WITH CARON
+0x97 U+015a #LATIN CAPITAL LETTER S WITH ACUTE
+0x98 U+015b #LATIN SMALL LETTER S WITH ACUTE
+0x99 U+00d6 #LATIN CAPITAL LETTER O WITH DIAERESIS
+0x9a U+00dc #LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b U+0164 #LATIN CAPITAL LETTER T WITH CARON
+0x9c U+0165 #LATIN SMALL LETTER T WITH CARON
+0x9d U+0141 #LATIN CAPITAL LETTER L WITH STROKE
+0x9e U+00d7 #MULTIPLICATION SIGN
+0x9f U+010d #LATIN SMALL LETTER C WITH CARON
+0xa0 U+00e1 #LATIN SMALL LETTER A WITH ACUTE
+0xa1 U+00ed #LATIN SMALL LETTER I WITH ACUTE
+0xa2 U+00f3 #LATIN SMALL LETTER O WITH ACUTE
+0xa3 U+00fa #LATIN SMALL LETTER U WITH ACUTE
+0xa4 U+0104 #LATIN CAPITAL LETTER A WITH OGONEK
+0xa5 U+0105 #LATIN SMALL LETTER A WITH OGONEK
+0xa6 U+017d #LATIN CAPITAL LETTER Z WITH CARON
+0xa7 U+017e #LATIN SMALL LETTER Z WITH CARON
+0xa8 U+0118 #LATIN CAPITAL LETTER E WITH OGONEK
+0xa9 U+0119 #LATIN SMALL LETTER E WITH OGONEK
+0xaa U+00ac #NOT SIGN
+0xab U+017a #LATIN SMALL LETTER Z WITH ACUTE
+0xac U+010c #LATIN CAPITAL LETTER C WITH CARON
+0xad U+015f #LATIN SMALL LETTER S WITH CEDILLA
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+00c1 #LATIN CAPITAL LETTER A WITH ACUTE
+0xb6 U+00c2 #LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xb7 U+011a #LATIN CAPITAL LETTER E WITH CARON
+0xb8 U+015e #LATIN CAPITAL LETTER S WITH CEDILLA
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+017b #LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xbe U+017c #LATIN SMALL LETTER Z WITH DOT ABOVE
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+0102 #LATIN CAPITAL LETTER A WITH BREVE
+0xc7 U+0103 #LATIN SMALL LETTER A WITH BREVE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+00a4 #CURRENCY SIGN
+0xd0 U+0111 #LATIN SMALL LETTER D WITH STROKE
+0xd1 U+0110 #LATIN CAPITAL LETTER D WITH STROKE
+0xd2 U+010e #LATIN CAPITAL LETTER D WITH CARON
+0xd3 U+00cb #LATIN CAPITAL LETTER E WITH DIAERESIS
+0xd4 U+010f #LATIN SMALL LETTER D WITH CARON
+0xd5 U+0147 #LATIN CAPITAL LETTER N WITH CARON
+0xd6 U+00cd #LATIN CAPITAL LETTER I WITH ACUTE
+0xd7 U+00ce #LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xd8 U+011b #LATIN SMALL LETTER E WITH CARON
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+0162 #LATIN CAPITAL LETTER T WITH CEDILLA
+0xde U+016e #LATIN CAPITAL LETTER U WITH RING ABOVE
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+00d3 #LATIN CAPITAL LETTER O WITH ACUTE
+0xe1 U+00df #LATIN SMALL LETTER SHARP S
+0xe2 U+00d4 #LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xe3 U+0143 #LATIN CAPITAL LETTER N WITH ACUTE
+0xe4 U+0144 #LATIN SMALL LETTER N WITH ACUTE
+0xe5 U+0148 #LATIN SMALL LETTER N WITH CARON
+0xe6 U+0160 #LATIN CAPITAL LETTER S WITH CARON
+0xe7 U+0161 #LATIN SMALL LETTER S WITH CARON
+0xe8 U+0154 #LATIN CAPITAL LETTER R WITH ACUTE
+0xe9 U+00da #LATIN CAPITAL LETTER U WITH ACUTE
+0xea U+0155 #LATIN SMALL LETTER R WITH ACUTE
+0xeb U+0170 #LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xec U+00fd #LATIN SMALL LETTER Y WITH ACUTE
+0xed U+00dd #LATIN CAPITAL LETTER Y WITH ACUTE
+0xee U+0163 #LATIN SMALL LETTER T WITH CEDILLA
+0xef U+00b4 #ACUTE ACCENT
+0xf0 U+00ad #SOFT HYPHEN
+0xf1 U+02dd #DOUBLE ACUTE ACCENT
+0xf2 U+02db #OGONEK
+0xf3 U+02c7 #CARON
+0xf4 U+02d8 #BREVE
+0xf5 U+00a7 #SECTION SIGN
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+00b8 #CEDILLA
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+00a8 #DIAERESIS
+0xfa U+02d9 #DOT ABOVE
+0xfb U+0171 #LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xfc U+0158 #LATIN CAPITAL LETTER R WITH CARON
+0xfd U+0159 #LATIN SMALL LETTER R WITH CARON
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp862_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp862_uni.tbl
new file mode 100644
index 00000000000..3d21c138d41
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp862_uni.tbl
@@ -0,0 +1,155 @@
+#The MIME name of this charset.
+Mcp862
+
+#Name as a Display Charset (used on Options screen).
+ODosHebrew (cp862)
+
+# Name: cp862_DOSHebrew to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp862_DOSHebrew code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp862_DOSHebrew order
+#
+##################
+
+0x20-0x7f idem
+#
+0x80 U+05d0 #HEBREW LETTER ALEF
+0x81 U+05d1 #HEBREW LETTER BET
+0x82 U+05d2 #HEBREW LETTER GIMEL
+0x83 U+05d3 #HEBREW LETTER DALET
+0x84 U+05d4 #HEBREW LETTER HE
+0x85 U+05d5 #HEBREW LETTER VAV
+0x86 U+05d6 #HEBREW LETTER ZAYIN
+0x87 U+05d7 #HEBREW LETTER HET
+0x88 U+05d8 #HEBREW LETTER TET
+0x89 U+05d9 #HEBREW LETTER YOD
+0x8a U+05da #HEBREW LETTER FINAL KAF
+0x8b U+05db #HEBREW LETTER KAF
+0x8c U+05dc #HEBREW LETTER LAMED
+0x8d U+05dd #HEBREW LETTER FINAL MEM
+0x8e U+05de #HEBREW LETTER MEM
+0x8f U+05df #HEBREW LETTER FINAL NUN
+0x90 U+05e0 #HEBREW LETTER NUN
+0x91 U+05e1 #HEBREW LETTER SAMEKH
+0x92 U+05e2 #HEBREW LETTER AYIN
+0x93 U+05e3 #HEBREW LETTER FINAL PE
+0x94 U+05e4 #HEBREW LETTER PE
+0x95 U+05e5 #HEBREW LETTER FINAL TSADI
+0x96 U+05e6 #HEBREW LETTER TSADI
+0x97 U+05e7 #HEBREW LETTER QOF
+0x98 U+05e8 #HEBREW LETTER RESH
+0x99 U+05e9 #HEBREW LETTER SHIN
+0x9a U+05ea #HEBREW LETTER TAV
+0x9b U+00a2 #CENT SIGN
+0x9c U+00a3 #POUND SIGN
+0x9d U+00a5 #YEN SIGN
+0x9e U+20a7 #PESETA SIGN
+0x9f U+0192 #LATIN SMALL LETTER F WITH HOOK
+0xa0 U+00e1 #LATIN SMALL LETTER A WITH ACUTE
+0xa1 U+00ed #LATIN SMALL LETTER I WITH ACUTE
+0xa2 U+00f3 #LATIN SMALL LETTER O WITH ACUTE
+0xa3 U+00fa #LATIN SMALL LETTER U WITH ACUTE
+0xa4 U+00f1 #LATIN SMALL LETTER N WITH TILDE
+0xa5 U+00d1 #LATIN CAPITAL LETTER N WITH TILDE
+0xa6 U+00aa #FEMININE ORDINAL INDICATOR
+0xa7 U+00ba #MASCULINE ORDINAL INDICATOR
+0xa8 U+00bf #INVERTED QUESTION MARK
+0xa9 U+2310 #REVERSED NOT SIGN
+0xaa U+00ac #NOT SIGN
+0xab U+00bd #VULGAR FRACTION ONE HALF
+0xac U+00bc #VULGAR FRACTION ONE QUARTER
+0xad U+00a1 #INVERTED EXCLAMATION MARK
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+2561 #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6 U+2562 #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7 U+2556 #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8 U+2555 #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+255c #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe U+255b #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+255e #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7 U+255f #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+2567 #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0 U+2568 #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1 U+2564 #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2 U+2565 #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3 U+2559 #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4 U+2558 #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5 U+2552 #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6 U+2553 #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7 U+256b #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8 U+256a #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+258c #LEFT HALF BLOCK
+0xde U+2590 #RIGHT HALF BLOCK
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+03b1 #GREEK SMALL LETTER ALPHA
+0xe1 U+00df #LATIN SMALL LETTER SHARP S (GERMAN)
+0xe2 U+0393 #GREEK CAPITAL LETTER GAMMA
+0xe3 U+03c0 #GREEK SMALL LETTER PI
+0xe4 U+03a3 #GREEK CAPITAL LETTER SIGMA
+0xe5 U+03c3 #GREEK SMALL LETTER SIGMA
+0xe6 U+00b5 #MICRO SIGN
+0xe7 U+03c4 #GREEK SMALL LETTER TAU
+0xe8 U+03a6 #GREEK CAPITAL LETTER PHI
+0xe9 U+0398 #GREEK CAPITAL LETTER THETA
+0xea U+03a9 #GREEK CAPITAL LETTER OMEGA
+0xeb U+03b4 #GREEK SMALL LETTER DELTA
+0xec U+221e #INFINITY
+0xed U+03c6 #GREEK SMALL LETTER PHI
+0xee U+03b5 #GREEK SMALL LETTER EPSILON
+0xef U+2229 #INTERSECTION
+0xf0 U+2261 #IDENTICAL TO
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+2265 #GREATER-THAN OR EQUAL TO
+0xf3 U+2264 #LESS-THAN OR EQUAL TO
+0xf4 U+2320 #TOP HALF INTEGRAL
+0xf5 U+2321 #BOTTOM HALF INTEGRAL
+0xf6 U+00f7 #DIVISION SIGN
+0xf7 U+2248 #ALMOST EQUAL TO
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+2219 #BULLET OPERATOR
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+221a #SQUARE ROOT
+0xfc U+207f #SUPERSCRIPT LATIN SMALL LETTER N
+0xfd U+00b2 #SUPERSCRIPT TWO
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp864_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp864_uni.tbl
new file mode 100644
index 00000000000..d6e9243129a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp864_uni.tbl
@@ -0,0 +1,155 @@
+#The MIME name of this charset.
+Mcp864
+
+#Name as a Display Charset (used on Options screen).
+ODosArabic (cp864)
+
+# Name: cp864_DOSArabic to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp864_DOSArabic code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp864_DOSArabic order
+#
+##################
+
+0x20-0x7f idem
+#
+0x80 U+00b0 #DEGREE SIGN
+0x81 U+00b7 #MIDDLE DOT
+0x82 U+2219 #BULLET OPERATOR
+0x83 U+221a #SQUARE ROOT
+0x84 U+2592 #MEDIUM SHADE
+0x85 U+2500 #FORMS LIGHT HORIZONTAL
+0x86 U+2502 #FORMS LIGHT VERTICAL
+0x87 U+253c #FORMS LIGHT VERTICAL AND HORIZONTAL
+0x88 U+2524 #FORMS LIGHT VERTICAL AND LEFT
+0x89 U+252c #FORMS LIGHT DOWN AND HORIZONTAL
+0x8a U+251c #FORMS LIGHT VERTICAL AND RIGHT
+0x8b U+2534 #FORMS LIGHT UP AND HORIZONTAL
+0x8c U+2510 #FORMS LIGHT DOWN AND LEFT
+0x8d U+250c #FORMS LIGHT DOWN AND RIGHT
+0x8e U+2514 #FORMS LIGHT UP AND RIGHT
+0x8f U+2518 #FORMS LIGHT UP AND LEFT
+0x90 U+03b2 #GREEK SMALL BETA
+0x91 U+221e #INFINITY
+0x92 U+03c6 #GREEK SMALL PHI
+0x93 U+00b1 #PLUS-OR-MINUS SIGN
+0x94 U+00bd #FRACTION 1/2
+0x95 U+00bc #FRACTION 1/4
+0x96 U+2248 #ALMOST EQUAL TO
+0x97 U+00ab #LEFT POINTING GUILLEMET
+0x98 U+00bb #RIGHT POINTING GUILLEMET
+0x99 U+fef7 #ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
+0x9a U+fef8 #ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
+#0x9b #UNDEFINED
+#0x9c #UNDEFINED
+0x9d U+fefb #ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
+0x9e U+fefc #ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+#0x9f #UNDEFINED
+0xa0 U+00a0 #NON-BREAKING SPACE
+0xa1 U+00ad #SOFT HYPHEN
+0xa2 U+fe82 #ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
+0xa3 U+00a3 #POUND SIGN
+0xa4 U+00a4 #CURRENCY SIGN
+0xa5 U+fe84 #ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
+#0xa6 #UNDEFINED
+#0xa7 #UNDEFINED
+0xa8 U+fe8e #ARABIC LETTER ALEF FINAL FORM
+0xa9 U+fe8f #ARABIC LETTER BEH ISOLATED FORM
+0xaa U+fe95 #ARABIC LETTER TEH ISOLATED FORM
+0xab U+fe99 #ARABIC LETTER THEH ISOLATED FORM
+0xac U+060c #ARABIC COMMA
+0xad U+fe9d #ARABIC LETTER JEEM ISOLATED FORM
+0xae U+fea1 #ARABIC LETTER HAH ISOLATED FORM
+0xaf U+fea5 #ARABIC LETTER KHAH ISOLATED FORM
+0xb0 U+0660 #ARABIC-INDIC DIGIT ZERO
+0xb1 U+0661 #ARABIC-INDIC DIGIT ONE
+0xb2 U+0662 #ARABIC-INDIC DIGIT TWO
+0xb3 U+0663 #ARABIC-INDIC DIGIT THREE
+0xb4 U+0664 #ARABIC-INDIC DIGIT FOUR
+0xb5 U+0665 #ARABIC-INDIC DIGIT FIVE
+0xb6 U+0666 #ARABIC-INDIC DIGIT SIX
+0xb7 U+0667 #ARABIC-INDIC DIGIT SEVEN
+0xb8 U+0668 #ARABIC-INDIC DIGIT EIGHT
+0xb9 U+0669 #ARABIC-INDIC DIGIT NINE
+0xba U+fed1 #ARABIC LETTER FEH ISOLATED FORM
+0xbb U+061b #ARABIC SEMICOLON
+0xbc U+feb1 #ARABIC LETTER SEEN ISOLATED FORM
+0xbd U+feb5 #ARABIC LETTER SHEEN ISOLATED FORM
+0xbe U+feb9 #ARABIC LETTER SAD ISOLATED FORM
+0xbf U+061f #ARABIC QUESTION MARK
+0xc0 U+00a2 #CENT SIGN
+0xc1 U+fe80 #ARABIC LETTER HAMZA ISOLATED FORM
+0xc2 U+fe81 #ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM
+0xc3 U+fe83 #ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM
+0xc4 U+fe85 #ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM
+0xc5 U+feca #ARABIC LETTER AIN FINAL FORM
+0xc6 U+fe8b #ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM
+0xc7 U+fe8d #ARABIC LETTER ALEF ISOLATED FORM
+0xc8 U+fe91 #ARABIC LETTER BEH INITIAL FORM
+0xc9 U+fe93 #ARABIC LETTER TEH MARBUTA ISOLATED FORM
+0xca U+fe97 #ARABIC LETTER TEH INITIAL FORM
+0xcb U+fe9b #ARABIC LETTER THEH INITIAL FORM
+0xcc U+fe9f #ARABIC LETTER JEEM INITIAL FORM
+0xcd U+fea3 #ARABIC LETTER HAH INITIAL FORM
+0xce U+fea7 #ARABIC LETTER KHAH INITIAL FORM
+0xcf U+fea9 #ARABIC LETTER DAL ISOLATED FORM
+0xd0 U+feab #ARABIC LETTER THAL ISOLATED FORM
+0xd1 U+fead #ARABIC LETTER REH ISOLATED FORM
+0xd2 U+feaf #ARABIC LETTER ZAIN ISOLATED FORM
+0xd3 U+feb3 #ARABIC LETTER SEEN INITIAL FORM
+0xd4 U+feb7 #ARABIC LETTER SHEEN INITIAL FORM
+0xd5 U+febb #ARABIC LETTER SAD INITIAL FORM
+0xd6 U+febf #ARABIC LETTER DAD INITIAL FORM
+0xd7 U+fec1 #ARABIC LETTER TAH ISOLATED FORM
+0xd8 U+fec5 #ARABIC LETTER ZAH ISOLATED FORM
+0xd9 U+fecb #ARABIC LETTER AIN INITIAL FORM
+0xda U+fecf #ARABIC LETTER GHAIN INITIAL FORM
+0xdb U+00a6 #BROKEN VERTICAL BAR
+0xdc U+00ac #NOT SIGN
+0xdd U+00f7 #DIVISION SIGN
+0xde U+00d7 #MULTIPLICATION SIGN
+0xdf U+fec9 #ARABIC LETTER AIN ISOLATED FORM
+0xe0 U+0640 #ARABIC TATWEEL
+0xe1 U+fed3 #ARABIC LETTER FEH INITIAL FORM
+0xe2 U+fed7 #ARABIC LETTER QAF INITIAL FORM
+0xe3 U+fedb #ARABIC LETTER KAF INITIAL FORM
+0xe4 U+fedf #ARABIC LETTER LAM INITIAL FORM
+0xe5 U+fee3 #ARABIC LETTER MEEM INITIAL FORM
+0xe6 U+fee7 #ARABIC LETTER NOON INITIAL FORM
+0xe7 U+feeb #ARABIC LETTER HEH INITIAL FORM
+0xe8 U+feed #ARABIC LETTER WAW ISOLATED FORM
+0xe9 U+feef #ARABIC LETTER ALEF MAKSURA ISOLATED FORM
+0xea U+fef3 #ARABIC LETTER YEH INITIAL FORM
+0xeb U+febd #ARABIC LETTER DAD ISOLATED FORM
+0xec U+fecc #ARABIC LETTER AIN MEDIAL FORM
+0xed U+fece #ARABIC LETTER GHAIN FINAL FORM
+0xee U+fecd #ARABIC LETTER GHAIN ISOLATED FORM
+0xef U+fee1 #ARABIC LETTER MEEM ISOLATED FORM
+0xf0 U+fe7d #ARABIC SHADDA MEDIAL FORM
+0xf1 U+0651 #ARABIC SHADDAH
+0xf2 U+fee5 #ARABIC LETTER NOON ISOLATED FORM
+0xf3 U+fee9 #ARABIC LETTER HEH ISOLATED FORM
+0xf4 U+feec #ARABIC LETTER HEH MEDIAL FORM
+0xf5 U+fef0 #ARABIC LETTER ALEF MAKSURA FINAL FORM
+0xf6 U+fef2 #ARABIC LETTER YEH FINAL FORM
+0xf7 U+fed0 #ARABIC LETTER GHAIN MEDIAL FORM
+0xf8 U+fed5 #ARABIC LETTER QAF ISOLATED FORM
+0xf9 U+fef5 #ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM
+0xfa U+fef6 #ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM
+0xfb U+fedd #ARABIC LETTER LAM ISOLATED FORM
+0xfc U+fed9 #ARABIC LETTER KAF ISOLATED FORM
+0xfd U+fef1 #ARABIC LETTER YEH ISOLATED FORM
+0xfe U+25a0 #BLACK SQUARE
+#0xff #UNDEFINED
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp866_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp866_uni.tbl
new file mode 100644
index 00000000000..2d02ce1b3a4
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp866_uni.tbl
@@ -0,0 +1,154 @@
+#
+#The MIME name of this charset.
+Mcp866
+
+#Name as a Display Charset (used on Options screen)
+ODosCyrillic (cp866)
+#
+# Name: cp866_DOSCyrillicRussian to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp866_DOSCyrillicRussian code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp866_DOSCyrillicRussian order
+#
+0x20-0x7f idem
+#
+0x80 U+0410 #CYRILLIC CAPITAL LETTER A
+0x81 U+0411 #CYRILLIC CAPITAL LETTER BE
+0x82 U+0412 #CYRILLIC CAPITAL LETTER VE
+0x83 U+0413 #CYRILLIC CAPITAL LETTER GHE
+0x84 U+0414 #CYRILLIC CAPITAL LETTER DE
+0x85 U+0415 #CYRILLIC CAPITAL LETTER IE
+0x86 U+0416 #CYRILLIC CAPITAL LETTER ZHE
+0x87 U+0417 #CYRILLIC CAPITAL LETTER ZE
+0x88 U+0418 #CYRILLIC CAPITAL LETTER I
+0x89 U+0419 #CYRILLIC CAPITAL LETTER SHORT I
+0x8a U+041a #CYRILLIC CAPITAL LETTER KA
+0x8b U+041b #CYRILLIC CAPITAL LETTER EL
+0x8c U+041c #CYRILLIC CAPITAL LETTER EM
+0x8d U+041d #CYRILLIC CAPITAL LETTER EN
+0x8e U+041e #CYRILLIC CAPITAL LETTER O
+0x8f U+041f #CYRILLIC CAPITAL LETTER PE
+0x90 U+0420 #CYRILLIC CAPITAL LETTER ER
+0x91 U+0421 #CYRILLIC CAPITAL LETTER ES
+0x92 U+0422 #CYRILLIC CAPITAL LETTER TE
+0x93 U+0423 #CYRILLIC CAPITAL LETTER U
+0x94 U+0424 #CYRILLIC CAPITAL LETTER EF
+0x95 U+0425 #CYRILLIC CAPITAL LETTER HA
+0x96 U+0426 #CYRILLIC CAPITAL LETTER TSE
+0x97 U+0427 #CYRILLIC CAPITAL LETTER CHE
+0x98 U+0428 #CYRILLIC CAPITAL LETTER SHA
+0x99 U+0429 #CYRILLIC CAPITAL LETTER SHCHA
+0x9a U+042a #CYRILLIC CAPITAL LETTER HARD SIGN
+0x9b U+042b #CYRILLIC CAPITAL LETTER YERU
+0x9c U+042c #CYRILLIC CAPITAL LETTER SOFT SIGN
+0x9d U+042d #CYRILLIC CAPITAL LETTER E
+0x9e U+042e #CYRILLIC CAPITAL LETTER YU
+0x9f U+042f #CYRILLIC CAPITAL LETTER YA
+0xa0 U+0430 #CYRILLIC SMALL LETTER A
+0xa1 U+0431 #CYRILLIC SMALL LETTER BE
+0xa2 U+0432 #CYRILLIC SMALL LETTER VE
+0xa3 U+0433 #CYRILLIC SMALL LETTER GHE
+0xa4 U+0434 #CYRILLIC SMALL LETTER DE
+0xa5 U+0435 #CYRILLIC SMALL LETTER IE
+0xa6 U+0436 #CYRILLIC SMALL LETTER ZHE
+0xa7 U+0437 #CYRILLIC SMALL LETTER ZE
+0xa8 U+0438 #CYRILLIC SMALL LETTER I
+0xa9 U+0439 #CYRILLIC SMALL LETTER SHORT I
+0xaa U+043a #CYRILLIC SMALL LETTER KA
+0xab U+043b #CYRILLIC SMALL LETTER EL
+0xac U+043c #CYRILLIC SMALL LETTER EM
+0xad U+043d #CYRILLIC SMALL LETTER EN
+0xae U+043e #CYRILLIC SMALL LETTER O
+0xaf U+043f #CYRILLIC SMALL LETTER PE
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+2561 #BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0xb6 U+2562 #BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0xb7 U+2556 #BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0xb8 U+2555 #BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+255c #BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0xbe U+255b #BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+255e #BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0xc7 U+255f #BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+2567 #BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0xd0 U+2568 #BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0xd1 U+2564 #BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xd2 U+2565 #BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xd3 U+2559 #BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0xd4 U+2558 #BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0xd5 U+2552 #BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0xd6 U+2553 #BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0xd7 U+256b #BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xd8 U+256a #BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+258c #LEFT HALF BLOCK
+0xde U+2590 #RIGHT HALF BLOCK
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+0440 #CYRILLIC SMALL LETTER ER
+0xe1 U+0441 #CYRILLIC SMALL LETTER ES
+0xe2 U+0442 #CYRILLIC SMALL LETTER TE
+0xe3 U+0443 #CYRILLIC SMALL LETTER U
+0xe4 U+0444 #CYRILLIC SMALL LETTER EF
+0xe5 U+0445 #CYRILLIC SMALL LETTER HA
+0xe6 U+0446 #CYRILLIC SMALL LETTER TSE
+0xe7 U+0447 #CYRILLIC SMALL LETTER CHE
+0xe8 U+0448 #CYRILLIC SMALL LETTER SHA
+0xe9 U+0449 #CYRILLIC SMALL LETTER SHCHA
+0xea U+044a #CYRILLIC SMALL LETTER HARD SIGN
+0xeb U+044b #CYRILLIC SMALL LETTER YERU
+0xec U+044c #CYRILLIC SMALL LETTER SOFT SIGN
+0xed U+044d #CYRILLIC SMALL LETTER E
+0xee U+044e #CYRILLIC SMALL LETTER YU
+0xef U+044f #CYRILLIC SMALL LETTER YA
+0xf0 U+0401 #CYRILLIC CAPITAL LETTER IO
+0xf1 U+0451 #CYRILLIC SMALL LETTER IO
+0xf2 U+0404 #CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xf3 U+0454 #CYRILLIC SMALL LETTER UKRAINIAN IE
+0xf4 U+0407 #CYRILLIC CAPITAL LETTER YI
+0xf5 U+0457 #CYRILLIC SMALL LETTER YI
+0xf6 U+040e #CYRILLIC CAPITAL LETTER SHORT U
+0xf7 U+045e #CYRILLIC SMALL LETTER SHORT U
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+2219 #BULLET OPERATOR
+0xfa U+00b7 #MIDDLE DOT
+0xfb U+221a #SQUARE ROOT
+0xfc U+2116 #NUMERO SIGN
+0xfd U+00a4 #CURRENCY SIGN
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/cp869_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/cp869_uni.tbl
new file mode 100644
index 00000000000..21cdeb956e6
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/cp869_uni.tbl
@@ -0,0 +1,155 @@
+#The MIME name of this charset.
+Mcp869
+
+#Name as a Display Charset (used on Options screen)
+ODosGreek2 (cp869)
+
+# Name: cp869_DOSGreek2 to Unicode table
+# Unicode version: 2.0
+# Table version: 2.00
+# Table format: Format A
+# Date: 04/24/96
+# Authors: Lori Brownell <loribr@microsoft.com>
+# K.D. Chang <a-kchang@microsoft.com>
+# General notes: none
+#
+# Format: Three tab-separated columns
+# Column #1 is the cp869_DOSGreek2 code (in hex)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in cp869_DOSGreek2 order
+#
+##################
+
+0x20-0x7f idem
+#
+#0x80 #UNDEFINED
+#0x81 #UNDEFINED
+#0x82 #UNDEFINED
+#0x83 #UNDEFINED
+#0x84 #UNDEFINED
+#0x85 #UNDEFINED
+0x86 U+0386 #GREEK CAPITAL LETTER ALPHA WITH TONOS
+#0x87 #UNDEFINED
+0x88 U+00b7 #MIDDLE DOT
+0x89 U+00ac #NOT SIGN
+0x8a U+00a6 #BROKEN BAR
+0x8b U+2018 #LEFT SINGLE QUOTATION MARK
+0x8c U+2019 #RIGHT SINGLE QUOTATION MARK
+0x8d U+0388 #GREEK CAPITAL LETTER EPSILON WITH TONOS
+0x8e U+2015 #HORIZONTAL BAR
+0x8f U+0389 #GREEK CAPITAL LETTER ETA WITH TONOS
+0x90 U+038a #GREEK CAPITAL LETTER IOTA WITH TONOS
+0x91 U+03aa #GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0x92 U+038c #GREEK CAPITAL LETTER OMICRON WITH TONOS
+#0x93 #UNDEFINED
+#0x94 #UNDEFINED
+0x95 U+038e #GREEK CAPITAL LETTER UPSILON WITH TONOS
+0x96 U+03ab #GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0x97 U+00a9 #COPYRIGHT SIGN
+0x98 U+038f #GREEK CAPITAL LETTER OMEGA WITH TONOS
+0x99 U+00b2 #SUPERSCRIPT TWO
+0x9a U+00b3 #SUPERSCRIPT THREE
+0x9b U+03ac #GREEK SMALL LETTER ALPHA WITH TONOS
+0x9c U+00a3 #POUND SIGN
+0x9d U+03ad #GREEK SMALL LETTER EPSILON WITH TONOS
+0x9e U+03ae #GREEK SMALL LETTER ETA WITH TONOS
+0x9f U+03af #GREEK SMALL LETTER IOTA WITH TONOS
+0xa0 U+03ca #GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xa1 U+0390 #GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0xa2 U+03cc #GREEK SMALL LETTER OMICRON WITH TONOS
+0xa3 U+03cd #GREEK SMALL LETTER UPSILON WITH TONOS
+0xa4 U+0391 #GREEK CAPITAL LETTER ALPHA
+0xa5 U+0392 #GREEK CAPITAL LETTER BETA
+0xa6 U+0393 #GREEK CAPITAL LETTER GAMMA
+0xa7 U+0394 #GREEK CAPITAL LETTER DELTA
+0xa8 U+0395 #GREEK CAPITAL LETTER EPSILON
+0xa9 U+0396 #GREEK CAPITAL LETTER ZETA
+0xaa U+0397 #GREEK CAPITAL LETTER ETA
+0xab U+00bd #VULGAR FRACTION ONE HALF
+0xac U+0398 #GREEK CAPITAL LETTER THETA
+0xad U+0399 #GREEK CAPITAL LETTER IOTA
+0xae U+00ab #LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xaf U+00bb #RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xb0 U+2591 #LIGHT SHADE
+0xb1 U+2592 #MEDIUM SHADE
+0xb2 U+2593 #DARK SHADE
+0xb3 U+2502 #BOX DRAWINGS LIGHT VERTICAL
+0xb4 U+2524 #BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0xb5 U+039a #GREEK CAPITAL LETTER KAPPA
+0xb6 U+039b #GREEK CAPITAL LETTER LAMDA
+0xb7 U+039c #GREEK CAPITAL LETTER MU
+0xb8 U+039d #GREEK CAPITAL LETTER NU
+0xb9 U+2563 #BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0xba U+2551 #BOX DRAWINGS DOUBLE VERTICAL
+0xbb U+2557 #BOX DRAWINGS DOUBLE DOWN AND LEFT
+0xbc U+255d #BOX DRAWINGS DOUBLE UP AND LEFT
+0xbd U+039e #GREEK CAPITAL LETTER XI
+0xbe U+039f #GREEK CAPITAL LETTER OMICRON
+0xbf U+2510 #BOX DRAWINGS LIGHT DOWN AND LEFT
+0xc0 U+2514 #BOX DRAWINGS LIGHT UP AND RIGHT
+0xc1 U+2534 #BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0xc2 U+252c #BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0xc3 U+251c #BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0xc4 U+2500 #BOX DRAWINGS LIGHT HORIZONTAL
+0xc5 U+253c #BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0xc6 U+03a0 #GREEK CAPITAL LETTER PI
+0xc7 U+03a1 #GREEK CAPITAL LETTER RHO
+0xc8 U+255a #BOX DRAWINGS DOUBLE UP AND RIGHT
+0xc9 U+2554 #BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0xca U+2569 #BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0xcb U+2566 #BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0xcc U+2560 #BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0xcd U+2550 #BOX DRAWINGS DOUBLE HORIZONTAL
+0xce U+256c #BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0xcf U+03a3 #GREEK CAPITAL LETTER SIGMA
+0xd0 U+03a4 #GREEK CAPITAL LETTER TAU
+0xd1 U+03a5 #GREEK CAPITAL LETTER UPSILON
+0xd2 U+03a6 #GREEK CAPITAL LETTER PHI
+0xd3 U+03a7 #GREEK CAPITAL LETTER CHI
+0xd4 U+03a8 #GREEK CAPITAL LETTER PSI
+0xd5 U+03a9 #GREEK CAPITAL LETTER OMEGA
+0xd6 U+03b1 #GREEK SMALL LETTER ALPHA
+0xd7 U+03b2 #GREEK SMALL LETTER BETA
+0xd8 U+03b3 #GREEK SMALL LETTER GAMMA
+0xd9 U+2518 #BOX DRAWINGS LIGHT UP AND LEFT
+0xda U+250c #BOX DRAWINGS LIGHT DOWN AND RIGHT
+0xdb U+2588 #FULL BLOCK
+0xdc U+2584 #LOWER HALF BLOCK
+0xdd U+03b4 #GREEK SMALL LETTER DELTA
+0xde U+03b5 #GREEK SMALL LETTER EPSILON
+0xdf U+2580 #UPPER HALF BLOCK
+0xe0 U+03b6 #GREEK SMALL LETTER ZETA
+0xe1 U+03b7 #GREEK SMALL LETTER ETA
+0xe2 U+03b8 #GREEK SMALL LETTER THETA
+0xe3 U+03b9 #GREEK SMALL LETTER IOTA
+0xe4 U+03ba #GREEK SMALL LETTER KAPPA
+0xe5 U+03bb #GREEK SMALL LETTER LAMDA
+0xe6 U+03bc #GREEK SMALL LETTER MU
+0xe7 U+03bd #GREEK SMALL LETTER NU
+0xe8 U+03be #GREEK SMALL LETTER XI
+0xe9 U+03bf #GREEK SMALL LETTER OMICRON
+0xea U+03c0 #GREEK SMALL LETTER PI
+0xeb U+03c1 #GREEK SMALL LETTER RHO
+0xec U+03c3 #GREEK SMALL LETTER SIGMA
+0xed U+03c2 #GREEK SMALL LETTER FINAL SIGMA
+0xee U+03c4 #GREEK SMALL LETTER TAU
+0xef U+0384 #GREEK TONOS
+0xf0 U+00ad #SOFT HYPHEN
+0xf1 U+00b1 #PLUS-MINUS SIGN
+0xf2 U+03c5 #GREEK SMALL LETTER UPSILON
+0xf3 U+03c6 #GREEK SMALL LETTER PHI
+0xf4 U+03c7 #GREEK SMALL LETTER CHI
+0xf5 U+00a7 #SECTION SIGN
+0xf6 U+03c8 #GREEK SMALL LETTER PSI
+0xf7 U+0385 #GREEK DIALYTIKA TONOS
+0xf8 U+00b0 #DEGREE SIGN
+0xf9 U+00a8 #DIAERESIS
+0xfa U+03c9 #GREEK SMALL LETTER OMEGA
+0xfb U+03cb #GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xfc U+03b0 #GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0xfd U+03ce #GREEK SMALL LETTER OMEGA WITH TONOS
+0xfe U+25a0 #BLACK SQUARE
+0xff U+00a0 #NO-BREAK SPACE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/def7_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/def7_uni.tbl
new file mode 100644
index 00000000000..66a63f76010
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/def7_uni.tbl
@@ -0,0 +1,2217 @@
+# Default 7bit replacements. If the MIME name is set to us-ascii,
+# this will be identified with the "7 bit approximations" Display
+# character set.
+
+#The MIME name of this charset.
+Mus-ascii
+
+# Shall this become the "default" translation table? YES!
+# There has to be exactly one table marked as "default".
+D1
+
+
+# us-ascii characters should not normally pass here,
+# they are always processed directly but let declare it here:
+0x20-0x7e idem
+
+
+# NO-BREAK SPACE,
+# should not happen (processed in the code):
+#U+00a0:NS
+U+00a1:!
+U+00a2:-c-
+U+00a3:-L-
+U+00a4:CUR
+U+00a5:YEN
+U+00a6:|
+U+00a7:S:
+U+00a8:"
+# COPYRIGHT SIGN:
+U+00a9:(c)
+U+00aa:-a
+U+00ab:<<
+U+00ac:NOT
+# SOFT HYPHEN,
+# should not happen (processed in the code):
+#U+00ad:-
+# REGISTERED SIGN:
+U+00ae:(R)
+U+00af:-
+U+00b0:DEG
+U+00b1:+-
+U+00b2:^2
+U+00b3:^3
+U+00b4:'
+# My -> u
+U+00b5:u
+U+00b6:P:
+U+00b7:.
+U+00b8:,
+U+00b9:^1
+U+00ba:-o
+U+00bb:>>
+U+00bc: 1/4
+U+00bd: 1/2
+U+00be: 3/4
+U+00bf:?
+0x41 U+00c0-U+00c3
+U+00c4:A:
+U+00c5:AA
+U+00c6:AE
+U+00c7:C,
+0x45 U+00c8-U+00cb
+0x49 U+00cc-U+00cf
+U+00d0:D-
+0x4e U+00d1
+0x4f U+00d2-U+00d5
+U+00d6:O:
+U+00d7: *
+U+00d8:O/
+0x55 U+00d9-U+00db
+U+00dc:U:
+0x59 U+00dd
+U+00de:TH
+U+00df:ss
+U+00e0:`a
+0x61 U+00e1-U+00e3
+U+00e4:a:
+U+00e5:aa
+U+00e6:ae
+U+00e7:c,
+0x65 U+00e8-U+00eb
+U+00ec:`i
+0x69 U+00ed-U+00ef
+U+00f0:d-
+0x6e U+00f1
+0x6f U+00f2-U+00f5
+U+00f6:o:
+U+00f7:-:
+U+00f8:o/
+0x75 U+00f9-U+00fb
+U+00fc:u:
+0x79 U+00fd
+U+00fe:th
+0x79 U+00ff
+# end of latin-1 repertoire
+0x41 U+0100 U+0102 U+0104 # A
+0x61 U+0101 U+0103 U+0105 # a
+0x43 U+0106 U+0108 U+010a U+010c # C
+# The following line is an example for mapping several accented versions
+# of small letter 'c' to 'c':
+0x63 U+0107 U+0109 U+010b U+010d # c
+0x44 U+010e
+0x64 U+010f
+U+0110:D/
+U+0111:d/
+0x45 U+0112 U+0114 U+0116 U+0118 U+011a # E
+0x65 U+0113 U+0115 U+0117 U+0119 U+011b # e
+0x47 U+011c U+011e U+0120 U+0122 # G
+0x67 U+011d U+011f U+0121 U+0123 # g
+0x48 U+0124
+0x68 U+0125
+U+0126:H/
+0x48 U+0127 # LATIN SMALL LETTER H BAR -> H
+0x49 U+0128 U+012a U+012c U+012e U+0130 # I
+0x69 U+0129 U+012b U+012d U+012f U+0131 # i
+U+0132:IJ
+U+0133:ij
+0x4a U+0134
+0x6a U+0135
+0x4b U+0136
+0x6b U+0137
+U+0138:kk
+0x4c U+0139 U+013b U+013d # L
+0x6c U+013a U+013c U+013e # l
+U+013f:L.
+U+0140:l.
+U+0141:L/
+U+0142:l/
+0x4e U+0143 U+0145 U+0147 # N
+0x6e U+0144 U+0146 U+0148 # n
+U+0149:'n
+U+014a:NG
+0x4e U+014B # LATIN SMALL LETTER ENG -> N
+0x4f U+014c U+014e # O
+0x6f U+014d U+014f # o
+U+0150:O"
+U+0151:o"
+U+0152:OE
+U+0153:oe
+0x52 U+0154 U+0156 U+0158 # R
+0x72 U+0155 U+0157 U+0159 # r
+0x53 U+015a U+015c U+015e U+0160 # S
+0x73 U+015b U+015d U+015f U+0161 # s
+0x54 U+0162 U+0164 # T
+0x74 U+0163 U+0165 # t
+U+0166:T/
+U+0167:t/
+0x55 U+0168 U+016a U+016c U+016e U+0172 # U
+0x75 U+0169 U+016b U+016d U+016f U+0173 # u
+U+0170:U"
+U+0171:u"
+0x57 U+0174
+0x77 U+0175
+0x59 U+0176 U+0178
+0x79 U+0177
+0x5a U+0179 U+017b U+017d
+0x7a U+017a U+017c U+017e
+U+017f:s1
+U+0187:C2
+U+0188:c2
+U+0191:F2
+U+0192: f
+U+0198:K2
+U+0199:k2
+U+01a0:O9
+U+01a1:o9
+U+01a2:OI
+U+01a3:oi
+U+01a6:yr
+U+01af:U9
+U+01b0:u9
+U+01b5:Z/
+U+01b6:z/
+U+01b7:ED
+0x41 U+01cd
+0x61 U+01ce
+0x49 U+01cf
+0x69 U+01d0
+0x4f U+01d1
+0x6f U+01d2
+0x55 U+01d3
+0x75 U+01d4
+U+01d5:U:-
+U+01d6:u:-
+U+01d7:U:'
+U+01d8:u:'
+U+01d9:U:<
+U+01da:u:<
+U+01db:U:!
+U+01dc:u:!
+U+01de:A1
+U+01df:a1
+U+01e0:A7
+U+01e1:a7
+U+01e2:A3
+U+01e3:a3
+U+01e4:G/
+U+01e5:g/
+0x47 U+01e6
+0x67 U+01e7
+0x4b U+01e8
+0x6b U+01e9
+0x4f U+01ea
+0x6f U+01eb
+U+01ec:O1
+U+01ed:o1
+U+01ee:EZ
+U+01ef:ez
+0x6a U+01f0
+0x47 U+01f4
+0x67 U+01f5
+U+01fa:AA'
+U+01fb:aa'
+U+01fc:AE'
+U+01fd:ae'
+U+01fe:O/'
+U+01ff:o/'
+U+0200:A!!
+U+0201:a!!
+U+0202:A)
+U+0203:a)
+U+0204:E!!
+U+0205:e!!
+U+0206:E)
+U+0207:e)
+U+0208:I!!
+U+0209:i!!
+U+020a:I)
+U+020b:i)
+U+020c:O!!
+U+020d:o!!
+U+020e:O)
+U+020f:o)
+U+0210:R!!
+U+0211:r!!
+U+0212:R)
+U+0213:r)
+U+0214:U!!
+U+0215:u!!
+U+0216:U)
+U+0217:u)
+
+# IPA symbols, from
+# Linkname: FAQ: Representing IPA Phonetics in ASCII
+# URL: http://www.hpl.hp.com/personal/Evan_Kirshenbaum/IPA/faq.html
+# (corrected in Russian Cyrillic area).
+# (corrected in Greek area).
+#
+0x41 U+0251 # LATIN SMALL LETTER SCRIPT A -> A
+U+0252:A.
+U+0253:b`
+0x4f U+0254 # LATIN SMALL LETTER OPEN O -> O
+U+0256:d.
+U+0257:d`
+U+0258:@<umd>
+0x40 U+0259 # LATIN SMALL LETTER SCHWA -> @
+0x52 U+025A # LATIN SMALL LETTER SCHWA HOOK -> R
+0x45 U+025B # LATIN SMALL LETTER EPSILON -> E
+U+025c:V"
+U+025d:R<umd>
+U+025e:O"
+0x4a U+025F # LATIN SMALL LETTER DOTLESS J BAR -> J
+U+0260:g`
+0x67 U+0261 # LATIN SMALL LETTER SCRIPT G
+0x47 U+0262 # LATIN LETTER SMALL CAPITAL G
+0x51 U+0263 # LATIN SMALL LETTER GAMMA -> Q
+U+0264:o-
+U+0265:j<rnd>
+U+0266:h<?>
+U+0268:i"
+0x49 U+026A U+0269 # LATIN LETTER SMALL CAPITAL I, LATIN SMALL LETTER IOTA
+0x4c U+026B # LATIN SMALL LETTER L WITH MIDDLE TILDE
+0x4c U+026C # LATIN SMALL LETTER L BELT
+U+026d:l.
+U+026e:z<lat>
+U+026f:u-
+U+0270:j<vel>
+0x4d U+0271 # LATIN SMALL LETTER M HOOK
+U+0273:n.
+U+0274:n"
+U+0275:@.
+U+0276:&.
+0x55 U+0277 # LATIN SMALL LETTER CLOSED OMEGA -> U
+0x72 U+0279 # LATIN SMALL LETTER TURNED R -> r
+U+027a:*<lat>
+U+027b:r.
+U+027d:*.
+0x2a U+027E # LATIN SMALL LETTER FISHHOOK R -> *
+U+0280:r"
+0x52 U+0280 # LATIN LETTER SMALL CAPITAL R -> R
+U+0281:g"
+U+0282:s.
+0x53 U+0283 # LATIN SMALL LETTER ESH -> S
+U+0284:J`
+U+0287:t!
+U+0288:t.
+U+0289:u"
+0x55 U+028A # LATIN SMALL LETTER UPSILON -> U
+U+028b:r<lbd>
+0x56 U+028C # LATIN SMALL LETTER TURNED V -> V
+U+028d:w<vls>
+U+028e:l^
+U+028f:I.
+U+0290:z.
+U+0292:ed
+0x3f U+0294 # LATIN SMALL LETTER GLOTTAL STOP -> ?
+U+0295:H<vcd>
+U+0296:l!
+U+0297:c!
+U+0298:p!
+U+0299:b<trl>
+U+029b:G`
+0x6a U+029d # LATIN SMALL LETTER CROSSED-TAIL J
+U+029e:k!
+0x4c U+029F # LATIN LETTER SMALL CAPITAL L
+U+02a0:q`
+U+02b0:<h>
+U+02b1:<?>
+0x3b U+02b2 U+0321
+U+02b3:<r>
+U+02b7:<w>
+U+02bb:;S
+0x60 U+02bc
+U+02c6:^
+U+02c7:'<
+U+02c9:1-
+U+02cb:1!
+0x3a U+02d0
+U+02d8:'(
+U+02d9:'.
+U+02da:'0
+U+02db:';
+U+02dc:~
+U+02dd:'"
+0x7e U+0303 U+0334
+0x2e U+0322 U+0323
+U+0324:<?>
+U+0325:<o>
+0x2d U+0329
+0x5b U+032a
+U+032b:<w>
+U+0334:<H>
+U+0374:'
+U+0375:,
+U+037a:j3
+U+037e:?%
+U+0384:'*
+U+0385:'%
+# Greek letters
+U+0386:A%
+U+0387:.*
+U+0388:E%
+U+0389:Y%
+U+038a:I%
+U+038c:O%
+U+038e:U%
+U+038f:W%
+U+0390:i3
+U+0391:A
+U+0392:B
+U+0393:G
+U+0394:D
+U+0395:E
+U+0396:Z
+U+0397:Y
+U+0398:TH
+U+0399:I
+U+039a:K
+U+039b:L
+U+039c:M
+U+039d:N
+U+039e:C
+U+039f:O
+U+03a0:P
+U+03a1:R
+U+03a3:S
+U+03a4:T
+U+03a5:U
+U+03a6:F
+U+03a7:X
+U+03a8:Q
+U+03a9:W
+U+03aa:J
+U+03ab:V*
+U+03ac:a%
+U+03ad:e%
+U+03ae:y%
+U+03af:i%
+U+03b0:u3
+U+03b1:a
+U+03b2:b
+U+03b3:g
+U+03b4:d
+U+03b5:e
+U+03b6:z
+U+03b7:y
+U+03b8:th
+U+03b9:i
+U+03ba:k
+U+03bb:l
+U+03bc:m
+U+03bd:n
+U+03be:c
+U+03bf:o
+U+03c0:p
+U+03c1:r
+U+03c2:*s
+U+03c3:s
+U+03c4:t
+U+03c5:u
+U+03c6:f
+U+03c7:x
+U+03c8:q
+U+03c9:w
+U+03ca:j
+U+03cb:v*
+U+03cc:o%
+U+03cd:u%
+U+03ce:w%
+# Greek symbols
+U+03d0:beta
+U+03d1:theta
+U+03d2:upsi
+U+03d5:phi
+U+03d6:pi
+U+03da:T3
+U+03db:t3
+U+03dc:M3
+U+03dd:m3
+U+03de:K3
+U+03df:k3
+U+03e0:P3
+U+03e1:p3
+U+03f0:kappa
+U+03f1:rho
+U+03f4:'%
+U+03f5:j3
+# Cyrillic capital letters
+U+0402:D%
+U+0403:G%
+U+0404:IE
+U+0405:DS
+U+0406:II
+U+0407:YI
+U+0408:J%
+U+0409:LJ
+U+040a:NJ
+U+040b:Ts
+U+040c:KJ
+U+040e:V%
+U+040f:DZ
+# Russian Cyrillic letters, transliterated
+U+0401:IO
+U+0410:A
+U+0411:B
+U+0412:V
+U+0413:G
+U+0414:D
+U+0415:E
+U+0416:ZH
+U+0417:Z
+U+0418:I
+U+0419:J
+U+041a:K
+U+041b:L
+U+041c:M
+U+041d:N
+U+041e:O
+U+041f:P
+U+0420:R
+U+0421:S
+U+0422:T
+U+0423:U
+U+0424:F
+U+0425:H
+U+0426:C
+U+0427:CH
+U+0428:SH
+U+0429:SCH
+U+042a:"
+U+042b:Y
+U+042c:'
+U+042d:`E
+U+042e:YU
+U+042f:YA
+U+0430:a
+U+0431:b
+U+0432:v
+U+0433:g
+U+0434:d
+U+0435:e
+U+0436:zh
+U+0437:z
+U+0438:i
+U+0439:j
+U+043a:k
+U+043b:l
+U+043c:m
+U+043d:n
+U+043e:o
+U+043f:p
+U+0440:r
+U+0441:s
+U+0442:t
+U+0443:u
+U+0444:f
+U+0445:h
+U+0446:c
+U+0447:ch
+U+0448:sh
+U+0449:sch
+U+044a:"
+U+044b:y
+U+044c:'
+U+044d:`e
+U+044e:yu
+U+044f:ya
+U+0451:io
+# end of Russian Cyrillic letters.
+# Cyrillic small letters (and some archaic)
+U+0452:d%
+U+0453:g%
+U+0454:ie
+U+0455:ds
+U+0456:ii
+U+0457:yi
+U+0458:j%
+U+0459:lj
+U+045a:nj
+U+045b:ts
+U+045c:kj
+U+045e:v%
+U+045f:dz
+U+0462:Y3
+U+0463:y3
+U+046a:O3
+U+046b:o3
+U+0472:F3
+U+0473:f3
+U+0474:V3
+U+0475:v3
+U+0480:C3
+U+0481:c3
+U+0490:G3
+U+0491:g3
+
+# These may make Yiddish slightly more readable, until we have
+# something better.
+
+0x69 U+05b4 # i
+0x61 U+05b7 # a
+0x6f U+05b8 # o
+0x75 U+05bc # u
+0x68 U+05bf # h
+0x3a U+05c2 # :
+
+0x76 U+05f0 # v
+U+05f1:oy
+U+05f2:ey
+
+# U+05d0:A+
+0x23 U+05d0 # '#'
+
+U+05d1:B+
+U+05d2:G+
+U+05d3:D+
+U+05d4:H+
+U+05d5:W+
+U+05d6:Z+
+U+05d7:X+
+U+05d8:Tj
+U+05d9:J+
+U+05da:K%
+U+05db:K+
+U+05dc:L+
+U+05dd:M%
+U+05de:M+
+U+05df:N%
+U+05e0:N+
+U+05e1:S+
+U+05e2:E+
+U+05e3:P%
+U+05e4:P+
+U+05e5:Zj
+U+05e6:ZJ
+U+05e7:Q+
+U+05e8:R+
+U+05e9:Sh
+U+05ea:T+
+
+U+060c:,+
+U+061b:;+
+U+061f:?+
+U+0621:H'
+U+0622:aM
+U+0623:aH
+U+0624:wH
+U+0625:ah
+U+0626:yH
+U+0627:a+
+U+0628:b+
+U+0629:tm
+U+062a:t+
+U+062b:tk
+U+062c:g+
+U+062d:hk
+U+062e:x+
+U+062f:d+
+U+0630:dk
+U+0631:r+
+U+0632:z+
+U+0633:s+
+U+0634:sn
+U+0635:c+
+U+0636:dd
+U+0637:tj
+U+0638:zH
+U+0639:e+
+U+063a:i+
+U+0640:++
+U+0641:f+
+U+0642:q+
+U+0643:k+
+U+0644:l+
+U+0645:m+
+U+0646:n+
+U+0647:h+
+U+0648:w+
+U+0649:j+
+U+064a:y+
+U+064b::+
+U+064c:"+
+U+064d:=+
+U+064e:/+
+U+064f:'+
+U+0650:1+
+U+0651:3+
+U+0652:0+
+U+0660:0a
+U+0661:1a
+U+0662:2a
+U+0663:3a
+U+0664:4a
+U+0665:5a
+U+0666:6a
+U+0667:7a
+U+0668:8a
+U+0669:9a
+U+0670:aS
+U+067e:p+
+U+0681:hH
+U+0686:tc
+U+0698:zj
+U+06a4:v+
+U+06af:gf
+U+06f0:0a
+U+06f1:1a
+U+06f2:2a
+U+06f3:3a
+U+06f4:4a
+U+06f5:5a
+U+06f6:6a
+U+06f7:7a
+U+06f8:8a
+U+06f9:9a
+
+# Replacement strings for Ethiopic characters
+U+1200:he
+U+1201:hu
+U+1202:hi
+U+1203:ha
+U+1204:hE
+0x68 U+1205 #:h
+U+1206:ho
+U+1208:le
+U+1209:lu
+U+120A:li
+U+120B:la
+U+120C:lE
+0x6c U+120D #:l
+U+120E:lo
+U+120F:lWa
+U+1210:He
+U+1211:Hu
+U+1212:Hi
+U+1213:Ha
+U+1214:HE
+0x48 U+1215 #:H
+U+1216:Ho
+U+1217:HWa
+U+1218:me
+U+1219:mu
+U+121A:mi
+U+121B:ma
+U+121C:mE
+0x6d U+121D #:m
+U+121E:mo
+U+121F:mWa
+U+1220:`se
+U+1221:`su
+U+1222:`si
+U+1223:`sa
+U+1224:`sE
+U+1225:`s
+U+1226:`so
+U+1227:`sWa
+U+1228:re
+U+1229:ru
+U+122A:ri
+U+122B:ra
+U+122C:rE
+0x72 U+122D #:r
+U+122E:ro
+U+122F:rWa
+U+1230:se
+U+1231:su
+U+1232:si
+U+1233:sa
+U+1234:sE
+0x73 U+1235 #:s
+U+1236:so
+U+1237:sWa
+U+1238:xe
+U+1239:xu
+U+123A:xi
+U+123B:xa
+U+123C:xE
+U+123D:xa
+U+123E:xo
+U+123F:xWa
+U+1240:qe
+U+1241:qu
+U+1242:qi
+U+1243:qa
+U+1244:qE
+0x71 U+1245 #:q
+U+1246:qo
+U+1248:qWe
+U+124A:qWi
+U+124B:qWa
+U+124C:qWE
+U+124D:qW
+U+1250:Qe
+U+1251:Qu
+U+1252:Qi
+U+1253:Qa
+U+1254:QE
+0x51 U+1255 #:Q
+U+1256:Qo
+U+1258:QWe
+U+125A:QWi
+U+125B:QWa
+U+125C:QWE
+U+125D:QW
+U+1260:be
+U+1261:bu
+U+1262:bi
+U+1263:ba
+U+1264:bE
+0x62 U+1265 #:b
+U+1266:bo
+U+1267:bWa
+U+1268:ve
+U+1269:vu
+U+126A:vi
+U+126B:va
+U+126C:vE
+0x76 U+126D #:v
+U+126E:vo
+U+126F:vWa
+U+1270:te
+U+1271:tu
+U+1272:ti
+U+1273:ta
+U+1274:tE
+0x74 U+1275 #:t
+U+1276:to
+U+1277:tWa
+U+1278:ce
+U+1279:cu
+U+127A:ci
+U+127B:ca
+U+127C:cE
+0x63 U+127D #:c
+U+127E:co
+U+127F:cWa
+U+1280:`he
+U+1281:`hu
+U+1282:`hi
+U+1283:`ha
+U+1284:`hE
+U+1285:`h
+U+1286:`ho
+U+1288:hWe
+U+128A:hWi
+U+128B:hWa
+U+128C:hWE
+U+128D:hW
+U+1290:na
+U+1291:nu
+U+1292:ni
+U+1293:na
+U+1294:nE
+0x6e U+1295 #:n
+U+1296:no
+U+1297:nWa
+U+1298:Ne
+U+1299:Nu
+U+129A:Ni
+U+129B:Na
+U+129C:NE
+0x4e U+129D #:N
+U+129E:No
+U+129F:NWa
+0x65 U+12A0 #:e
+0x75 U+12A1 #:u
+0x69 U+12A2 #:i
+0x61 U+12A3 #:a
+0x45 U+12A4 #:E
+0x49 U+12A5 #:I
+0x6f U+12A6 #:o
+U+12A7:e3
+U+12A8:ke
+U+12A9:ku
+U+12AA:ki
+U+12AB:ka
+U+12AC:kE
+0x6b U+12AD #:k
+U+12AE:ko
+U+12B0:kWe
+U+12B2:kWi
+U+12B3:kWa
+U+12B4:kWE
+U+12B5:kW
+U+12B8:Ke
+U+12B9:Ku
+U+12BA:Ki
+U+12BB:Ka
+U+12BC:KE
+0x4b U+12BD #:K
+U+12BE:Ko
+U+12C0:KWe
+U+12C2:KWi
+U+12C3:KWa
+U+12C4:KWE
+U+12C5:KW
+U+12C8:we
+U+12C9:wu
+U+12CA:wi
+U+12CB:wa
+U+12CC:wE
+0x77 U+12CD #:w
+U+12CE:wo
+U+12D0:`e
+U+12D1:`u
+U+12D2:`i
+U+12D3:`a
+U+12D4:`E
+U+12D5:`I
+U+12D6:`o
+U+12D8:ze
+U+12D9:zu
+U+12DA:zi
+U+12DB:za
+U+12DC:zE
+0x7a U+12DD #:z
+U+12DE:zo
+U+12DF:zWa
+U+12E0:Ze
+U+12E1:Zu
+U+12E2:Zi
+U+12E3:Za
+U+12E4:ZE
+0x5a U+12E5 #:Z
+U+12E6:Zo
+U+12E7:ZWa
+U+12E8:ye
+U+12E9:yu
+U+12EA:yi
+U+12EB:ya
+U+12EC:yE
+0x79 U+12ED #:y
+U+12EE:yo
+U+12EF:yWa
+U+12F0:de
+U+12F1:du
+U+12F2:di
+U+12F3:da
+U+12F4:dE
+0x64 U+12F5 #:d
+U+12F6:do
+U+12F7:dWa
+U+12F8:De
+U+12F9:Du
+U+12FA:Di
+U+12FB:Da
+U+12FC:DE
+0x44 U+12FD #:D
+U+12FE:Do
+U+12FF:DWa
+U+1300:je
+U+1301:ju
+U+1302:ji
+U+1303:ja
+U+1304:jE
+0x6a U+1305 #:j
+U+1306:jo
+U+1307:jWa
+U+1308:ga
+U+1309:gu
+U+130A:gi
+U+130B:ga
+U+130C:gE
+0x67 U+130D #:g
+U+130E:go
+U+1310:gWu
+U+1312:gWi
+U+1313:gWa
+U+1314:gWE
+U+1315:gW
+U+1318:Ge
+U+1319:Gu
+U+131A:Gi
+U+131B:Ga
+U+131C:GE
+0x47 U+131D #:G
+U+131E:Go
+U+131F:GWa
+U+1320:Te
+U+1321:Tu
+U+1322:Ti
+U+1323:Ta
+U+1324:TE
+0x54 U+1325 #:T
+U+1326:To
+U+1327:TWa
+U+1328:Ce
+U+1329:Ca
+U+132A:Cu
+U+132B:Ca
+U+132C:CE
+0x43 U+132D #:C
+U+132E:Co
+U+132F:CWa
+U+1330:Pe
+U+1331:Pu
+U+1332:Pi
+U+1333:Pa
+U+1334:PE
+0x50 U+1335 #:P
+U+1336:Po
+U+1337:PWa
+U+1338:SWe
+U+1339:SWu
+U+133A:SWi
+U+133B:SWa
+U+133C:SWE
+U+133D:SW
+U+133E:SWo
+U+133F:SWa
+U+1340:`Sa
+U+1341:`Su
+U+1342:`Si
+U+1343:`Sa
+U+1344:`SE
+U+1345:`S
+U+1346:`So
+U+1348:fa
+U+1349:fu
+U+134A:fi
+U+134B:fa
+U+134C:fE
+0x6f U+134D #:f
+U+134E:fo
+U+134F:fWa
+U+1350:pe
+U+1351:pu
+U+1352:pi
+U+1353:pa
+U+1354:pE
+0x70 U+1355 #:p
+U+1356:po
+U+1357:pWa
+U+1358:mYa
+U+1359:rYa
+U+135A:fYa
+# ETHIOPIC SPACE U+1360 mapped to ASCII space
+0x20 U+1360
+0x3a U+1361 #::
+U+1362:::
+0x2c U+1363 #:,
+U+1364:;
+U+1365:-:
+U+1366::-
+U+1367:`?
+U+1368::|:
+U+1369:`1
+U+136A:`2
+U+136B:`3
+U+136C:`4
+U+136D:`5
+U+136E:`6
+U+136F:`7
+U+1370:`8
+U+1371:`9
+U+1372:`10
+U+1373:`20
+U+1374:`30
+U+1375:`40
+U+1376:`50
+U+1377:`60
+U+1378:`70
+U+1379:`80
+U+137A:`90
+U+137B:`100
+U+137C:`10000
+
+
+U+1e00:A-0
+U+1e01:a-0
+U+1e02:B.
+U+1e03:b.
+U+1e04:B-.
+U+1e05:b-.
+U+1e06:B_
+U+1e07:b_
+U+1e08:C,'
+U+1e09:c,'
+U+1e0a:D.
+U+1e0b:d.
+U+1e0c:D-.
+U+1e0d:d-.
+U+1e0e:D_
+U+1e0f:d_
+U+1e10:D,
+U+1e11:d,
+U+1e12:D->
+U+1e13:d->
+U+1e14:E-!
+U+1e15:e-!
+U+1e16:E-'
+U+1e17:e-'
+U+1e18:E->
+U+1e19:e->
+U+1e1a:E-?
+U+1e1b:e-?
+U+1e1c:E,(
+U+1e1d:e,(
+U+1e1e:F.
+U+1e1f:f.
+U+1e20:G-
+U+1e21:g-
+U+1e22:H.
+U+1e23:h.
+U+1e24:H-.
+U+1e25:h-.
+U+1e26:H:
+U+1e27:h:
+U+1e28:H,
+U+1e29:h,
+U+1e2a:H-(
+U+1e2b:h-(
+U+1e2c:I-?
+U+1e2d:i-?
+U+1e2e:I:'
+U+1e2f:i:'
+U+1e30:K'
+U+1e31:k'
+U+1e32:K-.
+U+1e33:k-.
+U+1e34:K_
+U+1e35:k_
+U+1e36:L-.
+U+1e37:l-.
+U+1e38:L--.
+U+1e39:l--.
+U+1e3a:L_
+U+1e3b:l_
+U+1e3c:L->
+U+1e3d:l->
+U+1e3e:M'
+U+1e3f:m'
+U+1e40:M.
+U+1e41:m.
+U+1e42:M-.
+U+1e43:m-.
+U+1e44:N.
+U+1e45:n.
+U+1e46:N-.
+U+1e47:n-.
+U+1e48:N_
+U+1e49:n_
+U+1e4a:N->
+U+1e4b:n->
+U+1e4c:O?'
+U+1e4d:o?'
+U+1e4e:O?:
+U+1e4f:o?:
+U+1e50:O-!
+U+1e51:o-!
+U+1e52:O-'
+U+1e53:o-'
+U+1e54:P'
+U+1e55:p'
+U+1e56:P.
+U+1e57:p.
+U+1e58:R.
+U+1e59:r.
+U+1e5a:R-.
+U+1e5b:r-.
+U+1e5c:R--.
+U+1e5d:r--.
+U+1e5e:R_
+U+1e5f:r_
+U+1e60:S.
+U+1e61:s.
+U+1e62:S-.
+U+1e63:s-.
+U+1e64:S'.
+U+1e65:s'.
+U+1e66:S<.
+U+1e67:s<.
+U+1e68:S.-.
+U+1e69:s.-.
+U+1e6a:T.
+U+1e6b:t.
+U+1e6c:T-.
+U+1e6d:t-.
+U+1e6e:T_
+U+1e6f:t_
+U+1e70:T->
+U+1e71:t->
+U+1e72:U--:
+U+1e73:u--:
+U+1e74:U-?
+U+1e75:u-?
+U+1e76:U->
+U+1e77:u->
+U+1e78:U?'
+U+1e79:u?'
+U+1e7a:U-:
+U+1e7b:u-:
+U+1e7c:V?
+U+1e7d:v?
+U+1e7e:V-.
+U+1e7f:v-.
+U+1e80:W!
+U+1e81:w!
+U+1e82:W'
+U+1e83:w'
+U+1e84:W:
+U+1e85:w:
+U+1e86:W.
+U+1e87:w.
+U+1e88:W-.
+U+1e89:w-.
+U+1e8a:X.
+U+1e8b:x.
+U+1e8c:X:
+U+1e8d:x:
+U+1e8e:Y.
+U+1e8f:y.
+U+1e90:Z>
+U+1e91:z>
+U+1e92:Z-.
+U+1e93:z-.
+U+1e94:Z_
+U+1e95:z_
+U+1e96:h_
+U+1e97:t:
+U+1e98:w0
+U+1e99:y0
+U+1ea0:A-.
+U+1ea1:a-.
+U+1ea2:A2
+U+1ea3:a2
+U+1ea4:A>'
+U+1ea5:a>'
+U+1ea6:A>!
+U+1ea7:a>!
+U+1ea8:A>2
+U+1ea9:a>2
+U+1eaa:A>?
+U+1eab:a>?
+U+1eac:A>-.
+U+1ead:a>-.
+U+1eae:A('
+U+1eaf:a('
+U+1eb0:A(!
+U+1eb1:a(!
+U+1eb2:A(2
+U+1eb3:a(2
+U+1eb4:A(?
+U+1eb5:a(?
+U+1eb6:A(-.
+U+1eb7:a(-.
+U+1eb8:E-.
+U+1eb9:e-.
+U+1eba:E2
+U+1ebb:e2
+U+1ebc:E?
+U+1ebd:e?
+U+1ebe:E>'
+U+1ebf:e>'
+U+1ec0:E>!
+U+1ec1:e>!
+U+1ec2:E>2
+U+1ec3:e>2
+U+1ec4:E>?
+U+1ec5:e>?
+U+1ec6:E>-.
+U+1ec7:e>-.
+U+1ec8:I2
+U+1ec9:i2
+U+1eca:I-.
+U+1ecb:i-.
+U+1ecc:O-.
+U+1ecd:o-.
+U+1ece:O2
+U+1ecf:o2
+U+1ed0:O>'
+U+1ed1:o>'
+U+1ed2:O>!
+U+1ed3:o>!
+U+1ed4:O>2
+U+1ed5:o>2
+U+1ed6:O>?
+U+1ed7:o>?
+U+1ed8:O>-.
+U+1ed9:o>-.
+U+1eda:O9'
+U+1edb:o9'
+U+1edc:O9!
+U+1edd:o9!
+U+1ede:O92
+U+1edf:o92
+U+1ee0:O9?
+U+1ee1:o9?
+U+1ee2:O9-.
+U+1ee3:o9-.
+U+1ee4:U-.
+U+1ee5:u-.
+U+1ee6:U2
+U+1ee7:u2
+U+1ee8:U9'
+U+1ee9:u9'
+U+1eea:U9!
+U+1eeb:u9!
+U+1eec:U92
+U+1eed:u92
+U+1eee:U9?
+U+1eef:u9?
+U+1ef0:U9-.
+U+1ef1:u9-.
+U+1ef2:Y!
+U+1ef3:y!
+U+1ef4:Y-.
+U+1ef5:y-.
+U+1ef6:Y2
+U+1ef7:y2
+U+1ef8:Y?
+U+1ef9:y?
+U+1f00:;'
+U+1f01:,'
+U+1f02:;!
+U+1f03:,!
+U+1f04:?;
+U+1f05:?,
+U+1f06:!:
+U+1f07:?:
+U+1fbf:,,
+U+1fc0:?*
+U+1fc1:?:
+U+1fcd:,!
+U+1fce:,'
+U+1fcf:?,
+U+1fdd:;!
+U+1fde:;'
+U+1fdf:?;
+U+1fed:!:
+U+1fef:!*
+U+1ffe:;;
+# General punctuation:
+0x20 U+2000 U+2002 U+2004-U+2009 # spaces
+U+2001:
+U+2003:
+U+200e:(->)
+U+200f:(<-)
+U+200a:
+0x2d U+2010 U+2013-U+2015 # hyphen-like
+U+2016:||
+U+2017:=2
+0x60 U+2018 # left single quotation mark <`>
+0x27 U+2019-U+201b # various single quotation marks <'>
+0x22 U+201c-U+201f # various double quotation marks <">
+U+2020:/-
+U+2021:/=
+U+2022: o
+U+2025:..
+U+2026:...
+
+# Dont wanna see these:
+# POP DIRECTIONAL FORMATTING 202C
+U+202c:
+# LEFT-TO-RIGHT OVERRIDE 202D
+U+202d:
+
+U+2030: 0/00
+U+2032:'
+U+2033:''
+U+2034:'''
+U+2035:`
+U+2036:``
+U+2037:```
+U+2038:Ca
+U+2039:<
+U+203a:>
+U+203b::X
+U+203c:!!
+U+203e:'-
+0x2d U+2043 # HYPHEN BULLET ?
+U+2044:/
+# end of General punctuation.
+U+2070:^0
+U+2074:^4
+U+2075:^5
+U+2076:^6
+U+2077:^7
+U+2078:^8
+U+2079:^9
+U+207a:^+
+U+207b:^-
+U+207c:^=
+U+207d:^(
+U+207e:^)
+U+207f:^n
+U+2080:_0
+U+2081:_1
+U+2082:_2
+U+2083:_3
+U+2084:_4
+U+2085:_5
+U+2086:_6
+U+2087:_7
+U+2088:_8
+U+2089:_9
+U+208a:_+
+U+208b:_-
+U+208c:_=
+U+208d:(
+U+208e:)
+# Old euro currency sign glyph:
+U+20A0:CE
+U+20a3:Ff
+U+20a4:Li
+U+20a7:Pt
+U+20a9:W=
+# New euro currency sign glyph ?
+# U+20AC:EUR
+U+2103:oC
+U+2105:c/o
+U+2109:oF
+U+2111:Im
+U+2116:No.
+U+2117:PO
+U+2118:P
+U+211C:Re
+U+211e:Rx
+U+2120:(SM)
+# TRADE MARK SIGN:
+U+2122:(TM)
+U+2126:Ohm
+0x4b U+212A # Kelvin sign - K
+U+212b:Ang.
+U+212E:est.
+U+2135:Aleph
+U+2136:Bet
+U+2137:Gimel
+U+2138:Dalet
+U+2153: 1/3
+U+2154: 2/3
+U+2155: 1/5
+U+2156: 2/5
+U+2157: 3/5
+U+2158: 4/5
+U+2159: 1/6
+U+215a: 5/6
+U+215b: 1/8
+U+215c: 3/8
+U+215d: 5/8
+U+215e: 7/8
+U+2160:I
+U+2161:II
+U+2162:III
+U+2163:IV
+U+2164:V
+U+2165:VI
+U+2166:VII
+U+2167:VIII
+U+2168:IX
+U+2169:X
+U+216a:XI
+U+216b:XII
+U+216c:L
+U+216d:C
+U+216e:D
+U+216f:M
+U+2170:i
+U+2171:ii
+U+2172:iii
+U+2173:iv
+U+2174:v
+U+2175:vi
+U+2176:vii
+U+2177:viii
+U+2178:ix
+U+2179:x
+U+217a:xi
+U+217b:xii
+U+217c:l
+U+217d:c
+U+217e:d
+U+217f:m
+U+2180:1000RCD
+U+2181:5000R
+U+2182:10000R
+U+2190:<-
+U+2191:-^
+U+2192:->
+U+2193:-v
+U+2194:<->
+U+2195:UD
+U+2196:<!!
+U+2197://>
+U+2198:!!>
+U+2199:<//
+U+21a8:UD-
+U+21B5:RET
+U+21c0:>V
+U+21d0:<=
+U+21d1:^^
+U+21d2:=>
+U+21d3:vv
+U+21d4:<=>
+U+2200:FA
+U+2202:\partial
+U+2203:TE
+U+2205:{}
+U+2206:decr.
+U+2207:Nabla
+U+2208:(-
+U+2209:!(-
+U+220b:-)
+U+220f:\prod
+U+2211:\sum
+U+2212: -
+U+2213:-/+
+U+2214:.+
+U+2217:*
+U+2218:Ob
+U+2219:sb
+U+221a: SQRT
+U+221d:0(
+U+221e:infty
+U+221f:-L
+U+2220:-V
+U+2225:PP
+U+2227:AND
+U+2228:OR
+U+2229:(U
+U+222a:)U
+U+222b:\int
+U+222c:DI
+U+222e:Io
+U+2234:.:
+U+2235::.
+U+2236::R
+U+2237:::
+U+223c:?1
+U+223e:CG
+U+2243:?-
+U+2245:?=
+# ALMOST EQUAL TO:
+U+2248:~=
+U+224c:=?
+U+2253:HI
+U+2260:!=
+U+2261:=3
+U+2264:=<
+U+2265:>=
+U+226a:<<
+U+226b:>>
+U+226e:!<
+U+226f:!>
+U+2282:(C
+U+2283:)C
+U+2282:!(C
+U+2286:(_
+U+2287:)_
+U+2295:(+)
+U+2297:(x)
+U+2299:0.
+U+229a:02
+U+22a5:-T
+U+22c5:.P
+U+22ee::3
+U+22ef:.3
+U+2302:Eh
+U+2308:<7
+U+2309:>7
+U+230a:7<
+U+230b:7>
+U+2310:NI
+U+2312:(A
+U+2315:TR
+U+2318:88
+U+2320:Iu
+U+2321:Il
+U+2323::)
+U+2329:</
+U+232a:/>
+U+2423:Vs
+U+2440:1h
+U+2441:3h
+U+2442:2h
+U+2443:4h
+U+2446:1j
+U+2447:2j
+U+2448:3j
+U+2449:4j
+U+2460:1-o
+U+2461:2-o
+U+2462:3-o
+U+2463:4-o
+U+2464:5-o
+U+2465:6-o
+U+2466:7-o
+U+2467:8-o
+U+2468:9-o
+U+2469:10-o
+U+246a:11-o
+U+246b:12-o
+U+246c:13-o
+U+246d:14-o
+U+246e:15-o
+U+246f:16-o
+U+2470:17-o
+U+2471:18-o
+U+2472:19-o
+U+2473:20-o
+U+2474:(1)
+U+2475:(2)
+U+2476:(3)
+U+2477:(4)
+U+2478:(5)
+U+2479:(6)
+U+247a:(7)
+U+247b:(8)
+U+247c:(9)
+U+247d:(10)
+U+247e:(11)
+U+247f:(12)
+U+2480:(13)
+U+2481:(14)
+U+2482:(15)
+U+2483:(16)
+U+2484:(17)
+U+2485:(18)
+U+2486:(19)
+U+2487:(20)
+U+2488:1.
+U+2489:2.
+U+248a:3.
+U+248b:4.
+U+248c:5.
+U+248d:6.
+U+248e:7.
+U+248f:8.
+U+2490:9.
+U+2491:10.
+U+2492:11.
+U+2493:12.
+U+2494:13.
+U+2495:14.
+U+2496:15.
+U+2497:16.
+U+2498:17.
+U+2499:18.
+U+249a:19.
+U+249b:20.
+U+249c:(a)
+U+249d:(b)
+U+249e:(c)
+U+249f:(d)
+U+24a0:(e)
+U+24a1:(f)
+U+24a2:(g)
+U+24a3:(h)
+U+24a4:(i)
+U+24a5:(j)
+U+24a6:(k)
+U+24a7:(l)
+U+24a8:(m)
+U+24a9:(n)
+U+24aa:(o)
+U+24ab:(p)
+U+24ac:(q)
+U+24ad:(r)
+U+24ae:(s)
+U+24af:(t)
+U+24b0:(u)
+U+24b1:(v)
+U+24b2:(w)
+U+24b3:(x)
+U+24b4:(y)
+U+24b5:(z)
+U+24b6:A-o
+U+24b7:B-o
+U+24b8:C-o
+U+24b9:D-o
+U+24ba:E-o
+U+24bb:F-o
+U+24bc:G-o
+U+24bd:H-o
+U+24be:I-o
+U+24bf:J-o
+U+24c0:K-o
+U+24c1:L-o
+U+24c2:M-o
+U+24c3:N-o
+U+24c4:O-o
+U+24c5:P-o
+U+24c6:Q-o
+U+24c7:R-o
+U+24c8:S-o
+U+24c9:T-o
+U+24ca:U-o
+U+24cb:V-o
+U+24cc:W-o
+U+24cd:X-o
+U+24ce:Y-o
+U+24cf:Z-o
+U+24d0:a-o
+U+24d1:b-o
+U+24d2:c-o
+U+24d3:d-o
+U+24d4:e-o
+U+24d5:f-o
+U+24d6:g-o
+U+24d7:h-o
+U+24d8:i-o
+U+24d9:j-o
+U+24da:k-o
+U+24db:l-o
+U+24dc:m-o
+U+24dd:n-o
+U+24de:o-o
+U+24df:p-o
+U+24e0:q-o
+U+24e1:r-o
+U+24e2:s-o
+U+24e3:t-o
+U+24e4:u-o
+U+24e5:v-o
+U+24e6:w-o
+U+24e7:x-o
+U+24e8:y-o
+U+24e9:z-o
+U+24ea:0-o
+U+2500:-
+U+2501:=
+U+2502:|
+U+2503:|
+U+2504:-
+U+2505:=
+U+2506:|
+U+2507:|
+U+2508:-
+U+2509:=
+U+250a:|
+U+250b:|
+0x2b U+250c-U+256c # box drawings, use +
+U+2571:/
+U+2572:\
+U+2580:TB
+U+2584:LB
+U+2588:FB
+U+258c:lB
+U+2590:RB
+U+2591:.S
+U+2592::S
+U+2593:?S
+U+25a0:fS
+U+25a1:OS
+U+25a2:RO
+U+25a3:Rr
+U+25a4:RF
+U+25a5:RY
+U+25a6:RH
+U+25a7:RZ
+U+25a8:RK
+U+25a9:RX
+U+25aa:sB
+U+25ac:SR
+U+25ad:Or
+U+25b2:UT
+U+25b3:uT
+U+25b6:PR
+U+25b7:Tr
+U+25ba:PR
+U+25bc:Dt
+U+25bd:dT
+U+25c0:PL
+U+25c1:Tl
+U+25c4:PL
+U+25c6:Db
+U+25c7:Dw
+U+25ca:LZ
+U+25cb:0m
+U+25ce:0o
+U+25cf:0M
+U+25d0:0L
+U+25d1:0R
+U+25d8:Sn
+U+25d9:Ic
+U+25e2:Fd
+U+25e3:Bd
+U+25ef:Ci
+U+2605:*2
+U+2606:*1
+U+260e:TEL
+U+260f:tel
+U+261c:<--
+U+261e:-->
+U+263a::-)
+U+263b:(-:
+U+263c:SU
+U+2640:f.
+U+2642:m.
+U+2660:cS
+U+2661:cH
+U+2662:cD
+U+2663:cC
+U+2664:cS-
+U+2665:cH-
+U+2666:cD-
+U+2667:cC-
+U+2669:Md
+U+266a:M8
+U+266b:M2
+U+266c:M16
+U+266d:b
+U+266e:Mx
+U+266f:#
+0x58 U+2713 U+2717 # check marks -> x
+U+2720:-X
+0x20 U+3000 # ideographic space
+U+3001:,_
+U+3002:._
+U+3003:+"
+U+3004:JIS
+U+3005:*_
+U+3006:;_
+U+3007:0_
+U+300a:<+
+U+300b:>+
+U+300c:<'
+U+300d:>'
+U+300e:<"
+U+300f:>"
+U+3010:("
+U+3011:)"
+U+3012:=T
+U+3013:=_
+U+3014:('
+U+3015:)'
+U+3016:(I
+U+3017:)I
+U+301c:-?
+U+3020:=T:)
+U+3041:A5
+U+3042:a5
+U+3043:I5
+U+3044:i5
+U+3045:U5
+U+3046:u5
+U+3047:E5
+U+3048:e5
+U+3049:O5
+U+304a:o5
+U+304b:ka
+U+304c:ga
+U+304d:ki
+U+304e:gi
+U+304f:ku
+U+3050:gu
+U+3051:ke
+U+3052:ge
+U+3053:ko
+U+3054:go
+U+3055:sa
+U+3056:za
+U+3057:si
+U+3058:zi
+U+3059:su
+U+305a:zu
+U+305b:se
+U+305c:ze
+U+305d:so
+U+305e:zo
+U+305f:ta
+U+3060:da
+U+3061:ti
+U+3062:di
+U+3063:tU
+U+3064:tu
+U+3065:du
+U+3066:te
+U+3067:de
+U+3068:to
+U+3069:do
+U+306a:na
+U+306b:ni
+U+306c:nu
+U+306d:ne
+U+306e:no
+U+306f:ha
+U+3070:ba
+U+3071:pa
+U+3072:hi
+U+3073:bi
+U+3074:pi
+U+3075:hu
+U+3076:bu
+U+3077:pu
+U+3078:he
+U+3079:be
+U+307a:pe
+U+307b:ho
+U+307c:bo
+U+307d:po
+U+307e:ma
+U+307f:mi
+U+3080:mu
+U+3081:me
+U+3082:mo
+U+3083:yA
+U+3084:ya
+U+3085:yU
+U+3086:yu
+U+3087:yO
+U+3088:yo
+U+3089:ra
+U+308a:ri
+U+308b:ru
+U+308c:re
+U+308d:ro
+U+308e:wA
+U+308f:wa
+U+3090:wi
+U+3091:we
+U+3092:wo
+U+3093:n5
+U+3094:vu
+U+309b:"5
+U+309c:05
+U+309d:*5
+U+309e:+5
+U+30a1:a6
+U+30a2:A6
+U+30a3:i6
+U+30a4:I6
+U+30a5:u6
+U+30a6:U6
+U+30a7:e6
+U+30a8:E6
+U+30a9:o6
+U+30aa:O6
+U+30ab:Ka
+U+30ac:Ga
+U+30ad:Ki
+U+30ae:Gi
+U+30af:Ku
+U+30b0:Gu
+U+30b1:Ke
+U+30b2:Ge
+U+30b3:Ko
+U+30b4:Go
+U+30b5:Sa
+U+30b6:Za
+U+30b7:Si
+U+30b8:Zi
+U+30b9:Su
+U+30ba:Zu
+U+30bb:Se
+U+30bc:Ze
+U+30bd:So
+U+30be:Zo
+U+30bf:Ta
+U+30c0:Da
+U+30c1:Ti
+U+30c2:Di
+U+30c3:TU
+U+30c4:Tu
+U+30c5:Du
+U+30c6:Te
+U+30c7:De
+U+30c8:To
+U+30c9:Do
+U+30ca:Na
+U+30cb:Ni
+U+30cc:Nu
+U+30cd:Ne
+U+30ce:No
+U+30cf:Ha
+U+30d0:Ba
+U+30d1:Pa
+U+30d2:Hi
+U+30d3:Bi
+U+30d4:Pi
+U+30d5:Hu
+U+30d6:Bu
+U+30d7:Pu
+U+30d8:He
+U+30d9:Be
+U+30da:Pe
+U+30db:Ho
+U+30dc:Bo
+U+30dd:Po
+U+30de:Ma
+U+30df:Mi
+U+30e0:Mu
+U+30e1:Me
+U+30e2:Mo
+U+30e3:YA
+U+30e4:Ya
+U+30e5:YU
+U+30e6:Yu
+U+30e7:YO
+U+30e8:Yo
+U+30e9:Ra
+U+30ea:Ri
+U+30eb:Ru
+U+30ec:Re
+U+30ed:Ro
+U+30ee:WA
+U+30ef:Wa
+U+30f0:Wi
+U+30f1:We
+U+30f2:Wo
+U+30f3:N6
+U+30f4:Vu
+U+30f5:KA
+U+30f6:KE
+U+30f7:Va
+U+30f8:Vi
+U+30f9:Ve
+U+30fa:Vo
+U+30fb:.6
+U+30fc:-6
+U+30fd:*6
+U+30fe:+6
+U+3105:b4
+U+3106:p4
+U+3107:m4
+U+3108:f4
+U+3109:d4
+U+310a:t4
+U+310b:n4
+U+310c:l4
+U+310d:g4
+U+310e:k4
+U+310f:h4
+U+3110:j4
+U+3111:q4
+U+3112:x4
+U+3113:zh
+U+3114:ch
+U+3115:sh
+U+3116:r4
+U+3117:z4
+U+3118:c4
+U+3119:s4
+U+311a:a4
+U+311b:o4
+U+311c:e4
+U+311d:eh4
+U+311e:ai
+U+311f:ei
+U+3120:au
+U+3121:ou
+U+3122:an
+U+3123:en
+U+3124:aN
+U+3125:eN
+U+3126:er
+U+3127:i4
+U+3128:u4
+U+3129:iu
+U+312a:v4
+U+312b:nG
+U+312c:gn
+U+321c:(JU)
+U+3220:1c
+U+3221:2c
+U+3222:3c
+U+3223:4c
+U+3224:5c
+U+3225:6c
+U+3226:7c
+U+3227:8c
+U+3228:9c
+U+3229:10c
+U+327f:KSC
+U+33c2:am
+U+33d8:pm
+U+fb00:ff
+U+fb01:fi
+U+fb02:fl
+U+fb03:ffi
+U+fb04:ffl
+U+fb05:St
+U+fb06:st
+U+fe7d:3+;
+U+fe82:aM.
+U+fe84:aH.
+U+fe88:ah.
+U+fe8d:a+-
+U+fe8e:a+.
+U+fe8f:b+-
+U+fe90:b+.
+U+fe91:b+,
+U+fe92:b+;
+U+fe93:tm-
+U+fe94:tm.
+U+fe95:t+-
+U+fe96:t+.
+U+fe97:t+,
+U+fe98:t+;
+U+fe99:tk-
+U+fe9a:tk.
+U+fe9b:tk,
+U+fe9c:tk;
+U+fe9d:g+-
+U+fe9e:g+.
+U+fe9f:g+,
+U+fea0:g+;
+U+fea1:hk-
+U+fea2:hk.
+U+fea3:hk,
+U+fea4:hk;
+U+fea5:x+-
+U+fea6:x+.
+U+fea7:x+,
+U+fea8:x+;
+U+fea9:d+-
+U+feaa:d+.
+U+feab:dk-
+U+feac:dk.
+U+fead:r+-
+U+feae:r+.
+U+feaf:z+-
+U+feb0:z+.
+U+feb1:s+-
+U+feb2:s+.
+U+feb3:s+,
+U+feb4:s+;
+U+feb5:sn-
+U+feb6:sn.
+U+feb7:sn,
+U+feb8:sn;
+U+feb9:c+-
+U+feba:c+.
+U+febb:c+,
+U+febc:c+;
+U+febd:dd-
+U+febe:dd.
+U+febf:dd,
+U+fec0:dd;
+U+fec1:tj-
+U+fec2:tj.
+U+fec3:tj,
+U+fec4:tj;
+U+fec5:zH-
+U+fec6:zH.
+U+fec7:zH,
+U+fec8:zH;
+U+fec9:e+-
+U+feca:e+.
+U+fecb:e+,
+U+fecc:e+;
+U+fecd:i+-
+U+fece:i+.
+U+fecf:i+,
+U+fed0:i+;
+U+fed1:f+-
+U+fed2:f+.
+U+fed3:f+,
+U+fed4:f+;
+U+fed5:q+-
+U+fed6:q+.
+U+fed7:q+,
+U+fed8:q+;
+U+fed9:k+-
+U+feda:k+.
+U+fedb:k+,
+U+fedc:k+;
+U+fedd:l+-
+U+fede:l+.
+U+fedf:l+,
+U+fee0:l+;
+U+fee1:m+-
+U+fee2:m+.
+U+fee3:m+,
+U+fee4:m+;
+U+fee5:n+-
+U+fee6:n+.
+U+fee7:n+,
+U+fee8:n+;
+U+fee9:h+-
+U+feea:h+.
+U+feeb:h+,
+U+feec:h+;
+U+feed:w+-
+U+feee:w+.
+U+feef:j+-
+U+fef0:j+.
+U+fef1:y+-
+U+fef2:y+.
+U+fef3:y+,
+U+fef4:y+;
+U+fef5:lM-
+U+fef6:lM.
+U+fef7:lH-
+U+fef8:lH.
+U+fef9:lh-
+U+fefa:lh.
+U+fefb:la-
+U+fefc:la.
+
+# Symbols for C0 and C1 control characters, in case they get through...
+U+0000:NUL
+U+0001:SH
+U+0002:SX
+U+0003:EX
+U+0004:ET
+U+0005:ENQ
+U+0006:AK
+U+0007:BL
+U+0008:BS
+U+0009:HT
+U+000a:LF
+U+000b:VT
+U+000c:FF
+U+000d:CR
+U+000e:SO
+U+000f:SI
+U+0010:DL
+U+0011:DC1
+U+0012:DC2
+U+0013:DC3
+U+0014:DC4
+U+0015:NAK
+U+0016:SYN
+U+0017:EB
+U+0018:CN
+U+0019:EM
+U+001a:SB
+U+001b:ESC
+U+001c:FS
+U+001d:GS
+U+001e:RS
+U+001f:US
+U+007f:DT
+U+0080:PA
+U+0081:HO
+# Most of these characters (82-9F) may be inflicted on us
+# by MS FrontPages which uses Unicode notation such as &#153;
+# but there are no assigned letters in Unicode 128-159 range.
+# It is assumed in the code that those codepoints are from windows-1252.
+#U+0082:BH
+#U+0083:NH
+#U+0084:IN
+#U+0085:NL
+#U+0086:SA
+#U+0087:ES
+#U+0088:HS
+#U+0089:HJ
+#U+008a:VS
+#U+008b:PD
+#U+008c:PU
+U+008d:RI
+U+008e:SS2
+U+008f:SS3
+U+0090:DCS
+#U+0091:P1
+#U+0092:P2
+#U+0093:TS
+#U+0094:CC
+#U+0095:MW
+#U+0096:SG
+#U+0097:EG
+#U+0098:SS
+#U+0099:GC
+U+009a:SC
+#U+009b:CSI
+#U+009c:ST
+#U+009d:OC
+#U+009e:PM
+#U+009f:AC
+
+# Characters in Private Use Area (e000-f8ff) do not have ussigned numbers.
+
+# Let's try to show a question mark for character that cannot
+# be shown. U+fffd is used for invalid characters.
+# It works, but let's stick with UHHH representatiion. - FM
+#U+fffd:?
diff --git a/gnu/usr.bin/lynx/src/chrtrans/dmcs_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/dmcs_uni.tbl
new file mode 100644
index 00000000000..676b728dcda
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/dmcs_uni.tbl
@@ -0,0 +1,226 @@
+#The MIME name of this charset.
+Mdec-mcs
+
+#Name as a Display Charset (used on Options screen)
+ODEC Multinational
+
+#
+# Name: DEC Multinational (dec-mcs) [to unicode]
+# Date: 29 October 1997
+# Author: Fote
+#
+##################
+
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+#
+0x20-0x7f idem
+#
+0xA1 U+00A1 # inverted exclamation mark (&#161;) - iexcl
+0xA2 U+00A2 # cent sign (&#162;) - cent
+0xA3 U+00A3 # pound sign (&#163;) - pound
+# currency sign (&#164;) - curren
+U+00A4:CUR
+0xA5 U+00A5 # yen sign (&#165;) - yen
+# broken vertical bar (&#166;) - brvbar, brkbar
+U+00A6:|
+0xA7 U+00A7 # section sign (&#167;) - sect
+0xA8 U+00A8 # spacing diaresis (&#168;) - uml, die
+0xA9 U+00A9 # copyright sign (&#169;) - copy
+0xAA U+00AA # feminine ordinal indicator (&#170;) - ordf
+0xAB U+00AB # angle quotation mark, left (&#171;) - laquo
+# negation sign (&#172); - not
+U+00AC:NOT
+# soft hyphen (&#173;) - shy
+#U+00AD
+# circled R registered sign (&#174;) - reg
+U+00AE:(R)
+# spacing macron (&#175;) - hibar, macr
+U+00AF:-
+0xB0 U+00B0 # degree sign (&#176;) - deg
+0xB1 U+00B1 # plus-or-minus sign (&#177;) - plusmn
+0xB2 U+00B2 # superscript 2 (&#178;) - sup2
+0xB3 U+00B3 # superscript 3 (&#179;) - sup3
+#spacing acute (&#180;) - acute
+U+00B4:'
+0xB5 U+00B5 # micro sign (&#181;) - micro
+0xB6 U+00B6 # paragraph sign (&#182;) - para
+0xB7 U+00B7 # middle dot (&#183;) - middot
+# spacing cedilla (&#184;) - cedil
+U+00B8:,
+0xB9 U+00B9 # superscript 1 (&#185;) - sup1
+0xBA U+00BA # masculine ordinal indicator (&#186;) - ordm
+0xBB U+00BB # angle quotation mark, right (&#187;) - raquo
+0xBC U+00BC # fraction 1/4 (&#188;) - frac14
+0xBD U+00BD # fraction 1/2 (&#189;) - frac12
+# fraction 3/4 (&#190;) - frac34
+U+00BE: 3/4
+0xBF U+00BF # inverted question mark (&#191;) - iquest
+0xC0 U+00C0 # capital A, grave accent (&#192;) - Agrave
+0xC1 U+00C1 # capital A, acute accent (&#193;) - Aacute
+0xC2 U+00C2 # capital A, circumflex accent (&#194;) - Acirc
+0xC3 U+00C3 # capital A, tilde (&#195;) - Atilde
+0xC4 U+00C4 # capital A, dieresis or umlaut mark (&#196;) - Auml
+0xC5 U+00C5 # capital A, ring (&#197;) - Aring
+0xC6 U+00C6 # capital AE diphthong (ligature) (&#198;) - AElig
+0xC7 U+00C7 # capital C, cedilla (&#199;) - Ccedil
+0xC8 U+00C8 # capital E, grave accent (&#200;) - Egrave
+0xC9 U+00C9 # capital E, acute accent (&#201;) - Eacute
+0xCA U+00CA # capital E, circumflex accent (&#202;) - Ecirc
+0xCB U+00CB # capital E, dieresis or umlaut mark (&#203;) - Euml
+0xCC U+00CC # capital I, grave accent (&#204;) - Igrave
+0xCD U+00CD # capital I, acute accent (&#205;) - Iacute
+0xCE U+00CE # capital I, circumflex accent (&#206;) - Icirc
+0xCF U+00CF # capital I, dieresis or umlaut mark (&#207;) - Iuml
+# capital Eth, Icelandic (&#208;) - ETH */
+U+00D0:DH
+# Dj # capital D with stroke - Dstrok
+0xD1 U+00D1 # capital N, tilde (&#209;) - Ntilde
+0xD2 U+00D2 # capital O, grave accent (&#210;) - Ograve
+0xD3 U+00D3 # capital O, acute accent (&#211;) - Oacute
+0xD4 U+00D4 # capital O, circumflex accent (&#212;) - Ocirc
+0xD5 U+00D5 # capital O, tilde (&#213;) - Otilde
+0xD6 U+00D6 # capital O, dieresis or umlaut mark (&#214;) - Ouml
+# multiplication sign (&#215;) - times
+U+00D7:*
+0xD8 U+00D8 # capital O, slash (&#216;) - Oslash
+0xD9 U+00D9 # capital U, grave accent (&#217;) - Ugrave
+0xDA U+00DA # capital U, acute accent (&#218;) - Uacute
+0xDB U+00DB # capital U, circumflex accent (&#219;) - Ucirc
+0xDC U+00DC # capital U, dieresis or umlaut mark (&#220;) - Uuml
+0xDD U+00DD # capital Y, acute accent (&#221;) - Yacute
+# capital THORN, Icelandic (&#222;) - THORN */
+U+00DE:P
+0xDF U+00DF # small sharp s, German (sz ligature) (&#223;) - szlig
+0xE0 U+00E0 # small a, grave accent (&#224;) - agrave
+0xE1 U+00E1 # small a, acute accent (&#225;) - aacute
+0xE2 U+00E2 # small a, circumflex accent (&#226;) - acirc
+0xE3 U+00E3 # small a, tilde (&#227;) - atilde
+0xE4 U+00E4 # small a, dieresis or umlaut mark (&#228;) - auml
+0xE5 U+00E5 # small a, ring (&#229;) - aring
+0xE6 U+00E6 # small ae diphthong (ligature) (&#230;) - aelig
+0xE7 U+00E7 # small c, cedilla (&#231;) - ccedil
+0xE8 U+00E8 # small e, grave accent (&#232;) - egrave
+0xE9 U+00E9 # small e, acute accent (&#233;) - eacute
+0xEA U+00EA # small e, circumflex accent (&#234;) - ecirc
+0xEB U+00EB # small e, dieresis or umlaut mark (&#235;) - euml
+0xEC U+00EC # small i, grave accent (&#236;) - igrave
+0xED U+00ED # small i, acute accent (&#237;) - iacute
+0xEE U+00EE # small i, circumflex accent (&#238;) - icirc
+0xEF U+00EF # small i, dieresis or umlaut mark (&#239;) - iuml
+# small eth, Icelandic (&#240;) - eth
+U+00F0:dh
+0xF1 U+00F1 # small n, tilde (&#241;) - ntilde
+0xF2 U+00F2 # small o, grave accent (&#242;) - ograve
+0xF3 U+00F3 # small o, acute accent (&#243;) - oacute
+0xF4 U+00F4 # small o, circumflex accent (&#244;) - ocirc
+0xF5 U+00F5 # small o, tilde (&#245;) - otilde
+0xF6 U+00F6 # small o, dieresis or umlaut mark (&#246;) - ouml
+# division sign (&#247;) - divide
+U+00F7:/
+0xF8 U+00F8 # small o, slash (&#248;) - oslash
+0xF9 U+00F9 # small u, grave accent (&#249;) - ugrave
+0xFA U+00FA # small u, acute accent (&#250;) - uacute
+0xFB U+00FB # small u, circumflex accent (&#251;) - ucirc
+0xFC U+00FC # small u, dieresis or umlaut mark (&#252;) - uuml
+0xFD U+00FF # small y, dieresis or umlaut mark (&#255;) - yuml
+# small y, acute accent (&#253;) - yacute
+U+00FD:y'
+# small thorn, Icelandic (&#254;) - thorn
+U+00FE:p
+#
+# TRADE MARK SIGN
+U+2122:(TM)
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso01_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso01_uni.tbl
new file mode 100644
index 00000000000..f792164d375
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso01_uni.tbl
@@ -0,0 +1,250 @@
+#Shall this become the "default" translation?
+#Meaning of that is currently not well defined. It is different
+#from the default input or default output charset...
+#but there has to be exactly one table marked as "default".
+D0
+#
+#The MIME name of this charset.
+Miso-8859-1
+
+#Name as a Display Charset (used on Options screen)
+OISO Latin 1
+
+#
+# Name: ISO 8859-1 (1987) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-1 (1987) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-1 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-1 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+0xa0-0xff idem # iso 8859-1 special: trivial mapping to Unicode
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+#0xA0 U+00A0 # NO-BREAK SPACE
+#0xA1 U+00A1 # INVERTED EXCLAMATION MARK
+#0xA2 U+00A2 # CENT SIGN
+#0xA3 U+00A3 # POUND SIGN
+#0xA4 U+00A4 # CURRENCY SIGN
+#0xA5 U+00A5 # YEN SIGN
+#0xA6 U+00A6 # BROKEN BAR
+#0xA7 U+00A7 # SECTION SIGN
+#0xA8 U+00A8 # DIAERESIS
+#0xA9 U+00A9 # COPYRIGHT SIGN
+#0xAA U+00AA # FEMININE ORDINAL INDICATOR
+#0xAB U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+#0xAC U+00AC # NOT SIGN
+#0xAD U+00AD # SOFT HYPHEN
+#0xAE U+00AE # REGISTERED SIGN
+#0xAF U+00AF # MACRON
+#0xB0 U+00B0 # DEGREE SIGN
+#0xB1 U+00B1 # PLUS-MINUS SIGN
+#0xB2 U+00B2 # SUPERSCRIPT TWO
+#0xB3 U+00B3 # SUPERSCRIPT THREE
+#0xB4 U+00B4 # ACUTE ACCENT
+#0xB5 U+00B5 # MICRO SIGN
+#0xB6 U+00B6 # PILCROW SIGN
+#0xB7 U+00B7 # MIDDLE DOT
+#0xB8 U+00B8 # CEDILLA
+#0xB9 U+00B9 # SUPERSCRIPT ONE
+#0xBA U+00BA # MASCULINE ORDINAL INDICATOR
+#0xBB U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+#0xBC U+00BC # VULGAR FRACTION ONE QUARTER
+#0xBD U+00BD # VULGAR FRACTION ONE HALF
+#0xBE U+00BE # VULGAR FRACTION THREE QUARTERS
+#0xBF U+00BF # INVERTED QUESTION MARK
+#0xC0 U+00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+#0xC1 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+#0xC2 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+#0xC3 U+00C3 # LATIN CAPITAL LETTER A WITH TILDE
+#0xC4 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+#0xC5 U+00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+#0xC6 U+00C6 # LATIN CAPITAL LETTER AE
+#0xC7 U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+#0xC8 U+00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+#0xC9 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+#0xCA U+00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+#0xCB U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+#0xCC U+00CC # LATIN CAPITAL LETTER I WITH GRAVE
+#0xCD U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+#0xCE U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+#0xCF U+00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+#0xD0 U+00D0 # LATIN CAPITAL LETTER ETH (Icelandic)
+#0xD1 U+00D1 # LATIN CAPITAL LETTER N WITH TILDE
+#0xD2 U+00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+#0xD3 U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+#0xD4 U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+#0xD5 U+00D5 # LATIN CAPITAL LETTER O WITH TILDE
+#0xD6 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+#0xD7 U+00D7 # MULTIPLICATION SIGN
+#0xD8 U+00D8 # LATIN CAPITAL LETTER O WITH STROKE
+#0xD9 U+00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+#0xDA U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+#0xDB U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+#0xDC U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+#0xDD U+00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+#0xDE U+00DE # LATIN CAPITAL LETTER THORN (Icelandic)
+#0xDF U+00DF # LATIN SMALL LETTER SHARP S (German)
+#0xE0 U+00E0 # LATIN SMALL LETTER A WITH GRAVE
+#0xE1 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+#0xE2 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+#0xE3 U+00E3 # LATIN SMALL LETTER A WITH TILDE
+#0xE4 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+#0xE5 U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+#0xE6 U+00E6 # LATIN SMALL LETTER AE
+#0xE7 U+00E7 # LATIN SMALL LETTER C WITH CEDILLA
+#0xE8 U+00E8 # LATIN SMALL LETTER E WITH GRAVE
+#0xE9 U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+#0xEA U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+#0xEB U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+#0xEC U+00EC # LATIN SMALL LETTER I WITH GRAVE
+#0xED U+00ED # LATIN SMALL LETTER I WITH ACUTE
+#0xEE U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+#0xEF U+00EF # LATIN SMALL LETTER I WITH DIAERESIS
+#0xF0 U+00F0 # LATIN SMALL LETTER ETH (Icelandic)
+#0xF1 U+00F1 # LATIN SMALL LETTER N WITH TILDE
+#0xF2 U+00F2 # LATIN SMALL LETTER O WITH GRAVE
+#0xF3 U+00F3 # LATIN SMALL LETTER O WITH ACUTE
+#0xF4 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+#0xF5 U+00F5 # LATIN SMALL LETTER O WITH TILDE
+#0xF6 U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+#0xF7 U+00F7 # DIVISION SIGN
+#0xF8 U+00F8 # LATIN SMALL LETTER O WITH STROKE
+#0xF9 U+00F9 # LATIN SMALL LETTER U WITH GRAVE
+#0xFA U+00FA # LATIN SMALL LETTER U WITH ACUTE
+#0xFB U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+#0xFC U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+#0xFD U+00FD # LATIN SMALL LETTER Y WITH ACUTE
+#0xFE U+00FE # LATIN SMALL LETTER THORN (Icelandic)
+#0xFF U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS
+
+
+0xd0 U+0110 # Dstrok and ETH are nearly the same...
+
+U+2297 "(\327)"
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso02_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso02_uni.tbl
new file mode 100644
index 00000000000..af97bc55507
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso02_uni.tbl
@@ -0,0 +1,242 @@
+#The MIME name of this charset.
+Miso-8859-2
+
+#Name as a Display Charset (used on Options screen)
+OISO Latin 2
+
+#
+# Name: ISO 8859-2 (1987) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-2 (1987) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-2 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-2 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 U+02D8 # BREVE
+0xA3 U+0141 # LATIN CAPITAL LETTER L WITH STROKE
+0xA4 U+00A4 # CURRENCY SIGN
+0xA5 U+013D # LATIN CAPITAL LETTER L WITH CARON
+0xA6 U+015A # LATIN CAPITAL LETTER S WITH ACUTE
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+0160 # LATIN CAPITAL LETTER S WITH CARON
+0xAA U+015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB U+0164 # LATIN CAPITAL LETTER T WITH CARON
+0xAC U+0179 # LATIN CAPITAL LETTER Z WITH ACUTE
+0xAD U+00AD # SOFT HYPHEN
+0xAE U+017D # LATIN CAPITAL LETTER Z WITH CARON
+0xAF U+017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+0105 # LATIN SMALL LETTER A WITH OGONEK
+0xB2 U+02DB # OGONEK
+0xB3 U+0142 # LATIN SMALL LETTER L WITH STROKE
+0xB4 U+00B4 # ACUTE ACCENT
+0xB5 U+013E # LATIN SMALL LETTER L WITH CARON
+0xB6 U+015B # LATIN SMALL LETTER S WITH ACUTE
+0xB7 U+02C7 # CARON
+0xB8 U+00B8 # CEDILLA
+0xB9 U+0161 # LATIN SMALL LETTER S WITH CARON
+0xBA U+015F # LATIN SMALL LETTER S WITH CEDILLA
+0xBB U+0165 # LATIN SMALL LETTER T WITH CARON
+0xBC U+017A # LATIN SMALL LETTER Z WITH ACUTE
+0xBD U+02DD # DOUBLE ACUTE ACCENT
+0xBE U+017E # LATIN SMALL LETTER Z WITH CARON
+0xBF U+017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 U+0154 # LATIN CAPITAL LETTER R WITH ACUTE
+0xC1 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 U+0102 # LATIN CAPITAL LETTER A WITH BREVE
+0xC4 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 U+0139 # LATIN CAPITAL LETTER L WITH ACUTE
+0xC6 U+0106 # LATIN CAPITAL LETTER C WITH ACUTE
+0xC7 U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 U+010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA U+0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xCB U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC U+011A # LATIN CAPITAL LETTER E WITH CARON
+0xCD U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF U+010E # LATIN CAPITAL LETTER D WITH CARON
+0xD0 U+0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xD1 U+0143 # LATIN CAPITAL LETTER N WITH ACUTE
+0xD2 U+0147 # LATIN CAPITAL LETTER N WITH CARON
+0xD3 U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 U+0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0xD6 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 U+00D7 # MULTIPLICATION SIGN
+0xD8 U+0158 # LATIN CAPITAL LETTER R WITH CARON
+0xD9 U+016E # LATIN CAPITAL LETTER U WITH RING ABOVE
+0xDA U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB U+0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0xDC U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD U+00DD # LATIN CAPITAL LETTER Y WITH ACUTE
+0xDE U+0162 # LATIN CAPITAL LETTER T WITH CEDILLA
+0xDF U+00DF # LATIN SMALL LETTER SHARP S
+0xE0 U+0155 # LATIN SMALL LETTER R WITH ACUTE
+0xE1 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 U+0103 # LATIN SMALL LETTER A WITH BREVE
+0xE4 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 U+013A # LATIN SMALL LETTER L WITH ACUTE
+0xE6 U+0107 # LATIN SMALL LETTER C WITH ACUTE
+0xE7 U+00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 U+010D # LATIN SMALL LETTER C WITH CARON
+0xE9 U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA U+0119 # LATIN SMALL LETTER E WITH OGONEK
+0xEB U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC U+011B # LATIN SMALL LETTER E WITH CARON
+0xED U+00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF U+010F # LATIN SMALL LETTER D WITH CARON
+0xF0 U+0111 # LATIN SMALL LETTER D WITH STROKE
+0xF1 U+0144 # LATIN SMALL LETTER N WITH ACUTE
+0xF2 U+0148 # LATIN SMALL LETTER N WITH CARON
+0xF3 U+00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 U+0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0xF6 U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 U+00F7 # DIVISION SIGN
+0xF8 U+0159 # LATIN SMALL LETTER R WITH CARON
+0xF9 U+016F # LATIN SMALL LETTER U WITH RING ABOVE
+0xFA U+00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB U+0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0xFC U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD U+00FD # LATIN SMALL LETTER Y WITH ACUTE
+0xFE U+0163 # LATIN SMALL LETTER T WITH CEDILLA
+0xFF U+02D9 # DOT ABOVE
+
+
+0xd0 U+00d0 # Dstrok and ETH are nearly the same...
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso03_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso03_uni.tbl
new file mode 100644
index 00000000000..bb8cd90f93a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso03_uni.tbl
@@ -0,0 +1,242 @@
+#The MIME name of this charset.
+Miso-8859-3
+
+#Name as a Display Charset (used on Options screen)
+OISO Latin 3
+
+#
+# Name: ISO 8859-3 (1988) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-3 (1988) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-3 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-3 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+0126 # LATIN CAPITAL LETTER H WITH STROKE
+0xA2 U+02D8 # BREVE
+0xA3 U+00A3 # POUND SIGN
+0xA4 U+00A4 # CURRENCY SIGN
+0xA6 U+0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xAA U+015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xAB U+011E # LATIN CAPITAL LETTER G WITH BREVE
+0xAC U+0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0xAD U+00AD # SOFT HYPHEN
+0xAF U+017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+0127 # LATIN SMALL LETTER H WITH STROKE
+0xB2 U+00B2 # SUPERSCRIPT TWO
+0xB3 U+00B3 # SUPERSCRIPT THREE
+0xB4 U+00B4 # ACUTE ACCENT
+0xB5 U+00B5 # MICRO SIGN
+0xB6 U+0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX
+0xB7 U+00B7 # MIDDLE DOT
+0xB8 U+00B8 # CEDILLA
+0xB9 U+0131 # LATIN SMALL LETTER DOTLESS I
+0xBA U+015F # LATIN SMALL LETTER S WITH CEDILLA
+0xBB U+011F # LATIN SMALL LETTER G WITH BREVE
+0xBC U+0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX
+0xBD U+00BD # VULGAR FRACTION ONE HALF
+0xBF U+017C # LATIN SMALL LETTER Z WITH DOT ABOVE
+0xC0 U+00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC4 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 U+010A # LATIN CAPITAL LETTER C WITH DOT ABOVE
+0xC6 U+0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0xC7 U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 U+00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA U+00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC U+00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF U+00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD1 U+00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 U+00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 U+0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0xD6 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 U+00D7 # MULTIPLICATION SIGN
+0xD8 U+011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0xD9 U+00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD U+016C # LATIN CAPITAL LETTER U WITH BREVE
+0xDE U+015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0xDF U+00DF # LATIN SMALL LETTER SHARP S
+0xE0 U+00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE4 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 U+010B # LATIN SMALL LETTER C WITH DOT ABOVE
+0xE6 U+0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX
+0xE7 U+00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 U+00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC U+00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED U+00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF U+00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF1 U+00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 U+00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 U+00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 U+0121 # LATIN SMALL LETTER G WITH DOT ABOVE
+0xF6 U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 U+00F7 # DIVISION SIGN
+0xF8 U+011D # LATIN SMALL LETTER G WITH CIRCUMFLEX
+0xF9 U+00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA U+00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD U+016D # LATIN SMALL LETTER U WITH BREVE
+0xFE U+015D # LATIN SMALL LETTER S WITH CIRCUMFLEX
+0xFF U+02D9 # DOT ABOVE
+
+
+# unassigned 8859-3 codepoints:
+# 0xa5 unused
+# 0xae unused
+# 0xbe unused
+# 0xc3 unused
+# 0xd0 unused
+# 0xe3 unused
+# 0xf0 unused
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso04_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso04_uni.tbl
new file mode 100644
index 00000000000..3f54afdacac
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso04_uni.tbl
@@ -0,0 +1,241 @@
+#The MIME name of this charset.
+Miso-8859-4
+
+#Name as a Display Charset (used on Options screen)
+OISO Latin 4
+
+#
+# Name: ISO 8859-4 (1988) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-4 (1988) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-4 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-4 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+0104 # LATIN CAPITAL LETTER A WITH OGONEK
+0xA2 U+0138 # LATIN SMALL LETTER KRA
+0xA3 U+0156 # LATIN CAPITAL LETTER R WITH CEDILLA
+0xA4 U+00A4 # CURRENCY SIGN
+0xA5 U+0128 # LATIN CAPITAL LETTER I WITH TILDE
+0xA6 U+013B # LATIN CAPITAL LETTER L WITH CEDILLA
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+0160 # LATIN CAPITAL LETTER S WITH CARON
+0xAA U+0112 # LATIN CAPITAL LETTER E WITH MACRON
+0xAB U+0122 # LATIN CAPITAL LETTER G WITH CEDILLA
+0xAC U+0166 # LATIN CAPITAL LETTER T WITH STROKE
+0xAD U+00AD # SOFT HYPHEN
+0xAE U+017D # LATIN CAPITAL LETTER Z WITH CARON
+0xAF U+00AF # MACRON
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+0105 # LATIN SMALL LETTER A WITH OGONEK
+0xB2 U+02DB # OGONEK
+0xB3 U+0157 # LATIN SMALL LETTER R WITH CEDILLA
+0xB4 U+00B4 # ACUTE ACCENT
+0xB5 U+0129 # LATIN SMALL LETTER I WITH TILDE
+0xB6 U+013C # LATIN SMALL LETTER L WITH CEDILLA
+0xB7 U+02C7 # CARON
+0xB8 U+00B8 # CEDILLA
+0xB9 U+0161 # LATIN SMALL LETTER S WITH CARON
+0xBA U+0113 # LATIN SMALL LETTER E WITH MACRON
+0xBB U+0123 # LATIN SMALL LETTER G WITH CEDILLA
+0xBC U+0167 # LATIN SMALL LETTER T WITH STROKE
+0xBD U+014A # LATIN CAPITAL LETTER ENG
+0xBE U+017E # LATIN SMALL LETTER Z WITH CARON
+0xBF U+014B # LATIN SMALL LETTER ENG
+0xC0 U+0100 # LATIN CAPITAL LETTER A WITH MACRON
+0xC1 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 U+00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 U+00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 U+00C6 # LATIN CAPITAL LETTER AE
+0xC7 U+012E # LATIN CAPITAL LETTER I WITH OGONEK
+0xC8 U+010C # LATIN CAPITAL LETTER C WITH CARON
+0xC9 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA U+0118 # LATIN CAPITAL LETTER E WITH OGONEK
+0xCB U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC U+0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0xCD U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF U+012A # LATIN CAPITAL LETTER I WITH MACRON
+0xD0 U+0110 # LATIN CAPITAL LETTER D WITH STROKE
+0xD1 U+0145 # LATIN CAPITAL LETTER N WITH CEDILLA
+0xD2 U+014C # LATIN CAPITAL LETTER O WITH MACRON
+0xD3 U+0136 # LATIN CAPITAL LETTER K WITH CEDILLA
+0xD4 U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 U+00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 U+00D7 # MULTIPLICATION SIGN
+0xD8 U+00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 U+0172 # LATIN CAPITAL LETTER U WITH OGONEK
+0xDA U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD U+0168 # LATIN CAPITAL LETTER U WITH TILDE
+0xDE U+016A # LATIN CAPITAL LETTER U WITH MACRON
+0xDF U+00DF # LATIN SMALL LETTER SHARP S
+0xE0 U+0101 # LATIN SMALL LETTER A WITH MACRON
+0xE1 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 U+00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 U+00E6 # LATIN SMALL LETTER AE
+0xE7 U+012F # LATIN SMALL LETTER I WITH OGONEK
+0xE8 U+010D # LATIN SMALL LETTER C WITH CARON
+0xE9 U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA U+0119 # LATIN SMALL LETTER E WITH OGONEK
+0xEB U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC U+0117 # LATIN SMALL LETTER E WITH DOT ABOVE
+0xED U+00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF U+012B # LATIN SMALL LETTER I WITH MACRON
+0xF0 U+0111 # LATIN SMALL LETTER D WITH STROKE
+0xF1 U+0146 # LATIN SMALL LETTER N WITH CEDILLA
+0xF2 U+014D # LATIN SMALL LETTER O WITH MACRON
+0xF3 U+0137 # LATIN SMALL LETTER K WITH CEDILLA
+0xF4 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 U+00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 U+00F7 # DIVISION SIGN
+0xF8 U+00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 U+0173 # LATIN SMALL LETTER U WITH OGONEK
+0xFA U+00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD U+0169 # LATIN SMALL LETTER U WITH TILDE
+0xFE U+016B # LATIN SMALL LETTER U WITH MACRON
+0xFF U+02D9 # DOT ABOVE
+
+
+0xd0 U+00d0 # Dstrok and ETH are nearly the same...
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso05_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso05_uni.tbl
new file mode 100644
index 00000000000..40cdc24dbd8
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso05_uni.tbl
@@ -0,0 +1,239 @@
+#The MIME name of this charset.
+Miso-8859-5
+
+#Name as a Display Charset (used on Options screen)
+OISO 8859-5 Cyrillic
+
+#
+# Name: ISO 8859-5 (1988) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-5 (1988) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-5 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-5 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+0401 # CYRILLIC CAPITAL LETTER IO
+0xA2 U+0402 # CYRILLIC CAPITAL LETTER DJE
+0xA3 U+0403 # CYRILLIC CAPITAL LETTER GJE
+0xA4 U+0404 # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0xA5 U+0405 # CYRILLIC CAPITAL LETTER DZE
+0xA6 U+0406 # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0xA7 U+0407 # CYRILLIC CAPITAL LETTER YI
+0xA8 U+0408 # CYRILLIC CAPITAL LETTER JE
+0xA9 U+0409 # CYRILLIC CAPITAL LETTER LJE
+0xAA U+040A # CYRILLIC CAPITAL LETTER NJE
+0xAB U+040B # CYRILLIC CAPITAL LETTER TSHE
+0xAC U+040C # CYRILLIC CAPITAL LETTER KJE
+0xAD U+00AD # SOFT HYPHEN
+0xAE U+040E # CYRILLIC CAPITAL LETTER SHORT U
+0xAF U+040F # CYRILLIC CAPITAL LETTER DZHE
+0xB0 U+0410 # CYRILLIC CAPITAL LETTER A
+0xB1 U+0411 # CYRILLIC CAPITAL LETTER BE
+0xB2 U+0412 # CYRILLIC CAPITAL LETTER VE
+0xB3 U+0413 # CYRILLIC CAPITAL LETTER GHE
+0xB4 U+0414 # CYRILLIC CAPITAL LETTER DE
+0xB5 U+0415 # CYRILLIC CAPITAL LETTER IE
+0xB6 U+0416 # CYRILLIC CAPITAL LETTER ZHE
+0xB7 U+0417 # CYRILLIC CAPITAL LETTER ZE
+0xB8 U+0418 # CYRILLIC CAPITAL LETTER I
+0xB9 U+0419 # CYRILLIC CAPITAL LETTER SHORT I
+0xBA U+041A # CYRILLIC CAPITAL LETTER KA
+0xBB U+041B # CYRILLIC CAPITAL LETTER EL
+0xBC U+041C # CYRILLIC CAPITAL LETTER EM
+0xBD U+041D # CYRILLIC CAPITAL LETTER EN
+0xBE U+041E # CYRILLIC CAPITAL LETTER O
+0xBF U+041F # CYRILLIC CAPITAL LETTER PE
+0xC0 U+0420 # CYRILLIC CAPITAL LETTER ER
+0xC1 U+0421 # CYRILLIC CAPITAL LETTER ES
+0xC2 U+0422 # CYRILLIC CAPITAL LETTER TE
+0xC3 U+0423 # CYRILLIC CAPITAL LETTER U
+0xC4 U+0424 # CYRILLIC CAPITAL LETTER EF
+0xC5 U+0425 # CYRILLIC CAPITAL LETTER HA
+0xC6 U+0426 # CYRILLIC CAPITAL LETTER TSE
+0xC7 U+0427 # CYRILLIC CAPITAL LETTER CHE
+0xC8 U+0428 # CYRILLIC CAPITAL LETTER SHA
+0xC9 U+0429 # CYRILLIC CAPITAL LETTER SHCHA
+0xCA U+042A # CYRILLIC CAPITAL LETTER HARD SIGN
+0xCB U+042B # CYRILLIC CAPITAL LETTER YERU
+0xCC U+042C # CYRILLIC CAPITAL LETTER SOFT SIGN
+0xCD U+042D # CYRILLIC CAPITAL LETTER E
+0xCE U+042E # CYRILLIC CAPITAL LETTER YU
+0xCF U+042F # CYRILLIC CAPITAL LETTER YA
+0xD0 U+0430 # CYRILLIC SMALL LETTER A
+0xD1 U+0431 # CYRILLIC SMALL LETTER BE
+0xD2 U+0432 # CYRILLIC SMALL LETTER VE
+0xD3 U+0433 # CYRILLIC SMALL LETTER GHE
+0xD4 U+0434 # CYRILLIC SMALL LETTER DE
+0xD5 U+0435 # CYRILLIC SMALL LETTER IE
+0xD6 U+0436 # CYRILLIC SMALL LETTER ZHE
+0xD7 U+0437 # CYRILLIC SMALL LETTER ZE
+0xD8 U+0438 # CYRILLIC SMALL LETTER I
+0xD9 U+0439 # CYRILLIC SMALL LETTER SHORT I
+0xDA U+043A # CYRILLIC SMALL LETTER KA
+0xDB U+043B # CYRILLIC SMALL LETTER EL
+0xDC U+043C # CYRILLIC SMALL LETTER EM
+0xDD U+043D # CYRILLIC SMALL LETTER EN
+0xDE U+043E # CYRILLIC SMALL LETTER O
+0xDF U+043F # CYRILLIC SMALL LETTER PE
+0xE0 U+0440 # CYRILLIC SMALL LETTER ER
+0xE1 U+0441 # CYRILLIC SMALL LETTER ES
+0xE2 U+0442 # CYRILLIC SMALL LETTER TE
+0xE3 U+0443 # CYRILLIC SMALL LETTER U
+0xE4 U+0444 # CYRILLIC SMALL LETTER EF
+0xE5 U+0445 # CYRILLIC SMALL LETTER HA
+0xE6 U+0446 # CYRILLIC SMALL LETTER TSE
+0xE7 U+0447 # CYRILLIC SMALL LETTER CHE
+0xE8 U+0448 # CYRILLIC SMALL LETTER SHA
+0xE9 U+0449 # CYRILLIC SMALL LETTER SHCHA
+0xEA U+044A # CYRILLIC SMALL LETTER HARD SIGN
+0xEB U+044B # CYRILLIC SMALL LETTER YERU
+0xEC U+044C # CYRILLIC SMALL LETTER SOFT SIGN
+0xED U+044D # CYRILLIC SMALL LETTER E
+0xEE U+044E # CYRILLIC SMALL LETTER YU
+0xEF U+044F # CYRILLIC SMALL LETTER YA
+0xF0 U+2116 # NUMERO SIGN
+0xF1 U+0451 # CYRILLIC SMALL LETTER IO
+0xF2 U+0452 # CYRILLIC SMALL LETTER DJE
+0xF3 U+0453 # CYRILLIC SMALL LETTER GJE
+0xF4 U+0454 # CYRILLIC SMALL LETTER UKRAINIAN IE
+0xF5 U+0455 # CYRILLIC SMALL LETTER DZE
+0xF6 U+0456 # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0xF7 U+0457 # CYRILLIC SMALL LETTER YI
+0xF8 U+0458 # CYRILLIC SMALL LETTER JE
+0xF9 U+0459 # CYRILLIC SMALL LETTER LJE
+0xFA U+045A # CYRILLIC SMALL LETTER NJE
+0xFB U+045B # CYRILLIC SMALL LETTER TSHE
+0xFC U+045C # CYRILLIC SMALL LETTER KJE
+0xFD U+00A7 # SECTION SIGN
+0xFE U+045E # CYRILLIC SMALL LETTER SHORT U
+0xFF U+045F # CYRILLIC SMALL LETTER DZHE
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso06_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso06_uni.tbl
new file mode 100644
index 00000000000..c9418864aa1
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso06_uni.tbl
@@ -0,0 +1,195 @@
+#The MIME name of this charset.
+Miso-8859-6
+
+#Name as a Display Charset (used on Options screen).
+OISO 8859-6 Arabic
+
+#
+# Name: ISO 8859-6 (1987) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-6 (1987) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-6 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-6 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0660 # ARABIC-INDIC DIGIT ZERO
+#0x31 U+0661 # ARABIC-INDIC DIGIT ONE
+#0x32 U+0662 # ARABIC-INDIC DIGIT TWO
+#0x33 U+0663 # ARABIC-INDIC DIGIT THREE
+#0x34 U+0664 # ARABIC-INDIC DIGIT FOUR
+#0x35 U+0665 # ARABIC-INDIC DIGIT FIVE
+#0x36 U+0666 # ARABIC-INDIC DIGIT SIX
+#0x37 U+0667 # ARABIC-INDIC DIGIT SEVEN
+#0x38 U+0668 # ARABIC-INDIC DIGIT EIGHT
+#0x39 U+0669 # ARABIC-INDIC DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA4 U+00A4 # CURRENCY SIGN
+0xAC U+060C # ARABIC COMMA
+0xAD U+00AD # SOFT HYPHEN
+0xBB U+061B # ARABIC SEMICOLON
+0xBF U+061F # ARABIC QUESTION MARK
+0xC1 U+0621 # ARABIC LETTER HAMZA
+0xC2 U+0622 # ARABIC LETTER ALEF WITH MADDA ABOVE
+0xC3 U+0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE
+0xC4 U+0624 # ARABIC LETTER WAW WITH HAMZA ABOVE
+0xC5 U+0625 # ARABIC LETTER ALEF WITH HAMZA BELOW
+0xC6 U+0626 # ARABIC LETTER YEH WITH HAMZA ABOVE
+0xC7 U+0627 # ARABIC LETTER ALEF
+0xC8 U+0628 # ARABIC LETTER BEH
+0xC9 U+0629 # ARABIC LETTER TEH MARBUTA
+0xCA U+062A # ARABIC LETTER TEH
+0xCB U+062B # ARABIC LETTER THEH
+0xCC U+062C # ARABIC LETTER JEEM
+0xCD U+062D # ARABIC LETTER HAH
+0xCE U+062E # ARABIC LETTER KHAH
+0xCF U+062F # ARABIC LETTER DAL
+0xD0 U+0630 # ARABIC LETTER THAL
+0xD1 U+0631 # ARABIC LETTER REH
+0xD2 U+0632 # ARABIC LETTER ZAIN
+0xD3 U+0633 # ARABIC LETTER SEEN
+0xD4 U+0634 # ARABIC LETTER SHEEN
+0xD5 U+0635 # ARABIC LETTER SAD
+0xD6 U+0636 # ARABIC LETTER DAD
+0xD7 U+0637 # ARABIC LETTER TAH
+0xD8 U+0638 # ARABIC LETTER ZAH
+0xD9 U+0639 # ARABIC LETTER AIN
+0xDA U+063A # ARABIC LETTER GHAIN
+0xE0 U+0640 # ARABIC TATWEEL
+0xE1 U+0641 # ARABIC LETTER FEH
+0xE2 U+0642 # ARABIC LETTER QAF
+0xE3 U+0643 # ARABIC LETTER KAF
+0xE4 U+0644 # ARABIC LETTER LAM
+0xE5 U+0645 # ARABIC LETTER MEEM
+0xE6 U+0646 # ARABIC LETTER NOON
+0xE7 U+0647 # ARABIC LETTER HEH
+0xE8 U+0648 # ARABIC LETTER WAW
+0xE9 U+0649 # ARABIC LETTER ALEF MAKSURA
+0xEA U+064A # ARABIC LETTER YEH
+0xEB U+064B # ARABIC FATHATAN
+0xEC U+064C # ARABIC DAMMATAN
+0xED U+064D # ARABIC KASRATAN
+0xEE U+064E # ARABIC FATHA
+0xEF U+064F # ARABIC DAMMA
+0xF0 U+0650 # ARABIC KASRA
+0xF1 U+0651 # ARABIC SHADDA
+0xF2 U+0652 # ARABIC SUKUN
+
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso07_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso07_uni.tbl
new file mode 100644
index 00000000000..368209bf831
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso07_uni.tbl
@@ -0,0 +1,233 @@
+#The MIME name of this charset.
+Miso-8859-7
+
+#Name as a Display Charset (used on Options screen)
+OISO 8859-7 Greek
+
+#
+# Name: ISO 8859-7 (1987) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-7 (1987) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-7 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-7 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+02BD # MODIFIER LETTER REVERSED COMMA
+0xA2 U+02BC # MODIFIER LETTER APOSTROPHE
+0xA3 U+00A3 # POUND SIGN
+0xA6 U+00A6 # BROKEN BAR
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+00A9 # COPYRIGHT SIGN
+0xAB U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC U+00AC # NOT SIGN
+0xAD U+00AD # SOFT HYPHEN
+0xAF U+2015 # HORIZONTAL BAR
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+00B1 # PLUS-MINUS SIGN
+0xB2 U+00B2 # SUPERSCRIPT TWO
+0xB3 U+00B3 # SUPERSCRIPT THREE
+0xB4 U+0384 # GREEK TONOS
+0xB5 U+0385 # GREEK DIALYTIKA TONOS
+0xB6 U+0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS
+0xB7 U+00B7 # MIDDLE DOT
+0xB8 U+0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS
+0xB9 U+0389 # GREEK CAPITAL LETTER ETA WITH TONOS
+0xBA U+038A # GREEK CAPITAL LETTER IOTA WITH TONOS
+0xBB U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+038C # GREEK CAPITAL LETTER OMICRON WITH TONOS
+0xBD U+00BD # VULGAR FRACTION ONE HALF
+0xBE U+038E # GREEK CAPITAL LETTER UPSILON WITH TONOS
+0xBF U+038F # GREEK CAPITAL LETTER OMEGA WITH TONOS
+0xC0 U+0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0xC1 U+0391 # GREEK CAPITAL LETTER ALPHA
+0xC2 U+0392 # GREEK CAPITAL LETTER BETA
+0xC3 U+0393 # GREEK CAPITAL LETTER GAMMA
+0xC4 U+0394 # GREEK CAPITAL LETTER DELTA
+0xC5 U+0395 # GREEK CAPITAL LETTER EPSILON
+0xC6 U+0396 # GREEK CAPITAL LETTER ZETA
+0xC7 U+0397 # GREEK CAPITAL LETTER ETA
+0xC8 U+0398 # GREEK CAPITAL LETTER THETA
+0xC9 U+0399 # GREEK CAPITAL LETTER IOTA
+0xCA U+039A # GREEK CAPITAL LETTER KAPPA
+0xCB U+039B # GREEK CAPITAL LETTER LAMDA
+0xCC U+039C # GREEK CAPITAL LETTER MU
+0xCD U+039D # GREEK CAPITAL LETTER NU
+0xCE U+039E # GREEK CAPITAL LETTER XI
+0xCF U+039F # GREEK CAPITAL LETTER OMICRON
+0xD0 U+03A0 # GREEK CAPITAL LETTER PI
+0xD1 U+03A1 # GREEK CAPITAL LETTER RHO
+0xD3 U+03A3 # GREEK CAPITAL LETTER SIGMA
+0xD4 U+03A4 # GREEK CAPITAL LETTER TAU
+0xD5 U+03A5 # GREEK CAPITAL LETTER UPSILON
+0xD6 U+03A6 # GREEK CAPITAL LETTER PHI
+0xD7 U+03A7 # GREEK CAPITAL LETTER CHI
+0xD8 U+03A8 # GREEK CAPITAL LETTER PSI
+0xD9 U+03A9 # GREEK CAPITAL LETTER OMEGA
+0xDA U+03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0xDB U+03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0xDC U+03AC # GREEK SMALL LETTER ALPHA WITH TONOS
+0xDD U+03AD # GREEK SMALL LETTER EPSILON WITH TONOS
+0xDE U+03AE # GREEK SMALL LETTER ETA WITH TONOS
+0xDF U+03AF # GREEK SMALL LETTER IOTA WITH TONOS
+0xE0 U+03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0xE1 U+03B1 # GREEK SMALL LETTER ALPHA
+0xE2 U+03B2 # GREEK SMALL LETTER BETA
+0xE3 U+03B3 # GREEK SMALL LETTER GAMMA
+0xE4 U+03B4 # GREEK SMALL LETTER DELTA
+0xE5 U+03B5 # GREEK SMALL LETTER EPSILON
+0xE6 U+03B6 # GREEK SMALL LETTER ZETA
+0xE7 U+03B7 # GREEK SMALL LETTER ETA
+0xE8 U+03B8 # GREEK SMALL LETTER THETA
+0xE9 U+03B9 # GREEK SMALL LETTER IOTA
+0xEA U+03BA # GREEK SMALL LETTER KAPPA
+0xEB U+03BB # GREEK SMALL LETTER LAMDA
+0xEC U+03BC # GREEK SMALL LETTER MU
+0xED U+03BD # GREEK SMALL LETTER NU
+0xEE U+03BE # GREEK SMALL LETTER XI
+0xEF U+03BF # GREEK SMALL LETTER OMICRON
+0xF0 U+03C0 # GREEK SMALL LETTER PI
+0xF1 U+03C1 # GREEK SMALL LETTER RHO
+0xF2 U+03C2 # GREEK SMALL LETTER FINAL SIGMA
+0xF3 U+03C3 # GREEK SMALL LETTER SIGMA
+0xF4 U+03C4 # GREEK SMALL LETTER TAU
+0xF5 U+03C5 # GREEK SMALL LETTER UPSILON
+0xF6 U+03C6 # GREEK SMALL LETTER PHI
+0xF7 U+03C7 # GREEK SMALL LETTER CHI
+0xF8 U+03C8 # GREEK SMALL LETTER PSI
+0xF9 U+03C9 # GREEK SMALL LETTER OMEGA
+0xFA U+03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0xFB U+03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0xFC U+03CC # GREEK SMALL LETTER OMICRON WITH TONOS
+0xFD U+03CD # GREEK SMALL LETTER UPSILON WITH TONOS
+0xFE U+03CE # GREEK SMALL LETTER OMEGA WITH TONOS
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso08_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso08_uni.tbl
new file mode 100644
index 00000000000..4d83f5c49fc
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso08_uni.tbl
@@ -0,0 +1,212 @@
+#The MIME name of this charset.
+Miso-8859-8
+
+#Name as a Display Charset (used on Options screen).
+OISO 8859-8 Hebrew
+
+#
+# Name: ISO 8859-8 (1988) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-8 (1988) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-8 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-8 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA2 U+00A2 # CENT SIGN
+0xA3 U+00A3 # POUND SIGN
+0xA4 U+00A4 # CURRENCY SIGN
+0xA5 U+00A5 # YEN SIGN
+0xA6 U+00A6 # BROKEN BAR
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+00A9 # COPYRIGHT SIGN
+0xAA U+00D7 # MULTIPLICATION SIGN
+0xAB U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC U+00AC # NOT SIGN
+0xAD U+00AD # SOFT HYPHEN
+0xAE U+00AE # REGISTERED SIGN
+0xAF U+203E # OVERLINE
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+00B1 # PLUS-MINUS SIGN
+0xB2 U+00B2 # SUPERSCRIPT TWO
+0xB3 U+00B3 # SUPERSCRIPT THREE
+0xB4 U+00B4 # ACUTE ACCENT
+0xB5 U+00B5 # MICRO SIGN
+0xB6 U+00B6 # PILCROW SIGN
+0xB7 U+00B7 # MIDDLE DOT
+0xB8 U+00B8 # CEDILLA
+0xB9 U+00B9 # SUPERSCRIPT ONE
+0xBA U+00F7 # DIVISION SIGN
+0xBB U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+00BC # VULGAR FRACTION ONE QUARTER
+0xBD U+00BD # VULGAR FRACTION ONE HALF
+0xBE U+00BE # VULGAR FRACTION THREE QUARTERS
+0xDF U+2017 # DOUBLE LOW LINE
+0xE0 U+05D0 # HEBREW LETTER ALEF
+0xE1 U+05D1 # HEBREW LETTER BET
+0xE2 U+05D2 # HEBREW LETTER GIMEL
+0xE3 U+05D3 # HEBREW LETTER DALET
+0xE4 U+05D4 # HEBREW LETTER HE
+0xE5 U+05D5 # HEBREW LETTER VAV
+0xE6 U+05D6 # HEBREW LETTER ZAYIN
+0xE7 U+05D7 # HEBREW LETTER HET
+0xE8 U+05D8 # HEBREW LETTER TET
+0xE9 U+05D9 # HEBREW LETTER YOD
+0xEA U+05DA # HEBREW LETTER FINAL KAF
+0xEB U+05DB # HEBREW LETTER KAF
+0xEC U+05DC # HEBREW LETTER LAMED
+0xED U+05DD # HEBREW LETTER FINAL MEM
+0xEE U+05DE # HEBREW LETTER MEM
+0xEF U+05DF # HEBREW LETTER FINAL NUN
+0xF0 U+05E0 # HEBREW LETTER NUN
+0xF1 U+05E1 # HEBREW LETTER SAMEKH
+0xF2 U+05E2 # HEBREW LETTER AYIN
+0xF3 U+05E3 # HEBREW LETTER FINAL PE
+0xF4 U+05E4 # HEBREW LETTER PE
+0xF5 U+05E5 # HEBREW LETTER FINAL TSADI
+0xF6 U+05E6 # HEBREW LETTER TSADI
+0xF7 U+05E7 # HEBREW LETTER QOF
+0xF8 U+05E8 # HEBREW LETTER RESH
+0xF9 U+05E9 # HEBREW LETTER SHIN
+0xFA U+05EA # HEBREW LETTER TAV
+
+
+#Hebrew points - map to empty string
+U+05B0-U+05C2:
+
+#HEBREW LETTER DOUBLE VAV #U+05F0:åå
+U+05F0 "\345\345"
+#HEBREW LETTER VAV YOD #U+05F1:éå
+U+05F1 "\351\345"
+#HEBREW LETTER DOUBLE YOD #U+05F2:éé
+U+05F2 "\351\351"
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso09_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso09_uni.tbl
new file mode 100644
index 00000000000..1b204835556
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso09_uni.tbl
@@ -0,0 +1,239 @@
+#The MIME name of this charset.
+Miso-8859-9
+
+#Name as a Display Charset (used on Options screen)
+OISO 8859-9 (Latin 5)
+
+#
+# Name: ISO 8859-9 (1989) to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 16 January 1995
+# Authors: Tim Greenwood <greenwood@r2me2.enet.dec.com>
+# John H. Jenkins <John_Jenkins@taligent.com>
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# ISO 8859-9 (1989) characters map into Unicode.
+#
+# Format: Three tab-separated columns
+# Column #1 is the ISO 8859-9 code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 the Unicode name (follows a comment sign, '#')
+#
+# The entries are in ISO 8859-9 order
+#
+# Any comments or problems, contact <John_Jenkins@taligent.com>
+#
+0x20-0x7e idem
+#
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+0xA0 U+00A0 # NO-BREAK SPACE
+0xA1 U+00A1 # INVERTED EXCLAMATION MARK
+0xA2 U+00A2 # CENT SIGN
+0xA3 U+00A3 # POUND SIGN
+0xA4 U+00A4 # CURRENCY SIGN
+0xA5 U+00A5 # YEN SIGN
+0xA6 U+00A6 # BROKEN BAR
+0xA7 U+00A7 # SECTION SIGN
+0xA8 U+00A8 # DIAERESIS
+0xA9 U+00A9 # COPYRIGHT SIGN
+0xAA U+00AA # FEMININE ORDINAL INDICATOR
+0xAB U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xAC U+00AC # NOT SIGN
+0xAD U+00AD # SOFT HYPHEN
+0xAE U+00AE # REGISTERED SIGN
+0xAF U+00AF # MACRON
+0xB0 U+00B0 # DEGREE SIGN
+0xB1 U+00B1 # PLUS-MINUS SIGN
+0xB2 U+00B2 # SUPERSCRIPT TWO
+0xB3 U+00B3 # SUPERSCRIPT THREE
+0xB4 U+00B4 # ACUTE ACCENT
+0xB5 U+00B5 # MICRO SIGN
+0xB6 U+00B6 # PILCROW SIGN
+0xB7 U+00B7 # MIDDLE DOT
+0xB8 U+00B8 # CEDILLA
+0xB9 U+00B9 # SUPERSCRIPT ONE
+0xBA U+00BA # MASCULINE ORDINAL INDICATOR
+0xBB U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xBC U+00BC # VULGAR FRACTION ONE QUARTER
+0xBD U+00BD # VULGAR FRACTION ONE HALF
+0xBE U+00BE # VULGAR FRACTION THREE QUARTERS
+0xBF U+00BF # INVERTED QUESTION MARK
+0xC0 U+00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xC1 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xC2 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xC3 U+00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xC4 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0xC5 U+00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0xC6 U+00C6 # LATIN CAPITAL LETTER AE
+0xC7 U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0xC8 U+00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xC9 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0xCA U+00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xCB U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xCC U+00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xCD U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xCE U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xCF U+00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xD0 U+011E # LATIN CAPITAL LETTER G WITH BREVE
+0xD1 U+00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0xD2 U+00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xD3 U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xD4 U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xD5 U+00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xD6 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0xD7 U+00D7 # MULTIPLICATION SIGN
+0xD8 U+00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xD9 U+00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xDA U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xDB U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xDC U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0xDD U+0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0xDE U+015E # LATIN CAPITAL LETTER S WITH CEDILLA
+0xDF U+00DF # LATIN SMALL LETTER SHARP S
+0xE0 U+00E0 # LATIN SMALL LETTER A WITH GRAVE
+0xE1 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+0xE2 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xE3 U+00E3 # LATIN SMALL LETTER A WITH TILDE
+0xE4 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xE5 U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xE6 U+00E6 # LATIN SMALL LETTER AE
+0xE7 U+00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0xE8 U+00E8 # LATIN SMALL LETTER E WITH GRAVE
+0xE9 U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+0xEA U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xEB U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0xEC U+00EC # LATIN SMALL LETTER I WITH GRAVE
+0xED U+00ED # LATIN SMALL LETTER I WITH ACUTE
+0xEE U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xEF U+00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0xF0 U+011F # LATIN SMALL LETTER G WITH BREVE
+0xF1 U+00F1 # LATIN SMALL LETTER N WITH TILDE
+0xF2 U+00F2 # LATIN SMALL LETTER O WITH GRAVE
+0xF3 U+00F3 # LATIN SMALL LETTER O WITH ACUTE
+0xF4 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xF5 U+00F5 # LATIN SMALL LETTER O WITH TILDE
+0xF6 U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xF7 U+00F7 # DIVISION SIGN
+0xF8 U+00F8 # LATIN SMALL LETTER O WITH STROKE
+0xF9 U+00F9 # LATIN SMALL LETTER U WITH GRAVE
+0xFA U+00FA # LATIN SMALL LETTER U WITH ACUTE
+0xFB U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xFC U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xFD U+0131 # LATIN SMALL LETTER DOTLESS I
+0xFE U+015F # LATIN SMALL LETTER S WITH CEDILLA
+0xFF U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/iso10_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/iso10_uni.tbl
new file mode 100644
index 00000000000..be3c02cd2df
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/iso10_uni.tbl
@@ -0,0 +1,123 @@
+#
+# Unicode mapping table for the fonts iso10.*
+# [use: unicode_start iso10.f16 iso10]
+#
+#This is not default font!
+D0
+
+#The MIME name of this charset.
+
+Miso-8859-10
+
+#Name as a Display Charset (used on Options screen)
+OISO 8859-10
+
+0x20-0x7e idem
+#0x7f U+2302
+#
+#0x00 U+fffd
+#0x01 U+263A
+#0x02 U+263B
+#0x03 U+2665
+#0x04 U+2666
+#0x05 U+2663
+#0x06 U+2660
+#0x07 U+2022
+#0x08 U+25D8
+#0x09 U+25CB
+#0x0A U+25D9
+#0x0B U+2642
+#0x0C U+2640
+#0x0D U+266A
+#0x0E U+266B
+#0x0E U+266C
+#0x0F U+263C
+#0x10 U+25B6
+#0x10 U+25BA
+#0x11 U+25C0
+#0x11 U+25C4
+#0x12 U+2195
+#0x13 U+203C
+#0x14 U+00B6
+#0x15 U+00A7
+#0x16 U+25AC
+#0x17 U+21A8
+#0x18 U+2191
+#0x19 U+2193
+#0x1A U+2192
+#0x1B U+2190
+#0x1C U+221F
+#0x1C U+2319
+#0x1D U+2194
+#0x1E U+25B2
+#0x1F U+25BC
+#
+0xa0 U+00a0
+0xa1 U+0104
+0xa2 U+0112
+0xa3 U+0122
+0xa4 U+012a
+0xa5 U+0128
+0xa6 U+0136
+0xa7 U+013b
+0xa8 U+0143
+0xa9 U+0156
+0xaa U+0160
+0xab U+0166
+0xac U+017d
+0xad U+00ad
+0xae U+0138
+0xaf U+014a
+0xb0 U+0111
+0xb1 U+0105
+0xb2 U+0113
+0xb3 U+0123
+0xb4 U+012b
+0xb5 U+0129
+0xb6 U+0137
+0xb7 U+013c
+0xb8 U+0144
+0xb9 U+0157
+0xba U+0161
+0xbb U+0167
+0xbc U+017e
+0xbd U+2015 # HORIZONTAL BAR
+0xbe U+00df
+0xbf U+014b
+0xc0 U+0100
+0xc1-0xc6 idem
+0xc7 U+012e
+0xc8 U+010c
+0xc9 U+00c9
+0xca U+0118
+0xcb U+00cb
+0xcc U+0116
+0xcd-0xd0 idem
+0xd1 U+0145
+0xd2 U+014c
+0xd3-0xd6 idem
+0xd7 U+0168
+0xd8 U+00d8
+0xd9 U+0172
+0xda-0xde idem
+0xdf U+016a
+0xe0 U+0101
+0xe1-0xe6 idem
+0xe7 U+012f
+0xe8 U+010d
+0xe9 U+00e9
+0xea U+0119
+0xeb U+00eb
+0xec U+0117
+0xed-0xf0 idem
+0xf1 U+0146
+0xf2 U+014d
+0xf3-0xf6 idem
+0xf7 U+0169
+0xf8 U+00f8
+0xf9 U+0173
+0xfa-0xfe idem
+0xff U+016b
+
+# TRADE MARK SIGN:
+U+2122:(TM)
diff --git a/gnu/usr.bin/lynx/src/chrtrans/koi8r_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/koi8r_uni.tbl
new file mode 100644
index 00000000000..09e8743cfeb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/koi8r_uni.tbl
@@ -0,0 +1,141 @@
+# Options screen name for this character set
+OKOI8-R Cyrillic
+
+# MIME name for this charset
+Mkoi8-r
+
+0x20-0x7f idem
+# Based on a table received from "Glenn E. Thobe" <thobe@lafn.org>
+# (verified against RFC1489).
+#
+#hex unicode # description
+#--- U+---- # ---------------
+0x80 U+2500 # FORMS LIGHT HORIZONTAL
+0x81 U+2502 # FORMS LIGHT VERTICAL
+0x82 U+250C # FORMS LIGHT DOWN AND RIGHT
+0x83 U+2510 # FORMS LIGHT DOWN AND LEFT
+0x84 U+2514 # FORMS LIGHT UP AND RIGHT
+0x85 U+2518 # FORMS LIGHT UP AND LEFT
+0x86 U+251C # FORMS LIGHT VERTICAL AND RIGHT
+0x87 U+2524 # FORMS LIGHT VERTICAL AND LEFT
+0x88 U+252C # FORMS LIGHT DOWN AND HORIZONTAL
+0x89 U+2534 # FORMS LIGHT UP AND HORIZONTAL
+0x8A U+253C # FORMS LIGHT VERTICAL AND HORIZONTAL
+0x8B U+2580 # UPPER HALF BLOCK
+0x8C U+2584 # LOWER HALF BLOCK
+0x8D U+2588 # FULL BLOCK
+0x8E U+258C # LEFT HALF BLOCK
+0x8F U+2590 # RIGHT HALF BLOCK
+0x90 U+2591 # LIGHT SHADE
+0x91 U+2592 # MEDIUM SHADE
+0x92 U+2593 # DARK SHADE
+0x93 U+2320 # TOP HALF INTEGRAL
+0x94 U+25A0 # BLACK SMALL SQUARE
+0x95 U+2219 # BULLET OPERATOR
+0x96 U+221A # SQUARE ROOT
+0x97 U+2248 # ALMOST EQUAL TO
+0x98 U+2264 # LESS THAN OR EQUAL TO
+0x99 U+2265 # GREATER THAN OR EQUAL TO
+0x9A U+00A0 # NON-BREAKING SPACE
+0x9B U+2321 # BOTTOM HALF INTEGRAL
+0x9C U+00B0 # DEGREE SIGN
+0x9D U+00B2 # SUPERSCRIPT DIGIT TWO
+0x9E U+00B7 # MIDDLE DOT
+0x9F U+00F7 # DIVISION SIGN
+0xA0 U+2550 # FORMS DOUBLE HORIZONTAL
+0xA1 U+2551 # FORMS DOUBLE VERTICAL
+0xA2 U+2552 # FORMS DOWN SINGLE AND RIGHT DOUBLE
+0xA3 U+0451 # SMA IO
+0xA4 U+2553 # FORMS DOWN DOUBLE AND RIGHT SINGLE
+0xA5 U+2554 # FORMS DOUBLE DOWN AND RIGHT
+0xA6 U+2555 # FORMS DOWN SINGLE AND LEFT DOUBLE
+0xA7 U+2556 # FORMS DOWN DOUBLE AND LEFT SINGLE
+0xA8 U+2557 # FORMS DOUBLE DOWN AND LEFT
+0xA9 U+2558 # FORMS UP SINGLE AND RIGHT DOUBLE
+0xAA U+2559 # FORMS UP DOUBLE AND RIGHT SINGLE
+0xAB U+255A # FORMS DOUBLE UP AND RIGHT
+0xAC U+255B # FORMS UP SINGLE AND LEFT DOUBLE
+0xAD U+255C # FORMS UP DOUBLE AND LEFT SINGLE
+0xAE U+255D # FORMS DOUBLE UP AND LEFT
+0xAF U+255E # FORMS VERTICAL SINGLE AND RIGHT DOUBLE
+0xB0 U+255F # FORMS VERTICAL DOUBLE AND RIGHT SINGLE
+0xB1 U+2560 # FORMS DOUBLE VERTICAL AND RIGHT
+0xB2 U+2561 # FORMS VERTICAL SINGLE AND LEFT DOUBLE
+0xB3 U+0401 # CAP IO
+0xB4 U+2562 # FORMS VERTICAL DOUBLE AND LEFT SINGLE
+0xB5 U+2563 # FORMS DOUBLE VERTICAL AND LEFT
+0xB6 U+2564 # FORMS DOWN SINGLE AND HORIZONTAL DOUBLE
+0xB7 U+2565 # FORMS DOWN DOUBLE AND HORIZONTAL SINGLE
+0xB8 U+2566 # FORMS DOUBLE DOWN AND HORIZONTAL
+0xB9 U+2567 # FORMS UP SINGLE AND HORIZONTAL DOUBLE
+0xBA U+2568 # FORMS UP DOUBLE AND HORIZONTAL SINGLE
+0xBB U+2569 # FORMS DOUBLE UP AND HORIZONTAL
+0xBC U+256A # FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0xBD U+256B # FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0xBE U+256C # FORMS DOUBLE VERTICAL AND HORIZONTAL
+0xBF U+00A9 # COPYRIGHT SIGN
+0xC0 U+044E # SMA IU
+0xC1 U+0430 # SMA A
+0xC2 U+0431 # SMA BE
+0xC3 U+0446 # SMA TSE
+0xC4 U+0434 # SMA DE
+0xC5 U+0435 # SMA IE
+0xC6 U+0444 # SMA EF
+0xC7 U+0433 # SMA GE
+0xC8 U+0445 # SMA KHA
+0xC9 U+0438 # SMA II
+0xCA U+0439 # SMA SHORT II
+0xCB U+043A # SMA KA
+0xCC U+043B # SMA EL
+0xCD U+043C # SMA EM
+0xCE U+043D # SMA EN
+0xCF U+043E # SMA O
+0xD0 U+043F # SMA PE
+0xD1 U+044F # SMA IA
+0xD2 U+0440 # SMA ER
+0xD3 U+0441 # SMA ES
+0xD4 U+0442 # SMA TE
+0xD5 U+0443 # SMA U
+0xD6 U+0436 # SMA ZHE
+0xD7 U+0432 # SMA VE
+0xD8 U+044C # SMA SOFT SIGN
+0xD9 U+044B # SMA YERI
+0xDA U+0437 # SMA ZE
+0xDB U+0448 # SMA SHA
+0xDC U+044D # SMA REVERSED E
+0xDD U+0449 # SMA SHCHA
+0xDE U+0447 # SMA CHE
+0xDF U+044A # SMA HARD SIGN
+0xE0 U+042E # CAP IU
+0xE1 U+0410 # CAP A
+0xE2 U+0411 # CAP BE
+0xE3 U+0426 # CAP TSE
+0xE4 U+0414 # CAP DE
+0xE5 U+0415 # CAP IE
+0xE6 U+0424 # CAP EF
+0xE7 U+0413 # CAP GE
+0xE8 U+0425 # CAP KHA
+0xE9 U+0418 # CAP II
+0xEA U+0419 # CAP SHORT II
+0xEB U+041A # CAP KA
+0xEC U+041B # CAP EL
+0xED U+041C # CAP EM
+0xEE U+041D # CAP EN
+0xEF U+041E # CAP O
+0xF0 U+041F # CAP PE
+0xF1 U+042F # CAP IA
+0xF2 U+0420 # CAP ER
+0xF3 U+0421 # CAP ES
+0xF4 U+0422 # CAP TE
+0xF5 U+0423 # CAP U
+0xF6 U+0416 # CAP ZHE
+0xF7 U+0412 # CAP VE
+0xF8 U+042C # CAP SOFT SIGN
+0xF9 U+042B # CAP YERI
+0xFA U+0417 # CAP ZE
+0xFB U+0428 # CAP SHA
+0xFC U+042D # CAP REVERSED E
+0xFD U+0429 # CAP SHCHA
+0xFE U+0427 # CAP CHE
+0xFF U+042A # CAP HARD SIGN
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/mac_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/mac_uni.tbl
new file mode 100644
index 00000000000..ea76d078dee
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/mac_uni.tbl
@@ -0,0 +1,340 @@
+#The MIME name of this charset.
+Mmacintosh
+
+#Name as a Display Charset (used on Options screen)
+OMacintosh (8 bit)
+
+#
+# Name: MacOS_Roman [to Unicode]
+# Unicode versions: 1.1, 2.0
+# Table version: 0.2 (from internal ufrm version <9>)
+# Date: 15 April 1995
+# Author: Peter Edberg <edberg1@applelink.apple.com>
+#
+# Copyright (c) 1995 Apple Computer, Inc. All Rights reserved.
+#
+# Apple, the Apple logo, and Macintosh are trademarks of Apple
+# Computer, Inc., registered in the United States and other countries.
+# Unicode is a trademark of Unicode Inc. For the sake of brevity,
+# throughout this document, "Macintosh" can be used to refer to
+# Macintosh computers and "Unicode" can be used to refer to the
+# Unicode standard.
+#
+# Apple makes no warranty or representation, either express or
+# implied, with respect to these tables, their quality, accuracy, or
+# fitness for a particular purpose. In no event will Apple be liable
+# for direct, indirect, special, incidental, or consequential damages
+# resulting from any defect or inaccuracy in this document or the
+# accompanying tables.
+#
+# These mapping tables and character lists are preliminary and
+# subject to change. Updated tables will be available from the
+# Unicode Inc. ftp site (unicode.org), the Apple Computer ftp site
+# (ftp.info.apple.com), the Apple Computer World-Wide Web pages
+# (http://www.info.apple.com), and possibly on diskette from APDA
+# (Apple's mail-order distribution service for developers).
+#
+# Format:
+# -------
+#
+# Three tab-separated columns;
+# '#' begins a comment which continues to the end of the line.
+# Column #1 is the MacOS Roman code (in hex as 0xNN)
+# Column #2 is the Unicode (in hex as 0xNNNN)
+# Column #3 is the Unicode name (follows a comment sign, '#')
+#
+# The entries are in MacOS Roman code order.
+#
+# One of these mappings requires the use of a corporate character
+# (for the Apple logo character). See the file "MacOS-CorpCharList".
+# NOTE: The graphic image associated with the Apple logo character
+# is not authorized for use without permission of Apple, and
+# unauthorized use might constitute trademark infringement.
+#
+# Notes on MacOS Roman:
+# ---------------------
+#
+# This character set is used for at least the following MacOS
+# localizations: U.S., British, Canadian French, French, Swiss
+# French, German, Swiss German, Italian, Swiss Italian, Dutch,
+# Swedish, Norwegian, Danish, Finnish, Spanish, Catalan,
+# Portuguese, Brazilian, and the default International system.
+#
+# Variants of MacRoman are used for Croatian, Icelandic,
+# Turkish, and Romanian. Separate mapping tables are available
+# for these encodings.
+#
+# At least through System 7.5, the bitmap versions of the fonts
+# Chicago, New York, Geneva, and Monaco do not implement the
+# full Roman character set; they only support MacOS Roman character
+# codes up to 0xD8. The TrueType versions of these fonts do
+# implement the full character set, as do both the bitmap and
+# TrueType versions of the other standard Roman fonts.
+#
+# In all MacOS encodings, fonts such as Chicago which are used
+# as "system" fonts (for menus, dialogs, etc.) have four glyphs
+# at code points 0x11-0x14 for transient use by the Menu Manager.
+# These glyphs are not intended as characters for use in normal
+# text, and the associated code points are not generally
+# interpreted as associated with these glyphs; they are usually
+# interpreted (if at all) as the control codes DC1-DC4.
+#
+##################
+
+#0x20 U+0020 # SPACE
+#0x21 U+0021 # EXCLAMATION MARK
+#0x22 U+0022 # QUOTATION MARK
+#0x23 U+0023 # NUMBER SIGN
+#0x24 U+0024 # DOLLAR SIGN
+#0x25 U+0025 # PERCENT SIGN
+#0x26 U+0026 # AMPERSAND
+#0x27 U+0027 # APOSTROPHE
+#0x28 U+0028 # LEFT PARENTHESIS
+#0x29 U+0029 # RIGHT PARENTHESIS
+#0x2A U+002A # ASTERISK
+#0x2B U+002B # PLUS SIGN
+#0x2C U+002C # COMMA
+#0x2D U+002D # HYPHEN-MINUS
+#0x2E U+002E # FULL STOP
+#0x2F U+002F # SOLIDUS
+#0x30 U+0030 # DIGIT ZERO
+#0x31 U+0031 # DIGIT ONE
+#0x32 U+0032 # DIGIT TWO
+#0x33 U+0033 # DIGIT THREE
+#0x34 U+0034 # DIGIT FOUR
+#0x35 U+0035 # DIGIT FIVE
+#0x36 U+0036 # DIGIT SIX
+#0x37 U+0037 # DIGIT SEVEN
+#0x38 U+0038 # DIGIT EIGHT
+#0x39 U+0039 # DIGIT NINE
+#0x3A U+003A # COLON
+#0x3B U+003B # SEMICOLON
+#0x3C U+003C # LESS-THAN SIGN
+#0x3D U+003D # EQUALS SIGN
+#0x3E U+003E # GREATER-THAN SIGN
+#0x3F U+003F # QUESTION MARK
+#0x40 U+0040 # COMMERCIAL AT
+#0x41 U+0041 # LATIN CAPITAL LETTER A
+#0x42 U+0042 # LATIN CAPITAL LETTER B
+#0x43 U+0043 # LATIN CAPITAL LETTER C
+#0x44 U+0044 # LATIN CAPITAL LETTER D
+#0x45 U+0045 # LATIN CAPITAL LETTER E
+#0x46 U+0046 # LATIN CAPITAL LETTER F
+#0x47 U+0047 # LATIN CAPITAL LETTER G
+#0x48 U+0048 # LATIN CAPITAL LETTER H
+#0x49 U+0049 # LATIN CAPITAL LETTER I
+#0x4A U+004A # LATIN CAPITAL LETTER J
+#0x4B U+004B # LATIN CAPITAL LETTER K
+#0x4C U+004C # LATIN CAPITAL LETTER L
+#0x4D U+004D # LATIN CAPITAL LETTER M
+#0x4E U+004E # LATIN CAPITAL LETTER N
+#0x4F U+004F # LATIN CAPITAL LETTER O
+#0x50 U+0050 # LATIN CAPITAL LETTER P
+#0x51 U+0051 # LATIN CAPITAL LETTER Q
+#0x52 U+0052 # LATIN CAPITAL LETTER R
+#0x53 U+0053 # LATIN CAPITAL LETTER S
+#0x54 U+0054 # LATIN CAPITAL LETTER T
+#0x55 U+0055 # LATIN CAPITAL LETTER U
+#0x56 U+0056 # LATIN CAPITAL LETTER V
+#0x57 U+0057 # LATIN CAPITAL LETTER W
+#0x58 U+0058 # LATIN CAPITAL LETTER X
+#0x59 U+0059 # LATIN CAPITAL LETTER Y
+#0x5A U+005A # LATIN CAPITAL LETTER Z
+#0x5B U+005B # LEFT SQUARE BRACKET
+#0x5C U+005C # REVERSE SOLIDUS
+#0x5D U+005D # RIGHT SQUARE BRACKET
+#0x5E U+005E # CIRCUMFLEX ACCENT
+#0x5F U+005F # LOW LINE
+#0x60 U+0060 # GRAVE ACCENT
+#0x61 U+0061 # LATIN SMALL LETTER A
+#0x62 U+0062 # LATIN SMALL LETTER B
+#0x63 U+0063 # LATIN SMALL LETTER C
+#0x64 U+0064 # LATIN SMALL LETTER D
+#0x65 U+0065 # LATIN SMALL LETTER E
+#0x66 U+0066 # LATIN SMALL LETTER F
+#0x67 U+0067 # LATIN SMALL LETTER G
+#0x68 U+0068 # LATIN SMALL LETTER H
+#0x69 U+0069 # LATIN SMALL LETTER I
+#0x6A U+006A # LATIN SMALL LETTER J
+#0x6B U+006B # LATIN SMALL LETTER K
+#0x6C U+006C # LATIN SMALL LETTER L
+#0x6D U+006D # LATIN SMALL LETTER M
+#0x6E U+006E # LATIN SMALL LETTER N
+#0x6F U+006F # LATIN SMALL LETTER O
+#0x70 U+0070 # LATIN SMALL LETTER P
+#0x71 U+0071 # LATIN SMALL LETTER Q
+#0x72 U+0072 # LATIN SMALL LETTER R
+#0x73 U+0073 # LATIN SMALL LETTER S
+#0x74 U+0074 # LATIN SMALL LETTER T
+#0x75 U+0075 # LATIN SMALL LETTER U
+#0x76 U+0076 # LATIN SMALL LETTER V
+#0x77 U+0077 # LATIN SMALL LETTER W
+#0x78 U+0078 # LATIN SMALL LETTER X
+#0x79 U+0079 # LATIN SMALL LETTER Y
+#0x7A U+007A # LATIN SMALL LETTER Z
+#0x7B U+007B # LEFT CURLY BRACKET
+#0x7C U+007C # VERTICAL LINE
+#0x7D U+007D # RIGHT CURLY BRACKET
+#0x7E U+007E # TILDE
+#
+0x20-0x7f idem
+#
+0x80 U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0x81 U+00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0x82 U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0x83 U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE
+0x84 U+00D1 # LATIN CAPITAL LETTER N WITH TILDE
+0x85 U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0x86 U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS
+0x87 U+00E1 # LATIN SMALL LETTER A WITH ACUTE
+0x88 U+00E0 # LATIN SMALL LETTER A WITH GRAVE
+0x89 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x8A U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS
+0x8B U+00E3 # LATIN SMALL LETTER A WITH TILDE
+0x8C U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE
+0x8D U+00E7 # LATIN SMALL LETTER C WITH CEDILLA
+0x8E U+00E9 # LATIN SMALL LETTER E WITH ACUTE
+0x8F U+00E8 # LATIN SMALL LETTER E WITH GRAVE
+0x90 U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x91 U+00EB # LATIN SMALL LETTER E WITH DIAERESIS
+0x92 U+00ED # LATIN SMALL LETTER I WITH ACUTE
+0x93 U+00EC # LATIN SMALL LETTER I WITH GRAVE
+0x94 U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x95 U+00EF # LATIN SMALL LETTER I WITH DIAERESIS
+0x96 U+00F1 # LATIN SMALL LETTER N WITH TILDE
+0x97 U+00F3 # LATIN SMALL LETTER O WITH ACUTE
+0x98 U+00F2 # LATIN SMALL LETTER O WITH GRAVE
+0x99 U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x9A U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS
+0x9B U+00F5 # LATIN SMALL LETTER O WITH TILDE
+0x9C U+00FA # LATIN SMALL LETTER U WITH ACUTE
+0x9D U+00F9 # LATIN SMALL LETTER U WITH GRAVE
+0x9E U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x9F U+00FC # LATIN SMALL LETTER U WITH DIAERESIS
+0xA0 U+2020 # DAGGER
+0xA1 U+00B0 # DEGREE SIGN
+0xA2 U+00A2 # CENT SIGN
+0xA3 U+00A3 # POUND SIGN
+0xA4 U+00A7 # SECTION SIGN
+0xA5 U+2022 # BULLET
+0xA6 U+00B6 # PILCROW SIGN
+0xA7 U+00DF # LATIN SMALL LETTER SHARP S
+0xA8 U+00AE # REGISTERED SIGN
+0xA9 U+00A9 # COPYRIGHT SIGN
+0xAA U+2122 # TRADE MARK SIGN
+0xAB U+00B4 # ACUTE ACCENT
+0xAC U+00A8 # DIAERESIS
+0xAD U+2260 # NOT EQUAL TO
+0xAE U+00C6 # LATIN CAPITAL LIGATURE AE
+0xAF U+00D8 # LATIN CAPITAL LETTER O WITH STROKE
+0xB0 U+221E # INFINITY
+0xB1 U+00B1 # PLUS-MINUS SIGN
+0xB2 U+2264 # LESS-THAN OR EQUAL TO
+0xB3 U+2265 # GREATER-THAN OR EQUAL TO
+0xB4 U+00A5 # YEN SIGN
+0xB5 U+00B5 # MICRO SIGN
+0xB6 U+2202 # PARTIAL DIFFERENTIAL
+0xB7 U+2211 # N-ARY SUMMATION
+0xB8 U+220F # N-ARY PRODUCT
+0xB9 U+03C0 # GREEK SMALL LETTER PI
+0xBA U+222B # INTEGRAL
+0xBB U+00AA # FEMININE ORDINAL INDICATOR
+0xBC U+00BA # MASCULINE ORDINAL INDICATOR
+0xBD U+2126 # OHM SIGN
+0xBE U+00E6 # LATIN SMALL LIGATURE AE
+0xBF U+00F8 # LATIN SMALL LETTER O WITH STROKE
+0xC0 U+00BF # INVERTED QUESTION MARK
+0xC1 U+00A1 # INVERTED EXCLAMATION MARK
+0xC2 U+00AC # NOT SIGN
+0xC3 U+221A # SQUARE ROOT
+0xC4 U+0192 # LATIN SMALL LETTER F WITH HOOK
+0xC5 U+2248 # ALMOST EQUAL TO
+0xC6 U+2206 # INCREMENT
+0xC7 U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC8 U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xC9 U+2026 # HORIZONTAL ELLIPSIS
+0xCA U+00A0 # NO-BREAK SPACE
+0xCB U+00C0 # LATIN CAPITAL LETTER A WITH GRAVE
+0xCC U+00C3 # LATIN CAPITAL LETTER A WITH TILDE
+0xCD U+00D5 # LATIN CAPITAL LETTER O WITH TILDE
+0xCE U+0152 # LATIN CAPITAL LIGATURE OE
+0xCF U+0153 # LATIN SMALL LIGATURE OE
+0xD0 U+2013 # EN DASH
+0xD1 U+2014 # EM DASH
+0xD2 U+201C # LEFT DOUBLE QUOTATION MARK
+0xD3 U+201D # RIGHT DOUBLE QUOTATION MARK
+0xD4 U+2018 # LEFT SINGLE QUOTATION MARK
+0xD5 U+2019 # RIGHT SINGLE QUOTATION MARK
+0xD6 U+00F7 # DIVISION SIGN
+0xD7 U+25CA # LOZENGE
+0xD8 U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS
+0xD9 U+0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0xDA U+2044 # FRACTION SLASH
+0xDB U+00A4 # CURRENCY SIGN
+0xDC U+2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0xDD U+203A # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0xDE U+FB01 # LATIN SMALL LIGATURE FI
+0xDF U+FB02 # LATIN SMALL LIGATURE FL
+0xE0 U+2021 # DOUBLE DAGGER
+0xE1 U+00B7 # MIDDLE DOT
+0xE2 U+201A # SINGLE LOW-9 QUOTATION MARK
+0xE3 U+201E # DOUBLE LOW-9 QUOTATION MARK
+0xE4 U+2030 # PER MILLE SIGN
+0xE5 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0xE6 U+00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0xE7 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE
+0xE8 U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS
+0xE9 U+00C8 # LATIN CAPITAL LETTER E WITH GRAVE
+0xEA U+00CD # LATIN CAPITAL LETTER I WITH ACUTE
+0xEB U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0xEC U+00CF # LATIN CAPITAL LETTER I WITH DIAERESIS
+0xED U+00CC # LATIN CAPITAL LETTER I WITH GRAVE
+0xEE U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE
+0xEF U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0xF0 U+F8FF # Apple logo
+0xF1 U+00D2 # LATIN CAPITAL LETTER O WITH GRAVE
+0xF2 U+00DA # LATIN CAPITAL LETTER U WITH ACUTE
+0xF3 U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0xF4 U+00D9 # LATIN CAPITAL LETTER U WITH GRAVE
+0xF5 U+0131 # LATIN SMALL LETTER DOTLESS I
+0xF6 U+02C6 # MODIFIER LETTER CIRCUMFLEX ACCENT
+0xF7 U+02DC # SMALL TILDE
+0xF8 U+00AF # MACRON
+0xF9 U+02D8 # BREVE
+0xFA U+02D9 # DOT ABOVE
+0xFB U+02DA # RING ABOVE
+0xFC U+00B8 # CEDILLA
+0xFD U+02DD # DOUBLE ACUTE ACCENT
+0xFE U+02DB # OGONEK
+0xFF U+02C7 # CARON
+#
+# broken vertical bar (&#166;) - brvbar, brkbar
+U+00A6:|
+# superscript 3 (&#179;) - sup3
+U+00B3:^3
+# superscript 2 (&#178;) - sup2
+U+00B2:^2
+# superscript 1 (&#185;) - sup1
+U+00B9:^1
+# fraction 1/4 (&#188;) - frac14
+U+00BC: 1/4
+# fraction 1/2 (&#189;) - frac12
+U+00BD: 1/2
+# fraction 3/4 (&#190;) - frac34
+U+00BE: 3/4
+# capital Eth, Icelandic (&#208;) - ETH
+U+00D0:DH
+# Dj # capital D with stroke - Dstrok
+# capital Y, acute accent (&#221;) - Yacute
+U+00DD:Y'
+# capital THORN, Icelandic (&#222;) - THORN
+U+00DE:P
+# multiplication sign (&#215;) - times
+U+00D7:*
+# small eth, Icelandic (&#240;) - eth
+U+00F0:dh
+# small y, acute accent (&#253;) - yacute
+U+00FD:y'
+# small thorn, Icelandic (&#254;) - thorn
+U+00FE:p
+#
diff --git a/gnu/usr.bin/lynx/src/chrtrans/makefile.dos b/gnu/usr.bin/lynx/src/chrtrans/makefile.dos
new file mode 100644
index 00000000000..6871b87a87c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/makefile.dos
@@ -0,0 +1,116 @@
+#
+# Makefile for the makeuctb and unicode tables
+# for use with DJGPP.
+#
+# Type make to build makeuctb and all character translation maps.
+# Type make fontmap to build makeuctb and translation map iso8859-1.
+# Type make makeuctb.exe to build makeuctb only.
+# Type make clean to remove makeuctb and character translation maps.
+# Type make distclean to remove makeuctb, character translation maps
+# and .bak files.
+#
+CFLAGS = $(MCFLAGS)
+
+CC = gcc
+MCFLAGS = -O3 -DDOSPATH -DNO_TTYTYP \
+-I../../WWW/library/implement -I../../djgpp/tcplib/include \
+-I../../djgpp/tcplib/include/tcp
+
+.SUFFIXES: .tbl
+#
+# This file contains the font map for the default (hardware) font
+#
+
+FONTMAP_INC = iso01_un.h
+
+TABLES= \
+ cp1250_uni.h \
+ cp1251_uni.h \
+ cp1252_uni.h \
+ cp1253_uni.h \
+ cp1255_uni.h \
+ cp1256_uni.h \
+ cp1257_uni.h \
+ cp437_uni.h \
+ cp737_uni.h \
+ cp775_uni.h \
+ cp850_uni.h \
+ cp852_uni.h \
+ cp862_uni.h \
+ cp864_uni.h \
+ cp866_uni.h \
+ cp869_uni.h \
+ def7_uni.h \
+ dmcs_uni.h \
+ iso01_uni.h \
+ iso02_uni.h \
+ iso03_uni.h \
+ iso04_uni.h \
+ iso05_uni.h \
+ iso06_uni.h \
+ iso07_uni.h \
+ iso08_uni.h \
+ iso09_uni.h \
+ iso10_uni.h \
+ koi8r_uni.h \
+ mac_uni.h \
+ mnem_suni.h \
+ mnem2_suni.h \
+ next_uni.h \
+ rfc_suni.h \
+ utf8_uni.h \
+ viscii_uni.h
+
+default: $(TABLES)
+
+fontmap: $(FONTMAP_INC)
+
+makeuctb.exe: makeuctb.c UCkd.h
+ $(CC) $(CFLAGS) -o makeuctb.exe makeuctb.c
+ strip makeuctb.exe
+
+.tbl.h:
+ ./makeuctb $*.tbl > $@
+
+cp1250_uni.h: cp1250_uni.tbl makeuctb.exe
+cp1251_uni.h: cp1251_uni.tbl makeuctb.exe
+cp1252_uni.h: cp1252_uni.tbl makeuctb.exe
+cp1253_uni.h: cp1253_uni.tbl makeuctb.exe
+cp1255_uni.h: cp1255_uni.tbl makeuctb.exe
+cp1256_uni.h: cp1256_uni.tbl makeuctb.exe
+cp1257_uni.h: cp1257_uni.tbl makeuctb.exe
+cp437_uni.h: cp437_uni.tbl makeuctb.exe
+cp737_uni.h: cp737_uni.tbl makeuctb.exe
+cp850_uni.h: cp850_uni.tbl makeuctb.exe
+cp852_uni.h: cp852_uni.tbl makeuctb.exe
+cp862_uni.h: cp862_uni.tbl makeuctb.exe
+cp864_uni.h: cp864_uni.tbl makeuctb.exe
+cp866_uni.h: cp866_uni.tbl makeuctb.exe
+cp869_uni.h: cp869_uni.tbl makeuctb.exe
+def7_uni.h: def7_uni.tbl makeuctb.exe
+dmcs_uni.h: dmcs_uni.tbl makeuctb.exe
+iso01_uni.h: iso01_uni.tbl makeuctb.exe
+iso02_uni.h: iso02_uni.tbl makeuctb.exe
+iso03_uni.h: iso03_uni.tbl makeuctb.exe
+iso04_uni.h: iso04_uni.tbl makeuctb.exe
+iso05_uni.h: iso05_uni.tbl makeuctb.exe
+iso06_uni.h: iso06_uni.tbl makeuctb.exe
+iso07_uni.h: iso07_uni.tbl makeuctb.exe
+iso08_uni.h: iso08_uni.tbl makeuctb.exe
+iso09_uni.h: iso09_uni.tbl makeuctb.exe
+iso10_uni.h: iso10_uni.tbl makeuctb.exe
+koi8r_uni.h: koi8r_uni.tbl makeuctb.exe
+mac_uni.h: mac_uni.tbl makeuctb.exe
+mnem_suni.h: mnem_suni.tbl makeuctb.exe
+mnem2_suni.h: mnem2_suni.tbl makeuctb.exe
+next_uni.h: next_uni.tbl makeuctb.exe
+rfc_suni.h: rfc_suni.tbl makeuctb.exe
+utf8_uni.h: utf8_uni.tbl makeuctb.exe
+viscii_uni.h: viscii_uni.tbl makeuctb.exe
+
+clean:
+ rm -f makeuctb.exe makeuctb *.o *un.h *u.h *c.h *i.h
+
+distclean: clean
+ -rm -f *.bak
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/makefile.in b/gnu/usr.bin/lynx/src/chrtrans/makefile.in
new file mode 100644
index 00000000000..c778a3242c0
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/makefile.in
@@ -0,0 +1,146 @@
+#
+# Makefile for the makeuctb and unicode tables.
+#
+# This may not yet work for the general case.
+# Only some dependencies included.
+#
+SHELL = /bin/sh
+
+x = @PROG_EXT@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = $(srcdir)
+
+WWWINC = WWW/Library/Implementation
+SITE_DEFS = # FIXME: set in parent makefile
+
+CC = @CC@
+CPP = @CPP@
+CFLAGS = @CFLAGS@
+CPP_OPTS = @DEFS@ @CPPFLAGS@ \
+ -I../.. \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/$(WWWINC) \
+ $(SITE_DEFS)
+CC_OPTS = $(CPP_OPTS) $(CFLAGS)
+
+#
+# This file contains the font map for the default (hardware) font
+#
+
+FONTMAP_INC = iso01_uni.h# default, if not set by recursive call
+
+### fastdep: $(FONTMAP_INC)
+
+TABLES= \
+ cp1250_uni.h \
+ cp1251_uni.h \
+ cp1252_uni.h \
+ cp1253_uni.h \
+ cp1255_uni.h \
+ cp1256_uni.h \
+ cp1257_uni.h \
+ cp437_uni.h \
+ cp737_uni.h \
+ cp775_uni.h \
+ cp850_uni.h \
+ cp852_uni.h \
+ cp862_uni.h \
+ cp864_uni.h \
+ cp866_uni.h \
+ cp869_uni.h \
+ def7_uni.h \
+ dmcs_uni.h \
+ iso01_uni.h \
+ iso02_uni.h \
+ iso03_uni.h \
+ iso04_uni.h \
+ iso05_uni.h \
+ iso06_uni.h \
+ iso07_uni.h \
+ iso08_uni.h \
+ iso09_uni.h \
+ iso10_uni.h \
+ koi8r_uni.h \
+ mac_uni.h \
+ mnem_suni.h \
+ mnem2_suni.h \
+ next_uni.h \
+ rfc_suni.h \
+ utf8_uni.h \
+ viscii_uni.h
+
+default: $(FONTMAP_INC)
+
+tables: $(TABLES)
+
+makeuctb$x: makeuctb.o
+ $(CC) $(CC_OPTS) -o $@ makeuctb.o
+
+makeuctb.o: $(srcdir)/UCkd.h $(srcdir)/makeuctb.c
+
+.SUFFIXES : .tbl .i
+
+.c.o:
+@RULE_CC@
+ @ECHO_CC@$(CC) $(CC_OPTS) -c $(srcdir)/$*.c
+
+.c.i:
+@RULE_CC@
+ @ECHO_CC@$(CPP) -C $(CPP_OPTS) $*.c >$@
+
+.tbl.h:
+ ./makeuctb $(srcdir)/$*.tbl > $@
+
+# table files listed here once again to get the make dependencies
+# right, in case makeuctb was recompiled.
+cp1250_uni.h: $(srcdir)/cp1250_uni.tbl makeuctb$x
+cp1251_uni.h: $(srcdir)/cp1251_uni.tbl makeuctb$x
+cp1252_uni.h: $(srcdir)/cp1252_uni.tbl makeuctb$x
+cp1253_uni.h: $(srcdir)/cp1253_uni.tbl makeuctb$x
+cp1255_uni.h: $(srcdir)/cp1255_uni.tbl makeuctb$x
+cp1256_uni.h: $(srcdir)/cp1256_uni.tbl makeuctb$x
+cp1257_uni.h: $(srcdir)/cp1257_uni.tbl makeuctb$x
+cp437_uni.h: $(srcdir)/cp437_uni.tbl makeuctb$x
+cp737_uni.h: $(srcdir)/cp737_uni.tbl makeuctb$x
+cp850_uni.h: $(srcdir)/cp850_uni.tbl makeuctb$x
+cp852_uni.h: $(srcdir)/cp852_uni.tbl makeuctb$x
+cp862_uni.h: $(srcdir)/cp862_uni.tbl makeuctb$x
+cp864_uni.h: $(srcdir)/cp864_uni.tbl makeuctb$x
+cp866_uni.h: $(srcdir)/cp866_uni.tbl makeuctb$x
+cp869_uni.h: $(srcdir)/cp869_uni.tbl makeuctb$x
+def7_uni.h: $(srcdir)/def7_uni.tbl makeuctb$x
+dmcs_uni.h: $(srcdir)/dmcs_uni.tbl makeuctb$x
+iso01_uni.h: $(srcdir)/iso01_uni.tbl makeuctb$x
+iso02_uni.h: $(srcdir)/iso02_uni.tbl makeuctb$x
+iso03_uni.h: $(srcdir)/iso03_uni.tbl makeuctb$x
+iso04_uni.h: $(srcdir)/iso04_uni.tbl makeuctb$x
+iso05_uni.h: $(srcdir)/iso05_uni.tbl makeuctb$x
+iso06_uni.h: $(srcdir)/iso06_uni.tbl makeuctb$x
+iso07_uni.h: $(srcdir)/iso07_uni.tbl makeuctb$x
+iso08_uni.h: $(srcdir)/iso08_uni.tbl makeuctb$x
+iso09_uni.h: $(srcdir)/iso09_uni.tbl makeuctb$x
+iso10_uni.h: $(srcdir)/iso10_uni.tbl makeuctb$x
+koi8r_uni.h: $(srcdir)/koi8r_uni.tbl makeuctb$x
+mac_uni.h: $(srcdir)/mac_uni.tbl makeuctb$x
+mnem_suni.h: $(srcdir)/mnem_suni.tbl makeuctb$x
+mnem2_suni.h: $(srcdir)/mnem2_suni.tbl makeuctb$x
+next_uni.h: $(srcdir)/next_uni.tbl makeuctb$x
+rfc_suni.h: $(srcdir)/rfc_suni.tbl makeuctb$x
+utf8_uni.h: $(srcdir)/utf8_uni.tbl makeuctb$x
+viscii_uni.h: $(srcdir)/viscii_uni.tbl makeuctb$x
+
+clean:
+ rm -f makeuctb$x *.o *uni.h *uni2.h
+
+distclean: clean
+ -rm -rf obsolete
+ rm -f core *.bak *.sav *~ *.h_old
+
+depend :
+ makedepend -fmakefile -- $(CPP_OPTS) -- $(C_SRC)
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/gnu/usr.bin/lynx/src/chrtrans/makeuctb.c b/gnu/usr.bin/lynx/src/chrtrans/makeuctb.c
new file mode 100644
index 00000000000..f1417cb71ca
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/makeuctb.c
@@ -0,0 +1,764 @@
+/*
+ * makeuctb.c, derived from conmakehash.c - kw
+ *
+ * Original comments from conmakehash.c:
+ *
+ * Create arrays for initializing the kernel folded tables (using a hash
+ * table turned out to be to limiting...) Unfortunately we can't simply
+ * preinitialize the tables at compile time since kfree() cannot accept
+ * memory not allocated by kmalloc(), and doing our own memory management
+ * just for this seems like massive overkill.
+ *
+ * Copyright (C) 1995 H. Peter Anvin
+ *
+ * This program is a part of the Linux kernel, and may be freely
+ * copied under the terms of the GNU General Public License (GPL),
+ * version 2, or at your option any later version.
+ */
+
+#ifdef NOTDEFINED
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <string.h>
+#include <ctype.h>
+#else
+#include "HTUtils.h"
+#include "tcp.h"
+/*
+ * Don't try to use LYexit().
+ */
+#ifdef exit
+#undef exit
+#endif /* exit */
+#endif /* NODEFINED */
+
+#ifndef TOLOWER
+#define TOLOWER(c) (isupper((unsigned char)c) ? tolower((unsigned char)c) : (c))
+#endif /* !TOLOWER */
+
+#include "UCkd.h"
+#include "UCDefs.h"
+
+#define MAX_FONTLEN 256
+
+/*
+ * We don't deal with UCS4 here. - KW
+ */
+typedef u16 unicode;
+
+PRIVATE void usage ARGS1(
+ char *, argv0)
+{
+ fprintf(stderr, "Usage: \n");
+ fprintf(stderr,
+ " %s chartable [charsetmimename] [charsetdisplayname]\n",
+ argv0);
+ fprintf(stderr,
+ "Utility to convert .tbl into .h files for Lynx compilation.\n");
+ exit(EX_USAGE);
+}
+
+/* copied from HTString.c, not everybody has strncasecmp */
+PUBLIC int strncasecomp ARGS3(
+ CONST char*, a,
+ CONST char *, b,
+ int, n)
+{
+ CONST char *p = a;
+ CONST char *q = b;
+
+ for (p = a, q = b; ; p++, q++) {
+ int diff;
+ if (p == (a+n))
+ return 0; /* Match up to n characters */
+ if (!(*p && *q))
+ return (*p - *q);
+ diff = TOLOWER(*p) - TOLOWER(*q);
+ if (diff)
+ return diff;
+ }
+ /*NOTREACHED*/
+}
+
+PRIVATE int getunicode ARGS1(
+ char **, p0)
+{
+ char *p = *p0;
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ if (*p == '-') {
+ return -2;
+ } else if (*p != 'U' || p[1] != '+' ||
+ !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) ||
+ !isxdigit(p[5]) || isxdigit(p[6])) {
+ return -1;
+ }
+ *p0 = p+6;
+ return strtol((p + 2), 0, 16);
+}
+
+/*
+ * Massive overkill, but who cares?
+ */
+unicode unitable[MAX_FONTLEN][255];
+int unicount[MAX_FONTLEN];
+
+struct unimapdesc_str themap_str = {0, NULL};
+
+char *tblname;
+
+PRIVATE int RawOrEnc = 0;
+PRIVATE int Raw_found = 0; /* whether explicit R directive found */
+
+PRIVATE void addpair_str ARGS2(
+ char *, str,
+ int, un)
+{
+ int i;
+
+ if (un <= 0xfffe) {
+ if (!themap_str.entry_ct) {
+ /*
+ * Initialize the map for replacement strings.
+ */
+ themap_str.entries =
+ (struct unipair_str *) malloc (2000 * sizeof (struct unipair_str));
+ if (!themap_str.entries) {
+ fprintf(stderr,
+ "%s: Out of memory\n", tblname);
+ exit(EX_DATAERR);
+ }
+ } else {
+ /*
+ * Check that it isn't a duplicate.
+ */
+ for (i = 0 ; i < themap_str.entry_ct; i++) {
+ if (themap_str.entries[i].unicode == un ) {
+ themap_str.entries[i].replace_str = str;
+ return;
+ }
+ }
+ }
+
+ /*
+ * Add to list.
+ */
+ if (themap_str.entry_ct > 1999) {
+ fprintf(stderr,
+ "ERROR: Only 2000 unicode replacement strings permitted!\n");
+ exit(EX_DATAERR);
+ }
+ themap_str.entries[themap_str.entry_ct].unicode = un;
+ themap_str.entries[themap_str.entry_ct].replace_str = str;
+ themap_str.entry_ct++;
+ }
+ /* otherwise: ignore */
+}
+
+PRIVATE void addpair ARGS2(
+ int, fp,
+ int, un)
+{
+ int i;
+
+ if (!Raw_found) { /* enc not (yet) explicitly given with 'R' */
+ if (fp >= 128) {
+ if (RawOrEnc != UCT_ENC_8BIT && RawOrEnc <= UCT_ENC_8859) {
+ if (fp < 160) { /* cannot be 8859 */
+ RawOrEnc = UCT_ENC_8BIT;
+ } else if (fp != 160 && fp != 173) {
+ RawOrEnc = UCT_ENC_8859; /* hmmm.. more tests needed? */
+ } else if (unicount[fp] == 0 && fp != un) {
+ /* first unicode for fp doesn't map to itself */
+ RawOrEnc = UCT_ENC_8BIT;
+ } else {
+ RawOrEnc = UCT_ENC_8859; /* hmmm.. more tests needed? */
+ }
+ }
+ }
+ }
+ if (un <= 0xfffe) {
+ /*
+ * Check that it isn't a duplicate.
+ */
+ for (i = 0; i < unicount[fp]; i++) {
+ if (unitable[fp][i] == un) {
+ return;
+ }
+ }
+
+ /*
+ * Add to list.
+ */
+ if (unicount[fp] > 254) {
+ fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n");
+ exit(EX_DATAERR);
+ }
+ unitable[fp][unicount[fp]] = un;
+ unicount[fp]++;
+ }
+ /* otherwise: ignore */
+}
+
+char this_MIMEcharset[UC_MAXLEN_MIMECSNAME +1];
+char this_LYNXcharset[UC_MAXLEN_LYNXCSNAME +1];
+char id_append[UC_MAXLEN_ID_APPEND +1] = "_";
+int this_isDefaultMap = -1;
+int useDefaultMap = 1;
+int lowest_eight = 999;
+
+PUBLIC int main ARGS2(
+ int, argc,
+ char **, argv)
+{
+ FILE *ctbl;
+ char buffer[65536];
+ int fontlen;
+ int i, nuni, nent;
+ int fp0, fp1, un0, un1;
+ char *p, *p1;
+ char *tbuf, ch;
+
+ if (argc < 2 || argc > 4) {
+ usage(argv[0]);
+ }
+
+ if (!strcmp(argv[1], "-")) {
+ ctbl = stdin;
+ tblname = "stdin";
+ } else {
+ ctbl = fopen(tblname = argv[1], "r");
+ if (!ctbl) {
+ perror(tblname);
+ exit(EX_NOINPUT);
+ }
+ }
+
+ /*
+ * For now we assume the default font is always 256 characters.
+ */
+ fontlen = 256;
+
+ /*
+ * Initialize table.
+ */
+ for (i = 0; i < fontlen; i++) {
+ unicount[i] = 0;
+ }
+
+ /*
+ * Now we comes to the tricky part. Parse the input table.
+ */
+ while (fgets(buffer, sizeof(buffer), ctbl) != NULL) {
+ if ((p = strchr(buffer, '\n')) != NULL) {
+ *p = '\0';
+ } else {
+ fprintf(stderr,
+ "%s: Warning: line too long or incomplete.\n",
+ tblname);
+ }
+
+ /*
+ * Syntax accepted:
+ * <fontpos> <unicode> <unicode> ...
+ * <fontpos> <unicode range> <unicode range> ...
+ * <fontpos> idem
+ * <range> idem
+ * <range> <unicode range>
+ * <unicode> :<replace>
+ * <unicode range> :<replace>
+ * <unicode> "<C replace>"
+ * <unicode range> "<C replace>"
+ *
+ * where <range> ::= <fontpos>-<fontpos>
+ * and <unicode> ::= U+<h><h><h><h>
+ * and <h> ::= <hexadecimal digit>
+ * and <replace> any string not containing '\n' or '\0'
+ * and <C replace> any string with C backslash escapes.
+ */
+ p = buffer;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (!(*p) || *p == '#') {
+ /*
+ * Skip comment or blank line.
+ */
+ continue;
+ }
+
+ switch (*p) {
+ /*
+ * Raw Unicode? I.e. needs some special
+ * processing. One digit code.
+ */
+ case 'R':
+ if (p[1] == 'a' || p[1] == 'A') {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strncasecomp(p, "RawOrEnc", 8)) {
+ p += 8;
+ }
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ RawOrEnc = strtol(p,0,10);
+ Raw_found = 1;
+ continue;
+
+ /*
+ * Is this the default table?
+ */
+ case 'D':
+ if (p[1] == 'e' || p[1] == 'E') {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strncasecomp(p, "Default", 7)) {
+ p += 7;
+ }
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ this_isDefaultMap = (*p == '1' || TOLOWER(*p) == 'y');
+ continue;
+
+ /*
+ * Is this the default table?
+ */
+ case 'F':
+ if (p[1] == 'a' || p[1] == 'A') {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strncasecomp(p, "FallBack", 8)) {
+ p += 8;
+ }
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ useDefaultMap = (*p == '1' || tolower(*p) == 'y');
+ continue;
+
+ case 'M':
+ if (p[1] == 'i' || p[1] == 'I') {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strncasecomp(p, "MIMEName", 8)) {
+ p += 8;
+ }
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ sscanf(p,"%40s",this_MIMEcharset);
+ continue;
+
+ /*
+ * Display charset name for options screen.
+ */
+ case 'O':
+ if (p[1] == 'p' || p[1] == 'P') {
+ buffer[sizeof(buffer) - 1] = '\0';
+ if (!strncasecomp(p, "OptionName", 10)) {
+ p += 10;
+ }
+ }
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ for (i = 0; *p && i < UC_MAXLEN_LYNXCSNAME; p++, i++) {
+ this_LYNXcharset[i] = *p;
+ }
+ this_LYNXcharset[i] = '\0';
+ continue;
+ }
+
+ if (*p == 'U') {
+ un0 = getunicode(&p);
+ if (un0 < 0) {
+ fprintf(stderr, "Bad input line: %s\n", buffer);
+ exit(EX_DATAERR);
+ fprintf(stderr,
+ "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
+ tblname, fp0, fp1);
+ exit(EX_DATAERR);
+ }
+ un1 = un0;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p == '-') {
+ p++;
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ un1 = getunicode(&p);
+ if (un1 < 0 || un1 < un0) {
+ fprintf(stderr,
+ "%s: Bad Unicode range U+%x-U+%x\n",
+ tblname, un0, un1);
+ fprintf(stderr, "Bad input line: %s\n", buffer);
+ exit(EX_DATAERR);
+ }
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ }
+
+ if (*p != ':' && *p != '"') {
+ fprintf(stderr, "No ':' or '\"' where expected: %s\n",
+ buffer);
+ continue;
+ }
+
+ tbuf = (char *)malloc(4*strlen(p));
+
+ if (!(p1 = tbuf)) {
+ fprintf(stderr, "%s: Out of memory\n", tblname);
+ exit(EX_DATAERR);
+ }
+ if (*p == '"') {
+ /*
+ * Handle "<C replace>".
+ * Copy chars verbatim until first '"' not \-escaped or
+ * end of buffer.
+ */
+ int escaped = 0;
+ for (ch = *(++p); (ch = *p) != '\0'; p++) {
+ if (escaped) {
+ escaped = 0;
+ } else if (ch == '"') {
+ break;
+ } else if (ch == '\\') {
+ escaped = 1;
+ }
+ *p1++ = ch;
+ }
+ if (escaped || ch != '"') {
+ fprintf(stderr, "Warning: String not terminated: %s\n",
+ buffer);
+ if (escaped)
+ *p1++ = '\n';
+ }
+ } else {
+ /*
+ * We had ':'.
+ */
+ for (ch = *(++p); (ch = *p) != '\0'; p++, p1++) {
+ if ((unsigned char)ch < 32 || ch == '\\' || ch == '\"' ||
+ (unsigned char)ch >= 127) {
+ sprintf(p1, "\\%.3o", (unsigned char)ch);
+#ifdef NOTDEFINED
+ fprintf(stderr, "%s\n", tbuf);
+#endif /* NOTDEFINED */
+ p1 += 3;
+ } else {
+ *p1 = ch;
+ }
+ }
+ }
+ *p1 = '\0';
+ for (i = un0; i <= un1; i++) {
+#ifdef NOTDEFINED
+ printf("U+0x%x:%s\n", i, tbuf); */
+#endif /* NOTDEFINED */
+ addpair_str(tbuf,i);
+ }
+ continue;
+ }
+
+ /*
+ * Input line (after skipping spaces) doesn't start with one
+ * of the specially recognized characters, so try to interpret
+ * it as starting with a fontpos.
+ */
+ fp0 = strtol(p, &p1, 0);
+ if (p1 == p) {
+ fprintf(stderr, "Bad input line: %s\n", buffer);
+ exit(EX_DATAERR);
+ }
+ p = p1;
+
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p == '-') {
+ p++;
+ fp1 = strtol(p, &p1, 0);
+ if (p1 == p) {
+ fprintf(stderr, "Bad input line: %s\n", buffer);
+ exit(EX_DATAERR);
+ }
+ p = p1;
+ } else {
+ fp1 = 0;
+ }
+
+ if (fp0 < 0 || fp0 >= fontlen) {
+ fprintf(stderr,
+ "%s: Glyph number (0x%x) larger than font length\n",
+ tblname, fp0);
+ exit(EX_DATAERR);
+ }
+ if (fp1 && (fp1 < fp0 || fp1 >= fontlen)) {
+ fprintf(stderr,
+ "%s: Bad end of range (0x%x)\n",
+ tblname, fp1);
+ exit(EX_DATAERR);
+ }
+
+ if (fp1) {
+ /*
+ * We have a range; expect the word "idem"
+ * or a Unicode range of the same length.
+ */
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (!strncmp(p, "idem", 4)) {
+ for (i = fp0; i <= fp1; i++) {
+ addpair(i,i);
+ }
+ p += 4;
+ } else {
+ un0 = getunicode(&p);
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p != '-') {
+ fprintf(stderr,
+ "%s: Corresponding to a range of font positions,",
+ tblname);
+ fprintf(stderr,
+ " there should be a Unicode range.\n");
+ exit(EX_DATAERR);
+ }
+ p++;
+ un1 = getunicode(&p);
+ if (un0 < 0 || un1 < 0) {
+ fprintf(stderr,
+ "%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n",
+ tblname, fp0, fp1);
+ exit(EX_DATAERR);
+ }
+ if (un1 - un0 != fp1 - fp0) {
+ fprintf(stderr,
+ "%s: Unicode range U+%x-U+%x not of the same length",
+ tblname, un0, un1);
+ fprintf(stderr,
+ " as font position range 0x%x-0x%x\n",
+ fp0, fp1);
+ exit(EX_DATAERR);
+ }
+ for (i = fp0; i <= fp1; i++) {
+ addpair(i,un0-fp0+i);
+ }
+ }
+ } else {
+ /*
+ * No range; expect a list of unicode values
+ * or unicode ranges for a single font position,
+ * or the word "idem"
+ */
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (!strncmp(p, "idem", 4)) {
+ addpair(fp0,fp0);
+ p += 4;
+ }
+ while ((un0 = getunicode(&p)) >= 0) {
+ addpair(fp0, un0);
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p == '-') {
+ p++;
+ un1 = getunicode(&p);
+ if (un1 < un0) {
+ fprintf(stderr,
+ "%s: Bad Unicode range 0x%x-0x%x\n",
+ tblname, un0, un1);
+ exit(EX_DATAERR);
+ }
+ for (un0++; un0 <= un1; un0++) {
+ addpair(fp0, un0);
+ }
+ }
+ }
+ }
+ while (*p == ' ' || *p == '\t') {
+ p++;
+ }
+ if (*p && *p != '#') {
+ fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p);
+ }
+ }
+
+ /*
+ * Okay, we hit EOF, now output tables.
+ */
+ fclose(ctbl);
+
+
+ /*
+ * Compute total size of Unicode list.
+ */
+ nuni = 0;
+ for (i = 0 ; i < fontlen ; i++) {
+ nuni += unicount[i];
+ }
+
+ if (argc >= 3) {
+ strncpy(this_MIMEcharset,argv[2],UC_MAXLEN_MIMECSNAME);
+ } else if (this_MIMEcharset[0] == '\0') {
+ strncpy(this_MIMEcharset,tblname,UC_MAXLEN_MIMECSNAME);
+ if ((p = strchr(this_MIMEcharset,'.')) != 0) {
+ *p = '\0';
+ }
+ }
+ for (p = this_MIMEcharset; *p; p++) {
+ *p = TOLOWER(*p);
+ }
+ if (argc >= 4) {
+ strncpy(this_LYNXcharset,argv[3],UC_MAXLEN_LYNXCSNAME);
+ } else if (this_LYNXcharset[0] == '\0') {
+ strncpy(this_LYNXcharset,this_MIMEcharset,UC_MAXLEN_LYNXCSNAME);
+ }
+ if ((i = strlen(this_LYNXcharset)) < UC_LEN_LYNXCSNAME) {
+ for (; i < UC_LEN_LYNXCSNAME; i++) {
+ this_LYNXcharset[i] = ' ';
+ }
+ this_LYNXcharset[i] = '\0';
+ }
+#ifdef NOTDEFINED
+ fprintf(stderr,"this_MIMEcharset: %s.\n",this_MIMEcharset);
+ fprintf(stderr,"this_LYNXcharset: %s.\n",this_LYNXcharset);
+#endif /* NOTDEFINED */
+ if (this_isDefaultMap == -1) {
+ this_isDefaultMap = !strncmp(this_MIMEcharset,"iso-8859-1", 10);
+ }
+ fprintf(stderr,
+ "makeuctb: %s: %stranslation map",
+ this_MIMEcharset, (this_isDefaultMap ? "default " : ""));
+ if (this_isDefaultMap == 1) {
+ *id_append = '\0';
+ } else {
+ for (i = 0, p = this_MIMEcharset;
+ *p && (i < UC_MAXLEN_ID_APPEND-1);
+ p++, i++) {
+ id_append[i+1] = isalnum(*p) ? *p : '_';
+ }
+ }
+ id_append[i+1] = '\0';
+ fprintf(stderr, " (%s).\n", id_append);
+
+ printf("\
+/*\n\
+ * uni_hash.tbl\n\
+ *\n\
+ * Do not edit this file; it was automatically generated by\n\
+ *\n\
+ * %s %s\n\
+ *\n\
+ */\n\
+\n\
+static u8 dfont_unicount%s[%d] = \n\
+{\n\t", argv[0], argv[1], id_append, fontlen);
+
+ for (i = 0; i < fontlen; i++) {
+ if (i >= 128 && unicount[i] > 0 && i < lowest_eight) {
+ lowest_eight = i;
+ }
+ printf("%3d", unicount[i]);
+ if (i == (fontlen - 1)) {
+ printf("\n};\n");
+ } else if ((i % 8) == 7) {
+ printf(",\n\t");
+ } else {
+ printf(", ");
+ }
+ }
+
+ /*
+ * If lowest_eightbit is anything else but 999,
+ * this can't be 7-bit only.
+ */
+ if (lowest_eight != 999 && !RawOrEnc) {
+ RawOrEnc = UCT_ENC_8BIT;
+ }
+
+ if (nuni) {
+ printf("\nstatic u16 dfont_unitable%s[%d] = \n{\n\t",
+ id_append, nuni);
+ } else {
+ printf("\nstatic u16 dfont_unitable%s[1]; /* dummy */\n", id_append);
+ }
+
+ fp0 = 0;
+ nent = 0;
+ for (i = 0; i < nuni; i++) {
+ while (nent >= unicount[fp0]) {
+ fp0++;
+ nent = 0;
+ }
+ printf("0x%04x", unitable[fp0][nent++]);
+ if (i == (nuni - 1)) {
+ printf("\n};\n");
+ } else if ((i % 8) == 7) {
+ printf(",\n\t");
+ } else {
+ printf(", ");
+ }
+ }
+
+ if (themap_str.entry_ct) {
+ printf("\n\
+static struct unipair_str repl_map%s[%d] = \n\
+{\n\t", id_append, themap_str.entry_ct);
+ } else {
+ printf("\n\
+/* static struct unipair_str repl_map%s[]; */\n", id_append);
+ }
+
+ for (i = 0; i < themap_str.entry_ct; i++) {
+ printf("{0x%x,\"%s\"}",
+ themap_str.entries[i].unicode,
+ themap_str.entries[i].replace_str);
+ if (i == (themap_str.entry_ct - 1)) {
+ printf("\n};\n");
+ } else if ((i % 4) == 3) {
+ printf(",\n\t");
+ } else {
+ printf(", ");
+ }
+ }
+ if (themap_str.entry_ct) {
+ printf("\n\
+static struct unimapdesc_str dfont_replacedesc%s = {%d,repl_map%s,",
+id_append, themap_str.entry_ct, id_append);
+ } else {
+ printf("\n\
+static struct unimapdesc_str dfont_replacedesc%s = {0,NULL,",id_append);
+ }
+ printf("%d,%d};\n",
+ this_isDefaultMap ? 1 : 0,
+ (useDefaultMap && !this_isDefaultMap) ? 1 : 0
+ );
+
+
+ printf("#define UC_CHARSET_SETUP%s UC_Charset_Setup(\
+\"%s\",\\\n\"%s\",\\\n\
+dfont_unicount%s,dfont_unitable%s,%d,\\\n\
+dfont_replacedesc%s,%d,%d)\n",
+id_append, this_MIMEcharset, this_LYNXcharset,
+id_append, id_append, nuni, id_append, lowest_eight, RawOrEnc);
+
+ exit(EX_OK);
+}
diff --git a/gnu/usr.bin/lynx/src/chrtrans/mnem2_suni.tbl b/gnu/usr.bin/lynx/src/chrtrans/mnem2_suni.tbl
new file mode 100644
index 00000000000..cdcd7628666
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/mnem2_suni.tbl
@@ -0,0 +1,1865 @@
+#The MIME name of this charset.
+# (this file was renamed from mnemonic_suni.tbl)
+M mnemonic
+
+#Name as a Display Charset (used on Options screen)
+O RFC 1345 Mnemonic
+
+# Don't fall back to default table for unicode -> 8bit
+Fallback NO
+
+# U+0020:&SP
+U+0021:!
+U+0022:"
+U+0023:&Nb
+U+0024:&DO
+U+0025:%
+U+0026:&&
+U+0027:'
+U+0028:(
+U+0029:)
+U+002a:*
+U+002b:+
+U+002c:,
+U+002d:-
+U+002e:.
+U+002f:/
+U+0030:0
+U+0031:1
+U+0032:2
+U+0033:3
+U+0034:4
+U+0035:5
+U+0036:6
+U+0037:7
+U+0038:8
+U+0039:9
+U+003a::
+U+003b:;
+U+003c:<
+U+003d:=
+U+003e:>
+U+003f:?
+U+0040:&At
+U+0041:A
+U+0042:B
+U+0043:C
+U+0044:D
+U+0045:E
+U+0046:F
+U+0047:G
+U+0048:H
+U+0049:I
+U+004a:J
+U+004b:K
+U+004c:L
+U+004d:M
+U+004e:N
+U+004f:O
+U+0050:P
+U+0051:Q
+U+0052:R
+U+0053:S
+U+0054:T
+U+0055:U
+U+0056:V
+U+0057:W
+U+0058:X
+U+0059:Y
+U+005a:Z
+U+005b:&<(
+U+005c:&//
+U+005d:&)>
+U+005e:&'>
+U+005f:_
+U+0060:&'!
+U+0061:a
+U+0062:b
+U+0063:c
+U+0064:d
+U+0065:e
+U+0066:f
+U+0067:g
+U+0068:h
+U+0069:i
+U+006a:j
+U+006b:k
+U+006c:l
+U+006d:m
+U+006e:n
+U+006f:o
+U+0070:p
+U+0071:q
+U+0072:r
+U+0073:s
+U+0074:t
+U+0075:u
+U+0076:v
+U+0077:w
+U+0078:x
+U+0079:y
+U+007a:z
+U+007b:&(!
+U+007c:&!!
+U+007d:&!)
+U+007e:&'?
+U+00a0:&NS
+U+00a1:&!I
+U+00a2:&Ct
+U+00a3:&Pd
+U+00a4:&Cu
+U+00a5:&Ye
+U+00a6:&BB
+U+00a7:&SE
+U+00a8:&':
+U+00a9:&Co
+U+00aa:&-a
+U+00ab:&<<
+U+00ac:&NO
+U+00ad:&--
+U+00ae:&Rg
+U+00af:&'m
+U+00b0:&DG
+U+00b1:&+-
+U+00b2:&2S
+U+00b3:&3S
+U+00b4:&''
+U+00b5:&My
+U+00b6:&PI
+U+00b7:&.M
+U+00b8:&',
+U+00b9:&1S
+U+00ba:&-o
+U+00bb:&>>
+U+00bc:&14
+U+00bd:&12
+U+00be:&34
+U+00bf:&?I
+U+00c0:&A!
+U+00c1:&A'
+U+00c2:&A>
+U+00c3:&A?
+U+00c4:&A:
+U+00c5:&AA
+U+00c6:&AE
+U+00c7:&C,
+U+00c8:&E!
+U+00c9:&E'
+U+00ca:&E>
+U+00cb:&E:
+U+00cc:&I!
+U+00cd:&I'
+U+00ce:&I>
+U+00cf:&I:
+U+00d0:&D-
+U+00d1:&N?
+U+00d2:&O!
+U+00d3:&O'
+U+00d4:&O>
+U+00d5:&O?
+U+00d6:&O:
+U+00d7:&*X
+U+00d8:&O/
+U+00d9:&U!
+U+00da:&U'
+U+00db:&U>
+U+00dc:&U:
+U+00dd:&Y'
+U+00de:&TH
+U+00df:&ss
+U+00e0:&a!
+U+00e1:&a'
+U+00e2:&a>
+U+00e3:&a?
+U+00e4:&a:
+U+00e5:&aa
+U+00e6:&ae
+U+00e7:&c,
+U+00e8:&e!
+U+00e9:&e'
+U+00ea:&e>
+U+00eb:&e:
+U+00ec:&i!
+U+00ed:&i'
+U+00ee:&i>
+U+00ef:&i:
+U+00f0:&d-
+U+00f1:&n?
+U+00f2:&o!
+U+00f3:&o'
+U+00f4:&o>
+U+00f5:&o?
+U+00f6:&o:
+U+00f7:&-:
+U+00f8:&o/
+U+00f9:&u!
+U+00fa:&u'
+U+00fb:&u>
+U+00fc:&u:
+U+00fd:&y'
+U+00fe:&th
+U+00ff:&y:
+U+0100:&A-
+U+0101:&a-
+U+0102:&A(
+U+0103:&a(
+U+0104:&A;
+U+0105:&a;
+U+0106:&C'
+U+0107:&c'
+U+0108:&C>
+U+0109:&c>
+U+010a:&C.
+U+010b:&c.
+U+010c:&C<
+U+010d:&c<
+U+010e:&D<
+U+010f:&d<
+U+0110:&D/
+U+0111:&d/
+U+0112:&E-
+U+0113:&e-
+U+0114:&E(
+U+0115:&e(
+U+0116:&E.
+U+0117:&e.
+U+0118:&E;
+U+0119:&e;
+U+011a:&E<
+U+011b:&e<
+U+011c:&G>
+U+011d:&g>
+U+011e:&G(
+U+011f:&g(
+U+0120:&G.
+U+0121:&g.
+U+0122:&G,
+U+0123:&g,
+U+0124:&H>
+U+0125:&h>
+U+0126:&H/
+U+0127:&h/
+U+0128:&I?
+U+0129:&i?
+U+012a:&I-
+U+012b:&i-
+U+012c:&I(
+U+012d:&i(
+U+012e:&I;
+U+012f:&i;
+U+0130:&I.
+U+0131:&i.
+U+0132:&IJ
+U+0133:&ij
+U+0134:&J>
+U+0135:&j>
+U+0136:&K,
+U+0137:&k,
+U+0138:&kk
+U+0139:&L'
+U+013a:&l'
+U+013b:&L,
+U+013c:&l,
+U+013d:&L<
+U+013e:&l<
+U+013f:&L.
+U+0140:&l.
+U+0141:&L/
+U+0142:&l/
+U+0143:&N'
+U+0144:&n'
+U+0145:&N,
+U+0146:&n,
+U+0147:&N<
+U+0148:&n<
+U+0149:&'n
+U+014a:&NG
+U+014b:&ng
+U+014c:&O-
+U+014d:&o-
+U+014e:&O(
+U+014f:&o(
+U+0150:&O"
+U+0151:&o"
+U+0152:&OE
+U+0153:&oe
+U+0154:&R'
+U+0155:&r'
+U+0156:&R,
+U+0157:&r,
+U+0158:&R<
+U+0159:&r<
+U+015a:&S'
+U+015b:&s'
+U+015c:&S>
+U+015d:&s>
+U+015e:&S,
+U+015f:&s,
+U+0160:&S<
+U+0161:&s<
+U+0162:&T,
+U+0163:&t,
+U+0164:&T<
+U+0165:&t<
+U+0166:&T/
+U+0167:&t/
+U+0168:&U?
+U+0169:&u?
+U+016a:&U-
+U+016b:&u-
+U+016c:&U(
+U+016d:&u(
+U+016e:&U0
+U+016f:&u0
+U+0170:&U"
+U+0171:&u"
+U+0172:&U;
+U+0173:&u;
+U+0174:&W>
+U+0175:&w>
+U+0176:&Y>
+U+0177:&y>
+U+0178:&Y:
+U+0179:&Z'
+U+017a:&z'
+U+017b:&Z.
+U+017c:&z.
+U+017d:&Z<
+U+017e:&z<
+U+01a0:&O9
+U+01a1:&o9
+U+01a2:&OI
+U+01a3:&oi
+U+01a6:&yr
+U+01af:&U9
+U+01b0:&u9
+U+01b5:&Z/
+U+01b6:&z/
+U+01b7:&ED
+U+01cd:&A<
+U+01ce:&a<
+U+01cf:&I<
+U+01d0:&i<
+U+01d1:&O<
+U+01d2:&o<
+U+01d3:&U<
+U+01d4:&u<
+U+01d5:&_U:-_
+U+01d6:&_u:-_
+U+01d7:&_U:'_
+U+01d8:&_u:'_
+U+01d9:&_U:<_
+U+01da:&_u:<_
+U+01db:&_U:!_
+U+01dc:&_u:!_
+U+01de:&A1
+U+01df:&a1
+U+01e0:&A7
+U+01e1:&a7
+U+01e2:&A3
+U+01e3:&a3
+U+01e4:&G/
+U+01e5:&g/
+U+01e6:&G<
+U+01e7:&g<
+U+01e8:&K<
+U+01e9:&k<
+U+01ea:&O;
+U+01eb:&o;
+U+01ec:&O1
+U+01ed:&o1
+U+01ee:&EZ
+U+01ef:&ez
+U+01f0:&j<
+U+01f4:&G'
+U+01f5:&g'
+U+01fa:&_AA'_
+U+01fb:&_aa'_
+U+01fc:&_AE'_
+U+01fd:&_ae'_
+U+01fe:&_O/'_
+U+01ff:&_o/'_
+U+02bf:&;S
+U+02c7:&'<
+U+02d8:&'(
+U+02d9:&'.
+U+02da:&'0
+U+02db:&';
+U+02dd:&'"
+U+0386:&A%
+U+0388:&E%
+U+0389:&Y%
+U+038a:&I%
+U+038c:&O%
+U+038e:&U%
+U+038f:&W%
+U+0390:&i3
+U+0391:&A*
+U+0392:&B*
+U+0393:&G*
+U+0394:&D*
+U+0395:&E*
+U+0396:&Z*
+U+0397:&Y*
+U+0398:&H*
+U+0399:&I*
+U+039a:&K*
+U+039b:&L*
+U+039c:&M*
+U+039d:&N*
+U+039e:&C*
+U+039f:&O*
+U+03a0:&P*
+U+03a1:&R*
+U+03a3:&S*
+U+03a4:&T*
+U+03a5:&U*
+U+03a6:&F*
+U+03a7:&X*
+U+03a8:&Q*
+U+03a9:&W*
+U+03aa:&J*
+U+03ab:&V*
+U+03ac:&a%
+U+03ad:&e%
+U+03ae:&y%
+U+03af:&i%
+U+03b0:&u3
+U+03b1:&a*
+U+03b2:&b*
+U+03b3:&g*
+U+03b4:&d*
+U+03b5:&e*
+U+03b6:&z*
+U+03b7:&y*
+U+03b8:&h*
+U+03b9:&i*
+U+03ba:&k*
+U+03bb:&l*
+U+03bc:&m*
+U+03bd:&n*
+U+03be:&c*
+U+03bf:&o*
+U+03c0:&p*
+U+03c1:&r*
+U+03c2:&*s
+U+03c3:&s*
+U+03c4:&t*
+U+03c5:&u*
+U+03c6:&f*
+U+03c7:&x*
+U+03c8:&q*
+U+03c9:&w*
+U+03ca:&j*
+U+03cb:&v*
+U+03cc:&o%
+U+03cd:&u%
+U+03ce:&w%
+U+03d8:&'G
+U+03d9:&,G
+U+03da:&T3
+U+03db:&t3
+U+03dc:&M3
+U+03dd:&m3
+U+03de:&K3
+U+03df:&k3
+U+03e0:&P3
+U+03e1:&p3
+U+03f4:&'%
+U+03f5:&j3
+U+0401:&IO
+U+0402:&D%
+U+0403:&G%
+U+0404:&IE
+U+0405:&DS
+U+0406:&II
+U+0407:&YI
+U+0408:&J%
+U+0409:&LJ
+U+040a:&NJ
+U+040b:&Ts
+U+040c:&KJ
+U+040e:&V%
+U+040f:&DZ
+U+0410:&A=
+U+0411:&B=
+U+0412:&V=
+U+0413:&G=
+U+0414:&D=
+U+0415:&E=
+U+0416:&Z%
+U+0417:&Z=
+U+0418:&I=
+U+0419:&J=
+U+041a:&K=
+U+041b:&L=
+U+041c:&M=
+U+041d:&N=
+U+041e:&O=
+U+041f:&P=
+U+0420:&R=
+U+0421:&S=
+U+0422:&T=
+U+0423:&U=
+U+0424:&F=
+U+0425:&H=
+U+0426:&C=
+U+0427:&C%
+U+0428:&S%
+U+0429:&Sc
+U+042a:&="
+U+042b:&Y=
+U+042c:&%"
+U+042d:&JE
+U+042e:&JU
+U+042f:&JA
+U+0430:&a=
+U+0431:&b=
+U+0432:&v=
+U+0433:&g=
+U+0434:&d=
+U+0435:&e=
+U+0436:&z%
+U+0437:&z=
+U+0438:&i=
+U+0439:&j=
+U+043a:&k=
+U+043b:&l=
+U+043c:&m=
+U+043d:&n=
+U+043e:&o=
+U+043f:&p=
+U+0440:&r=
+U+0441:&s=
+U+0442:&t=
+U+0443:&u=
+U+0444:&f=
+U+0445:&h=
+U+0446:&c=
+U+0447:&c%
+U+0448:&s%
+U+0449:&sc
+U+044a:&='
+U+044b:&y=
+U+044c:&%'
+U+044d:&je
+U+044e:&ju
+U+044f:&ja
+U+0451:&io
+U+0452:&d%
+U+0453:&g%
+U+0454:&ie
+U+0455:&ds
+U+0456:&ii
+U+0457:&yi
+U+0458:&j%
+U+0459:&lj
+U+045a:&nj
+U+045b:&ts
+U+045c:&kj
+U+045e:&v%
+U+045f:&dz
+U+0462:&Y3
+U+0463:&y3
+U+046a:&O3
+U+046b:&o3
+U+0472:&F3
+U+0473:&f3
+U+0474:&V3
+U+0475:&v3
+U+0480:&C3
+U+0481:&c3
+U+0490:&G3
+U+0491:&g3
+U+05d0:&A+
+U+05d1:&B+
+U+05d2:&G+
+U+05d3:&D+
+U+05d4:&H+
+U+05d5:&W+
+U+05d6:&Z+
+U+05d7:&X+
+U+05d8:&Tj
+U+05d9:&J+
+U+05da:&K%
+U+05db:&K+
+U+05dc:&L+
+U+05dd:&M%
+U+05de:&M+
+U+05df:&N%
+U+05e0:&N+
+U+05e1:&S+
+U+05e2:&E+
+U+05e3:&P%
+U+05e4:&P+
+U+05e5:&Zj
+U+05e6:&ZJ
+U+05e7:&Q+
+U+05e8:&R+
+U+05e9:&Sh
+U+05ea:&T+
+U+060c:&,+
+U+061b:&;+
+U+061f:&?+
+U+0621:&H'
+U+0622:&aM
+U+0623:&aH
+U+0624:&wH
+U+0625:&ah
+U+0626:&yH
+U+0627:&a+
+U+0628:&b+
+U+0629:&tm
+U+062a:&t+
+U+062b:&tk
+U+062c:&g+
+U+062d:&hk
+U+062e:&x+
+U+062f:&d+
+U+0630:&dk
+U+0631:&r+
+U+0632:&z+
+U+0633:&s+
+U+0634:&sn
+U+0635:&c+
+U+0636:&dd
+U+0637:&tj
+U+0638:&zH
+U+0639:&e+
+U+063a:&i+
+U+0640:&++
+U+0641:&f+
+U+0642:&q+
+U+0643:&k+
+U+0644:&l+
+U+0645:&m+
+U+0646:&n+
+U+0647:&h+
+U+0648:&w+
+U+0649:&j+
+U+064a:&y+
+U+064b:&:+
+U+064c:&"+
+U+064d:&=+
+U+064e:&/+
+U+064f:&'+
+U+0650:&1+
+U+0651:&3+
+U+0652:&0+
+U+0670:&aS
+U+067e:&p+
+U+06a4:&v+
+U+06af:&gf
+U+06f0:&0a
+U+06f1:&1a
+U+06f2:&2a
+U+06f3:&3a
+U+06f4:&4a
+U+06f5:&5a
+U+06f6:&6a
+U+06f7:&7a
+U+06f8:&8a
+U+06f9:&9a
+U+1e00:&_A-0_
+U+1e01:&_a-0_
+U+1e02:&B.
+U+1e03:&b.
+U+1e04:&_B-._
+U+1e05:&_b-._
+U+1e06:&B_
+U+1e07:&b_
+U+1e08:&_C,'_
+U+1e09:&_c,'_
+U+1e0a:&D.
+U+1e0b:&d.
+U+1e0c:&_D-._
+U+1e0d:&_d-._
+U+1e0e:&D_
+U+1e0f:&d_
+U+1e10:&D,
+U+1e11:&d,
+U+1e12:&_D->_
+U+1e13:&_d->_
+U+1e14:&_E-!_
+U+1e15:&_e-!_
+U+1e16:&_E-'_
+U+1e17:&_e-'_
+U+1e18:&_E->_
+U+1e19:&_e->_
+U+1e1a:&_E-?_
+U+1e1b:&_e-?_
+U+1e1c:&_E,(_
+U+1e1d:&_e,(_
+U+1e1e:&F.
+U+1e1f:&f.
+U+1e20:&G-
+U+1e21:&g-
+U+1e22:&H.
+U+1e23:&h.
+U+1e24:&_H-._
+U+1e25:&_h-._
+U+1e26:&H:
+U+1e27:&h:
+U+1e28:&H,
+U+1e29:&h,
+U+1e2a:&_H-(_
+U+1e2b:&_h-(_
+U+1e2c:&_I-?_
+U+1e2d:&_i-?_
+U+1e2e:&_I:'_
+U+1e2f:&_i:'_
+U+1e30:&K'
+U+1e31:&k'
+U+1e32:&_K-._
+U+1e33:&_k-._
+U+1e34:&K_
+U+1e35:&k_
+U+1e36:&_L-._
+U+1e37:&_l-._
+U+1e38:&_L--._
+U+1e39:&_l--._
+U+1e3a:&L_
+U+1e3b:&l_
+U+1e3c:&_L->_
+U+1e3d:&_l->_
+U+1e3e:&M'
+U+1e3f:&m'
+U+1e40:&M.
+U+1e41:&m.
+U+1e42:&_M-._
+U+1e43:&_m-._
+U+1e44:&N.
+U+1e45:&n.
+U+1e46:&_N-._
+U+1e47:&_n-._
+U+1e48:&N_
+U+1e49:&n_
+U+1e4a:&_N->_
+U+1e4b:&_N->_
+U+1e4c:&_O?'_
+U+1e4d:&_o?'_
+U+1e4e:&_O?:_
+U+1e4f:&_o?:_
+U+1e50:&_O-!_
+U+1e51:&_o-!_
+U+1e52:&_O-'_
+U+1e53:&_o-'_
+U+1e54:&P'
+U+1e55:&p'
+U+1e56:&P.
+U+1e57:&p.
+U+1e58:&R.
+U+1e59:&r.
+U+1e5a:&_R-._
+U+1e5b:&_r-._
+U+1e5c:&_R--._
+U+1e5d:&_r--._
+U+1e5e:&R_
+U+1e5f:&r_
+U+1e60:&S.
+U+1e61:&s.
+U+1e62:&_S-._
+U+1e63:&_s-._
+U+1e64:&_S'._
+U+1e65:&_s'._
+U+1e66:&_S<._
+U+1e67:&_s<._
+U+1e68:&_S.-._
+U+1e69:&_S.-._
+U+1e6a:&T.
+U+1e6b:&t.
+U+1e6c:&_T-._
+U+1e6d:&_t-._
+U+1e6e:&T_
+U+1e6f:&t_
+U+1e70:&_T->_
+U+1e71:&_t->_
+U+1e72:&_U--:_
+U+1e73:&_u--:_
+U+1e74:&_U-?_
+U+1e75:&_u-?_
+U+1e76:&_U->_
+U+1e77:&_u->_
+U+1e78:&_U?'_
+U+1e79:&_u?'_
+U+1e7a:&_U-:_
+U+1e7b:&_u-:_
+U+1e7c:&V?
+U+1e7d:&v?
+U+1e7e:&_V-._
+U+1e7f:&_v-._
+U+1e80:&W!
+U+1e81:&w!
+U+1e82:&W'
+U+1e83:&w'
+U+1e84:&W:
+U+1e85:&w:
+U+1e86:&W.
+U+1e87:&w.
+U+1e88:&_W-._
+U+1e89:&_w-._
+U+1e8a:&X.
+U+1e8b:&x.
+U+1e8c:&X:
+U+1e8d:&x:
+U+1e8e:&Y.
+U+1e8f:&y.
+U+1e90:&Z>
+U+1e91:&z>
+U+1e92:&_Z-._
+U+1e93:&_z-._
+U+1e94:&Z_
+U+1e95:&z_
+U+1e96:&h_
+U+1e97:&t:
+U+1e98:&w0
+U+1e99:&y0
+U+1ea0:&_A-._
+U+1ea1:&_a-._
+U+1ea2:&A2
+U+1ea3:&a2
+U+1ea4:&_A>'_
+U+1ea5:&_a>'_
+U+1ea6:&_A>!_
+U+1ea7:&_a>!_
+U+1ea8:&_A>2_
+U+1ea9:&_a>2_
+U+1eaa:&_A>?_
+U+1eab:&_a>?_
+U+1eac:&_A>-._
+U+1ead:&_a>-._
+U+1eae:&_A('_
+U+1eaf:&_a('_
+U+1eb0:&_A(!_
+U+1eb1:&_a(!_
+U+1eb2:&_A(2_
+U+1eb3:&_a(2_
+U+1eb4:&_A(?_
+U+1eb5:&_a(?_
+U+1eb6:&_A(-._
+U+1eb7:&_a(-._
+U+1eb8:&_E-._
+U+1eb9:&_e-._
+U+1eba:&E2
+U+1ebb:&e2
+U+1ebc:&E?
+U+1ebd:&e?
+U+1ebe:&_E>'_
+U+1ebf:&_e>'_
+U+1ec0:&_E>!_
+U+1ec1:&_e>!_
+U+1ec2:&_E>2_
+U+1ec3:&_e>2_
+U+1ec4:&_E>?_
+U+1ec5:&_e>?_
+U+1ec6:&_E>-._
+U+1ec7:&_e>-._
+U+1ec8:&I2
+U+1ec9:&i2
+U+1eca:&_I-._
+U+1ecb:&_i-._
+U+1ecc:&_O-._
+U+1ecd:&_o-._
+U+1ece:&O2
+U+1ecf:&o2
+U+1ed0:&_O>'_
+U+1ed1:&_o>'_
+U+1ed2:&_O>!_
+U+1ed3:&_o>!_
+U+1ed4:&_O>2_
+U+1ed5:&_o>2_
+U+1ed6:&_O>?_
+U+1ed7:&_o>?_
+U+1ed8:&_O>-._
+U+1ed9:&_o>-._
+U+1eda:&_O9'_
+U+1edb:&_o9'_
+U+1edc:&_O9!_
+U+1edd:&_o9!_
+U+1ede:&_O92_
+U+1edf:&_o92_
+U+1ee0:&_O9?_
+U+1ee1:&_o9?_
+U+1ee2:&_O9-._
+U+1ee3:&_o9-._
+U+1ee4:&_U-._
+U+1ee5:&_u-._
+U+1ee6:&U2
+U+1ee7:&u2
+U+1ee8:&_U9'_
+U+1ee9:&_u9'_
+U+1eea:&_U9!_
+U+1eeb:&_u9!_
+U+1eec:&_U92_
+U+1eed:&_u92_
+U+1eee:&_U9?_
+U+1eef:&_u9?_
+U+1ef0:&_U9-._
+U+1ef1:&_u9-._
+U+1ef2:&Y!
+U+1ef3:&y!
+U+1ef4:&_Y-._
+U+1ef5:&_y-._
+U+1ef6:&Y2
+U+1ef7:&y2
+U+1ef8:&Y?
+U+1ef9:&y?
+U+1f00:&;'
+U+1f01:&,'
+U+1f02:&;!
+U+1f03:&,!
+U+1f04:&?;
+U+1f05:&?,
+U+1f06:&!:
+U+1f07:&?:
+U+2002:&1N
+U+2003:&1M
+U+2004:&3M
+U+2005:&4M
+U+2006:&6M
+U+2009:&1T
+U+200a:&1H
+U+2010:&-1
+U+2013:&-N
+U+2014:&-M
+U+2015:&-3
+U+2016:&!2
+U+2017:&=2
+U+2018:&'6
+U+2019:&'9
+U+201a:&.9
+U+201b:&9'
+U+201c:&"6
+U+201d:&"9
+U+201e:&:9
+U+201f:&9"
+U+2020:&/-
+U+2021:&/=
+U+2025:&..
+U+2030:&%0
+U+2032:&1'
+U+2033:&2'
+U+2034:&3'
+U+2035:&1"
+U+2036:&2"
+U+2037:&3"
+U+2038:&Ca
+U+2039:&<1
+U+203a:&>1
+U+203b:&:X
+U+203c:&_!*2_
+U+203e:&'-
+U+2044:&/f
+U+2070:&0S
+U+2074:&4S
+U+2075:&5S
+U+2076:&6S
+U+2077:&7S
+U+2078:&8S
+U+2079:&9S
+U+207a:&+S
+U+207b:&-S
+U+207c:&=S
+U+207d:&(S
+U+207e:&)S
+U+207f:&nS
+U+2080:&0s
+U+2081:&1s
+U+2082:&2s
+U+2083:&3s
+U+2084:&4s
+U+2085:&5s
+U+2086:&6s
+U+2087:&7s
+U+2088:&8s
+U+2089:&9s
+U+208a:&+s
+U+208b:&-s
+U+208c:&=s
+U+208d:&(s
+U+208e:&)s
+U+20a4:&Li
+U+20a7:&Pt
+U+20a9:&W=
+U+2103:&oC
+U+2105:&co
+U+2109:&oF
+U+2116:&N0
+U+2117:&PO
+U+211e:&Rx
+U+2120:&SM
+U+2122:&TM
+U+2126:&Om
+U+212b:&AO
+U+2153:&13
+U+2154:&23
+U+2155:&15
+U+2156:&25
+U+2157:&35
+U+2158:&45
+U+2159:&16
+U+215a:&56
+U+215b:&18
+U+215c:&38
+U+215d:&58
+U+215e:&78
+U+2160:&1R
+U+2161:&2R
+U+2162:&3R
+U+2163:&4R
+U+2164:&5R
+U+2165:&6R
+U+2166:&7R
+U+2167:&8R
+U+2168:&9R
+U+2169:&aR
+U+216a:&bR
+U+216b:&cR
+U+216c:&_50R_
+U+216d:&_100R_
+U+216e:&_500R_
+U+216f:&_1000R_
+U+2170:&1r
+U+2171:&2r
+U+2172:&3r
+U+2173:&4r
+U+2174:&5r
+U+2175:&6r
+U+2176:&7r
+U+2177:&8r
+U+2178:&9r
+U+2179:&ar
+U+217a:&br
+U+217b:&cr
+U+217c:&_50r_
+U+217d:&_100r_
+U+217e:&_500r_
+U+217f:&_1000r_
+U+2180:&_1000RCD_
+U+2181:&_5000R_
+U+2182:&_10000R_
+U+2190:&<-
+U+2191:&-!
+U+2192:&->
+U+2193:&-v
+U+2194:&<>
+U+2195:&UD
+U+2196:&_<!!_
+U+2197:&_//>_
+U+2198:&_!!>_
+U+2199:&_<//_
+U+21d0:&<=
+U+21d2:&=>
+U+21d4:&==
+U+2200:&FA
+U+2202:&dP
+U+2203:&TE
+U+2205:&/0
+U+2206:&DE
+U+2207:&NB
+U+2208:&(-
+U+220b:&-)
+U+220f:&*P
+U+2211:&+Z
+U+2212:&-2
+U+2213:&-+
+U+2217:&*-
+U+2218:&Ob
+U+2219:&Sb
+U+221a:&RT
+U+221d:&0(
+U+221e:&00
+U+221f:&-L
+U+2220:&-V
+U+2225:&PP
+U+2227:&AN
+U+2228:&OR
+U+2229:&(U
+U+222a:&)U
+U+222b:&In
+U+222c:&DI
+U+222e:&Io
+U+2234:&.:
+U+2235:&:.
+U+2236:&:R
+U+2237:&::
+U+223c:&?1
+U+223e:&CG
+U+2243:&?-
+U+2245:&?=
+U+2248:&?2
+U+224c:&=?
+U+2253:&HI
+U+2260:&!=
+U+2261:&=3
+U+2264:&=<
+U+2265:&>=
+U+226a:&<*
+U+226b:&*>
+U+226e:&!<
+U+226f:&!>
+U+2282:&(C
+U+2283:&)C
+U+2286:&(_
+U+2287:&)_
+U+2299:&0.
+U+229a:&02
+U+22a5:&-T
+U+22c5:&.P
+U+22ee:&:3
+U+22ef:&.3
+U+2302:&Eh
+U+2308:&<7
+U+2309:&>7
+U+230a:&7<
+U+230b:&7>
+U+2310:&NI
+U+2312:&(A
+U+2315:&TR
+U+2320:&Iu
+U+2321:&Il
+U+2329:&</
+U+232a:&/>
+U+2423:&Vs
+U+2440:&1h
+U+2441:&3h
+U+2442:&2h
+U+2443:&4h
+U+2446:&1j
+U+2447:&2j
+U+2448:&3j
+U+2449:&4j
+U+2460:&_1-o_
+U+2461:&_2-o_
+U+2462:&_3-o_
+U+2463:&_4-o_
+U+2464:&_5-o_
+U+2465:&_6-o_
+U+2466:&_7-o_
+U+2467:&_8-o_
+U+2468:&_9-o_
+U+2469:&_10-o_
+U+246a:&_11-o_
+U+246b:&_12-o_
+U+246c:&_13-o_
+U+246d:&_14-o_
+U+246e:&_15-o_
+U+246f:&_16-o_
+U+2470:&_17-o_
+U+2471:&_18-o_
+U+2472:&_19-o_
+U+2473:&_20-o_
+U+2474:&_(1)_
+U+2475:&_(2)_
+U+2476:&_(3)_
+U+2477:&_(4)_
+U+2478:&_(5)_
+U+2479:&_(6)_
+U+247a:&_(7)_
+U+247b:&_(8)_
+U+247c:&_(9)_
+U+247d:&_(10)_
+U+247e:&_(11)_
+U+247f:&_(12)_
+U+2480:&_(13)_
+U+2481:&_(14)_
+U+2482:&_(15)_
+U+2483:&_(16)_
+U+2484:&_(17)_
+U+2485:&_(18)_
+U+2486:&_(19)_
+U+2487:&_(20)_
+U+2488:&1.
+U+2489:&2.
+U+248a:&3.
+U+248b:&4.
+U+248c:&5.
+U+248d:&6.
+U+248e:&7.
+U+248f:&8.
+U+2490:&9.
+U+2491:&_10._
+U+2492:&_11._
+U+2493:&_12._
+U+2494:&_13._
+U+2495:&_14._
+U+2496:&_15._
+U+2497:&_16._
+U+2498:&_17._
+U+2499:&_18._
+U+249a:&_19._
+U+249b:&_20._
+U+249c:&_(a)_
+U+249d:&_(b)_
+U+249e:&_(c)_
+U+249f:&_(d)_
+U+24a0:&_(e)_
+U+24a1:&_(f)_
+U+24a2:&_(g)_
+U+24a3:&_(h)_
+U+24a4:&_(i)_
+U+24a5:&_(j)_
+U+24a6:&_(k)_
+U+24a7:&_(l)_
+U+24a8:&_(m)_
+U+24a9:&_(n)_
+U+24aa:&_(o)_
+U+24ab:&_(p)_
+U+24ac:&_(q)_
+U+24ad:&_(r)_
+U+24ae:&_(s)_
+U+24af:&_(t)_
+U+24b0:&_(u)_
+U+24b1:&_(v)_
+U+24b2:&_(w)_
+U+24b3:&_(x)_
+U+24b4:&_(y)_
+U+24b5:&_(z)_
+U+24b6:&_A-o_
+U+24b7:&_B-o_
+U+24b8:&_C-o_
+U+24b9:&_D-o_
+U+24ba:&_E-o_
+U+24bb:&_F-o_
+U+24bc:&_G-o_
+U+24bd:&_H-o_
+U+24be:&_I-o_
+U+24bf:&_J-o_
+U+24c0:&_K-o_
+U+24c1:&_L-o_
+U+24c2:&_M-o_
+U+24c3:&_N-o_
+U+24c4:&_O-o_
+U+24c5:&_P-o_
+U+24c6:&_Q-o_
+U+24c7:&_R-o_
+U+24c8:&_S-o_
+U+24c9:&_T-o_
+U+24ca:&_U-o_
+U+24cb:&_V-o_
+U+24cc:&_W-o_
+U+24cd:&_X-o_
+U+24ce:&_Y-o_
+U+24cf:&_Z-o_
+U+24d0:&_a-o_
+U+24d1:&_b-o_
+U+24d2:&_c-o_
+U+24d3:&_d-o_
+U+24d4:&_e-o_
+U+24d5:&_f-o_
+U+24d6:&_g-o_
+U+24d7:&_h-o_
+U+24d8:&_i-o_
+U+24d9:&_j-o_
+U+24da:&_k-o_
+U+24db:&_l-o_
+U+24dc:&_m-o_
+U+24dd:&_n-o_
+U+24de:&_o-o_
+U+24df:&_p-o_
+U+24e0:&_q-o_
+U+24e1:&_r-o_
+U+24e2:&_s-o_
+U+24e3:&_t-o_
+U+24e4:&_u-o_
+U+24e5:&_v-o_
+U+24e6:&_w-o_
+U+24e7:&_x-o_
+U+24e8:&_y-o_
+U+24e9:&_z-o_
+U+24ea:&_0-o_
+U+2500:&hh
+U+2501:&HH
+U+2502:&vv
+U+2503:&VV
+U+2504:&3-
+U+2505:&3_
+U+2506:&3!
+U+2507:&3/
+U+2508:&4-
+U+2509:&4_
+U+250a:&4!
+U+250b:&4/
+U+250c:&dr
+U+250d:&dR
+U+250e:&Dr
+U+250f:&DR
+U+2510:&dl
+U+2511:&dL
+U+2512:&Dl
+U+2513:&LD
+U+2514:&ur
+U+2515:&uR
+U+2516:&Ur
+U+2517:&UR
+U+2518:&ul
+U+2519:&uL
+U+251a:&Ul
+U+251b:&UL
+U+251c:&vr
+U+251d:&vR
+U+251e:&_Udr_
+U+251f:&_uDr_
+U+2520:&Vr
+U+2521:&_UdR_
+U+2522:&_uDR_
+U+2523:&VR
+U+2524:&vl
+U+2525:&vL
+U+2526:&_Udl_
+U+2527:&_uDl_
+U+2528:&Vl
+U+2529:&_UdL_
+U+252a:&_uDL_
+U+252b:&VL
+U+252c:&dh
+U+252d:&_dLr_
+U+252e:&_dlR_
+U+252f:&dH
+U+2530:&Dh
+U+2531:&_DLr_
+U+2532:&_DlR_
+U+2533:&DH
+U+2534:&uh
+U+2535:&_uLr_
+U+2536:&_ulR_
+U+2537:&uH
+U+2538:&Uh
+U+2539:&_ULr_
+U+253a:&_UlR_
+U+253b:&UH
+U+253c:&vh
+U+253d:&_vLr_
+U+253e:&_vlR_
+U+253f:&vH
+U+2540:&_Udh_
+U+2541:&_uDh_
+U+2542:&Vh
+U+2543:&_UdLr_
+U+2544:&_UdlR_
+U+2545:&_uDLr_
+U+2546:&_uDlR_
+U+2547:&_UdH_
+U+2548:&_uDH_
+U+2549:&_VLr_
+U+254a:&_VlR_
+U+254b:&VH
+U+2571:&FD
+U+2572:&BD
+U+2580:&TB
+U+2584:&LB
+U+2588:&FB
+U+258c:&lB
+U+2590:&RB
+U+2591:&.S
+U+2592:&:S
+U+2593:&?S
+U+25a0:&fS
+U+25a1:&OS
+U+25a2:&RO
+U+25a3:&Rr
+U+25a4:&RF
+U+25a5:&RY
+U+25a6:&RH
+U+25a7:&RZ
+U+25a8:&RK
+U+25a9:&RX
+U+25aa:&sB
+U+25ac:&SR
+U+25ad:&Or
+U+25b2:&UT
+U+25b3:&uT
+U+25b6:&PR
+U+25b7:&Tr
+U+25bc:&Dt
+U+25bd:&dT
+U+25c0:&PL
+U+25c1:&Tl
+U+25c6:&Db
+U+25c7:&Dw
+U+25ca:&LZ
+U+25cb:&0m
+U+25ce:&0o
+U+25cf:&0M
+U+25d0:&0L
+U+25d1:&0R
+U+25d8:&Sn
+U+25d9:&Ic
+U+25e2:&Fd
+U+25e3:&Bd
+U+2605:&*2
+U+2606:&*1
+U+260e:&_TEL_
+U+260f:&_tel_
+U+261c:&<H
+U+261e:&>H
+U+263a:&0u
+U+263b:&0U
+U+263c:&SU
+U+2640:&Fm
+U+2642:&Ml
+U+2660:&cS
+U+2661:&cH
+U+2662:&cD
+U+2663:&cC
+U+2664:&_cS-_
+U+2665:&_cH-_
+U+2666:&_cD-_
+U+2667:&_cC-_
+U+2669:&Md
+U+266a:&M8
+U+266b:&M2
+U+266c:&_M16_
+U+266d:&Mb
+U+266e:&Mx
+U+266f:&MX
+U+2713:&OK
+U+2717:&XX
+U+2720:&-X
+U+3000:&IS
+U+3001:&,_
+U+3002:&._
+U+3003:&+"
+U+3004:&+_
+U+3005:&*_
+U+3006:&;_
+U+3007:&0_
+U+300a:&<+
+U+300b:&>+
+U+300c:&<'
+U+300d:&>'
+U+300e:&<"
+U+300f:&>"
+U+3010:&("
+U+3011:&)"
+U+3012:&=T
+U+3013:&=_
+U+3014:&('
+U+3015:&)'
+U+3016:&(I
+U+3017:&)I
+U+301c:&-?
+U+3020:&_=T:)_
+U+3041:&A5
+U+3042:&a5
+U+3043:&I5
+U+3044:&i5
+U+3045:&U5
+U+3046:&u5
+U+3047:&E5
+U+3048:&e5
+U+3049:&O5
+U+304a:&o5
+U+304b:&ka
+U+304c:&ga
+U+304d:&ki
+U+304e:&gi
+U+304f:&ku
+U+3050:&gu
+U+3051:&ke
+U+3052:&ge
+U+3053:&ko
+U+3054:&go
+U+3055:&sa
+U+3056:&za
+U+3057:&si
+U+3058:&zi
+U+3059:&su
+U+305a:&zu
+U+305b:&se
+U+305c:&ze
+U+305d:&so
+U+305e:&zo
+U+305f:&ta
+U+3060:&da
+U+3061:&ti
+U+3062:&di
+U+3063:&tU
+U+3064:&tu
+U+3065:&du
+U+3066:&te
+U+3067:&de
+U+3068:&to
+U+3069:&do
+U+306a:&na
+U+306b:&ni
+U+306c:&nu
+U+306d:&ne
+U+306e:&no
+U+306f:&ha
+U+3070:&ba
+U+3071:&pa
+U+3072:&hi
+U+3073:&bi
+U+3074:&pi
+U+3075:&hu
+U+3076:&bu
+U+3077:&pu
+U+3078:&he
+U+3079:&be
+U+307a:&pe
+U+307b:&ho
+U+307c:&bo
+U+307d:&po
+U+307e:&ma
+U+307f:&mi
+U+3080:&mu
+U+3081:&me
+U+3082:&mo
+U+3083:&yA
+U+3084:&ya
+U+3085:&yU
+U+3086:&yu
+U+3087:&yO
+U+3088:&yo
+U+3089:&ra
+U+308a:&ri
+U+308b:&ru
+U+308c:&re
+U+308d:&ro
+U+308e:&wA
+U+308f:&wa
+U+3090:&wi
+U+3091:&we
+U+3092:&wo
+U+3093:&n5
+U+3094:&vu
+U+309b:&"5
+U+309c:&05
+U+309d:&*5
+U+309e:&+5
+U+30a1:&a6
+U+30a2:&A6
+U+30a3:&i6
+U+30a4:&I6
+U+30a5:&u6
+U+30a6:&U6
+U+30a7:&e6
+U+30a8:&E6
+U+30a9:&o6
+U+30aa:&O6
+U+30ab:&Ka
+U+30ac:&Ga
+U+30ad:&Ki
+U+30ae:&Gi
+U+30af:&Ku
+U+30b0:&Gu
+U+30b1:&Ke
+U+30b2:&Ge
+U+30b3:&Ko
+U+30b4:&Go
+U+30b5:&Sa
+U+30b6:&Za
+U+30b7:&Si
+U+30b8:&Zi
+U+30b9:&Su
+U+30ba:&Zu
+U+30bb:&Se
+U+30bc:&Ze
+U+30bd:&So
+U+30be:&Zo
+U+30bf:&Ta
+U+30c0:&Da
+U+30c1:&Ti
+U+30c2:&Di
+U+30c3:&TU
+U+30c4:&Tu
+U+30c5:&Du
+U+30c6:&Te
+U+30c7:&De
+U+30c8:&To
+U+30c9:&Do
+U+30ca:&Na
+U+30cb:&Ni
+U+30cc:&Nu
+U+30cd:&Ne
+U+30ce:&No
+U+30cf:&Ha
+U+30d0:&Ba
+U+30d1:&Pa
+U+30d2:&Hi
+U+30d3:&Bi
+U+30d4:&Pi
+U+30d5:&Hu
+U+30d6:&Bu
+U+30d7:&Pu
+U+30d8:&He
+U+30d9:&Be
+U+30da:&Pe
+U+30db:&Ho
+U+30dc:&Bo
+U+30dd:&Po
+U+30de:&Ma
+U+30df:&Mi
+U+30e0:&Mu
+U+30e1:&Me
+U+30e2:&Mo
+U+30e3:&YA
+U+30e4:&Ya
+U+30e5:&YU
+U+30e6:&Yu
+U+30e7:&YO
+U+30e8:&Yo
+U+30e9:&Ra
+U+30ea:&Ri
+U+30eb:&Ru
+U+30ec:&Re
+U+30ed:&Ro
+U+30ee:&WA
+U+30ef:&Wa
+U+30f0:&Wi
+U+30f1:&We
+U+30f2:&Wo
+U+30f3:&N6
+U+30f4:&Vu
+U+30f5:&KA
+U+30f6:&KE
+U+30f7:&Va
+U+30f8:&Vi
+U+30f9:&Ve
+U+30fa:&Vo
+U+30fb:&.6
+U+30fc:&-6
+U+30fd:&*6
+U+30fe:&+6
+U+3105:&b4
+U+3106:&p4
+U+3107:&m4
+U+3108:&f4
+U+3109:&d4
+U+310a:&t4
+U+310b:&n4
+U+310c:&l4
+U+310d:&g4
+U+310e:&k4
+U+310f:&h4
+U+3110:&j4
+U+3111:&q4
+U+3112:&x4
+U+3113:&zh
+U+3114:&ch
+U+3115:&sh
+U+3116:&r4
+U+3117:&z4
+U+3118:&c4
+U+3119:&s4
+U+311a:&a4
+U+311b:&o4
+U+311c:&e4
+U+311d:&_eh4_
+U+311e:&ai
+U+311f:&ei
+U+3120:&au
+U+3121:&ou
+U+3122:&an
+U+3123:&en
+U+3124:&aN
+U+3125:&eN
+U+3126:&er
+U+3127:&i4
+U+3128:&u4
+U+3129:&iu
+U+312a:&v4
+U+312b:&nG
+U+312c:&gn
+U+321c:&_(JU)_
+U+3220:&1c
+U+3221:&2c
+U+3222:&3c
+U+3223:&4c
+U+3224:&5c
+U+3225:&6c
+U+3226:&7c
+U+3227:&8c
+U+3228:&9c
+U+3229:&_10c_
+U+327f:&_KSC_
+U+fb00:&ff
+U+fb01:&fi
+U+fb02:&fl
+U+fb03:&_ffi_
+U+fb04:&_ffl_
+U+fb05:&ft
+U+fb06:&st
+U+fe7d:&_3+;_
+U+fe82:&_aM._
+U+fe84:&_aH._
+U+fe8d:&_a+-_
+U+fe8e:&_a+._
+U+fe8f:&_b+-_
+U+fe90:&_b+,_
+U+fe91:&_b+;_
+U+fe92:&_b+._
+U+fe93:&_tm-_
+U+fe94:&_tm._
+U+fe95:&_t+-_
+U+fe96:&_t+,_
+U+fe97:&_t+;_
+U+fe98:&_t+._
+U+fe99:&_tk-_
+U+fe9a:&_tk,_
+U+fe9b:&_tk;_
+U+fe9c:&_tk._
+U+fe9d:&_g+-_
+U+fe9e:&_g+,_
+U+fe9f:&_g+;_
+U+fea0:&_g+._
+U+fea1:&_hk-_
+U+fea2:&_hk,_
+U+fea3:&_hk;_
+U+fea4:&_hk._
+U+fea5:&_x+-_
+U+fea6:&_x+,_
+U+fea7:&_x+;_
+U+fea8:&_x+._
+U+fea9:&_d+-_
+U+feaa:&_d+._
+U+feab:&_dk-_
+U+feac:&_dk._
+U+fead:&_r+-_
+U+feae:&_r+._
+U+feaf:&_z+-_
+U+feb0:&_z+._
+U+feb1:&_s+-_
+U+feb2:&_s+,_
+U+feb3:&_s+;_
+U+feb4:&_s+._
+U+feb5:&_sn-_
+U+feb6:&_sn,_
+U+feb7:&_sn;_
+U+feb8:&_sn._
+U+feb9:&_c+-_
+U+feba:&_c+,_
+U+febb:&_c+;_
+U+febc:&_c+._
+U+febd:&_dd-_
+U+febe:&_dd,_
+U+febf:&_dd;_
+U+fec0:&_dd._
+U+fec1:&_tj-_
+U+fec2:&_tj,_
+U+fec3:&_tj;_
+U+fec4:&_tj._
+U+fec5:&_zH-_
+U+fec6:&_zH,_
+U+fec7:&_zH;_
+U+fec8:&_zH._
+U+fec9:&_e+-_
+U+feca:&_e+,_
+U+fecb:&_e+;_
+U+fecc:&_e+._
+U+fecd:&_i+-_
+U+fece:&_i+,_
+U+fecf:&_i+;_
+U+fed0:&_i+._
+U+fed1:&_f+-_
+U+fed2:&_f+,_
+U+fed3:&_f+;_
+U+fed4:&_f+._
+U+fed5:&_q+-_
+U+fed6:&_q+,_
+U+fed7:&_q+;_
+U+fed8:&_q+._
+U+fed9:&_k+-_
+U+feda:&_k+,_
+U+fedb:&_k+;_
+U+fedc:&_k+._
+U+fedd:&_l+-_
+U+fede:&_l+,_
+U+fedf:&_l+;_
+U+fee0:&_l+._
+U+fee1:&_m+-_
+U+fee2:&_m+,_
+U+fee3:&_m+;_
+U+fee4:&_m+._
+U+fee5:&_n+-_
+U+fee6:&_n+,_
+U+fee7:&_n+;_
+U+fee8:&_n+._
+U+fee9:&_h+-_
+U+feea:&_h+,_
+U+feeb:&_h+;_
+U+feec:&_h+._
+U+feed:&_w+-_
+U+feee:&_w+._
+U+feef:&_j+-_
+U+fef0:&_j+._
+U+fef1:&_y+-_
+U+fef2:&_y+,_
+U+fef3:&_y+;_
+U+fef4:&_y+._
+U+fef5:&_lM-_
+U+fef6:&_lM._
+U+fef7:&_lH-_
+U+fef8:&_lH._
+U+fef9:&_lh-_
+U+fefa:&_lh._
+U+fefb:&_la-_
+U+fefc:&_la._
+U+0000:&NU
+U+0001:&SH
+U+0002:&SX
+U+0003:&EX
+U+0004:&ET
+U+0005:&EQ
+U+0006:&AK
+U+0007:&BL
+U+0008:&BS
+U+0009:&HT
+# U+000a:&LF
+U+000b:&VT
+U+000c:&FF
+U+000d:&CR
+U+000e:&SO
+U+000f:&SI
+U+0010:&DL
+U+0011:&D1
+U+0012:&D2
+U+0013:&D3
+U+0014:&D4
+U+0015:&NK
+U+0016:&SY
+U+0017:&EB
+U+0018:&CN
+U+0019:&EM
+U+001a:&SB
+U+001b:&EC
+U+001c:&FS
+U+001d:&GS
+U+001e:&RS
+U+001f:&US
+U+007f:&DT
+U+0080:&PA
+U+0081:&HO
+U+0082:&BH
+U+0083:&NH
+U+0084:&IN
+U+0085:&NL
+U+0086:&SA
+U+0087:&ES
+U+0088:&HS
+U+0089:&HJ
+U+008a:&VS
+U+008b:&PD
+U+008c:&PU
+U+008d:&RI
+U+008e:&S2
+U+008f:&S3
+U+0090:&DC
+U+0091:&P1
+U+0092:&P2
+U+0093:&TS
+U+0094:&CC
+U+0095:&MW
+U+0096:&SG
+U+0097:&EG
+U+0098:&SS
+U+0099:&GC
+U+009a:&SC
+U+009b:&CI
+U+009c:&ST
+U+009d:&OC
+U+009e:&PM
+U+009f:&AC
+# Characters in Private Use Area (e000-f8ff) do not have ussigned numbers
+# according Unicode 2.0
diff --git a/gnu/usr.bin/lynx/src/chrtrans/mnem_suni.tbl b/gnu/usr.bin/lynx/src/chrtrans/mnem_suni.tbl
new file mode 100644
index 00000000000..ddf8600d82a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/mnem_suni.tbl
@@ -0,0 +1,1861 @@
+#The MIME name of this charset.
+Mmnem
+
+#Name as a Display Charset (used on Options screen)
+ORFC1345 Mnem
+
+# U+0020: SP
+U+0021:!
+U+0022:"
+U+0023: Nb
+U+0024: DO
+U+0025:%
+U+0026:&&
+U+0027:'
+U+0028:(
+U+0029:)
+U+002a:*
+U+002b:+
+U+002c:,
+U+002d:-
+U+002e:.
+U+002f:/
+U+0030:0
+U+0031:1
+U+0032:2
+U+0033:3
+U+0034:4
+U+0035:5
+U+0036:6
+U+0037:7
+U+0038:8
+U+0039:9
+U+003a::
+U+003b:;
+U+003c:<
+U+003d:=
+U+003e:>
+U+003f:?
+U+0040: At
+U+0041:A
+U+0042:B
+U+0043:C
+U+0044:D
+U+0045:E
+U+0046:F
+U+0047:G
+U+0048:H
+U+0049:I
+U+004a:J
+U+004b:K
+U+004c:L
+U+004d:M
+U+004e:N
+U+004f:O
+U+0050:P
+U+0051:Q
+U+0052:R
+U+0053:S
+U+0054:T
+U+0055:U
+U+0056:V
+U+0057:W
+U+0058:X
+U+0059:Y
+U+005a:Z
+U+005b: <(
+U+005c: //
+U+005d: )>
+U+005e: '>
+U+005f:_
+U+0060: '!
+U+0061:a
+U+0062:b
+U+0063:c
+U+0064:d
+U+0065:e
+U+0066:f
+U+0067:g
+U+0068:h
+U+0069:i
+U+006a:j
+U+006b:k
+U+006c:l
+U+006d:m
+U+006e:n
+U+006f:o
+U+0070:p
+U+0071:q
+U+0072:r
+U+0073:s
+U+0074:t
+U+0075:u
+U+0076:v
+U+0077:w
+U+0078:x
+U+0079:y
+U+007a:z
+U+007b: (!
+U+007c: !!
+U+007d: !)
+U+007e: '?
+U+00a0: NS
+U+00a1: !I
+U+00a2: Ct
+U+00a3: Pd
+U+00a4: Cu
+U+00a5: Ye
+U+00a6: BB
+U+00a7: SE
+U+00a8: ':
+U+00a9: Co
+U+00aa: -a
+U+00ab: <<
+U+00ac: NO
+U+00ad: --
+U+00ae: Rg
+U+00af: 'm
+U+00b0: DG
+U+00b1: +-
+U+00b2: 2S
+U+00b3: 3S
+U+00b4: ''
+U+00b5: My
+U+00b6: PI
+U+00b7: .M
+U+00b8: ',
+U+00b9: 1S
+U+00ba: -o
+U+00bb: >>
+U+00bc: 14
+U+00bd: 12
+U+00be: 34
+U+00bf: ?I
+U+00c0: A!
+U+00c1: A'
+U+00c2: A>
+U+00c3: A?
+U+00c4: A:
+U+00c5: AA
+U+00c6: AE
+U+00c7: C,
+U+00c8: E!
+U+00c9: E'
+U+00ca: E>
+U+00cb: E:
+U+00cc: I!
+U+00cd: I'
+U+00ce: I>
+U+00cf: I:
+U+00d0: D-
+U+00d1: N?
+U+00d2: O!
+U+00d3: O'
+U+00d4: O>
+U+00d5: O?
+U+00d6: O:
+U+00d7: *X
+U+00d8: O/
+U+00d9: U!
+U+00da: U'
+U+00db: U>
+U+00dc: U:
+U+00dd: Y'
+U+00de: TH
+U+00df: ss
+U+00e0: a!
+U+00e1: a'
+U+00e2: a>
+U+00e3: a?
+U+00e4: a:
+U+00e5: aa
+U+00e6: ae
+U+00e7: c,
+U+00e8: e!
+U+00e9: e'
+U+00ea: e>
+U+00eb: e:
+U+00ec: i!
+U+00ed: i'
+U+00ee: i>
+U+00ef: i:
+U+00f0: d-
+U+00f1: n?
+U+00f2: o!
+U+00f3: o'
+U+00f4: o>
+U+00f5: o?
+U+00f6: o:
+U+00f7: -:
+U+00f8: o/
+U+00f9: u!
+U+00fa: u'
+U+00fb: u>
+U+00fc: u:
+U+00fd: y'
+U+00fe: th
+U+00ff: y:
+U+0100: A-
+U+0101: a-
+U+0102: A(
+U+0103: a(
+U+0104: A;
+U+0105: a;
+U+0106: C'
+U+0107: c'
+U+0108: C>
+U+0109: c>
+U+010a: C.
+U+010b: c.
+U+010c: C<
+U+010d: c<
+U+010e: D<
+U+010f: d<
+U+0110: D/
+U+0111: d/
+U+0112: E-
+U+0113: e-
+U+0114: E(
+U+0115: e(
+U+0116: E.
+U+0117: e.
+U+0118: E;
+U+0119: e;
+U+011a: E<
+U+011b: e<
+U+011c: G>
+U+011d: g>
+U+011e: G(
+U+011f: g(
+U+0120: G.
+U+0121: g.
+U+0122: G,
+U+0123: g,
+U+0124: H>
+U+0125: h>
+U+0126: H/
+U+0127: h/
+U+0128: I?
+U+0129: i?
+U+012a: I-
+U+012b: i-
+U+012c: I(
+U+012d: i(
+U+012e: I;
+U+012f: i;
+U+0130: I.
+U+0131: i.
+U+0132: IJ
+U+0133: ij
+U+0134: J>
+U+0135: j>
+U+0136: K,
+U+0137: k,
+U+0138: kk
+U+0139: L'
+U+013a: l'
+U+013b: L,
+U+013c: l,
+U+013d: L<
+U+013e: l<
+U+013f: L.
+U+0140: l.
+U+0141: L/
+U+0142: l/
+U+0143: N'
+U+0144: n'
+U+0145: N,
+U+0146: n,
+U+0147: N<
+U+0148: n<
+U+0149: 'n
+U+014a: NG
+U+014b: ng
+U+014c: O-
+U+014d: o-
+U+014e: O(
+U+014f: o(
+U+0150: O"
+U+0151: o"
+U+0152: OE
+U+0153: oe
+U+0154: R'
+U+0155: r'
+U+0156: R,
+U+0157: r,
+U+0158: R<
+U+0159: r<
+U+015a: S'
+U+015b: s'
+U+015c: S>
+U+015d: s>
+U+015e: S,
+U+015f: s,
+U+0160: S<
+U+0161: s<
+U+0162: T,
+U+0163: t,
+U+0164: T<
+U+0165: t<
+U+0166: T/
+U+0167: t/
+U+0168: U?
+U+0169: u?
+U+016a: U-
+U+016b: u-
+U+016c: U(
+U+016d: u(
+U+016e: U0
+U+016f: u0
+U+0170: U"
+U+0171: u"
+U+0172: U;
+U+0173: u;
+U+0174: W>
+U+0175: w>
+U+0176: Y>
+U+0177: y>
+U+0178: Y:
+U+0179: Z'
+U+017a: z'
+U+017b: Z.
+U+017c: z.
+U+017d: Z<
+U+017e: z<
+U+01a0: O9
+U+01a1: o9
+U+01a2: OI
+U+01a3: oi
+U+01a6: yr
+U+01af: U9
+U+01b0: u9
+U+01b5: Z/
+U+01b6: z/
+U+01b7: ED
+U+01cd: A<
+U+01ce: a<
+U+01cf: I<
+U+01d0: i<
+U+01d1: O<
+U+01d2: o<
+U+01d3: U<
+U+01d4: u<
+U+01d5: _U:-_
+U+01d6: _u:-_
+U+01d7: _U:'_
+U+01d8: _u:'_
+U+01d9: _U:<_
+U+01da: _u:<_
+U+01db: _U:!_
+U+01dc: _u:!_
+U+01de: A1
+U+01df: a1
+U+01e0: A7
+U+01e1: a7
+U+01e2: A3
+U+01e3: a3
+U+01e4: G/
+U+01e5: g/
+U+01e6: G<
+U+01e7: g<
+U+01e8: K<
+U+01e9: k<
+U+01ea: O;
+U+01eb: o;
+U+01ec: O1
+U+01ed: o1
+U+01ee: EZ
+U+01ef: ez
+U+01f0: j<
+U+01f4: G'
+U+01f5: g'
+U+01fa: _AA'_
+U+01fb: _aa'_
+U+01fc: _AE'_
+U+01fd: _ae'_
+U+01fe: _O/'_
+U+01ff: _o/'_
+U+02bf: ;S
+U+02c7: '<
+U+02d8: '(
+U+02d9: '.
+U+02da: '0
+U+02db: ';
+U+02dd: '"
+U+0386: A%
+U+0388: E%
+U+0389: Y%
+U+038a: I%
+U+038c: O%
+U+038e: U%
+U+038f: W%
+U+0390: i3
+U+0391: A*
+U+0392: B*
+U+0393: G*
+U+0394: D*
+U+0395: E*
+U+0396: Z*
+U+0397: Y*
+U+0398: H*
+U+0399: I*
+U+039a: K*
+U+039b: L*
+U+039c: M*
+U+039d: N*
+U+039e: C*
+U+039f: O*
+U+03a0: P*
+U+03a1: R*
+U+03a3: S*
+U+03a4: T*
+U+03a5: U*
+U+03a6: F*
+U+03a7: X*
+U+03a8: Q*
+U+03a9: W*
+U+03aa: J*
+U+03ab: V*
+U+03ac: a%
+U+03ad: e%
+U+03ae: y%
+U+03af: i%
+U+03b0: u3
+U+03b1: a*
+U+03b2: b*
+U+03b3: g*
+U+03b4: d*
+U+03b5: e*
+U+03b6: z*
+U+03b7: y*
+U+03b8: h*
+U+03b9: i*
+U+03ba: k*
+U+03bb: l*
+U+03bc: m*
+U+03bd: n*
+U+03be: c*
+U+03bf: o*
+U+03c0: p*
+U+03c1: r*
+U+03c2: *s
+U+03c3: s*
+U+03c4: t*
+U+03c5: u*
+U+03c6: f*
+U+03c7: x*
+U+03c8: q*
+U+03c9: w*
+U+03ca: j*
+U+03cb: v*
+U+03cc: o%
+U+03cd: u%
+U+03ce: w%
+U+03d8: 'G
+U+03d9: ,G
+U+03da: T3
+U+03db: t3
+U+03dc: M3
+U+03dd: m3
+U+03de: K3
+U+03df: k3
+U+03e0: P3
+U+03e1: p3
+U+03f4: '%
+U+03f5: j3
+U+0401: IO
+U+0402: D%
+U+0403: G%
+U+0404: IE
+U+0405: DS
+U+0406: II
+U+0407: YI
+U+0408: J%
+U+0409: LJ
+U+040a: NJ
+U+040b: Ts
+U+040c: KJ
+U+040e: V%
+U+040f: DZ
+U+0410: A=
+U+0411: B=
+U+0412: V=
+U+0413: G=
+U+0414: D=
+U+0415: E=
+U+0416: Z%
+U+0417: Z=
+U+0418: I=
+U+0419: J=
+U+041a: K=
+U+041b: L=
+U+041c: M=
+U+041d: N=
+U+041e: O=
+U+041f: P=
+U+0420: R=
+U+0421: S=
+U+0422: T=
+U+0423: U=
+U+0424: F=
+U+0425: H=
+U+0426: C=
+U+0427: C%
+U+0428: S%
+U+0429: Sc
+U+042a: ="
+U+042b: Y=
+U+042c: %"
+U+042d: JE
+U+042e: JU
+U+042f: JA
+U+0430: a=
+U+0431: b=
+U+0432: v=
+U+0433: g=
+U+0434: d=
+U+0435: e=
+U+0436: z%
+U+0437: z=
+U+0438: i=
+U+0439: j=
+U+043a: k=
+U+043b: l=
+U+043c: m=
+U+043d: n=
+U+043e: o=
+U+043f: p=
+U+0440: r=
+U+0441: s=
+U+0442: t=
+U+0443: u=
+U+0444: f=
+U+0445: h=
+U+0446: c=
+U+0447: c%
+U+0448: s%
+U+0449: sc
+U+044a: ='
+U+044b: y=
+U+044c: %'
+U+044d: je
+U+044e: ju
+U+044f: ja
+U+0451: io
+U+0452: d%
+U+0453: g%
+U+0454: ie
+U+0455: ds
+U+0456: ii
+U+0457: yi
+U+0458: j%
+U+0459: lj
+U+045a: nj
+U+045b: ts
+U+045c: kj
+U+045e: v%
+U+045f: dz
+U+0462: Y3
+U+0463: y3
+U+046a: O3
+U+046b: o3
+U+0472: F3
+U+0473: f3
+U+0474: V3
+U+0475: v3
+U+0480: C3
+U+0481: c3
+U+0490: G3
+U+0491: g3
+U+05d0: A+
+U+05d1: B+
+U+05d2: G+
+U+05d3: D+
+U+05d4: H+
+U+05d5: W+
+U+05d6: Z+
+U+05d7: X+
+U+05d8: Tj
+U+05d9: J+
+U+05da: K%
+U+05db: K+
+U+05dc: L+
+U+05dd: M%
+U+05de: M+
+U+05df: N%
+U+05e0: N+
+U+05e1: S+
+U+05e2: E+
+U+05e3: P%
+U+05e4: P+
+U+05e5: Zj
+U+05e6: ZJ
+U+05e7: Q+
+U+05e8: R+
+U+05e9: Sh
+U+05ea: T+
+U+060c: ,+
+U+061b: ;+
+U+061f: ?+
+U+0621: H'
+U+0622: aM
+U+0623: aH
+U+0624: wH
+U+0625: ah
+U+0626: yH
+U+0627: a+
+U+0628: b+
+U+0629: tm
+U+062a: t+
+U+062b: tk
+U+062c: g+
+U+062d: hk
+U+062e: x+
+U+062f: d+
+U+0630: dk
+U+0631: r+
+U+0632: z+
+U+0633: s+
+U+0634: sn
+U+0635: c+
+U+0636: dd
+U+0637: tj
+U+0638: zH
+U+0639: e+
+U+063a: i+
+U+0640: ++
+U+0641: f+
+U+0642: q+
+U+0643: k+
+U+0644: l+
+U+0645: m+
+U+0646: n+
+U+0647: h+
+U+0648: w+
+U+0649: j+
+U+064a: y+
+U+064b: :+
+U+064c: "+
+U+064d: =+
+U+064e: /+
+U+064f: '+
+U+0650: 1+
+U+0651: 3+
+U+0652: 0+
+U+0670: aS
+U+067e: p+
+U+06a4: v+
+U+06af: gf
+U+06f0: 0a
+U+06f1: 1a
+U+06f2: 2a
+U+06f3: 3a
+U+06f4: 4a
+U+06f5: 5a
+U+06f6: 6a
+U+06f7: 7a
+U+06f8: 8a
+U+06f9: 9a
+U+1e00: _A-0_
+U+1e01: _a-0_
+U+1e02: B.
+U+1e03: b.
+U+1e04: _B-._
+U+1e05: _b-._
+U+1e06: B_
+U+1e07: b_
+U+1e08: _C,'_
+U+1e09: _c,'_
+U+1e0a: D.
+U+1e0b: d.
+U+1e0c: _D-._
+U+1e0d: _d-._
+U+1e0e: D_
+U+1e0f: d_
+U+1e10: D,
+U+1e11: d,
+U+1e12: _D->_
+U+1e13: _d->_
+U+1e14: _E-!_
+U+1e15: _e-!_
+U+1e16: _E-'_
+U+1e17: _e-'_
+U+1e18: _E->_
+U+1e19: _e->_
+U+1e1a: _E-?_
+U+1e1b: _e-?_
+U+1e1c: _E,(_
+U+1e1d: _e,(_
+U+1e1e: F.
+U+1e1f: f.
+U+1e20: G-
+U+1e21: g-
+U+1e22: H.
+U+1e23: h.
+U+1e24: _H-._
+U+1e25: _h-._
+U+1e26: H:
+U+1e27: h:
+U+1e28: H,
+U+1e29: h,
+U+1e2a: _H-(_
+U+1e2b: _h-(_
+U+1e2c: _I-?_
+U+1e2d: _i-?_
+U+1e2e: _I:'_
+U+1e2f: _i:'_
+U+1e30: K'
+U+1e31: k'
+U+1e32: _K-._
+U+1e33: _k-._
+U+1e34: K_
+U+1e35: k_
+U+1e36: _L-._
+U+1e37: _l-._
+U+1e38: _L--._
+U+1e39: _l--._
+U+1e3a: L_
+U+1e3b: l_
+U+1e3c: _L->_
+U+1e3d: _l->_
+U+1e3e: M'
+U+1e3f: m'
+U+1e40: M.
+U+1e41: m.
+U+1e42: _M-._
+U+1e43: _m-._
+U+1e44: N.
+U+1e45: n.
+U+1e46: _N-._
+U+1e47: _n-._
+U+1e48: N_
+U+1e49: n_
+U+1e4a: _N->_
+U+1e4b: _N->_
+U+1e4c: _O?'_
+U+1e4d: _o?'_
+U+1e4e: _O?:_
+U+1e4f: _o?:_
+U+1e50: _O-!_
+U+1e51: _o-!_
+U+1e52: _O-'_
+U+1e53: _o-'_
+U+1e54: P'
+U+1e55: p'
+U+1e56: P.
+U+1e57: p.
+U+1e58: R.
+U+1e59: r.
+U+1e5a: _R-._
+U+1e5b: _r-._
+U+1e5c: _R--._
+U+1e5d: _r--._
+U+1e5e: R_
+U+1e5f: r_
+U+1e60: S.
+U+1e61: s.
+U+1e62: _S-._
+U+1e63: _s-._
+U+1e64: _S'._
+U+1e65: _s'._
+U+1e66: _S<._
+U+1e67: _s<._
+U+1e68: _S.-._
+U+1e69: _S.-._
+U+1e6a: T.
+U+1e6b: t.
+U+1e6c: _T-._
+U+1e6d: _t-._
+U+1e6e: T_
+U+1e6f: t_
+U+1e70: _T->_
+U+1e71: _t->_
+U+1e72: _U--:_
+U+1e73: _u--:_
+U+1e74: _U-?_
+U+1e75: _u-?_
+U+1e76: _U->_
+U+1e77: _u->_
+U+1e78: _U?'_
+U+1e79: _u?'_
+U+1e7a: _U-:_
+U+1e7b: _u-:_
+U+1e7c: V?
+U+1e7d: v?
+U+1e7e: _V-._
+U+1e7f: _v-._
+U+1e80: W!
+U+1e81: w!
+U+1e82: W'
+U+1e83: w'
+U+1e84: W:
+U+1e85: w:
+U+1e86: W.
+U+1e87: w.
+U+1e88: _W-._
+U+1e89: _w-._
+U+1e8a: X.
+U+1e8b: x.
+U+1e8c: X:
+U+1e8d: x:
+U+1e8e: Y.
+U+1e8f: y.
+U+1e90: Z>
+U+1e91: z>
+U+1e92: _Z-._
+U+1e93: _z-._
+U+1e94: Z_
+U+1e95: z_
+U+1e96: h_
+U+1e97: t:
+U+1e98: w0
+U+1e99: y0
+U+1ea0: _A-._
+U+1ea1: _a-._
+U+1ea2: A2
+U+1ea3: a2
+U+1ea4: _A>'_
+U+1ea5: _a>'_
+U+1ea6: _A>!_
+U+1ea7: _a>!_
+U+1ea8: _A>2_
+U+1ea9: _a>2_
+U+1eaa: _A>?_
+U+1eab: _a>?_
+U+1eac: _A>-._
+U+1ead: _a>-._
+U+1eae: _A('_
+U+1eaf: _a('_
+U+1eb0: _A(!_
+U+1eb1: _a(!_
+U+1eb2: _A(2_
+U+1eb3: _a(2_
+U+1eb4: _A(?_
+U+1eb5: _a(?_
+U+1eb6: _A(-._
+U+1eb7: _a(-._
+U+1eb8: _E-._
+U+1eb9: _e-._
+U+1eba: E2
+U+1ebb: e2
+U+1ebc: E?
+U+1ebd: e?
+U+1ebe: _E>'_
+U+1ebf: _e>'_
+U+1ec0: _E>!_
+U+1ec1: _e>!_
+U+1ec2: _E>2_
+U+1ec3: _e>2_
+U+1ec4: _E>?_
+U+1ec5: _e>?_
+U+1ec6: _E>-._
+U+1ec7: _e>-._
+U+1ec8: I2
+U+1ec9: i2
+U+1eca: _I-._
+U+1ecb: _i-._
+U+1ecc: _O-._
+U+1ecd: _o-._
+U+1ece: O2
+U+1ecf: o2
+U+1ed0: _O>'_
+U+1ed1: _o>'_
+U+1ed2: _O>!_
+U+1ed3: _o>!_
+U+1ed4: _O>2_
+U+1ed5: _o>2_
+U+1ed6: _O>?_
+U+1ed7: _o>?_
+U+1ed8: _O>-._
+U+1ed9: _o>-._
+U+1eda: _O9'_
+U+1edb: _o9'_
+U+1edc: _O9!_
+U+1edd: _o9!_
+U+1ede: _O92_
+U+1edf: _o92_
+U+1ee0: _O9?_
+U+1ee1: _o9?_
+U+1ee2: _O9-._
+U+1ee3: _o9-._
+U+1ee4: _U-._
+U+1ee5: _u-._
+U+1ee6: U2
+U+1ee7: u2
+U+1ee8: _U9'_
+U+1ee9: _u9'_
+U+1eea: _U9!_
+U+1eeb: _u9!_
+U+1eec: _U92_
+U+1eed: _u92_
+U+1eee: _U9?_
+U+1eef: _u9?_
+U+1ef0: _U9-._
+U+1ef1: _u9-._
+U+1ef2: Y!
+U+1ef3: y!
+U+1ef4: _Y-._
+U+1ef5: _y-._
+U+1ef6: Y2
+U+1ef7: y2
+U+1ef8: Y?
+U+1ef9: y?
+U+1f00: ;'
+U+1f01: ,'
+U+1f02: ;!
+U+1f03: ,!
+U+1f04: ?;
+U+1f05: ?,
+U+1f06: !:
+U+1f07: ?:
+U+2002: 1N
+U+2003: 1M
+U+2004: 3M
+U+2005: 4M
+U+2006: 6M
+U+2009: 1T
+U+200a: 1H
+U+2010: -1
+U+2013: -N
+U+2014: -M
+U+2015: -3
+U+2016: !2
+U+2017: =2
+U+2018: '6
+U+2019: '9
+U+201a: .9
+U+201b: 9'
+U+201c: "6
+U+201d: "9
+U+201e: :9
+U+201f: 9"
+U+2020: /-
+U+2021: /=
+U+2025: ..
+U+2030: %0
+U+2032: 1'
+U+2033: 2'
+U+2034: 3'
+U+2035: 1"
+U+2036: 2"
+U+2037: 3"
+U+2038: Ca
+U+2039: <1
+U+203a: >1
+U+203b: :X
+U+203c: _!*2_
+U+203e: '-
+U+2044: /f
+U+2070: 0S
+U+2074: 4S
+U+2075: 5S
+U+2076: 6S
+U+2077: 7S
+U+2078: 8S
+U+2079: 9S
+U+207a: +S
+U+207b: -S
+U+207c: =S
+U+207d: (S
+U+207e: )S
+U+207f: nS
+U+2080: 0s
+U+2081: 1s
+U+2082: 2s
+U+2083: 3s
+U+2084: 4s
+U+2085: 5s
+U+2086: 6s
+U+2087: 7s
+U+2088: 8s
+U+2089: 9s
+U+208a: +s
+U+208b: -s
+U+208c: =s
+U+208d: (s
+U+208e: )s
+U+20a4: Li
+U+20a7: Pt
+U+20a9: W=
+U+2103: oC
+U+2105: co
+U+2109: oF
+U+2116: N0
+U+2117: PO
+U+211e: Rx
+U+2120: SM
+U+2122: TM
+U+2126: Om
+U+212b: AO
+U+2153: 13
+U+2154: 23
+U+2155: 15
+U+2156: 25
+U+2157: 35
+U+2158: 45
+U+2159: 16
+U+215a: 56
+U+215b: 18
+U+215c: 38
+U+215d: 58
+U+215e: 78
+U+2160: 1R
+U+2161: 2R
+U+2162: 3R
+U+2163: 4R
+U+2164: 5R
+U+2165: 6R
+U+2166: 7R
+U+2167: 8R
+U+2168: 9R
+U+2169: aR
+U+216a: bR
+U+216b: cR
+U+216c: _50R_
+U+216d: _100R_
+U+216e: _500R_
+U+216f: _1000R_
+U+2170: 1r
+U+2171: 2r
+U+2172: 3r
+U+2173: 4r
+U+2174: 5r
+U+2175: 6r
+U+2176: 7r
+U+2177: 8r
+U+2178: 9r
+U+2179: ar
+U+217a: br
+U+217b: cr
+U+217c: _50r_
+U+217d: _100r_
+U+217e: _500r_
+U+217f: _1000r_
+U+2180: _1000RCD_
+U+2181: _5000R_
+U+2182: _10000R_
+U+2190: <-
+U+2191: -!
+U+2192: ->
+U+2193: -v
+U+2194: <>
+U+2195: UD
+U+2196: _<!!_
+U+2197: _//>_
+U+2198: _!!>_
+U+2199: _<//_
+U+21d0: <=
+U+21d2: =>
+U+21d4: ==
+U+2200: FA
+U+2202: dP
+U+2203: TE
+U+2205: /0
+U+2206: DE
+U+2207: NB
+U+2208: (-
+U+220b: -)
+U+220f: *P
+U+2211: +Z
+U+2212: -2
+U+2213: -+
+U+2217: *-
+U+2218: Ob
+U+2219: Sb
+U+221a: RT
+U+221d: 0(
+U+221e: 00
+U+221f: -L
+U+2220: -V
+U+2225: PP
+U+2227: AN
+U+2228: OR
+U+2229: (U
+U+222a: )U
+U+222b: In
+U+222c: DI
+U+222e: Io
+U+2234: .:
+U+2235: :.
+U+2236: :R
+U+2237: ::
+U+223c: ?1
+U+223e: CG
+U+2243: ?-
+U+2245: ?=
+U+2248: ?2
+U+224c: =?
+U+2253: HI
+U+2260: !=
+U+2261: =3
+U+2264: =<
+U+2265: >=
+U+226a: <*
+U+226b: *>
+U+226e: !<
+U+226f: !>
+U+2282: (C
+U+2283: )C
+U+2286: (_
+U+2287: )_
+U+2299: 0.
+U+229a: 02
+U+22a5: -T
+U+22c5: .P
+U+22ee: :3
+U+22ef: .3
+U+2302: Eh
+U+2308: <7
+U+2309: >7
+U+230a: 7<
+U+230b: 7>
+U+2310: NI
+U+2312: (A
+U+2315: TR
+U+2320: Iu
+U+2321: Il
+U+2329: </
+U+232a: />
+U+2423: Vs
+U+2440: 1h
+U+2441: 3h
+U+2442: 2h
+U+2443: 4h
+U+2446: 1j
+U+2447: 2j
+U+2448: 3j
+U+2449: 4j
+U+2460: _1-o_
+U+2461: _2-o_
+U+2462: _3-o_
+U+2463: _4-o_
+U+2464: _5-o_
+U+2465: _6-o_
+U+2466: _7-o_
+U+2467: _8-o_
+U+2468: _9-o_
+U+2469: _10-o_
+U+246a: _11-o_
+U+246b: _12-o_
+U+246c: _13-o_
+U+246d: _14-o_
+U+246e: _15-o_
+U+246f: _16-o_
+U+2470: _17-o_
+U+2471: _18-o_
+U+2472: _19-o_
+U+2473: _20-o_
+U+2474: _(1)_
+U+2475: _(2)_
+U+2476: _(3)_
+U+2477: _(4)_
+U+2478: _(5)_
+U+2479: _(6)_
+U+247a: _(7)_
+U+247b: _(8)_
+U+247c: _(9)_
+U+247d: _(10)_
+U+247e: _(11)_
+U+247f: _(12)_
+U+2480: _(13)_
+U+2481: _(14)_
+U+2482: _(15)_
+U+2483: _(16)_
+U+2484: _(17)_
+U+2485: _(18)_
+U+2486: _(19)_
+U+2487: _(20)_
+U+2488: 1.
+U+2489: 2.
+U+248a: 3.
+U+248b: 4.
+U+248c: 5.
+U+248d: 6.
+U+248e: 7.
+U+248f: 8.
+U+2490: 9.
+U+2491: _10._
+U+2492: _11._
+U+2493: _12._
+U+2494: _13._
+U+2495: _14._
+U+2496: _15._
+U+2497: _16._
+U+2498: _17._
+U+2499: _18._
+U+249a: _19._
+U+249b: _20._
+U+249c: _(a)_
+U+249d: _(b)_
+U+249e: _(c)_
+U+249f: _(d)_
+U+24a0: _(e)_
+U+24a1: _(f)_
+U+24a2: _(g)_
+U+24a3: _(h)_
+U+24a4: _(i)_
+U+24a5: _(j)_
+U+24a6: _(k)_
+U+24a7: _(l)_
+U+24a8: _(m)_
+U+24a9: _(n)_
+U+24aa: _(o)_
+U+24ab: _(p)_
+U+24ac: _(q)_
+U+24ad: _(r)_
+U+24ae: _(s)_
+U+24af: _(t)_
+U+24b0: _(u)_
+U+24b1: _(v)_
+U+24b2: _(w)_
+U+24b3: _(x)_
+U+24b4: _(y)_
+U+24b5: _(z)_
+U+24b6: _A-o_
+U+24b7: _B-o_
+U+24b8: _C-o_
+U+24b9: _D-o_
+U+24ba: _E-o_
+U+24bb: _F-o_
+U+24bc: _G-o_
+U+24bd: _H-o_
+U+24be: _I-o_
+U+24bf: _J-o_
+U+24c0: _K-o_
+U+24c1: _L-o_
+U+24c2: _M-o_
+U+24c3: _N-o_
+U+24c4: _O-o_
+U+24c5: _P-o_
+U+24c6: _Q-o_
+U+24c7: _R-o_
+U+24c8: _S-o_
+U+24c9: _T-o_
+U+24ca: _U-o_
+U+24cb: _V-o_
+U+24cc: _W-o_
+U+24cd: _X-o_
+U+24ce: _Y-o_
+U+24cf: _Z-o_
+U+24d0: _a-o_
+U+24d1: _b-o_
+U+24d2: _c-o_
+U+24d3: _d-o_
+U+24d4: _e-o_
+U+24d5: _f-o_
+U+24d6: _g-o_
+U+24d7: _h-o_
+U+24d8: _i-o_
+U+24d9: _j-o_
+U+24da: _k-o_
+U+24db: _l-o_
+U+24dc: _m-o_
+U+24dd: _n-o_
+U+24de: _o-o_
+U+24df: _p-o_
+U+24e0: _q-o_
+U+24e1: _r-o_
+U+24e2: _s-o_
+U+24e3: _t-o_
+U+24e4: _u-o_
+U+24e5: _v-o_
+U+24e6: _w-o_
+U+24e7: _x-o_
+U+24e8: _y-o_
+U+24e9: _z-o_
+U+24ea: _0-o_
+U+2500: hh
+U+2501: HH
+U+2502: vv
+U+2503: VV
+U+2504: 3-
+U+2505: 3_
+U+2506: 3!
+U+2507: 3/
+U+2508: 4-
+U+2509: 4_
+U+250a: 4!
+U+250b: 4/
+U+250c: dr
+U+250d: dR
+U+250e: Dr
+U+250f: DR
+U+2510: dl
+U+2511: dL
+U+2512: Dl
+U+2513: LD
+U+2514: ur
+U+2515: uR
+U+2516: Ur
+U+2517: UR
+U+2518: ul
+U+2519: uL
+U+251a: Ul
+U+251b: UL
+U+251c: vr
+U+251d: vR
+U+251e: _Udr_
+U+251f: _uDr_
+U+2520: Vr
+U+2521: _UdR_
+U+2522: _uDR_
+U+2523: VR
+U+2524: vl
+U+2525: vL
+U+2526: _Udl_
+U+2527: _uDl_
+U+2528: Vl
+U+2529: _UdL_
+U+252a: _uDL_
+U+252b: VL
+U+252c: dh
+U+252d: _dLr_
+U+252e: _dlR_
+U+252f: dH
+U+2530: Dh
+U+2531: _DLr_
+U+2532: _DlR_
+U+2533: DH
+U+2534: uh
+U+2535: _uLr_
+U+2536: _ulR_
+U+2537: uH
+U+2538: Uh
+U+2539: _ULr_
+U+253a: _UlR_
+U+253b: UH
+U+253c: vh
+U+253d: _vLr_
+U+253e: _vlR_
+U+253f: vH
+U+2540: _Udh_
+U+2541: _uDh_
+U+2542: Vh
+U+2543: _UdLr_
+U+2544: _UdlR_
+U+2545: _uDLr_
+U+2546: _uDlR_
+U+2547: _UdH_
+U+2548: _uDH_
+U+2549: _VLr_
+U+254a: _VlR_
+U+254b: VH
+U+2571: FD
+U+2572: BD
+U+2580: TB
+U+2584: LB
+U+2588: FB
+U+258c: lB
+U+2590: RB
+U+2591: .S
+U+2592: :S
+U+2593: ?S
+U+25a0: fS
+U+25a1: OS
+U+25a2: RO
+U+25a3: Rr
+U+25a4: RF
+U+25a5: RY
+U+25a6: RH
+U+25a7: RZ
+U+25a8: RK
+U+25a9: RX
+U+25aa: sB
+U+25ac: SR
+U+25ad: Or
+U+25b2: UT
+U+25b3: uT
+U+25b6: PR
+U+25b7: Tr
+U+25bc: Dt
+U+25bd: dT
+U+25c0: PL
+U+25c1: Tl
+U+25c6: Db
+U+25c7: Dw
+U+25ca: LZ
+U+25cb: 0m
+U+25ce: 0o
+U+25cf: 0M
+U+25d0: 0L
+U+25d1: 0R
+U+25d8: Sn
+U+25d9: Ic
+U+25e2: Fd
+U+25e3: Bd
+U+2605: *2
+U+2606: *1
+U+260e: _TEL_
+U+260f: _tel_
+U+261c: <H
+U+261e: >H
+U+263a: 0u
+U+263b: 0U
+U+263c: SU
+U+2640: Fm
+U+2642: Ml
+U+2660: cS
+U+2661: cH
+U+2662: cD
+U+2663: cC
+U+2664: _cS-_
+U+2665: _cH-_
+U+2666: _cD-_
+U+2667: _cC-_
+U+2669: Md
+U+266a: M8
+U+266b: M2
+U+266c: _M16_
+U+266d: Mb
+U+266e: Mx
+U+266f: MX
+U+2713: OK
+U+2717: XX
+U+2720: -X
+U+3000: IS
+U+3001: ,_
+U+3002: ._
+U+3003: +"
+U+3004: +_
+U+3005: *_
+U+3006: ;_
+U+3007: 0_
+U+300a: <+
+U+300b: >+
+U+300c: <'
+U+300d: >'
+U+300e: <"
+U+300f: >"
+U+3010: ("
+U+3011: )"
+U+3012: =T
+U+3013: =_
+U+3014: ('
+U+3015: )'
+U+3016: (I
+U+3017: )I
+U+301c: -?
+U+3020: _=T:)_
+U+3041: A5
+U+3042: a5
+U+3043: I5
+U+3044: i5
+U+3045: U5
+U+3046: u5
+U+3047: E5
+U+3048: e5
+U+3049: O5
+U+304a: o5
+U+304b: ka
+U+304c: ga
+U+304d: ki
+U+304e: gi
+U+304f: ku
+U+3050: gu
+U+3051: ke
+U+3052: ge
+U+3053: ko
+U+3054: go
+U+3055: sa
+U+3056: za
+U+3057: si
+U+3058: zi
+U+3059: su
+U+305a: zu
+U+305b: se
+U+305c: ze
+U+305d: so
+U+305e: zo
+U+305f: ta
+U+3060: da
+U+3061: ti
+U+3062: di
+U+3063: tU
+U+3064: tu
+U+3065: du
+U+3066: te
+U+3067: de
+U+3068: to
+U+3069: do
+U+306a: na
+U+306b: ni
+U+306c: nu
+U+306d: ne
+U+306e: no
+U+306f: ha
+U+3070: ba
+U+3071: pa
+U+3072: hi
+U+3073: bi
+U+3074: pi
+U+3075: hu
+U+3076: bu
+U+3077: pu
+U+3078: he
+U+3079: be
+U+307a: pe
+U+307b: ho
+U+307c: bo
+U+307d: po
+U+307e: ma
+U+307f: mi
+U+3080: mu
+U+3081: me
+U+3082: mo
+U+3083: yA
+U+3084: ya
+U+3085: yU
+U+3086: yu
+U+3087: yO
+U+3088: yo
+U+3089: ra
+U+308a: ri
+U+308b: ru
+U+308c: re
+U+308d: ro
+U+308e: wA
+U+308f: wa
+U+3090: wi
+U+3091: we
+U+3092: wo
+U+3093: n5
+U+3094: vu
+U+309b: "5
+U+309c: 05
+U+309d: *5
+U+309e: +5
+U+30a1: a6
+U+30a2: A6
+U+30a3: i6
+U+30a4: I6
+U+30a5: u6
+U+30a6: U6
+U+30a7: e6
+U+30a8: E6
+U+30a9: o6
+U+30aa: O6
+U+30ab: Ka
+U+30ac: Ga
+U+30ad: Ki
+U+30ae: Gi
+U+30af: Ku
+U+30b0: Gu
+U+30b1: Ke
+U+30b2: Ge
+U+30b3: Ko
+U+30b4: Go
+U+30b5: Sa
+U+30b6: Za
+U+30b7: Si
+U+30b8: Zi
+U+30b9: Su
+U+30ba: Zu
+U+30bb: Se
+U+30bc: Ze
+U+30bd: So
+U+30be: Zo
+U+30bf: Ta
+U+30c0: Da
+U+30c1: Ti
+U+30c2: Di
+U+30c3: TU
+U+30c4: Tu
+U+30c5: Du
+U+30c6: Te
+U+30c7: De
+U+30c8: To
+U+30c9: Do
+U+30ca: Na
+U+30cb: Ni
+U+30cc: Nu
+U+30cd: Ne
+U+30ce: No
+U+30cf: Ha
+U+30d0: Ba
+U+30d1: Pa
+U+30d2: Hi
+U+30d3: Bi
+U+30d4: Pi
+U+30d5: Hu
+U+30d6: Bu
+U+30d7: Pu
+U+30d8: He
+U+30d9: Be
+U+30da: Pe
+U+30db: Ho
+U+30dc: Bo
+U+30dd: Po
+U+30de: Ma
+U+30df: Mi
+U+30e0: Mu
+U+30e1: Me
+U+30e2: Mo
+U+30e3: YA
+U+30e4: Ya
+U+30e5: YU
+U+30e6: Yu
+U+30e7: YO
+U+30e8: Yo
+U+30e9: Ra
+U+30ea: Ri
+U+30eb: Ru
+U+30ec: Re
+U+30ed: Ro
+U+30ee: WA
+U+30ef: Wa
+U+30f0: Wi
+U+30f1: We
+U+30f2: Wo
+U+30f3: N6
+U+30f4: Vu
+U+30f5: KA
+U+30f6: KE
+U+30f7: Va
+U+30f8: Vi
+U+30f9: Ve
+U+30fa: Vo
+U+30fb: .6
+U+30fc: -6
+U+30fd: *6
+U+30fe: +6
+U+3105: b4
+U+3106: p4
+U+3107: m4
+U+3108: f4
+U+3109: d4
+U+310a: t4
+U+310b: n4
+U+310c: l4
+U+310d: g4
+U+310e: k4
+U+310f: h4
+U+3110: j4
+U+3111: q4
+U+3112: x4
+U+3113: zh
+U+3114: ch
+U+3115: sh
+U+3116: r4
+U+3117: z4
+U+3118: c4
+U+3119: s4
+U+311a: a4
+U+311b: o4
+U+311c: e4
+U+311d: _eh4_
+U+311e: ai
+U+311f: ei
+U+3120: au
+U+3121: ou
+U+3122: an
+U+3123: en
+U+3124: aN
+U+3125: eN
+U+3126: er
+U+3127: i4
+U+3128: u4
+U+3129: iu
+U+312a: v4
+U+312b: nG
+U+312c: gn
+U+321c: _(JU)_
+U+3220: 1c
+U+3221: 2c
+U+3222: 3c
+U+3223: 4c
+U+3224: 5c
+U+3225: 6c
+U+3226: 7c
+U+3227: 8c
+U+3228: 9c
+U+3229: _10c_
+U+327f: _KSC_
+U+fb00: ff
+U+fb01: fi
+U+fb02: fl
+U+fb03: _ffi_
+U+fb04: _ffl_
+U+fb05: ft
+U+fb06: st
+U+fe7d: _3+;_
+U+fe82: _aM._
+U+fe84: _aH._
+U+fe8d: _a+-_
+U+fe8e: _a+._
+U+fe8f: _b+-_
+U+fe90: _b+,_
+U+fe91: _b+;_
+U+fe92: _b+._
+U+fe93: _tm-_
+U+fe94: _tm._
+U+fe95: _t+-_
+U+fe96: _t+,_
+U+fe97: _t+;_
+U+fe98: _t+._
+U+fe99: _tk-_
+U+fe9a: _tk,_
+U+fe9b: _tk;_
+U+fe9c: _tk._
+U+fe9d: _g+-_
+U+fe9e: _g+,_
+U+fe9f: _g+;_
+U+fea0: _g+._
+U+fea1: _hk-_
+U+fea2: _hk,_
+U+fea3: _hk;_
+U+fea4: _hk._
+U+fea5: _x+-_
+U+fea6: _x+,_
+U+fea7: _x+;_
+U+fea8: _x+._
+U+fea9: _d+-_
+U+feaa: _d+._
+U+feab: _dk-_
+U+feac: _dk._
+U+fead: _r+-_
+U+feae: _r+._
+U+feaf: _z+-_
+U+feb0: _z+._
+U+feb1: _s+-_
+U+feb2: _s+,_
+U+feb3: _s+;_
+U+feb4: _s+._
+U+feb5: _sn-_
+U+feb6: _sn,_
+U+feb7: _sn;_
+U+feb8: _sn._
+U+feb9: _c+-_
+U+feba: _c+,_
+U+febb: _c+;_
+U+febc: _c+._
+U+febd: _dd-_
+U+febe: _dd,_
+U+febf: _dd;_
+U+fec0: _dd._
+U+fec1: _tj-_
+U+fec2: _tj,_
+U+fec3: _tj;_
+U+fec4: _tj._
+U+fec5: _zH-_
+U+fec6: _zH,_
+U+fec7: _zH;_
+U+fec8: _zH._
+U+fec9: _e+-_
+U+feca: _e+,_
+U+fecb: _e+;_
+U+fecc: _e+._
+U+fecd: _i+-_
+U+fece: _i+,_
+U+fecf: _i+;_
+U+fed0: _i+._
+U+fed1: _f+-_
+U+fed2: _f+,_
+U+fed3: _f+;_
+U+fed4: _f+._
+U+fed5: _q+-_
+U+fed6: _q+,_
+U+fed7: _q+;_
+U+fed8: _q+._
+U+fed9: _k+-_
+U+feda: _k+,_
+U+fedb: _k+;_
+U+fedc: _k+._
+U+fedd: _l+-_
+U+fede: _l+,_
+U+fedf: _l+;_
+U+fee0: _l+._
+U+fee1: _m+-_
+U+fee2: _m+,_
+U+fee3: _m+;_
+U+fee4: _m+._
+U+fee5: _n+-_
+U+fee6: _n+,_
+U+fee7: _n+;_
+U+fee8: _n+._
+U+fee9: _h+-_
+U+feea: _h+,_
+U+feeb: _h+;_
+U+feec: _h+._
+U+feed: _w+-_
+U+feee: _w+._
+U+feef: _j+-_
+U+fef0: _j+._
+U+fef1: _y+-_
+U+fef2: _y+,_
+U+fef3: _y+;_
+U+fef4: _y+._
+U+fef5: _lM-_
+U+fef6: _lM._
+U+fef7: _lH-_
+U+fef8: _lH._
+U+fef9: _lh-_
+U+fefa: _lh._
+U+fefb: _la-_
+U+fefc: _la._
+U+0000: NU
+U+0001: SH
+U+0002: SX
+U+0003: EX
+U+0004: ET
+U+0005: EQ
+U+0006: AK
+U+0007: BL
+U+0008: BS
+U+0009: HT
+# U+000a: LF
+U+000b: VT
+U+000c: FF
+U+000d: CR
+U+000e: SO
+U+000f: SI
+U+0010: DL
+U+0011: D1
+U+0012: D2
+U+0013: D3
+U+0014: D4
+U+0015: NK
+U+0016: SY
+U+0017: EB
+U+0018: CN
+U+0019: EM
+U+001a: SB
+U+001b: EC
+U+001c: FS
+U+001d: GS
+U+001e: RS
+U+001f: US
+U+007f: DT
+U+0080: PA
+U+0081: HO
+U+0082: BH
+U+0083: NH
+U+0084: IN
+U+0085: NL
+U+0086: SA
+U+0087: ES
+U+0088: HS
+U+0089: HJ
+U+008a: VS
+U+008b: PD
+U+008c: PU
+U+008d: RI
+U+008e: S2
+U+008f: S3
+U+0090: DC
+U+0091: P1
+U+0092: P2
+U+0093: TS
+U+0094: CC
+U+0095: MW
+U+0096: SG
+U+0097: EG
+U+0098: SS
+U+0099: GC
+U+009a: SC
+U+009b: CI
+U+009c: ST
+U+009d: OC
+U+009e: PM
+U+009f: AC
+# Characters in Private Use Area (e000-f8ff) do not have ussigned numbers
+# according Unicode 2.0
diff --git a/gnu/usr.bin/lynx/src/chrtrans/next_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/next_uni.tbl
new file mode 100644
index 00000000000..d2bc974f334
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/next_uni.tbl
@@ -0,0 +1,177 @@
+#The MIME name of this charset.
+Mnext
+
+#Name as a Display Charset (used on Options screen)
+ONeXT character set
+
+# Name: NextStep Encoding to Unicode
+# Unicode version: 1.1
+# Table version: 0.1
+# Table format: Format A
+# Date: 14 February 1995
+# Authors: Rick McGowan (rick@unicode.org)
+#
+# Copyright (c) 1991-1995 Unicode, Inc. All Rights reserved.
+#
+# This file is provided as-is by Unicode, Inc. (The Unicode Consortium).
+# No claims are made as to fitness for any particular purpose. No
+# warranties of any kind are expressed or implied. The recipient
+# agrees to determine applicability of information provided. If this
+# file has been provided on magnetic media by Unicode, Inc., the sole
+# remedy for any claim will be exchange of defective media within 90
+# days of receipt.
+#
+# Recipient is granted the right to make copies in any form for
+# internal distribution and to freely use the information supplied
+# in the creation of products supporting Unicode. Unicode, Inc.
+# specifically excludes the right to re-distribute this file directly
+# to third parties or other organizations whether for profit or not.
+#
+# General notes:
+#
+# This table contains the data the Unicode Consortium has on how
+# NextStep Encoding characters map into Unicode. Since the first
+# 128 characters (0x0 - 0x7f) are identical to ASCII and Unicode,
+# this table only maps the NextStep range from 0x80 - 0xFF.
+#
+# Format: Three tab-separated columns
+# Column #1 is the NextStep code (in hex as 0xXX)
+# Column #2 is the Unicode (in hex as 0xXXXX)
+# Column #3 NextStep name, Unicode name (follows a comment sign)
+#
+# The entries are in NextStep order
+#
+# Any comments or problems, contact rick@unicode.org
+#
+#
+0x20-0x7f idem
+#
+0x80 U+00a0 # NO-BREAK SPACE
+0x81 U+00c0 # LATIN CAPITAL LETTER A WITH GRAVE
+0x82 U+00c1 # LATIN CAPITAL LETTER A WITH ACUTE
+0x83 U+00c2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0x84 U+00c3 # LATIN CAPITAL LETTER A WITH TILDE
+0x85 U+00c4 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0x86 U+00c5 # LATIN CAPITAL LETTER A WITH RING
+0x87 U+00c7 # LATIN CAPITAL LETTER C WITH CEDILLA
+0x88 U+00c8 # LATIN CAPITAL LETTER E WITH GRAVE
+0x89 U+00c9 # LATIN CAPITAL LETTER E WITH ACUTE
+0x8a U+00ca # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0x8b U+00cb # LATIN CAPITAL LETTER E WITH DIAERESIS
+0x8c U+00cc # LATIN CAPITAL LETTER I WITH GRAVE
+0x8d U+00cd # LATIN CAPITAL LETTER I WITH ACUTE
+0x8e U+00ce # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0x8f U+00cf # LATIN CAPITAL LETTER I WITH DIAERESIS
+0x90 U+00d0 # LATIN CAPITAL LETTER ETH
+0x91 U+00d1 # LATIN CAPITAL LETTER N WITH TILDE
+0x92 U+00d2 # LATIN CAPITAL LETTER O WITH GRAVE
+0x93 U+00d3 # LATIN CAPITAL LETTER O WITH ACUTE
+0x94 U+00d4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0x95 U+00d5 # LATIN CAPITAL LETTER O WITH TILDE
+0x96 U+00d6 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0x97 U+00d9 # LATIN CAPITAL LETTER U WITH GRAVE
+0x98 U+00da # LATIN CAPITAL LETTER U WITH ACUTE
+0x99 U+00db # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0x9a U+00dc # LATIN CAPITAL LETTER U WITH DIAERESIS
+0x9b U+00dd # LATIN CAPITAL LETTER Y WITH ACUTE
+0x9c U+00de # LATIN CAPITAL LETTER THORN
+0x9d U+00b5 # MICRO SIGN
+0x9e U+00d7 # MULTIPLICATION SIGN
+0x9f U+00f7 # DIVISION SIGN
+0xa0 U+00a9 # COPYRIGHT SIGN
+0xa1 U+00a1 # INVERTED EXCLAMATION MARK
+0xa2 U+00a2 # CENT SIGN
+0xa3 U+00a3 # POUND SIGN
+0xa4 U+2044 # FRACTION SLASH
+0xa5 U+00a5 # YEN SIGN
+0xa6 U+0192 # LATIN SMALL LETTER F WITH HOOK
+0xa7 U+00a7 # SECTION SIGN
+0xa8 U+00a4 # CURRENCY SIGN
+0xa9 U+2019 # RIGHT SINGLE QUOTATION MARK
+0xaa U+201c # LEFT DOUBLE QUOTATION MARK
+0xab U+00ab # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xac U+2039 # LATIN SMALL LETTER
+0xad U+203a # LATIN SMALL LETTER
+0xae U+fb01 # LATIN SMALL LIGATURE FI
+0xaf U+fb02 # LATIN SMALL LIGATURE FL
+0xb0 U+00ae # REGISTERED SIGN
+0xb1 U+2013 # EN DASH
+0xb2 U+2020 # DAGGER
+0xb3 U+2021 # DOUBLE DAGGER
+0xb4 U+00b7 # MIDDLE DOT
+0xb5 U+00a6 # BROKEN BAR
+0xb6 U+00b6 # PILCROW SIGN
+0xb7 U+2022 # BULLET
+0xb8 U+201a # SINGLE LOW-9 QUOTATION MARK
+0xb9 U+201e # DOUBLE LOW-9 QUOTATION MARK
+0xba U+201d # RIGHT DOUBLE QUOTATION MARK
+0xbb U+00bb # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0xbc U+2026 # HORIZONTAL ELLIPSIS
+0xbd U+2030 # PER MILLE SIGN
+0xbe U+00ac # NOT SIGN
+0xbf U+00bf # INVERTED QUESTION MARK
+0xc0 U+00b9 # SUPERSCRIPT ONE
+0xc1 U+02cb # MODIFIER LETTER GRAVE ACCENT
+0xc2 U+00b4 # ACUTE ACCENT
+0xc3 U+02c6 # MODIFIER LETTER CIRCUMFLEX ACCENT
+0xc4 U+02dc # SMALL TILDE
+0xc5 U+00af # MACRON
+0xc6 U+02d8 # BREVE
+0xc7 U+02d9 # DOT ABOVE
+0xc8 U+00a8 # DIAERESIS
+0xc9 U+00b2 # SUPERSCRIPT TWO
+0xca U+02da # RING ABOVE
+0xcb U+00b8 # CEDILLA
+0xcc U+00b3 # SUPERSCRIPT THREE
+0xcd U+02dd # DOUBLE ACUTE ACCENT
+0xce U+02db # OGONEK
+0xcf U+02c7 # CARON
+0xd0 U+2014 # EM DASH
+0xd1 U+00b1 # PLUS-MINUS SIGN
+0xd2 U+00bc # VULGAR FRACTION ONE QUARTER
+0xd3 U+00bd # VULGAR FRACTION ONE HALF
+0xd4 U+00be # VULGAR FRACTION THREE QUARTERS
+0xd5 U+00e0 # LATIN SMALL LETTER A WITH GRAVE
+0xd6 U+00e1 # LATIN SMALL LETTER A WITH ACUTE
+0xd7 U+00e2 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0xd8 U+00e3 # LATIN SMALL LETTER A WITH TILDE
+0xd9 U+00e4 # LATIN SMALL LETTER A WITH DIAERESIS
+0xda U+00e5 # LATIN SMALL LETTER A WITH RING ABOVE
+0xdb U+00e7 # LATIN SMALL LETTER C WITH CEDILLA
+0xdc U+00e8 # LATIN SMALL LETTER E WITH GRAVE
+0xdd U+00e9 # LATIN SMALL LETTER E WITH ACUTE
+0xde U+00ea # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0xdf U+00eb # LATIN SMALL LETTER E WITH DIAERESIS
+0xe0 U+00ec # LATIN SMALL LETTER I WITH GRAVE
+0xe1 U+00c6 # LATIN CAPITAL LETTER AE
+0xe2 U+00ed # LATIN SMALL LETTER I WITH ACUTE
+0xe3 U+00aa # FEMININE ORDINAL INDICATOR
+0xe4 U+00ee # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0xe5 U+00ef # LATIN SMALL LETTER I WITH DIAERESIS
+0xe6 U+00f0 # LATIN SMALL LETTER ETH
+0xe7 U+00f1 # LATIN SMALL LETTER N WITH TILDE
+0xe8 U+0141 # LATIN CAPITAL LETTER L WITH STROKE
+0xe9 U+00d8 # LATIN CAPITAL LETTER O WITH STROKE
+0xea U+0152 # LATIN CAPITAL LIGATURE OE
+0xeb U+00ba # MASCULINE ORDINAL INDICATOR
+0xec U+00f2 # LATIN SMALL LETTER O WITH GRAVE
+0xed U+00f3 # LATIN SMALL LETTER O WITH ACUTE
+0xee U+00f4 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0xef U+00f5 # LATIN SMALL LETTER O WITH TILDE
+0xf0 U+00f6 # LATIN SMALL LETTER O WITH DIAERESIS
+0xf1 U+00e6 # LATIN SMALL LETTER AE
+0xf2 U+00f9 # LATIN SMALL LETTER U WITH GRAVE
+0xf3 U+00fa # LATIN SMALL LETTER U WITH ACUTE
+0xf4 U+00fb # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0xf5 U+0131 # LATIN SMALL LETTER DOTLESS I
+0xf6 U+00fc # LATIN SMALL LETTER U WITH DIAERESIS
+0xf7 U+00fd # LATIN SMALL LETTER Y WITH ACUTE
+0xf8 U+0142 # LATIN SMALL LETTER L WITH STROKE
+0xf9 U+00f8 # LATIN SMALL LETTER O WITH STROKE
+0xfa U+0153 # LATIN SMALL LIGATURE OE
+0xfb U+00df # LATIN SMALL LETTER SHARP S
+0xfc U+00fe # LATIN SMALL LETTER THORN
+0xfd U+00ff # LATIN SMALL LETTER Y WITH DIAERESIS
+#0xfe U+fffd # .notdef, REPLACEMENT CHARACTER
+#0xff U+fffd # .notdef, REPLACEMENT CHARACTER
+
diff --git a/gnu/usr.bin/lynx/src/chrtrans/rfc_suni.tbl b/gnu/usr.bin/lynx/src/chrtrans/rfc_suni.tbl
new file mode 100644
index 00000000000..8ad8d54d7fe
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/rfc_suni.tbl
@@ -0,0 +1,1958 @@
+# Generated from the mnemonic file found under ftp://dkuug.dk/i18n/
+# then hand-tweaked
+# perl -n -e \
+# 'if (s|<([^ \t]+)>\s+<U([\dA-Z]{4})>\s.*$|U+\L\2\E:\1|) {s|/?(.)|\1|g&&print}'\
+# mnemonic,ds
+
+#The MIME name of this charset.
+Mmnemonic+ascii+0
+
+#Name as a Display Charset (used on Options screen)
+ORFC 1345 w/o Intro
+
+# Don't fall back to default table for unicode -> 8bit
+Fallback NO
+
+U+0020:SP
+U+0021:!
+U+0022:"
+U+0023:Nb
+U+0024:DO
+U+0025:%
+U+0026:&
+U+0027:'
+U+0028:(
+U+0029:)
+U+002a:*
+U+002b:+
+U+002c:,
+U+002d:-
+U+002e:.
+U+002f:/
+U+0030:0
+U+0031:1
+U+0032:2
+U+0033:3
+U+0034:4
+U+0035:5
+U+0036:6
+U+0037:7
+U+0038:8
+U+0039:9
+U+003a::
+U+003b:;
+U+003c:<
+U+003d:=
+U+003e:>
+U+003f:?
+U+0040:At
+U+0041:A
+U+0042:B
+U+0043:C
+U+0044:D
+U+0045:E
+U+0046:F
+U+0047:G
+U+0048:H
+U+0049:I
+U+004a:J
+U+004b:K
+U+004c:L
+U+004d:M
+U+004e:N
+U+004f:O
+U+0050:P
+U+0051:Q
+U+0052:R
+U+0053:S
+U+0054:T
+U+0055:U
+U+0056:V
+U+0057:W
+U+0058:X
+U+0059:Y
+U+005a:Z
+U+005b:<(
+U+005c://
+U+005d:)>
+U+005e:'>
+U+005f:_
+U+0060:'!
+U+0061:a
+U+0062:b
+U+0063:c
+U+0064:d
+U+0065:e
+U+0066:f
+U+0067:g
+U+0068:h
+U+0069:i
+U+006a:j
+U+006b:k
+U+006c:l
+U+006d:m
+U+006e:n
+U+006f:o
+U+0070:p
+U+0071:q
+U+0072:r
+U+0073:s
+U+0074:t
+U+0075:u
+U+0076:v
+U+0077:w
+U+0078:x
+U+0079:y
+U+007a:z
+U+007b:(!
+U+007c:!!
+U+007d:!)
+U+007e:'?
+U+00a0:NS
+U+00a1:!I
+U+00a2:Ct
+U+00a3:Pd
+U+00a4:Cu
+U+00a5:Ye
+U+00a6:BB
+U+00a7:SE
+U+00a8:':
+U+00a9:Co
+U+00aa:-a
+U+00ab:<<
+U+00ac:NO
+U+00ad:--
+U+00ae:Rg
+U+00af:'m
+U+00b0:DG
+U+00b1:+-
+U+00b2:2S
+U+00b3:3S
+U+00b4:''
+U+00b5:My
+U+00b6:PI
+U+00b7:.M
+U+00b8:',
+U+00b9:1S
+U+00ba:-o
+U+00bb:>>
+U+00bc:14
+U+00bd:12
+U+00be:34
+U+00bf:?I
+U+00c0:A!
+U+00c1:A'
+U+00c2:A>
+U+00c3:A?
+U+00c4:A:
+U+00c5:AA
+U+00c6:AE
+U+00c7:C,
+U+00c8:E!
+U+00c9:E'
+U+00ca:E>
+U+00cb:E:
+U+00cc:I!
+U+00cd:I'
+U+00ce:I>
+U+00cf:I:
+U+00d0:D-
+U+00d1:N?
+U+00d2:O!
+U+00d3:O'
+U+00d4:O>
+U+00d5:O?
+U+00d6:O:
+U+00d7:*X
+U+00d8:O/
+U+00d9:U!
+U+00da:U'
+U+00db:U>
+U+00dc:U:
+U+00dd:Y'
+U+00de:TH
+U+00df:ss
+U+00e0:a!
+U+00e1:a'
+U+00e2:a>
+U+00e3:a?
+U+00e4:a:
+U+00e5:aa
+U+00e6:ae
+U+00e7:c,
+U+00e8:e!
+U+00e9:e'
+U+00ea:e>
+U+00eb:e:
+U+00ec:i!
+U+00ed:i'
+U+00ee:i>
+U+00ef:i:
+U+00f0:d-
+U+00f1:n?
+U+00f2:o!
+U+00f3:o'
+U+00f4:o>
+U+00f5:o?
+U+00f6:o:
+U+00f7:-:
+U+00f8:o/
+U+00f9:u!
+U+00fa:u'
+U+00fb:u>
+U+00fc:u:
+U+00fd:y'
+U+00fe:th
+U+00ff:y:
+U+0100:A-
+U+0101:a-
+U+0102:A(
+U+0103:a(
+U+0104:A;
+U+0105:a;
+U+0106:C'
+U+0107:c'
+U+0108:C>
+U+0109:c>
+U+010a:C.
+U+010b:c.
+U+010c:C<
+U+010d:c<
+U+010e:D<
+U+010f:d<
+U+0110:D/
+U+0111:d/
+U+0112:E-
+U+0113:e-
+U+0114:E(
+U+0115:e(
+U+0116:E.
+U+0117:e.
+U+0118:E;
+U+0119:e;
+U+011a:E<
+U+011b:e<
+U+011c:G>
+U+011d:g>
+U+011e:G(
+U+011f:g(
+U+0120:G.
+U+0121:g.
+U+0122:G,
+U+0123:g,
+U+0124:H>
+U+0125:h>
+U+0126:H/
+U+0127:h/
+U+0128:I?
+U+0129:i?
+U+012a:I-
+U+012b:i-
+U+012c:I(
+U+012d:i(
+U+012e:I;
+U+012f:i;
+U+0130:I.
+U+0131:i.
+U+0132:IJ
+U+0133:ij
+U+0134:J>
+U+0135:j>
+U+0136:K,
+U+0137:k,
+U+0138:kk
+U+0139:L'
+U+013a:l'
+U+013b:L,
+U+013c:l,
+U+013d:L<
+U+013e:l<
+U+013f:L.
+U+0140:l.
+U+0141:L/
+U+0142:l/
+U+0143:N'
+U+0144:n'
+U+0145:N,
+U+0146:n,
+U+0147:N<
+U+0148:n<
+U+0149:'n
+U+014a:NG
+U+014b:ng
+U+014c:O-
+U+014d:o-
+U+014e:O(
+U+014f:o(
+U+0150:O"
+U+0151:o"
+U+0152:OE
+U+0153:oe
+U+0154:R'
+U+0155:r'
+U+0156:R,
+U+0157:r,
+U+0158:R<
+U+0159:r<
+U+015a:S'
+U+015b:s'
+U+015c:S>
+U+015d:s>
+U+015e:S,
+U+015f:s,
+U+0160:S<
+U+0161:s<
+U+0162:T,
+U+0163:t,
+U+0164:T<
+U+0165:t<
+U+0166:T/
+U+0167:t/
+U+0168:U?
+U+0169:u?
+U+016a:U-
+U+016b:u-
+U+016c:U(
+U+016d:u(
+U+016e:U0
+U+016f:u0
+U+0170:U"
+U+0171:u"
+U+0172:U;
+U+0173:u;
+U+0174:W>
+U+0175:w>
+U+0176:Y>
+U+0177:y>
+U+0178:Y:
+U+0179:Z'
+U+017a:z'
+U+017b:Z.
+U+017c:z.
+U+017d:Z<
+U+017e:z<
+U+017f:s1
+U+0187:C2
+U+0188:c2
+U+0191:F2
+U+0192:f2
+U+0198:K2
+U+0199:k2
+U+01a0:O9
+U+01a1:o9
+U+01a2:OI
+U+01a3:oi
+U+01a6:yr
+U+01af:U9
+U+01b0:u9
+U+01b5:Z/
+U+01b6:z/
+U+01b7:ED
+U+01cd:A<
+U+01ce:a<
+U+01cf:I<
+U+01d0:i<
+U+01d1:O<
+U+01d2:o<
+U+01d3:U<
+U+01d4:u<
+U+01d5:U:-
+U+01d6:u:-
+U+01d7:U:'
+U+01d8:u:'
+U+01d9:U:<
+U+01da:u:<
+U+01db:U:!
+U+01dc:u:!
+U+01de:A1
+U+01df:a1
+U+01e0:A7
+U+01e1:a7
+U+01e2:A3
+U+01e3:a3
+U+01e4:G/
+U+01e5:g/
+U+01e6:G<
+U+01e7:g<
+U+01e8:K<
+U+01e9:k<
+U+01ea:O;
+U+01eb:o;
+U+01ec:O1
+U+01ed:o1
+U+01ee:EZ
+U+01ef:ez
+U+01f0:j<
+U+01f4:G'
+U+01f5:g'
+U+01fa:AA'
+U+01fb:aa'
+U+01fc:AE'
+U+01fd:ae'
+U+01fe:O/'
+U+01ff:o/'
+U+0200:A!!
+U+0201:a!!
+U+0202:A)
+U+0203:a)
+U+0204:E!!
+U+0205:e!!
+U+0206:E)
+U+0207:e)
+U+0208:I!!
+U+0209:i!!
+U+020a:I)
+U+020b:i)
+U+020c:O!!
+U+020d:o!!
+U+020e:O)
+U+020f:o)
+U+0210:R!!
+U+0211:r!!
+U+0212:R)
+U+0213:r)
+U+0214:U!!
+U+0215:u!!
+U+0216:U)
+U+0217:u)
+U+0292:ed
+U+02bb:;S
+U+02c6:1>
+U+02c7:'<
+U+02c9:1-
+U+02cb:1!
+U+02d8:'(
+U+02d9:'.
+U+02da:'0
+U+02db:';
+U+02dc:1?
+U+02dd:'"
+U+0374:'G
+U+0375:,G
+U+037a:j3
+U+037e:?%
+U+0384:'*
+U+0385:'%
+U+0386:A%
+U+0387:.*
+U+0388:E%
+U+0389:Y%
+U+038a:I%
+U+038c:O%
+U+038e:U%
+U+038f:W%
+U+0390:i3
+U+0391:A*
+U+0392:B*
+U+0393:G*
+U+0394:D*
+U+0395:E*
+U+0396:Z*
+U+0397:Y*
+U+0398:H*
+U+0399:I*
+U+039a:K*
+U+039b:L*
+U+039c:M*
+U+039d:N*
+U+039e:C*
+U+039f:O*
+U+03a0:P*
+U+03a1:R*
+U+03a3:S*
+U+03a4:T*
+U+03a5:U*
+U+03a6:F*
+U+03a7:X*
+U+03a8:Q*
+U+03a9:W*
+U+03aa:J*
+U+03ab:V*
+U+03ac:a%
+U+03ad:e%
+U+03ae:y%
+U+03af:i%
+U+03b0:u3
+U+03b1:a*
+U+03b2:b*
+U+03b3:g*
+U+03b4:d*
+U+03b5:e*
+U+03b6:z*
+U+03b7:y*
+U+03b8:h*
+U+03b9:i*
+U+03ba:k*
+U+03bb:l*
+U+03bc:m*
+U+03bd:n*
+U+03be:c*
+U+03bf:o*
+U+03c0:p*
+U+03c1:r*
+U+03c2:*s
+U+03c3:s*
+U+03c4:t*
+U+03c5:u*
+U+03c6:f*
+U+03c7:x*
+U+03c8:q*
+U+03c9:w*
+U+03ca:j*
+U+03cb:v*
+U+03cc:o%
+U+03cd:u%
+U+03ce:w%
+U+03d0:b3
+U+03da:T3
+U+03db:t3
+U+03dc:M3
+U+03dd:m3
+U+03de:K3
+U+03df:k3
+U+03e0:P3
+U+03e1:p3
+U+0401:IO
+U+0402:D%
+U+0403:G%
+U+0404:IE
+U+0405:DS
+U+0406:II
+U+0407:YI
+U+0408:J%
+U+0409:LJ
+U+040a:NJ
+U+040b:Ts
+U+040c:KJ
+U+040e:V%
+U+040f:DZ
+U+0410:A=
+U+0411:B=
+U+0412:V=
+U+0413:G=
+U+0414:D=
+U+0415:E=
+U+0416:Z%
+U+0417:Z=
+U+0418:I=
+U+0419:J=
+U+041a:K=
+U+041b:L=
+U+041c:M=
+U+041d:N=
+U+041e:O=
+U+041f:P=
+U+0420:R=
+U+0421:S=
+U+0422:T=
+U+0423:U=
+U+0424:F=
+U+0425:H=
+U+0426:C=
+U+0427:C%
+U+0428:S%
+U+0429:Sc
+U+042a:="
+U+042b:Y=
+U+042c:%"
+U+042d:JE
+U+042e:JU
+U+042f:JA
+U+0430:a=
+U+0431:b=
+U+0432:v=
+U+0433:g=
+U+0434:d=
+U+0435:e=
+U+0436:z%
+U+0437:z=
+U+0438:i=
+U+0439:j=
+U+043a:k=
+U+043b:l=
+U+043c:m=
+U+043d:n=
+U+043e:o=
+U+043f:p=
+U+0440:r=
+U+0441:s=
+U+0442:t=
+U+0443:u=
+U+0444:f=
+U+0445:h=
+U+0446:c=
+U+0447:c%
+U+0448:s%
+U+0449:sc
+U+044a:='
+U+044b:y=
+U+044c:%'
+U+044d:je
+U+044e:ju
+U+044f:ja
+U+0451:io
+U+0452:d%
+U+0453:g%
+U+0454:ie
+U+0455:ds
+U+0456:ii
+U+0457:yi
+U+0458:j%
+U+0459:lj
+U+045a:nj
+U+045b:ts
+U+045c:kj
+U+045e:v%
+U+045f:dz
+U+0462:Y3
+U+0463:y3
+U+046a:O3
+U+046b:o3
+U+0472:F3
+U+0473:f3
+U+0474:V3
+U+0475:v3
+U+0480:C3
+U+0481:c3
+U+0490:G3
+U+0491:g3
+U+05d0:A+
+U+05d1:B+
+U+05d2:G+
+U+05d3:D+
+U+05d4:H+
+U+05d5:W+
+U+05d6:Z+
+U+05d7:X+
+U+05d8:Tj
+U+05d9:J+
+U+05da:K%
+U+05db:K+
+U+05dc:L+
+U+05dd:M%
+U+05de:M+
+U+05df:N%
+U+05e0:N+
+U+05e1:S+
+U+05e2:E+
+U+05e3:P%
+U+05e4:P+
+U+05e5:Zj
+U+05e6:ZJ
+U+05e7:Q+
+U+05e8:R+
+U+05e9:Sh
+U+05ea:T+
+U+060c:,+
+U+061b:;+
+U+061f:?+
+U+0621:H'
+U+0622:aM
+U+0623:aH
+U+0624:wH
+U+0625:ah
+U+0626:yH
+U+0627:a+
+U+0628:b+
+U+0629:tm
+U+062a:t+
+U+062b:tk
+U+062c:g+
+U+062d:hk
+U+062e:x+
+U+062f:d+
+U+0630:dk
+U+0631:r+
+U+0632:z+
+U+0633:s+
+U+0634:sn
+U+0635:c+
+U+0636:dd
+U+0637:tj
+U+0638:zH
+U+0639:e+
+U+063a:i+
+U+0640:++
+U+0641:f+
+U+0642:q+
+U+0643:k+
+U+0644:l+
+U+0645:m+
+U+0646:n+
+U+0647:h+
+U+0648:w+
+U+0649:j+
+U+064a:y+
+U+064b::+
+U+064c:"+
+U+064d:=+
+U+064e:/+
+U+064f:'+
+U+0650:1+
+U+0651:3+
+U+0652:0+
+U+0660:0a
+U+0661:1a
+U+0662:2a
+U+0663:3a
+U+0664:4a
+U+0665:5a
+U+0666:6a
+U+0667:7a
+U+0668:8a
+U+0669:9a
+U+0670:aS
+U+067e:p+
+U+0681:hH
+U+0686:tc
+U+0698:zj
+U+06a4:v+
+U+06af:gf
+U+1e00:A-0
+U+1e01:a-0
+U+1e02:B.
+U+1e03:b.
+U+1e04:B-.
+U+1e05:b-.
+U+1e06:B_
+U+1e07:b_
+U+1e08:C,'
+U+1e09:c,'
+U+1e0a:D.
+U+1e0b:d.
+U+1e0c:D-.
+U+1e0d:d-.
+U+1e0e:D_
+U+1e0f:d_
+U+1e10:D,
+U+1e11:d,
+U+1e12:D->
+U+1e13:d->
+U+1e14:E-!
+U+1e15:e-!
+U+1e16:E-'
+U+1e17:e-'
+U+1e18:E->
+U+1e19:e->
+U+1e1a:E-?
+U+1e1b:e-?
+U+1e1c:E,(
+U+1e1d:e,(
+U+1e1e:F.
+U+1e1f:f.
+U+1e20:G-
+U+1e21:g-
+U+1e22:H.
+U+1e23:h.
+U+1e24:H-.
+U+1e25:h-.
+U+1e26:H:
+U+1e27:h:
+U+1e28:H,
+U+1e29:h,
+U+1e2a:H-(
+U+1e2b:h-(
+U+1e2c:I-?
+U+1e2d:i-?
+U+1e2e:I:'
+U+1e2f:i:'
+U+1e30:K'
+U+1e31:k'
+U+1e32:K-.
+U+1e33:k-.
+U+1e34:K_
+U+1e35:k_
+U+1e36:L-.
+U+1e37:l-.
+U+1e38:L--.
+U+1e39:l--.
+U+1e3a:L_
+U+1e3b:l_
+U+1e3c:L->
+U+1e3d:l->
+U+1e3e:M'
+U+1e3f:m'
+U+1e40:M.
+U+1e41:m.
+U+1e42:M-.
+U+1e43:m-.
+U+1e44:N.
+U+1e45:n.
+U+1e46:N-.
+U+1e47:n-.
+U+1e48:N_
+U+1e49:n_
+U+1e4a:N->
+U+1e4b:n->
+U+1e4c:O?'
+U+1e4d:o?'
+U+1e4e:O?:
+U+1e4f:o?:
+U+1e50:O-!
+U+1e51:o-!
+U+1e52:O-'
+U+1e53:o-'
+U+1e54:P'
+U+1e55:p'
+U+1e56:P.
+U+1e57:p.
+U+1e58:R.
+U+1e59:r.
+U+1e5a:R-.
+U+1e5b:r-.
+U+1e5c:R--.
+U+1e5d:r--.
+U+1e5e:R_
+U+1e5f:r_
+U+1e60:S.
+U+1e61:s.
+U+1e62:S-.
+U+1e63:s-.
+U+1e64:S'.
+U+1e65:s'.
+U+1e66:S<.
+U+1e67:s<.
+U+1e68:S.-.
+U+1e69:s.-.
+U+1e6a:T.
+U+1e6b:t.
+U+1e6c:T-.
+U+1e6d:t-.
+U+1e6e:T_
+U+1e6f:t_
+U+1e70:T->
+U+1e71:t->
+U+1e72:U--:
+U+1e73:u--:
+U+1e74:U-?
+U+1e75:u-?
+U+1e76:U->
+U+1e77:u->
+U+1e78:U?'
+U+1e79:u?'
+U+1e7a:U-:
+U+1e7b:u-:
+U+1e7c:V?
+U+1e7d:v?
+U+1e7e:V-.
+U+1e7f:v-.
+U+1e80:W!
+U+1e81:w!
+U+1e82:W'
+U+1e83:w'
+U+1e84:W:
+U+1e85:w:
+U+1e86:W.
+U+1e87:w.
+U+1e88:W-.
+U+1e89:w-.
+U+1e8a:X.
+U+1e8b:x.
+U+1e8c:X:
+U+1e8d:x:
+U+1e8e:Y.
+U+1e8f:y.
+U+1e90:Z>
+U+1e91:z>
+U+1e92:Z-.
+U+1e93:z-.
+U+1e94:Z_
+U+1e95:z_
+U+1e96:h_
+U+1e97:t:
+U+1e98:w0
+U+1e99:y0
+U+1ea0:A-.
+U+1ea1:a-.
+U+1ea2:A2
+U+1ea3:a2
+U+1ea4:A>'
+U+1ea5:a>'
+U+1ea6:A>!
+U+1ea7:a>!
+U+1ea8:A>2
+U+1ea9:a>2
+U+1eaa:A>?
+U+1eab:a>?
+U+1eac:A>-.
+U+1ead:a>-.
+U+1eae:A('
+U+1eaf:a('
+U+1eb0:A(!
+U+1eb1:a(!
+U+1eb2:A(2
+U+1eb3:a(2
+U+1eb4:A(?
+U+1eb5:a(?
+U+1eb6:A(-.
+U+1eb7:a(-.
+U+1eb8:E-.
+U+1eb9:e-.
+U+1eba:E2
+U+1ebb:e2
+U+1ebc:E?
+U+1ebd:e?
+U+1ebe:E>'
+U+1ebf:e>'
+U+1ec0:E>!
+U+1ec1:e>!
+U+1ec2:E>2
+U+1ec3:e>2
+U+1ec4:E>?
+U+1ec5:e>?
+U+1ec6:E>-.
+U+1ec7:e>-.
+U+1ec8:I2
+U+1ec9:i2
+U+1eca:I-.
+U+1ecb:i-.
+U+1ecc:O-.
+U+1ecd:o-.
+U+1ece:O2
+U+1ecf:o2
+U+1ed0:O>'
+U+1ed1:o>'
+U+1ed2:O>!
+U+1ed3:o>!
+U+1ed4:O>2
+U+1ed5:o>2
+U+1ed6:O>?
+U+1ed7:o>?
+U+1ed8:O>-.
+U+1ed9:o>-.
+U+1eda:O9'
+U+1edb:o9'
+U+1edc:O9!
+U+1edd:o9!
+U+1ede:O92
+U+1edf:o92
+U+1ee0:O9?
+U+1ee1:o9?
+U+1ee2:O9-.
+U+1ee3:o9-.
+U+1ee4:U-.
+U+1ee5:u-.
+U+1ee6:U2
+U+1ee7:u2
+U+1ee8:U9'
+U+1ee9:u9'
+U+1eea:U9!
+U+1eeb:u9!
+U+1eec:U92
+U+1eed:u92
+U+1eee:U9?
+U+1eef:u9?
+U+1ef0:U9-.
+U+1ef1:u9-.
+U+1ef2:Y!
+U+1ef3:y!
+U+1ef4:Y-.
+U+1ef5:y-.
+U+1ef6:Y2
+U+1ef7:y2
+U+1ef8:Y?
+U+1ef9:y?
+U+1fbf:,,
+U+1fc0:?*
+U+1fc1:?:
+U+1fcd:,!
+U+1fce:,'
+U+1fcf:?,
+U+1fdd:;!
+U+1fde:;'
+U+1fdf:?;
+U+1fed:!:
+U+1fef:!*
+U+1ffe:;;
+U+2002:1N
+U+2003:1M
+U+2004:3M
+U+2005:4M
+U+2006:6M
+U+200e:LR
+U+200f:RL
+U+2009:1T
+U+200a:1H
+U+2010:-1
+U+2013:-N
+U+2014:-M
+U+2015:-3
+U+2016:!2
+U+2017:=2
+U+2018:'6
+U+2019:'9
+U+201a:.9
+U+201b:9'
+U+201c:"6
+U+201d:"9
+U+201e::9
+U+201f:9"
+U+2020:/-
+U+2021:/=
+U+2022:Sb
+U+2025:..
+U+2026:.3
+U+2030:%0
+U+2032:1'
+U+2033:2'
+U+2034:3'
+U+2035:1"
+U+2036:2"
+U+2037:3"
+U+2038:Ca
+U+2039:<1
+U+203a:>1
+U+203b::X
+U+203c:!*2
+U+203e:'-
+U+2044:/f
+U+2070:0S
+U+2074:4S
+U+2075:5S
+U+2076:6S
+U+2077:7S
+U+2078:8S
+U+2079:9S
+U+207a:+S
+U+207b:-S
+U+207c:=S
+U+207d:(S
+U+207e:)S
+U+207f:nS
+U+2080:0s
+U+2081:1s
+U+2082:2s
+U+2083:3s
+U+2084:4s
+U+2085:5s
+U+2086:6s
+U+2087:7s
+U+2088:8s
+U+2089:9s
+U+208a:+s
+U+208b:-s
+U+208c:=s
+U+208d:(s
+U+208e:)s
+U+20a3:Ff
+U+20a4:Li
+U+20a7:Pt
+U+20a9:W=
+U+2103:oC
+U+2105:co
+U+2109:oF
+U+2116:N0
+U+2117:PO
+U+211e:Rx
+U+2120:SM
+U+2122:TM
+U+2126:Om
+U+212b:AO
+U+2153:13
+U+2154:23
+U+2155:15
+U+2156:25
+U+2157:35
+U+2158:45
+U+2159:16
+U+215a:56
+U+215b:18
+U+215c:38
+U+215d:58
+U+215e:78
+U+2160:1R
+U+2161:2R
+U+2162:3R
+U+2163:4R
+U+2164:5R
+U+2165:6R
+U+2166:7R
+U+2167:8R
+U+2168:9R
+U+2169:aR
+U+216a:bR
+U+216b:cR
+U+216c:50R
+U+216d:100R
+U+216e:500R
+U+216f:1000R
+U+2170:1r
+U+2171:2r
+U+2172:3r
+U+2173:4r
+U+2174:5r
+U+2175:6r
+U+2176:7r
+U+2177:8r
+U+2178:9r
+U+2179:ar
+U+217a:br
+U+217b:cr
+U+217c:50r
+U+217d:100r
+U+217e:500r
+U+217f:1000r
+U+2180:1000RCD
+U+2181:5000R
+U+2182:10000R
+U+2190:<-
+U+2191:-!
+U+2192:->
+U+2193:-v
+U+2194:<>
+U+2195:UD
+U+2196:<!!
+U+2197://>
+U+2198:!!>
+U+2199:<//
+U+21a8:UD-
+U+21c0:>V
+U+21d0:<=
+U+21d2:=>
+U+21d4:==
+U+2200:FA
+U+2202:dP
+U+2203:TE
+U+2205:/0
+U+2206:DE
+U+2207:NB
+U+2208:(-
+U+220b:-)
+U+220f:*P
+U+2211:+Z
+U+2212:-2
+U+2213:-+
+U+2214:.+
+U+2217:*-
+U+2218:Ob
+U+2219:sb
+U+221a:RT
+U+221d:0(
+U+221e:00
+U+221f:-L
+U+2220:-V
+U+2225:PP
+U+2227:AN
+U+2228:OR
+U+2229:(U
+U+222a:)U
+U+222b:In
+U+222c:DI
+U+222e:Io
+U+2234:.:
+U+2235::.
+U+2236::R
+U+2237:::
+U+223c:?1
+U+223e:CG
+U+2243:?-
+U+2245:?=
+U+2248:?2
+U+224c:=?
+U+2253:HI
+U+2260:!=
+U+2261:=3
+U+2264:=<
+U+2265:>=
+U+226a:<*
+U+226b:*>
+U+226e:!<
+U+226f:!>
+U+2282:(C
+U+2283:)C
+U+2286:(_
+U+2287:)_
+U+2299:0.
+U+229a:02
+U+22a5:-T
+U+22c5:.P
+U+22ee::3
+U+2302:Eh
+U+2308:<7
+U+2309:>7
+U+230a:7<
+U+230b:7>
+U+2310:NI
+U+2312:(A
+U+2315:TR
+U+2318:88
+U+2320:Iu
+U+2321:Il
+U+2329:</
+U+232a:/>
+U+2423:Vs
+U+2440:1h
+U+2441:3h
+U+2442:2h
+U+2443:4h
+U+2446:1j
+U+2447:2j
+U+2448:3j
+U+2449:4j
+U+2460:1-o
+U+2461:2-o
+U+2462:3-o
+U+2463:4-o
+U+2464:5-o
+U+2465:6-o
+U+2466:7-o
+U+2467:8-o
+U+2468:9-o
+U+2469:10-o
+U+246a:11-o
+U+246b:12-o
+U+246c:13-o
+U+246d:14-o
+U+246e:15-o
+U+246f:16-o
+U+2470:17-o
+U+2471:18-o
+U+2472:19-o
+U+2473:20-o
+U+2474:(1)
+U+2475:(2)
+U+2476:(3)
+U+2477:(4)
+U+2478:(5)
+U+2479:(6)
+U+247a:(7)
+U+247b:(8)
+U+247c:(9)
+U+247d:(10)
+U+247e:(11)
+U+247f:(12)
+U+2480:(13)
+U+2481:(14)
+U+2482:(15)
+U+2483:(16)
+U+2484:(17)
+U+2485:(18)
+U+2486:(19)
+U+2487:(20)
+U+2488:1.
+U+2489:2.
+U+248a:3.
+U+248b:4.
+U+248c:5.
+U+248d:6.
+U+248e:7.
+U+248f:8.
+U+2490:9.
+U+2491:10.
+U+2492:11.
+U+2493:12.
+U+2494:13.
+U+2495:14.
+U+2496:15.
+U+2497:16.
+U+2498:17.
+U+2499:18.
+U+249a:19.
+U+249b:20.
+U+249c:(a)
+U+249d:(b)
+U+249e:(c)
+U+249f:(d)
+U+24a0:(e)
+U+24a1:(f)
+U+24a2:(g)
+U+24a3:(h)
+U+24a4:(i)
+U+24a5:(j)
+U+24a6:(k)
+U+24a7:(l)
+U+24a8:(m)
+U+24a9:(n)
+U+24aa:(o)
+U+24ab:(p)
+U+24ac:(q)
+U+24ad:(r)
+U+24ae:(s)
+U+24af:(t)
+U+24b0:(u)
+U+24b1:(v)
+U+24b2:(w)
+U+24b3:(x)
+U+24b4:(y)
+U+24b5:(z)
+U+24b6:A-o
+U+24b7:B-o
+U+24b8:C-o
+U+24b9:D-o
+U+24ba:E-o
+U+24bb:F-o
+U+24bc:G-o
+U+24bd:H-o
+U+24be:I-o
+U+24bf:J-o
+U+24c0:K-o
+U+24c1:L-o
+U+24c2:M-o
+U+24c3:N-o
+U+24c4:O-o
+U+24c5:P-o
+U+24c6:Q-o
+U+24c7:R-o
+U+24c8:S-o
+U+24c9:T-o
+U+24ca:U-o
+U+24cb:V-o
+U+24cc:W-o
+U+24cd:X-o
+U+24ce:Y-o
+U+24cf:Z-o
+U+24d0:a-o
+U+24d1:b-o
+U+24d2:c-o
+U+24d3:d-o
+U+24d4:e-o
+U+24d5:f-o
+U+24d6:g-o
+U+24d7:h-o
+U+24d8:i-o
+U+24d9:j-o
+U+24da:k-o
+U+24db:l-o
+U+24dc:m-o
+U+24dd:n-o
+U+24de:o-o
+U+24df:p-o
+U+24e0:q-o
+U+24e1:r-o
+U+24e2:s-o
+U+24e3:t-o
+U+24e4:u-o
+U+24e5:v-o
+U+24e6:w-o
+U+24e7:x-o
+U+24e8:y-o
+U+24e9:z-o
+U+24ea:0-o
+U+2500:hh
+U+2501:HH-
+U+2502:vv
+U+2503:VV-
+U+2504:3-
+U+2505:3_
+U+2506:3!
+U+2507:3/
+U+2508:4-
+U+2509:4_
+U+250a:4!
+U+250b:4/
+U+250c:dr
+U+250d:dR-
+U+250e:Dr-
+U+250f:DR-
+U+2510:dl
+U+2511:dL-
+U+2512:Dl-
+U+2513:LD-
+U+2514:ur
+U+2515:uR-
+U+2516:Ur-
+U+2517:UR-
+U+2518:ul
+U+2519:uL-
+U+251a:Ul-
+U+251b:UL-
+U+251c:vr
+U+251d:vR-
+U+251e:Udr
+U+251f:uDr
+U+2520:Vr-
+U+2521:UdR
+U+2522:uDR
+U+2523:VR-
+U+2524:vl
+U+2525:vL-
+U+2526:Udl
+U+2527:uDl
+U+2528:Vl-
+U+2529:UdL
+U+252a:uDL
+U+252b:VL-
+U+252c:dh
+U+252d:dLr
+U+252e:dlR
+U+252f:dH-
+U+2530:Dh-
+U+2531:DLr
+U+2532:DlR
+U+2533:DH-
+U+2534:uh
+U+2535:uLr
+U+2536:ulR
+U+2537:uH-
+U+2538:Uh-
+U+2539:ULr
+U+253a:UlR
+U+253b:UH-
+U+253c:vh
+U+253d:vLr
+U+253e:vlR
+U+253f:vH-
+U+2540:Udh
+U+2541:uDh
+U+2542:Vh-
+U+2543:UdLr
+U+2544:UdlR
+U+2545:uDLr
+U+2546:uDlR
+U+2547:UdH
+U+2548:uDH
+U+2549:VLr
+U+254a:VlR
+U+254b:VH-
+U+2550:HH
+U+2551:VV
+U+2552:dR
+U+2553:Dr
+U+2554:DR
+U+2555:dL
+U+2556:Dl
+U+2557:LD
+U+2558:uR
+U+2559:Ur
+U+255a:UR
+U+255b:uL
+U+255c:Ul
+U+255d:UL
+U+255e:vR
+U+255f:Vr
+U+2560:VR
+U+2561:vL
+U+2562:Vl
+U+2563:VL
+U+2564:dH
+U+2565:Dh
+U+2566:DH
+U+2567:uH
+U+2568:Uh
+U+2569:UH
+U+256a:vH
+U+256b:Vh
+U+256c:VH
+U+2571:FD
+U+2572:BD
+U+2580:TB
+U+2584:LB
+U+2588:FB
+U+258c:lB
+U+2590:RB
+U+2591:.S
+U+2592::S
+U+2593:?S
+U+25a0:fS
+U+25a1:OS
+U+25a2:RO
+U+25a3:Rr
+U+25a4:RF
+U+25a5:RY
+U+25a6:RH
+U+25a7:RZ
+U+25a8:RK
+U+25a9:RX
+U+25aa:sB
+U+25ac:SR
+U+25ad:Or
+U+25b2:UT
+U+25b3:uT
+U+25b7:Tr
+U+25ba:PR
+U+25bc:Dt
+U+25bd:dT
+U+25c1:Tl
+U+25c4:PL
+U+25c6:Db
+U+25c7:Dw
+U+25ca:LZ
+U+25cb:0m
+U+25ce:0o
+U+25cf:0M
+U+25d0:0L
+U+25d1:0R
+U+25d8:Sn
+U+25d9:Ic
+U+25e2:Fd
+U+25e3:Bd
+U+25ef:Ci
+U+2605:*2
+U+2606:*1
+U+260e:TEL
+U+260f:tel
+U+261c:<H
+U+261e:>H
+U+263a:0u
+U+263b:0U
+U+263c:SU
+U+2640:Fm
+U+2642:Ml
+U+2660:cS
+U+2661:cH
+U+2662:cD
+U+2663:cC
+U+2664:cS-
+U+2665:cH-
+U+2666:cD-
+U+2667:cC-
+U+2669:Md
+U+266a:M8
+U+266b:M2
+U+266c:M16
+U+266d:Mb
+U+266e:Mx
+U+266f:MX
+U+2713:OK
+U+2717:XX
+U+2720:-X
+U+3000:IS
+U+3001:,_
+U+3002:._
+U+3003:+"
+U+3004:JIS
+U+3005:*_
+U+3006:;_
+U+3007:0_
+U+300a:<+
+U+300b:>+
+U+300c:<'
+U+300d:>'
+U+300e:<"
+U+300f:>"
+U+3010:("
+U+3011:)"
+U+3012:=T
+U+3013:=_
+U+3014:('
+U+3015:)'
+U+3016:(I
+U+3017:)I
+U+301c:-?
+U+3020:=T:)
+U+3041:A5
+U+3042:a5
+U+3043:I5
+U+3044:i5
+U+3045:U5
+U+3046:u5
+U+3047:E5
+U+3048:e5
+U+3049:O5
+U+304a:o5
+U+304b:ka
+U+304c:ga
+U+304d:ki
+U+304e:gi
+U+304f:ku
+U+3050:gu
+U+3051:ke
+U+3052:ge
+U+3053:ko
+U+3054:go
+U+3055:sa
+U+3056:za
+U+3057:si
+U+3058:zi
+U+3059:su
+U+305a:zu
+U+305b:se
+U+305c:ze
+U+305d:so
+U+305e:zo
+U+305f:ta
+U+3060:da
+U+3061:ti
+U+3062:di
+U+3063:tU
+U+3064:tu
+U+3065:du
+U+3066:te
+U+3067:de
+U+3068:to
+U+3069:do
+U+306a:na
+U+306b:ni
+U+306c:nu
+U+306d:ne
+U+306e:no
+U+306f:ha
+U+3070:ba
+U+3071:pa
+U+3072:hi
+U+3073:bi
+U+3074:pi
+U+3075:hu
+U+3076:bu
+U+3077:pu
+U+3078:he
+U+3079:be
+U+307a:pe
+U+307b:ho
+U+307c:bo
+U+307d:po
+U+307e:ma
+U+307f:mi
+U+3080:mu
+U+3081:me
+U+3082:mo
+U+3083:yA
+U+3084:ya
+U+3085:yU
+U+3086:yu
+U+3087:yO
+U+3088:yo
+U+3089:ra
+U+308a:ri
+U+308b:ru
+U+308c:re
+U+308d:ro
+U+308e:wA
+U+308f:wa
+U+3090:wi
+U+3091:we
+U+3092:wo
+U+3093:n5
+U+3094:vu
+U+309b:"5
+U+309c:05
+U+309d:*5
+U+309e:+5
+U+30a1:a6
+U+30a2:A6
+U+30a3:i6
+U+30a4:I6
+U+30a5:u6
+U+30a6:U6
+U+30a7:e6
+U+30a8:E6
+U+30a9:o6
+U+30aa:O6
+U+30ab:Ka
+U+30ac:Ga
+U+30ad:Ki
+U+30ae:Gi
+U+30af:Ku
+U+30b0:Gu
+U+30b1:Ke
+U+30b2:Ge
+U+30b3:Ko
+U+30b4:Go
+U+30b5:Sa
+U+30b6:Za
+U+30b7:Si
+U+30b8:Zi
+U+30b9:Su
+U+30ba:Zu
+U+30bb:Se
+U+30bc:Ze
+U+30bd:So
+U+30be:Zo
+U+30bf:Ta
+U+30c0:Da
+U+30c1:Ti
+U+30c2:Di
+U+30c3:TU
+U+30c4:Tu
+U+30c5:Du
+U+30c6:Te
+U+30c7:De
+U+30c8:To
+U+30c9:Do
+U+30ca:Na
+U+30cb:Ni
+U+30cc:Nu
+U+30cd:Ne
+U+30ce:No
+U+30cf:Ha
+U+30d0:Ba
+U+30d1:Pa
+U+30d2:Hi
+U+30d3:Bi
+U+30d4:Pi
+U+30d5:Hu
+U+30d6:Bu
+U+30d7:Pu
+U+30d8:He
+U+30d9:Be
+U+30da:Pe
+U+30db:Ho
+U+30dc:Bo
+U+30dd:Po
+U+30de:Ma
+U+30df:Mi
+U+30e0:Mu
+U+30e1:Me
+U+30e2:Mo
+U+30e3:YA
+U+30e4:Ya
+U+30e5:YU
+U+30e6:Yu
+U+30e7:YO
+U+30e8:Yo
+U+30e9:Ra
+U+30ea:Ri
+U+30eb:Ru
+U+30ec:Re
+U+30ed:Ro
+U+30ee:WA
+U+30ef:Wa
+U+30f0:Wi
+U+30f1:We
+U+30f2:Wo
+U+30f3:N6
+U+30f4:Vu
+U+30f5:KA
+U+30f6:KE
+U+30f7:Va
+U+30f8:Vi
+U+30f9:Ve
+U+30fa:Vo
+U+30fb:.6
+U+30fc:-6
+U+30fd:*6
+U+30fe:+6
+U+3105:b4
+U+3106:p4
+U+3107:m4
+U+3108:f4
+U+3109:d4
+U+310a:t4
+U+310b:n4
+U+310c:l4
+U+310d:g4
+U+310e:k4
+U+310f:h4
+U+3110:j4
+U+3111:q4
+U+3112:x4
+U+3113:zh
+U+3114:ch
+U+3115:sh
+U+3116:r4
+U+3117:z4
+U+3118:c4
+U+3119:s4
+U+311a:a4
+U+311b:o4
+U+311c:e4
+U+311d:eh4
+U+311e:ai
+U+311f:ei
+U+3120:au
+U+3121:ou
+U+3122:an
+U+3123:en
+U+3124:aN
+U+3125:eN
+U+3126:er
+U+3127:i4
+U+3128:u4
+U+3129:iu
+U+312a:v4
+U+312b:nG
+U+312c:gn
+U+321c:(JU)
+U+3220:1c
+U+3221:2c
+U+3222:3c
+U+3223:4c
+U+3224:5c
+U+3225:6c
+U+3226:7c
+U+3227:8c
+U+3228:9c
+U+3229:10c
+U+327f:KSC
+U+33c2:am
+U+33d8:pm
+U+fb00:ff
+U+fb01:fi
+U+fb02:fl
+U+fb03:ffi
+U+fb04:ffl
+U+fb05:St
+U+fb06:st
+U+fe7d:3+;
+U+fe82:aM.
+U+fe84:aH.
+U+fe88:ah.
+U+fe8d:a+-
+U+fe8e:a+.
+U+fe8f:b+-
+U+fe90:b+.
+U+fe91:b+,
+U+fe92:b+;
+U+fe93:tm-
+U+fe94:tm.
+U+fe95:t+-
+U+fe96:t+.
+U+fe97:t+,
+U+fe98:t+;
+U+fe99:tk-
+U+fe9a:tk.
+U+fe9b:tk,
+U+fe9c:tk;
+U+fe9d:g+-
+U+fe9e:g+.
+U+fe9f:g+,
+U+fea0:g+;
+U+fea1:hk-
+U+fea2:hk.
+U+fea3:hk,
+U+fea4:hk;
+U+fea5:x+-
+U+fea6:x+.
+U+fea7:x+,
+U+fea8:x+;
+U+fea9:d+-
+U+feaa:d+.
+U+feab:dk-
+U+feac:dk.
+U+fead:r+-
+U+feae:r+.
+U+feaf:z+-
+U+feb0:z+.
+U+feb1:s+-
+U+feb2:s+.
+U+feb3:s+,
+U+feb4:s+;
+U+feb5:sn-
+U+feb6:sn.
+U+feb7:sn,
+U+feb8:sn;
+U+feb9:c+-
+U+feba:c+.
+U+febb:c+,
+U+febc:c+;
+U+febd:dd-
+U+febe:dd.
+U+febf:dd,
+U+fec0:dd;
+U+fec1:tj-
+U+fec2:tj.
+U+fec3:tj,
+U+fec4:tj;
+U+fec5:zH-
+U+fec6:zH.
+U+fec7:zH,
+U+fec8:zH;
+U+fec9:e+-
+U+feca:e+.
+U+fecb:e+,
+U+fecc:e+;
+U+fecd:i+-
+U+fece:i+.
+U+fecf:i+,
+U+fed0:i+;
+U+fed1:f+-
+U+fed2:f+.
+U+fed3:f+,
+U+fed4:f+;
+U+fed5:q+-
+U+fed6:q+.
+U+fed7:q+,
+U+fed8:q+;
+U+fed9:k+-
+U+feda:k+.
+U+fedb:k+,
+U+fedc:k+;
+U+fedd:l+-
+U+fede:l+.
+U+fedf:l+,
+U+fee0:l+;
+U+fee1:m+-
+U+fee2:m+.
+U+fee3:m+,
+U+fee4:m+;
+U+fee5:n+-
+U+fee6:n+.
+U+fee7:n+,
+U+fee8:n+;
+U+fee9:h+-
+U+feea:h+.
+U+feeb:h+,
+U+feec:h+;
+U+feed:w+-
+U+feee:w+.
+U+feef:j+-
+U+fef0:j+.
+U+fef1:y+-
+U+fef2:y+.
+U+fef3:y+,
+U+fef4:y+;
+U+fef5:lM-
+U+fef6:lM.
+U+fef7:lH-
+U+fef8:lH.
+U+fef9:lh-
+U+fefa:lh.
+U+fefb:la-
+U+fefc:la.
+U+0000:NU
+U+0001:SH
+U+0002:SX
+U+0003:EX
+U+0004:ET
+U+0005:EQ
+U+0006:AK
+U+0007:BL
+U+0008:BS
+U+0009:HT
+U+000a:LF
+U+000b:VT
+U+000c:FF
+U+000d:CR
+U+000e:SO
+U+000f:SI
+U+0010:DL
+U+0011:D1
+U+0012:D2
+U+0013:D3
+U+0014:D4
+U+0015:NK
+U+0016:SY
+U+0017:EB
+U+0018:CN
+U+0019:EM
+U+001a:SB
+U+001b:EC
+U+001c:FS
+U+001d:GS
+U+001e:RS
+U+001f:US
+U+007f:DT
+U+0080:PA
+U+0081:HO
+U+0082:BH
+U+0083:NH
+U+0084:IN
+U+0085:NL
+U+0086:SA
+U+0087:ES
+U+0088:HS
+U+0089:HJ
+U+008a:VS
+U+008b:PD
+U+008c:PU
+U+008d:RI
+U+008e:S2
+U+008f:S3
+U+0090:DC
+U+0091:P1
+U+0092:P2
+U+0093:TS
+U+0094:CC
+U+0095:MW
+U+0096:SG
+U+0097:EG
+U+0098:SS
+U+0099:GC
+U+009a:SC
+U+009b:CI
+U+009c:ST
+U+009d:OC
+U+009e:PM
+U+009f:AC
+# Characters in Private Use Area (e000-f8ff) do not have ussigned numbers
+# according Unicode 2.0
diff --git a/gnu/usr.bin/lynx/src/chrtrans/utf8_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/utf8_uni.tbl
new file mode 100644
index 00000000000..67ff3460640
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/utf8_uni.tbl
@@ -0,0 +1,35 @@
+#
+# This one is not really much of a "translation table", it mostly just
+# tells Lynx that "utf-8" is Unicode/UCS2 encoded in UTF8. Note that
+# "unicode-1-1-utf-8" and "utf8" are treated as synonyms.
+#
+#The MIME name of this charset.
+Mutf-8
+
+#Name as a Display Charset (used on Options screen)
+OUNICODE UTF-8
+
+# Some kind of raw Unicode?
+# Use 6 for for really "raw" 16bit UCS-2, 7 for UTF-8, ...
+
+# most of these codes currently don't make much sense in a *.tbl file,
+# but for completeness (from UCDefs.h):
+# #define UCT_ENC_7BIT 0
+# #define UCT_ENC_8BIT 1
+# #define UCT_ENC_8859 2
+# #define UCT_ENC_8BIT_C0 3
+# #define UCT_ENC_MAYBE2022 4
+# #define UCT_ENC_CJK 5
+# #define UCT_ENC_16BIT 6
+# #define UCT_ENC_UTF8 7
+
+R 7
+
+#Shall this become the "default" translation?
+#There has to be exactly one table marked as "default".
+Default NO
+
+# Don't fall back to default table for unicode -> 8bit
+Fallback NO
+
+0x20-0x7f idem
diff --git a/gnu/usr.bin/lynx/src/chrtrans/viscii_uni.tbl b/gnu/usr.bin/lynx/src/chrtrans/viscii_uni.tbl
new file mode 100644
index 00000000000..5b05585621a
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/chrtrans/viscii_uni.tbl
@@ -0,0 +1,300 @@
+#
+# Unicode mapping table for VISCII 1.1 fonts and charset=viscii,
+# described in RFC 1456.
+# See also <URL:http://www.trichlor.org/vietstd/report/rep92.htm>,
+# also for testing.
+# The 6 characters encoded in the C0 control region should not
+# be passed through to the terminal but be mapped to VIQR strings.
+# THe two changed mappings of MacVISCII are recognized in documents.
+
+# [convert with makeuctb]
+#
+#The MIME name of this charset.
+Mviscii
+
+#Name as a Display Charset (used on Options screen).
+OVietnamese (VISCII)
+
+# Special 'enc' flag to signal that some C0 characters are used.
+# Tables with R3 should properly map the allowed C0 control chars!
+#
+# most of these codes currently don't make much sense in a *.tbl file,
+# but for completeness (from UCDefs.h):
+# #define UCT_ENC_7BIT 0
+# #define UCT_ENC_8BIT 1
+# #define UCT_ENC_8859 2
+# #define UCT_ENC_8BIT_C0 3
+# #define UCT_ENC_MAYBE2022 4
+# #define UCT_ENC_CJK 5
+# #define UCT_ENC_16BIT 6
+# #define UCT_ENC_UTF8 7
+
+R 3
+
+#0x00 U+0000
+#0x01 U+0001
+#0x03 U+0003
+#0x04 U+0004
+#0x07 U+0007
+#0x08 U+0008
+0x09 U+0009
+0x0a U+000a
+#0x0b U+000b
+0x0c U+000c
+U+000c:
+0x0d U+000d
+#0x0e U+000e
+#0x0f U+000f
+#0x10 U+0010
+#0x11 U+0011
+#0x12 U+0012
+#0x13 U+0013
+#0x15 U+0015
+#0x16 U+0016
+#0x17 U+0017
+#0x18 U+0018
+0x1a U+001a
+U+001a:^Z
+#0x1b U+001b
+#0x1c U+001c
+#0x1d U+001d
+#0x1f U+001f
+#0x20 U+0020
+#0x21 U+0021
+#0x22 U+0022
+#0x23 U+0023
+#0x24 U+0024
+#0x25 U+0025
+#0x26 U+0026
+#0x27 U+0027
+#0x28 U+0028
+#0x29 U+0029
+#0x2a U+002a
+#0x2b U+002b
+#0x2c U+002c
+#0x2d U+002d
+#0x2e U+002e
+#0x2f U+002f
+#0x30 U+0030
+#0x31 U+0031
+#0x32 U+0032
+#0x33 U+0033
+#0x34 U+0034
+#0x35 U+0035
+#0x36 U+0036
+#0x37 U+0037
+#0x38 U+0038
+#0x39 U+0039
+#0x3a U+003a
+#0x3b U+003b
+#0x3c U+003c
+#0x3d U+003d
+#0x3e U+003e
+#0x3f U+003f
+#0x40 U+0040
+#0x41 U+0041
+#0x42 U+0042
+#0x43 U+0043
+#0x44 U+0044
+#0x45 U+0045
+#0x46 U+0046
+#0x47 U+0047
+#0x48 U+0048
+#0x49 U+0049
+#0x4a U+004a
+#0x4b U+004b
+#0x4c U+004c
+#0x4d U+004d
+#0x4e U+004e
+#0x4f U+004f
+#0x50 U+0050
+#0x51 U+0051
+#0x52 U+0052
+#0x53 U+0053
+#0x54 U+0054
+#0x55 U+0055
+#0x56 U+0056
+#0x57 U+0057
+#0x58 U+0058
+#0x59 U+0059
+#0x5a U+005a
+#0x5b U+005b
+#0x5c U+005c
+#0x5d U+005d
+#0x5e U+005e
+#0x5f U+005f
+#0x60 U+0060
+#0x61 U+0061
+#0x62 U+0062
+#0x63 U+0063
+#0x64 U+0064
+#0x65 U+0065
+#0x66 U+0066
+#0x67 U+0067
+#0x68 U+0068
+#0x69 U+0069
+#0x6a U+006a
+#0x6b U+006b
+#0x6c U+006c
+#0x6d U+006d
+#0x6e U+006e
+#0x6f U+006f
+#0x70 U+0070
+#0x71 U+0071
+#0x72 U+0072
+#0x73 U+0073
+#0x74 U+0074
+#0x75 U+0075
+#0x76 U+0076
+#0x77 U+0077
+#0x78 U+0078
+#0x79 U+0079
+#0x7a U+007a
+#0x7b U+007b
+#0x7c U+007c
+#0x7d U+007d
+#0x7e U+007e
+#0x7f U+007f
+0xc0 U+00c0
+0xc1 U+00c1
+0xc2 U+00c2
+0xc3 U+00c3
+0xc8 U+00c8
+0xc9 U+00c9
+0xca U+00ca
+0xcc U+00cc
+0xcd U+00cd
+0xd2 U+00d2
+0xd3 U+00d3
+0xd4 U+00d4
+0xa0 U+00d5
+0xd9 U+00d9
+0xda U+00da
+0xdd U+00dd
+0xe0 U+00e0
+0xe1 U+00e1
+0xe2 U+00e2
+0xe3 U+00e3
+0xe8 U+00e8
+0xe9 U+00e9
+0xea U+00ea
+0xec U+00ec
+0xed U+00ed
+0xf2 U+00f2
+0xf3 U+00f3
+0xf4 U+00f4
+0xf5 U+00f5
+0xf9 U+00f9
+0xfa U+00fa
+0xfd U+00fd
+0xc5 U+0102
+0xe5 U+0103
+0xd0 U+0110
+0xf0 U+0111 U+00f0 # "edh" is similar enough to map it here
+0xce U+0128
+0xee U+0129
+0x9d U+0168
+0xfb U+0169
+0xb4 U+01a0
+0xbd U+01a1
+0xbf U+01af
+0xdf U+01b0
+0x80 U+1ea0
+0xd5 U+1ea1
+0xc4 U+1ea2
+0xe4 U+1ea3
+0x84 U+1ea4
+0xa4 U+1ea5
+0x85 U+1ea6
+0xa5 U+1ea7
+0x86 U+1ea8
+0xa6 U+1ea9
+0x06 U+1eaa
+U+1eaa "\302~" # A with circumflex (same code as in iso-8859-1) and tilde
+0xe7 U+1eab
+0x87 U+1eac
+0xa7 U+1ead
+0x81 U+1eae
+0xa1 U+1eaf
+0x82 U+1eb0
+0xa2 U+1eb1
+0x02 U+1eb2
+U+1eb2:A(?
+0xc6 U+1eb3
+0x05 U+1eb4
+U+1eb4:A(~
+0xc7 U+1eb5
+0x83 U+1eb6
+0xa3 U+1eb7
+0x89 U+1eb8
+0xa9 U+1eb9
+0xcb U+1eba
+0xeb U+1ebb
+0x88 U+1ebc
+0xa8 U+1ebd
+0x8a U+1ebe
+0xaa U+1ebf
+0x8b U+1ec0
+0xab U+1ec1
+0x8c U+1ec2
+0xac U+1ec3
+0x8d U+1ec4
+0xad U+1ec5
+0x8e U+1ec6
+0xae U+1ec7
+0x9b U+1ec8
+0xef U+1ec9
+0x98 U+1eca
+0xb8 U+1ecb
+0x9a U+1ecc
+0xf7 U+1ecd
+0x99 U+1ece
+0xf6 U+1ecf
+0x8f U+1ed0
+0xaf U+1ed1
+0x90 U+1ed2
+0xb0 U+1ed3
+0x91 U+1ed4
+0xb1 U+1ed5
+0x92 U+1ed6
+0xb2 U+1ed7
+0x93 U+1ed8
+0xb5 U+1ed9
+0x95 U+1eda
+0xbe U+1edb
+0x96 U+1edc
+0xb6 U+1edd
+0x97 U+1ede
+0xb7 U+1edf
+0xb3 U+1ee0
+0xde U+1ee1
+0x94 U+1ee2
+0xfe U+1ee3
+0x9e U+1ee4
+0xf8 U+1ee5
+0x9c U+1ee6
+0xfc U+1ee7
+0xba U+1ee8
+0xd1 U+1ee9
+0xbb U+1eea
+0xd7 U+1eeb
+0xbc U+1eec
+0xd8 U+1eed
+0xff U+1eee
+0xe6 U+1eef
+0xb9 U+1ef0
+0xf1 U+1ef1
+0x9f U+1ef2
+0xcf U+1ef3
+0x18 U+1ef4 # MacVISCII
+0x1e U+1ef4
+U+1ef4:Y.
+0xdc U+1ef5
+0x17 U+1ef6 # MacVISCII
+0x14 U+1ef6
+U+1ef6:Y?
+0xd6 U+1ef7
+0x19 U+1ef8
+U+1ef8:Y~
+0xdb U+1ef9
+
diff --git a/gnu/usr.bin/lynx/src/cmu_tcp.opt b/gnu/usr.bin/lynx/src/cmu_tcp.opt
new file mode 100644
index 00000000000..24e43fe3bec
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/cmu_tcp.opt
@@ -0,0 +1 @@
+cmuip_root:[syslib]libcmu/library
diff --git a/gnu/usr.bin/lynx/src/decc.opt b/gnu/usr.bin/lynx/src/decc.opt
new file mode 100644
index 00000000000..670a21b024d
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/decc.opt
@@ -0,0 +1,2 @@
+sys$library:vaxcrtl/library
+sys$library:vaxccurse/library
diff --git a/gnu/usr.bin/lynx/src/descrip.mms b/gnu/usr.bin/lynx/src/descrip.mms
new file mode 100644
index 00000000000..9f84a7b84ee
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/descrip.mms
@@ -0,0 +1,170 @@
+! Make LYNX hypertext browser under VMS
+! =====================================
+!
+! NOTE: Use [.SRC.CHRTRANS]BUILD-CHRTRANS.COM to create the
+! chrtrans header files before using this descrip.mms.
+!
+! History:
+! 1/1/93 creation at KU (Lou montulli@ukanaix.cc.ukans.edu).
+! 4/12/93 (seb@lns61.tn.cornell.edu)
+! modified to support either UCX or MULTINET
+! 12/2/93 modified to support Lynx rewrite
+! 12/13/93 (macrides@sci.wfeb.edu)
+! Added conditional compilations for VAXC vs. DECC
+! (dependencies not yet specified; this is just a
+! "starter", should anyone want to do it well).
+! 10/31/94 RLD Updated for Lynx v2.3.4-VMS, supporting OpenCMU
+! and TCPWare
+! 11/11/94 RLD Updated for Lynx v2.3.5-VMS
+! 11/18/94 FM Updated for SOCKETSHR/NETLIB
+! 12/07/94 FM Updated for DECC/VAX, VAXC/VAX and DECC/AXP
+! 05/03/95 FM Include /NoMember for DECC (not the default on AXP, and
+! the code assumes byte alignment).
+! 06/14/95 FM Added LYList.
+! 07/26/95 FM Separated transport (TOPT) and compiler (COPT) option files.
+! 07/29/95 FM Added support for GNUC.
+! 02/29/96 FM Added LYMap.
+! 06/28/97 FM Added UCAuto, UCAux, and UCdomap.
+!
+! Instructions:
+! Use the correct command line for your TCP/IP implementation:
+!
+! $ MMS for VAXC - MultiNet
+! $ MMS /Macro = (MULTINET=1) for VAXC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1) for VAXC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1) for VAXC - UCX
+! $ MMS /Macro = (CMU_TCP=1) for VAXC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1) for VAXC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1) for VAXC - TCPWare TCP/IP
+! $ MMS /Macro = (DECNET=1) for VAXC - socket emulation over DECnet
+!
+! $ MMS /Macro = (MULTINET=1, DEC_C=1) for DECC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1, DEC_C=1) for DECC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1, DEC_C=1) for DECC - UCX
+! $ MMS /Macro = (CMU_TCP=1, DEC_C=1) for DECC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1,DEC_C=1) for DECC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1, DEC_C=1) for DECC - OpenCMU TCP/IP
+! $ MMS /Macro = (DECNET=1, DEC_C=1) for DECC - socket emulation over DECnet
+!
+! $ MMS /Macro = (MULTINET=1, GNU_C=1) for GNUC - MultiNet
+! $ MMS /Macro = (WIN_TCP=1, GNU_C=1) for GNUC - Wollongong TCP/IP
+! $ MMS /Macro = (UCX=1, GNU_C=1) for GNUC - UCX
+! $ MMS /Macro = (CMU_TCP=1, GNU_C=1) for GNUC - OpenCMU TCP/IP
+! $ MMS /Macro = (SOCKETSHR_TCP=1,GNU_C=1) for GNUC - SOCKETSHR/NETLIB
+! $ MMS /Macro = (TCPWARE=1, GNU_C=1) for GNUC - OpenCMU TCP/IP
+! $ MMS /Macro = (DECNET=1, GNU_C=1) for GNUC - socket emulation over DECnet
+
+OBJS = DefaultStyle.obj, GridText.obj, HTAlert.obj, HTFWriter.obj, -
+ HTInit.obj, HTML.obj, LYBookmark.obj, LYCgi.obj, LYCharSets.obj, -
+ LYCharUtils.obj, LYClean.obj, LYCookie.obj, LYCurses.obj, -
+ LYDownload.obj, LYEdit.obj, LYEditmap.obj, LYexit.obj, LYForms.obj, -
+ LYGetFile.obj, LYHistory.obj, LYJump.obj, LYKeymap.obj, LYLeaks.obj, -
+ LYList.obj, LYMail.obj, LYMain.obj, LYMainLoop.obj, LYMap.obj, -
+ LYNews.obj, LYOptions.obj, LYPrint.obj, LYrcFile.obj, LYReadCFG.obj, -
+ LYSearch.obj, LYShowInfo.obj, LYStrings.obj, LYTraversal.obj, -
+ LYUpload.obj, LYUtils.obj, UCAuto.obj, UCAux.obj, UCdomap.obj
+
+.ifdef WIN_TCP
+TCP = WIN_TCP
+TCPOPT = WIN_TCP
+.ifdef DEC_C
+CDEF = __VMS_CURSES
+.endif
+.endif
+
+.ifdef CMU_TCP
+TCP = CMU_TCP
+TCPOPT = CMU_TCP
+.ifdef DEC_C
+CDEF = __VMS_CURSES
+.endif
+.endif
+
+.ifdef SOCKETSHR_TCP
+TCP = SOCKETSHR_TCP
+TCPOPT = SOCKETSHR_TCP
+.ifdef DEC_C
+CDEF = __VMS_CURSES
+.endif
+.endif
+
+.ifdef UCX
+TCP = UCX
+.ifdef DEC_C
+TCPOPT = UCXSHR
+CDEF = __VMS_CURSES
+.else
+TCPOPT = UCXOLB
+.endif
+.endif
+
+.ifdef TCPWARE
+TCP = TCPWARE
+.ifdef DEC_C
+TCTOPT= TCPWARESHR
+CDEF = __VMS_CURSES
+.else
+TCTOPT= TCPWAREOLB
+.endif
+.endif
+
+.ifdef MULTINET
+TCP = MULTINET
+TCPOPT = MULTINET
+.ifdef DEC_C
+CDEF = _DECC_V4_SOURCE,__SOCKET_TYPEDEFS,__VMS_CURSES
+.endif
+.endif
+
+.ifdef DECnet
+TCP = DECNET
+TCPOPT = DECNET
+.endif
+
+.ifdef TCP
+.else
+TCP = MULTINET
+TCPOPT = MULTINET
+.ifdef DEC_C
+CDEF = _DECC_V4_SOURCE,__SOCKET_TYPEDEFS,__VMS_CURSES
+.endif
+.endif
+
+.ifdef DEC_C
+COMPILER = DECC
+.ifdef TCPWARE
+TCPFLAGS = /decc/Prefix=All/NoMember/Define=(DEBUG,ACCESS_AUTH,$(TCP),UCX,$(CDEF))
+.else
+TCPFLAGS = /decc/Prefix=All/NoMember/Define=(DEBUG,ACCESS_AUTH,$(TCP),$(CDEF))
+.endif
+.else
+.ifdef GNU_C
+COMPILER = GNUC
+CC = gcc
+.else
+COMPILER = VAXC
+.endif
+.ifdef TCPWARE
+TCPFLAGS = /Define = (DEBUG, ACCESS_AUTH, $(TCP), UCX)
+.else
+TCPFLAGS = /Define = (DEBUG, ACCESS_AUTH, $(TCP))
+.endif
+.endif
+
+TOPT = sys$disk:[]$(TCPOPT).opt
+COPT = sys$disk:[]$(COMPILER).opt
+WWWLIB = [-.WWW.Library.Implementation]WWWLib_$(TCP).olb
+CFLAGS = $(TCPFLAGS) $(CFLAGS)/Include = ([-], [.chrtrans], [-.WWW.Library.Implementation])
+
+
+lynx : lynx.exe
+ @ Continue
+
+lynx.exe : $(OBJS) $(WWWLIB)
+ $(LINK) /Executable = Lynx.exe $(OBJS), $(WWWLIB)/lib, $(TOPT)/opt, $(COPT)/opt
+
+clean :
+ - Set Protection = (Owner:RWED) *.*;-1
+ - Purge /NoLog /NoConfirm
+ - Delete /NoConfirm /NoLog *.obj;*
+ - Delete /NoConfirm /NoLog *.exe;*
diff --git a/gnu/usr.bin/lynx/src/gnuc.opt b/gnu/usr.bin/lynx/src/gnuc.opt
new file mode 100644
index 00000000000..0fe5159b3cb
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/gnuc.opt
@@ -0,0 +1,3 @@
+gnu_cc:[000000]gcclib/library
+sys$share:vaxcrtl/share
+sys$library:vaxccurse/library
diff --git a/gnu/usr.bin/lynx/src/makefile.dos b/gnu/usr.bin/lynx/src/makefile.dos
new file mode 100644
index 00000000000..91ace376cac
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/makefile.dos
@@ -0,0 +1,63 @@
+OBJS= UCdomap.o UCAux.o UCAuto.o \
+LYClean.o LYShowInfo.o LYEdit.o LYStrings.o \
+LYMail.o HTAlert.o GridText.o LYGetFile.o \
+LYMain.o LYMainLoop.o LYCurses.o LYBookmark.o LYUtils.o \
+LYOptions.o LYReadCFG.o LYSearch.o LYHistory.o \
+LYForms.o LYPrint.o LYrcFile.o LYDownload.o LYNews.o LYKeymap.o \
+HTML.o HTFWriter.o HTInit.o DefaultStyle.o LYLocal.o LYUpload.o \
+LYLeaks.o LYexit.o LYJump.o LYList.o LYCgi.o LYTraversal.o \
+LYEditmap.o LYCharSets.o LYCharUtils.o LYMap.o LYCookie.o LYExtern.o \
+LYStyle.o LYHash.o
+
+CFLAGS= $(MCFLAGS) -I. -I.. $(SLANGINC)
+
+CC = gcc
+MCFLAGS = -O3 -DRAWDOSKEYHACK -DUSE_ZLIB -DUSE_EXTERNALS -DCOLOR_CURSES -DNCURSES -DFANCY_CURSES -DACCESS_AUTH -DNO_CUSERID -DNOUSERS -DDOSPATH -DNO_TTYTYPE -DNO_UTMP -Ichrtrans -I../WWW/library/implementation -I../curses -I../djgpp/tcplib/include -I../djgpp/tcplib/include/tcp
+WWWLIB = ../WWW/library/djgpp/libwww.a ../curses/pdcurses.a ../djgpp/tcplib/obj/libtcp.a
+LIBS=-lz
+
+all: lynx
+
+lynx: message $(OBJS) $(WWWLIB)
+ @echo "Linking and creating Lynx executable"
+ $(CC) $(CFLAGS) -o lynx $(OBJS) $(WWWLIB) $(SLANGLIB) $(LIBS)
+ @echo "Welcome to Lynx!"
+
+message:
+ @echo "Compiling Lynx sources"
+
+dbg: $(OBJS) $(WWWLIB)
+ @echo "Making Lynx code"
+ $(CC) -g $(OBJS) $(CFLAGS) $(WWWLIB) $(SLANGLIB) $(LIBS)
+
+lint:
+ lint *.c > ../lint.out
+
+clean:
+ rm -f lynx core *.[ob]
+
+LYMain.o: ../userdefs.h
+LYMainLoop.o: LYMainLoop.c ../userdefs.h
+LYReadCFG.o: LYReadCFG.c ../userdefs.h
+HTFWriter.o: HTFWriter.c ../userdefs.h
+LYGetFile.o: LYGetFile.c ../userdefs.h
+LYOptions.o: LYOptions.c ../userdefs.h
+LYReadCFG.o: LYReadCFG.c ../userdefs.h
+LYTraversal.o: LYTraversal.c ../userdefs.h
+LYCharSets.o: LYCharSets.c ../userdefs.h
+LYShowInfo.o: LYShowInfo.c ../userdefs.h
+LYStrings.o: LYStrings.c ../userdefs.h
+LYBookmark.o: LYBookmark.c ../userdefs.h
+LYHistory.o: LYHistory.c ../userdefs.h
+LYDownload.o: LYDownload.c ../userdefs.h
+DefaultStyle.o: DefaultStyle.c ../userdefs.h
+LYEditmap.o: LYEditmap.c ../userdefs.h
+LYCharUtils.o: LYCharUtils.c ../userdefs.h
+LYExtern.o: LYExtern.c ../userdefs.h
+LYCookie.o: ../userdefs.h
+
+#UCdomap.o: UCdomap.c ../userdefs.h lycharsets.h
+#UCdomap.o: UCdomap.c chrtrans/UCkd.h chrtrans/makeuctb chrtrans/makeuctb.c \
+# UCdomap.h UCMap.h ../userdefs.h
+#UCAux.o : UCAux.c $(CMN)UCAux.h $(CMN)UCDefs.h
+
diff --git a/gnu/usr.bin/lynx/src/makefile.in b/gnu/usr.bin/lynx/src/makefile.in
new file mode 100644
index 00000000000..749c7a0acc4
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/makefile.in
@@ -0,0 +1,168 @@
+# template-makefile for Lynx src directory
+
+SHELL = /bin/sh
+
+x = @PROG_EXT@
+
+@SET_MAKE@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+top_srcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = $(srcdir)
+
+# Symbols which the configure script can set in each makefile:
+CC = @CC@
+CPP = @CPP@
+CFLAGS = @CFLAGS@
+DEFS = @DEFS@
+CPPFLAGS = @CPPFLAGS@
+
+LIBS = @LIBS@ $(RESOLVLIB) $(WAISLIB) $(SOCKSLIB) $(SITE_LIBS)
+LDFLAGS = @LDFLAGS@
+
+# Symbols inherited from the top-level makefile
+RESOLVLIB = # FIXME: set in parent makefile
+SITE_DEFS = # FIXME: set in parent makefile
+SITE_LIBS = # FIXME: set in parent makefile
+SOCKSLIB = # FIXME: set in parent makefile
+WAISLIB = # FIXME: set in parent makefile
+
+WWWINC = WWW/Library/Implementation
+WWWLIB = ../WWW/Library/unix/libwww.a
+
+CPP_OPTS = $(DEFS) $(CPPFLAGS) \
+ -I. \
+ -I.. \
+ -Ichrtrans \
+ -I$(srcdir)/chrtrans \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/$(WWWINC) \
+ $(SITE_DEFS)
+CC_OPTS = $(CPP_OPTS) $(CFLAGS)
+
+LINT = @LINT@
+LINTOPTS =
+
+CHARTRANS_OBJS=UCdomap.o UCAux.o UCAuto.o
+OBJS= LYClean.o LYShowInfo.o LYEdit.o LYStrings.o \
+LYMail.o HTAlert.o GridText.o LYGetFile.o \
+LYMain.o LYMainLoop.o LYCurses.o LYBookmark.o LYUtils.o \
+LYOptions.o LYReadCFG.o LYSearch.o LYHistory.o \
+LYForms.o LYPrint.o LYrcFile.o LYDownload.o LYNews.o LYKeymap.o \
+HTML.o HTFWriter.o HTInit.o DefaultStyle.o LYLocal.o LYUpload.o \
+LYLeaks.o LYexit.o LYJump.o LYList.o LYCgi.o LYTraversal.o \
+LYEditmap.o LYCharSets.o LYCharUtils.o LYMap.o LYCookie.o LYExtern.o \
+LYStyle.o LYHash.o $(CHARTRANS_OBJS) @LIBOBJS@
+
+C_SRC = $(OBJS:.o=.c)
+
+all: lynx$x
+
+.SUFFIXES : .i
+
+.c.o:
+@RULE_CC@
+ @ECHO_CC@$(CC) $(CC_OPTS) -c $(srcdir)/$*.c
+
+.c.i:
+@RULE_CC@
+ @ECHO_CC@$(CPP) -C $(CPP_OPTS) $*.c >$@
+
+lynx$x: message do_chartrans_stuff $(OBJS) $(WWWLIB)
+ @echo "Linking and creating Lynx executable"
+ $(CC) $(CC_OPTS) $(LDFLAGS) -o $@ $(OBJS) $(WWWLIB) $(LIBS)
+ @echo "Copying Lynx executable into top-level directory"
+ cp $@ ..
+ @echo "Welcome to Lynx!"
+
+message:
+ @echo "Compiling Lynx sources"
+
+do_chartrans_stuff:
+ -cd chrtrans && $(MAKE) \
+ SITE_DEFS="$(SITE_DEFS)" \
+ CFLAGS="$(CFLAGS)" \
+ CPPFLAGS="$(CPPFLAGS)" \
+ CC="$(CC)" tables
+
+lint:
+ $(LINT) $(LINTOPTS) $(CPP_OPTS) *.c > ../lint.out
+
+clean:
+ rm -f lynx$x core *.[ob] *.bak
+ cd chrtrans && $(MAKE) clean
+
+distclean: clean
+
+LYMain.o: ../userdefs.h
+LYMainLoop.o: ../userdefs.h
+LYReadCFG.o: ../userdefs.h
+HTFWriter.o: ../userdefs.h
+LYGetFile.o: ../userdefs.h
+LYOptions.o: ../userdefs.h
+LYReadCFG.o: ../userdefs.h
+LYrcFile.o: ../userdefs.h
+LYMail.o: ../userdefs.h
+LYUtils.o: ../userdefs.h
+HTInit.o: ../userdefs.h
+LYTraversal.o: ../userdefs.h
+LYMail.o: ../userdefs.h
+LYCharSets.o: ../userdefs.h
+
+CHRTR= chrtrans/
+
+TABLES= \
+ $(CHRTR)cp1250_uni.h \
+ $(CHRTR)cp1251_uni.h \
+ $(CHRTR)cp1252_uni.h \
+ $(CHRTR)cp1253_uni.h \
+ $(CHRTR)cp1255_uni.h \
+ $(CHRTR)cp1256_uni.h \
+ $(CHRTR)cp1257_uni.h \
+ $(CHRTR)cp437_uni.h \
+ $(CHRTR)cp737_uni.h \
+ $(CHRTR)cp775_uni.h \
+ $(CHRTR)cp850_uni.h \
+ $(CHRTR)cp852_uni.h \
+ $(CHRTR)cp862_uni.h \
+ $(CHRTR)cp864_uni.h \
+ $(CHRTR)cp866_uni.h \
+ $(CHRTR)cp869_uni.h \
+ $(CHRTR)def7_uni.h \
+ $(CHRTR)dmcs_uni.h \
+ $(CHRTR)iso01_uni.h \
+ $(CHRTR)iso02_uni.h \
+ $(CHRTR)iso03_uni.h \
+ $(CHRTR)iso04_uni.h \
+ $(CHRTR)iso05_uni.h \
+ $(CHRTR)iso06_uni.h \
+ $(CHRTR)iso07_uni.h \
+ $(CHRTR)iso08_uni.h \
+ $(CHRTR)iso09_uni.h \
+ $(CHRTR)iso10_uni.h \
+ $(CHRTR)koi8r_uni.h \
+ $(CHRTR)mac_uni.h \
+ $(CHRTR)mnem_suni.h \
+ $(CHRTR)mnem2_suni.h \
+ $(CHRTR)next_uni.h \
+ $(CHRTR)rfc_suni.h \
+ $(CHRTR)utf8_uni.h \
+ $(CHRTR)viscii_uni.h
+
+CMN=../WWW/Library/Implementation/
+
+$(TABLES):
+ -cd chrtrans && $(MAKE) tables
+
+UCdomap.o: UCdomap.c chrtrans/UCkd.h chrtrans/makeuctb chrtrans/makeuctb.c \
+ UCdomap.h $(CMN)UCMap.h $(TABLES) ../userdefs.h
+
+UCAux.o : UCAux.c $(CMN)UCAux.h $(CMN)UCDefs.h
+LYCookie.o: ../userdefs.h
+
+depend :
+ makedepend -fmakefile -- $(CC_OPTS) -- $(C_SRC)
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/gnu/usr.bin/lynx/src/mktime.c b/gnu/usr.bin/lynx/src/mktime.c
new file mode 100644
index 00000000000..46ca944b3e7
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/mktime.c
@@ -0,0 +1,77 @@
+/*
+ * mktime.c -- converts a struct tm into a time_t
+ *
+ * Copyright (C) 1997 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Written by Philippe De Muyter <phdm@macqel.be>. */
+
+#include <time.h>
+
+static time_t
+mkgmtime(t)
+register struct tm *t;
+{
+ register short month, year;
+ register time_t result;
+ static int m_to_d[12] =
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ month = t->tm_mon;
+ year = t->tm_year + month / 12 + 1900;
+ month %= 12;
+ if (month < 0)
+ {
+ year -= 1;
+ month += 12;
+ }
+ result = (year - 1970) * 365 + (year - 1969) / 4 + m_to_d[month];
+ result = (year - 1970) * 365 + m_to_d[month];
+ if (month <= 1)
+ year -= 1;
+ result += (year - 1968) / 4;
+ result -= (year - 1900) / 100;
+ result += (year - 1600) / 400;
+ result += t->tm_mday;
+ result -= 1;
+ result *= 24;
+ result += t->tm_hour;
+ result *= 60;
+ result += t->tm_min;
+ result *= 60;
+ result += t->tm_sec;
+ return(result);
+}
+
+/*
+** mktime -- convert tm struct to time_t
+** if tm_isdst >= 0 use it, else compute it
+*/
+
+time_t
+mktime(t)
+struct tm *t;
+{
+ time_t result;
+
+ tzset();
+ result = mkgmtime(t) + timezone;
+ if (t->tm_isdst > 0
+ || (t->tm_isdst < 0 && localtime(&result)->tm_isdst))
+ result -= 3600;
+ return(result);
+}
diff --git a/gnu/usr.bin/lynx/src/multinet.opt b/gnu/usr.bin/lynx/src/multinet.opt
new file mode 100644
index 00000000000..97b420f4079
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/multinet.opt
@@ -0,0 +1 @@
+multinet:multinet_socket_library/share
diff --git a/gnu/usr.bin/lynx/src/socketshr_tcp.opt b/gnu/usr.bin/lynx/src/socketshr_tcp.opt
new file mode 100644
index 00000000000..f6e31316269
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/socketshr_tcp.opt
@@ -0,0 +1 @@
+socketshr/share
diff --git a/gnu/usr.bin/lynx/src/strstr.c b/gnu/usr.bin/lynx/src/strstr.c
new file mode 100644
index 00000000000..3d7442c1bf9
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/strstr.c
@@ -0,0 +1,64 @@
+/*
+ * strstr.c -- return the offset of one string within another.
+ *
+ * Copyright (C) 1997 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* Written by Philippe De Muyter <phdm@macqel.be>. */
+
+/*
+ * NAME
+ *
+ * strstr -- locate first occurrence of a substring
+ *
+ * SYNOPSIS
+ *
+ * char *strstr (char *s1, char *s2)
+ *
+ * DESCRIPTION
+ *
+ * Locates the first occurrence in the string pointed to by S1 of the string
+ * pointed to by S2. Returns a pointer to the substring found, or a NULL
+ * pointer if not found. If S2 points to a string with zero length, the
+ * function returns S1.
+ *
+ * BUGS
+ *
+ */
+
+char *
+strstr (buf, sub)
+ register char *buf;
+ register char *sub;
+{
+ register char *bp;
+ register char *sp;
+
+ if (!*sub)
+ return buf;
+ while (*buf)
+ {
+ bp = buf;
+ sp = sub;
+ do {
+ if (!*sp)
+ return buf;
+ } while (*bp++ == *sp++);
+ buf += 1;
+ }
+ return 0;
+}
diff --git a/gnu/usr.bin/lynx/src/tcpwareolb.opt b/gnu/usr.bin/lynx/src/tcpwareolb.opt
new file mode 100644
index 00000000000..045d770cc9d
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/tcpwareolb.opt
@@ -0,0 +1 @@
+tcpware:ucx$ipc/library
diff --git a/gnu/usr.bin/lynx/src/tcpwareshr.opt b/gnu/usr.bin/lynx/src/tcpwareshr.opt
new file mode 100644
index 00000000000..e34f846936f
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/tcpwareshr.opt
@@ -0,0 +1 @@
+tcpware:ucx$ipc_shr.exe/share
diff --git a/gnu/usr.bin/lynx/src/ucxolb.opt b/gnu/usr.bin/lynx/src/ucxolb.opt
new file mode 100644
index 00000000000..2c7cb546c6c
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/ucxolb.opt
@@ -0,0 +1 @@
+sys$library:ucx$ipc/library
diff --git a/gnu/usr.bin/lynx/src/ucxshr.opt b/gnu/usr.bin/lynx/src/ucxshr.opt
new file mode 100644
index 00000000000..ba84be0de88
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/ucxshr.opt
@@ -0,0 +1 @@
+sys$share:ucx$ipc_shr/share
diff --git a/gnu/usr.bin/lynx/src/vaxc.opt b/gnu/usr.bin/lynx/src/vaxc.opt
new file mode 100644
index 00000000000..fbb523b0852
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/vaxc.opt
@@ -0,0 +1,2 @@
+sys$share:vaxcrtl/share
+sys$library:vaxccurse/library
diff --git a/gnu/usr.bin/lynx/src/win_tcp.opt b/gnu/usr.bin/lynx/src/win_tcp.opt
new file mode 100644
index 00000000000..7fcb9fdf22b
--- /dev/null
+++ b/gnu/usr.bin/lynx/src/win_tcp.opt
@@ -0,0 +1 @@
+twg$tcp:[netdist.lib]twglib/library
diff --git a/gnu/usr.bin/lynx/test/ALT88592.html b/gnu/usr.bin/lynx/test/ALT88592.html
new file mode 100644
index 00000000000..b464cb4c798
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/ALT88592.html
@@ -0,0 +1,170 @@
+<HTML>
+<HEAD>
+<TITLE>Character table modified and enhanced for iso8859-2 - ALT test</TITLE>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">
+<LINK REV="made" HREF="mailto:kweide@tezcat.com">
+<LINK REV="owner" HREF="http://www.flora.org/lynx-dev/">
+<!-- A BASE tag for the SRC attributes of dummy images.
+ They should be inaccessible so that the ALT text will be shown in graphical browsers.
+ Use file: to save network resources. -->
+<BASE HREF="file://localhost/this.path.intentionally.invalid/">
+</HEAD>
+
+<BODY>
+
+<H1 ALIGN=center>iso8859-2 plus table - ALT test</H1>
+
+<PRE>
+Description Code Entity name
+=================================== ============ ==============
+quotation mark <IMG SRC=X ALT=" &amp;#34; --> &#34; &amp;quot; --> &quot;">
+ampersand <IMG SRC=X ALT=" &amp;#38; --> &#38; &amp;amp; --> &amp;">
+less-than sign <IMG SRC=X ALT=" &amp;#60; --> &#60; &amp;lt; --> &lt;">
+greater-than sign <IMG SRC=X ALT=" &amp;#62; --> &#62; &amp;gt; --> &gt;">
+
+Description Char Code Entity name
+=================================== ==== ============ ==============
+non-breaking space <IMG SRC=X ALT="   &amp;#160; --> &#160; &amp;nbsp; --> &nbsp;">
+capital A, ogonek <IMG SRC=X ALT=" ¡ &amp;#260; --> &#260; &amp;Aogon; --> &Aogon;">
+breve <IMG SRC=X ALT=" {¢} {&amp;#728;}-->{&#728;} {&amp;breve;} -->{&breve;}">
+capital L, stroke <IMG SRC=X ALT=" £ &amp;#321; --> &#321; &amp;Lstrok; --> &Lstrok;">
+general currency sign <IMG SRC=X ALT=" ¤ &amp;#164; --> &#164; &amp;curren; --> &curren;">
+capital L, caron <IMG SRC=X ALT=" ¥ &amp;#317; --> &#317; &amp;Lcaron; --> &Lcaron;">
+capital S, acute accent <IMG SRC=X ALT=" ¦ &amp;#346; --> &#346; &amp;Sacute; --> &Sacute;">
+section sign <IMG SRC=X ALT=" § &amp;#167; --> &#167; &amp;sect; --> &sect;">
+umlaut (dieresis) <IMG SRC=X ALT=" ¨ &amp;#168; --> &#168; &amp;uml; --> &uml;">
+ <IMG SRC=X ALT=" &amp;die; --> &die;">
+capital S, caron <IMG SRC=X ALT=" © &amp;#352; --> &#352; &amp;Scaron; --> &Scaron;">
+capital S, cedilla <IMG SRC=X ALT=" ª &amp;#350; --> &#350; &amp;Scedil; --> &Scedil;">
+capital T, caron <IMG SRC=X ALT=" « &amp;#356; --> &#356; &amp;Tcaron; --> &Tcaron;">
+capital Z, acute accent <IMG SRC=X ALT=" ¬ &amp;#377; --> &#377; &amp;Zacute; --> &Zacute;">
+soft hyphen <IMG SRC=X ALT=" [­] [&amp;#173;]-->[&#173;] [&amp;shy;] -->[&shy;]">
+capital Z, caron <IMG SRC=X ALT=" ® &amp;#381; --> &#381; &amp;Zcaron; --> &Zcaron;">
+capital Z, dot above <IMG SRC=X ALT=" ¯ &amp;#379; --> &#379; &amp;Zdot; --> &Zdot;">
+degree sign <IMG SRC=X ALT=" ° &amp;#176; --> &#176; &amp;deg; --> &deg;">
+small a, ogonek <IMG SRC=X ALT=" ± &amp;#261; --> &#261; &amp;aogon; --> &aogon;">
+ogonek <IMG SRC=X ALT=" {²} {&amp;#731;}-->{&#731;} {&amp;ogon;} -->{&ogon;}">
+small l, stroke <IMG SRC=X ALT=" ³ &amp;#322; --> &#322; &amp;lstrok; --> &lstrok;">
+acute accent <IMG SRC=X ALT=" ´ &amp;#180; --> &#180; &amp;acute; --> &acute;">
+small l, caron <IMG SRC=X ALT=" µ &amp;#318; --> &#318; &amp;lcaron; --> &lcaron;">
+small s, acute accent <IMG SRC=X ALT=" ¶ &amp;#347; --> &#347; &amp;sacute; --> &sacute;">
+caron <IMG SRC=X ALT=" {·} {&amp;#711;}-->{&#711;} {&amp;caron;} -->{&caron;}">
+cedilla <IMG SRC=X ALT=" ¸ &amp;#184; --> &#184; &amp;cedil; --> &cedil;">
+small s, caron <IMG SRC=X ALT=" ¹ &amp;#353; --> &#353; &amp;scaron; --> &scaron;">
+small s, cedilla <IMG SRC=X ALT=" º &amp;#351; --> &#351; &amp;scedil; --> &scedil;">
+small t, caron <IMG SRC=X ALT=" » &amp;#357; --> &#357; &amp;tcaron; --> &tcaron;">
+small z, acute accent <IMG SRC=X ALT=" ¼ &amp;#378; --> &#378; &amp;zacute; --> &zacute;">
+double acute accent <IMG SRC=X ALT=" {½} {&amp;#733;}-->{&#733;} {&amp;dblac;} -->{&dblac;}">
+small z, caron <IMG SRC=X ALT=" ¾ &amp;#382; --> &#382; &amp;zcaron; --> &zcaron;">
+small z, dot above <IMG SRC=X ALT=" ¿ &amp;#380; --> &#380; &amp;zdot; --> &zdot; ">
+capital R, acute accent <IMG SRC=X ALT=" À &amp;#340; --> &#340; &amp;Racute; --> &Racute;">
+capital A, acute accent <IMG SRC=X ALT=" Á &amp;#193; --> &#193; &amp;Aacute; --> &Aacute;">
+capital A, circumflex accent <IMG SRC=X ALT=" Â &amp;#194; --> &#194; &amp;Acirc; --> &Acirc;">
+capital A, breve <IMG SRC=X ALT=" Ã &amp;#258; --> &#258; &amp;Abreve; --> &Abreve;">
+capital A, dieresis or umlaut mark <IMG SRC=X ALT=" Ä &amp;#196; --> &#196; &amp;Auml; --> &Auml;">
+capital L, acute accent <IMG SRC=X ALT=" Å &amp;#313; --> &#313; &amp;Lacute; --> &Lacute;">
+capital C, acute accent <IMG SRC=X ALT=" Æ &amp;#262; --> &#262; &amp;Cacute; --> &Cacute;">
+capital C, cedilla <IMG SRC=X ALT=" Ç &amp;#199; --> &#199; &amp;Ccedil; --> &Ccedil;">
+capital C, caron <IMG SRC=X ALT=" È &amp;#268; --> &#268; &amp;Ccaron; --> &Ccaron;">
+capital E, acute accent <IMG SRC=X ALT=" É &amp;#201; --> &#201; &amp;Eacute; --> &Eacute;">
+capital E, ogonek <IMG SRC=X ALT=" Ê &amp;#280; --> &#280; &amp;Eogon; --> &Eogon;">
+capital E, dieresis or umlaut mark <IMG SRC=X ALT=" Ë &amp;#203; --> &#203; &amp;Euml; --> &Euml;">
+capital E, caron <IMG SRC=X ALT=" Ì &amp;#282; --> &#282; &amp;Ecaron; --> &Ecaron;">
+capital I, acute accent <IMG SRC=X ALT=" Í &amp;#205; --> &#205; &amp;Iacute; --> &Iacute;">
+capital I, circumflex accent <IMG SRC=X ALT=" Î &amp;#206; --> &#206; &amp;Icirc; --> &Icirc;">
+capital D, caron <IMG SRC=X ALT=" Ï &amp;#270; --> &#270; &amp;Dcaron; --> &Dcaron;">
+capital D, stroke <IMG SRC=X ALT=" Ð &amp;#272; --> &#272; &amp;Dstrok; --> &Dstrok;">
+capital Eth, Icelandic <IMG SRC=X ALT=" N/A &amp;#208; --> &#208; &amp;ETH; --> &ETH;">
+capital N, acute accent <IMG SRC=X ALT=" Ñ &amp;#323; --> &#323; &amp;Nacute; --> &Nacute;">
+capital N, caron <IMG SRC=X ALT=" Ò &amp;#327; --> &#327; &amp;Ncaron; --> &Ncaron;">
+capital O, acute accent <IMG SRC=X ALT=" Ó &amp;#211; --> &#211; &amp;Oacute; --> &Oacute;">
+capital O, circumflex accent <IMG SRC=X ALT=" Ô &amp;#212; --> &#212; &amp;Ocirc; --> &Ocirc;">
+capital O, double acute accent <IMG SRC=X ALT=" Õ &amp;#368; --> &#368; &amp;Odblac; --> &Odblac;">
+capital O, dieresis or umlaut mark <IMG SRC=X ALT=" Ö &amp;#214; --> &#214; &amp;Ouml; --> &Ouml;">
+multiply sign <IMG SRC=X ALT=" × &amp;#215; --> &#215; &amp;times; --> &times;">
+capital R, caron <IMG SRC=X ALT=" Ø &amp;#344; --> &#344; &amp;Rcaron; --> &Rcaron;">
+capital U, ring <IMG SRC=X ALT=" Ù &amp;#366; --> &#366; &amp;Uring; --> &Uring;">
+capital U, acute accent <IMG SRC=X ALT=" Ú &amp;#218; --> &#218; &amp;Uacute; --> &Uacute;">
+capital U, double acute accent <IMG SRC=X ALT=" Û &amp;#368; --> &#368; &amp;Udblac; --> &Udblac;">
+capital U, dieresis or umlaut mark <IMG SRC=X ALT=" Ü &amp;#220; --> &#220; &amp;Uuml; --> &Uuml;">
+capital Y, acute accent <IMG SRC=X ALT=" Ý &amp;#221; --> &#221; &amp;Yacute; --> &Yacute;">
+capital T, cedilla <IMG SRC=X ALT=" Þ &amp;#354; --> &#354; &amp;Tcedil; --> &Tcedil;">
+small sharp s, German (sz ligature) <IMG SRC=X ALT=" ß &amp;#223; --> &#223; &amp;szlig; --> &szlig;">
+small r, acute accent <IMG SRC=X ALT=" à &amp;#341; --> &#341; &amp;racute; --> &racute;">
+small a, acute accent <IMG SRC=X ALT=" á &amp;#225; --> &#225; &amp;aacute; --> &aacute;">
+small a, circumflex accent <IMG SRC=X ALT=" â &amp;#226; --> &#226; &amp;acirc; --> &acirc;">
+small a, breve <IMG SRC=X ALT=" ã &amp;#259; --> &#259; &amp;abreve; --> &abreve;">
+small a, dieresis or umlaut mark <IMG SRC=X ALT=" ä &amp;#228; --> &#228; &amp;auml; --> &auml;">
+small l, acute accent <IMG SRC=X ALT=" å &amp;#314; --> &#314; &amp;lacute; --> &lacute;">
+small c, acute accent <IMG SRC=X ALT=" æ &amp;#263; --> &#263; &amp;cacute; --> &cacute;">
+small c, cedilla <IMG SRC=X ALT=" ç &amp;#231; --> &#231; &amp;ccedil; --> &ccedil;">
+small c, caron <IMG SRC=X ALT=" è &amp;#269; --> &#269; &amp;ccaron; --> &ccaron;">
+small e, acute accent <IMG SRC=X ALT=" é &amp;#233; --> &#233; &amp;eacute; --> &eacute;">
+small e, ogonek <IMG SRC=X ALT=" ê &amp;#281; --> &#281; &amp;eogon; --> &eogon;">
+small e, dieresis or umlaut mark <IMG SRC=X ALT=" ë &amp;#235; --> &#235; &amp;euml; --> &euml;">
+small e, caron <IMG SRC=X ALT=" ì &amp;#283; --> &#283; &amp;ecaron; --> &ecaron;">
+small i, acute accent <IMG SRC=X ALT=" í &amp;#237; --> &#237; &amp;iacute; --> &iacute;">
+small i, circumflex accent <IMG SRC=X ALT=" î &amp;#238; --> &#238; &amp;icirc; --> &icirc;">
+small d, caron <IMG SRC=X ALT=" ï &amp;#271; --> &#271; &amp;dcaron; --> &dcaron;">
+small d, stroke <IMG SRC=X ALT=" ð &amp;#273; --> &#273; &amp;dstrok; --> &dstrok;">
+small eth, Icelandic <IMG SRC=X ALT=" N/A &amp;#240; --> &#240; &amp;eth; --> &eth;">
+small n, acute accent <IMG SRC=X ALT=" ñ &amp;#324; --> &#324; &amp;nacute; --> &nacute;">
+small n, caron <IMG SRC=X ALT=" ò &amp;#328; --> &#328; &amp;ncaron; --> &ncaron;">
+small o, acute accent <IMG SRC=X ALT=" ó &amp;#243; --> &#243; &amp;oacute; --> &oacute;">
+small o, circumflex accent <IMG SRC=X ALT=" ô &amp;#244; --> &#244; &amp;ocirc; --> &ocirc;">
+small o, double acute accent <IMG SRC=X ALT=" õ &amp;#369; --> &#369; &amp;odblac; --> &odblac;">
+small o, dieresis or umlaut mark <IMG SRC=X ALT=" ö &amp;#246; --> &#246; &amp;ouml; --> &ouml;">
+division sign <IMG SRC=X ALT=" ÷ &amp;#247; --> &#247; &amp;divide; --> &divide;">
+small r, caron <IMG SRC=X ALT=" ø &amp;#345; --> &#345; &amp;rcaron; --> &rcaron;">
+small u, ring <IMG SRC=X ALT=" ù &amp;#367; --> &#367; &amp;uring; --> &uring;">
+small u, acute accent <IMG SRC=X ALT=" ú &amp;#250; --> &#250; &amp;uacute; --> &uacute;">
+small u, double acute accent <IMG SRC=X ALT=" û &amp;#369; --> &#369; &amp;udblac; --> &udblac;">
+small u, dieresis or umlaut mark <IMG SRC=X ALT=" ü &amp;#252; --> &#252; &amp;uuml; --> &uuml;">
+small y, acute accent <IMG SRC=X ALT=" ý &amp;#253; --> &#253; &amp;yacute; --> &yacute;">
+small t, cedilla <IMG SRC=X ALT=" þ &amp;#355; --> &#355; &amp;tcedil; --> &tcedil;">
+dot above <IMG SRC=X ALT=" {ÿ} {&amp;#729;}-->{&#729;} {&amp;dot;} -->{&dot;}">
+
+Some other characters of interest Char Code Entity name
+=================================== ==== ============ ==============
+capital AE diphthong (ligature) <IMG SRC=X ALT=" N/A &amp;#198; --> &#198; &amp;AElig; --> &AElig;">
+small ae diphthong (ligature) <IMG SRC=X ALT=" N/A &amp;#230; --> &#230; &amp;aelig; --> &aelig;">
+capital OE ligature <IMG SRC=X ALT=" N/A {&amp;#338;}-->{&#338;} {&amp;OElig;} -->{&OElig;}">
+small oe ligature <IMG SRC=X ALT=" N/A {&amp;#339;}-->{&#339;} {&amp;oelig;} -->{&oelig;}">
+copyright <IMG SRC=X ALT=" N/A &amp;#169; --> &#169; &amp;copy; --> &copy;">
+registered trademark <IMG SRC=X ALT=" N/A &amp;#174; --> &#174; &amp;reg; --> &reg;">
+trademark sign <IMG SRC=X ALT=" N/A &amp;#8482;--> &#8482; &amp;trade; --> &trade;">
+em space <IMG SRC=X ALT=" N/A [&amp;#8195;]->[&#8195;] [&amp;emsp;] -->[&emsp;]">
+en space <IMG SRC=X ALT=" N/A [&amp;#8194;]->[&#8194;] [&amp;ensp;] -->[&ensp;]">
+1/3-em space <IMG SRC=X ALT=" N/A [&amp;#8196;]->[&#8196;] [&amp;emsp13;] -->[&emsp13;]">
+1/4-em space <IMG SRC=X ALT=" N/A [&amp;#8197;]->[&#8197;] [&amp;emsp14;] -->[&emsp14;]">
+thin space <IMG SRC=X ALT=" N/A [&amp;#8201;]->[&#8201;] [&amp;thinsp;]-->[&thinsp;]">
+hair space <IMG SRC=X ALT=" N/A [&amp;#8202;]->[&#8202;] [&amp;hairsp;]-->[&hairsp;]">
+em dash <IMG SRC=X ALT=" N/A [&amp;#8212;]->[&#8212;] [&amp;mdash;] -->[&mdash;]">
+en dash <IMG SRC=X ALT=" N/A [&amp;#8211;]->[&#8211;] [&amp;ndash;] -->[&ndash;]">
+
+</PRE><!-- </PRE> no HotJava preBeta hackx - kw -->
+<!-- second /PRE is a hack for HotJava 1.0 preBeta 1 -->
+<HR>
+<P>
+Characters not found in ISO-8859-2 have "N/A" in the <TT>Char</TT> column.
+Some characters for which I could not find entity names in either
+<A HREF="http://www.internic.net/rfc/rfc2070.txt">RFC 2070</A>
+or the
+<A HREF="ftp://www.ucc.ie/pub/sgml/">ISOlat1, ISOlat2, ISOnum, ISOpub and ISOtech</A>
+sets (the ones included by Peter Flynn's
+<A HREF="http://www.ucc.ie/doc/www/html/dtds/htmlpro.html">HTML Pro DTD</A>)
+are shown enclosed in <TT>{</TT>braces<TT>}</TT>.
+</P>
+<P>
+See Martin Ramsch's original
+<A CHARSET="iso-8859-1" HREF="http://www.uni-passau.de/~ramsch/iso8859-1.html">ISO-8859-1 Table</A>
+for related info and links, and for some notes on entity names.
+This file is mostly just an adaptation of his table
+to the ISO-8859-2 character set.
+
+<HR>
+
+<ADDRESS>kweide@tezcat.com 1997-03-09</ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/test/ISO_LATIN1_test.html b/gnu/usr.bin/lynx/test/ISO_LATIN1_test.html
new file mode 100644
index 00000000000..48016757519
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/ISO_LATIN1_test.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html public "-//IETF//DTD HTML 3.0//EN">
+<html>
+<head>
+<title>Test of minimal ISO LATIN1 character set</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+
+<body>
+<h1>minimal ISO LATIN1 text entities</h1>
+<ul>
+ <li>"&AElig;", /* capital AE diphthong (ligature) */
+ <li>"&Aacute;", /* capital A, acute accent */
+ <li>"&Acirc;", /* capital A, circumflex accent */
+ <li>"&Agrave;", /* capital A, grave accent */
+ <li>"&Aring;", /* capital A, ring */
+ <li>"&Atilde;", /* capital A, tilde */
+ <li>"&Auml;", /* capital A, dieresis or umlaut mark */
+ <li>"&Ccedil;", /* capital C, cedilla */
+ <li>"&ETH;", /* capital Eth, Icelandic */
+ <li>"&Eacute;", /* capital E, acute accent */
+ <li>"&Ecirc;", /* capital E, circumflex accent */
+ <li>"&Egrave;", /* capital E, grave accent */
+ <li>"&Euml;", /* capital E, dieresis or umlaut mark */
+ <li>"&Iacute;", /* capital I, acute accent */
+ <li>"&Icirc;", /* capital I, circumflex accent */
+ <li>"&Igrave;", /* capital I, grave accent */
+ <li>"&Iuml;", /* capital I, dieresis or umlaut mark */
+ <li>"&Ntilde;", /* capital N, tilde */
+ <li>"&Oacute;", /* capital O, acute accent */
+ <li>"&Ocirc;", /* capital O, circumflex accent */
+ <li>"&Ograve;", /* capital O, grave accent */
+ <li>"&Oslash;", /* capital O, slash */
+ <li>"&Otilde;", /* capital O, tilde */
+ <li>"&Ouml;", /* capital O, dieresis or umlaut mark */
+ <li>"&THORN;", /* capital THORN, Icelandic */
+ <li>"&Uacute;", /* capital U, acute accent */
+ <li>"&Ucirc;", /* capital U, circumflex accent */
+ <li>"&Ugrave;", /* capital U, grave accent */
+ <li>"&Uuml;", /* capital U, dieresis or umlaut mark */
+ <li>"&Yacute;", /* capital Y, acute accent */
+ <li>"&aacute;", /* small a, acute accent */
+ <li>"&acirc;", /* small a, circumflex accent */
+ <li>"&aelig;", /* small ae diphthong (ligature) */
+ <li>"&agrave;", /* small a, grave accent */
+ <li>"&amp;", /* ampersand */
+ <li>"&aring;", /* small a, ring */
+ <li>"&atilde;", /* small a, tilde */
+ <li>"&auml;", /* small a, dieresis or umlaut mark */
+ <li>"&ccedil;", /* small c, cedilla */
+ <li>"&eacute;", /* small e, acute accent */
+ <li>"&ecirc;", /* small e, circumflex accent */
+ <li>"&egrave;", /* small e, grave accent */
+ <li>"&emsp;", /* emsp, em space - not collapsed */
+ <li>"&ensp;", /* ensp, en space - not collapsed */
+ <li>"&eth;", /* small eth, Icelandic */
+ <li>"&euml;", /* small e, dieresis or umlaut mark */
+ <li>"&gt;", /* greater than */
+ <li>"&iacute;", /* small i, acute accent */
+ <li>"&icirc;", /* small i, circumflex accent */
+ <li>"&igrave;", /* small i, grave accent */
+ <li>"&iuml;", /* small i, dieresis or umlaut mark */
+ <li>"&lt;", /* less than */
+ <li>"&nbsp;", /* nbsp, non breaking space */
+ <li>"&ntilde;", /* small n, tilde */
+ <li>"&oacute;", /* small o, acute accent */
+ <li>"&ocirc;", /* small o, circumflex accent */
+ <li>"&ograve;", /* small o, grave accent */
+ <li>"&oslash;", /* small o, slash */
+ <li>"&otilde;", /* small o, tilde */
+ <li>"&ouml;", /* small o, dieresis or umlaut mark */
+ <li>"&quot;", /* quote, '"' */
+ <li>"&szlig;", /* small sharp s, German (sz ligature) */
+ <li>"&thorn;", /* small thorn, Icelandic */
+ <li>"&uacute;", /* small u, acute accent */
+ <li>"&ucirc;", /* small u, circumflex accent */
+ <li>"&ugrave;", /* small u, grave accent */
+ <li>"&uuml;", /* small u, dieresis or umlaut mark */
+ <li>"&yacute;", /* small y, acute accent */
+ <li>"&yuml;", /* small y, dieresis or umlaut mark */
+</ul>
+
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/test/README.txt b/gnu/usr.bin/lynx/test/README.txt
new file mode 100644
index 00000000000..b681e3f3cb3
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/README.txt
@@ -0,0 +1,8 @@
+ISO_LATIN1_test.html and iso8859-1.html are for testing the translation of
+HTML entities with the character sets that are selectable via the 'o'ptions
+menu.
+
+TestComment.html and tabtest.html are for testing comment and TAB handling.
+
+Any other files in this directory do not represent a test suite. They
+are used during program testing to track down odd and mysterious bugs.
diff --git a/gnu/usr.bin/lynx/test/TestComment.html b/gnu/usr.bin/lynx/test/TestComment.html
new file mode 100644
index 00000000000..873169f2d8a
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/TestComment.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Level 2//EN">
+<html>
+<head>
+<title>HTML Comment Parser Test</title>
+<link rev="made" href="mailto:pg@sweng.stortek.com">
+<base href="http://nyx10.cs.du.edu:8001/~pgilmart/TestComment.html">
+</head>
+
+<body>
+<P> Test of the HTML/SGML comment syntax, as given in the W3 HTML Spec:
+<a
+href="http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_3.html#SEC15">
+Comments</a>
+
+<P>See especially, the footnote:
+<a
+href="http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_foot.html#FOOT10"
+>(10)</a>
+
+<P>
+Co-vary the LYK_MINIMAL and LYK_HISTORICAL command key toggles (use the
+'k'eymap command to see their key bindings) to establish Valid, Minimal
+or Historical comment parsing, and toggle trace mode on (Ctrl-T), to see
+how comment parsing is affected.
+
+<P>Case 01 through Case 14 should appear
+as short separate paragraphs with the case numbers aligned vertically.
+Some noise characters may appear to the right as a byproduct of code present
+for error recovery, but there should be no noise before each case number.
+
+<P> Case <!-- trivial --> | 01 | Trivial
+<P> Case <!-- extra hyphens and spaces -- -- -- > | 02 | Hyphens and Spaces
+<P> Case <!-- extra < < < --> | 03 | Extra LT --> --> -->
+<P> Case <!-- balanced < < < > > > --> | 04 | Balanced
+<P> Case <!-- extra > -- --> > still in comment --> | 05 | Extra GT
+<P> Case <!-- stuff between -- and > -- still in comment --> | 06 | Stuff Inside
+<P> Case <!-- Extra <!-- -- Second Comment --> | 07 | Extra Open --> -->
+<P> Case <!-- New Line between --
+ -- Second Comment --
+ > | 08 | New line
+<P> Case <!---> degenerate --> | 09 | Degenerate <P> Case <!----> | 10 | Empty
+<P> Case <!-- perverse <!--> | 11 | Perverse --> --> -->
+<P> Case <!-- Comment -- -- and a half > this is still in comment -- > | 12 | Multiple Comments --> --> -->
+<P> Case <!> | 13 | Zero Comments
+<P> Case <!-- < >
+< > Still in comment --> | 14 | Last
+
+<P>&lt;<STRONG>Tests completed!</STRONG>&gt;
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/test/iso8859-1.html b/gnu/usr.bin/lynx/test/iso8859-1.html
new file mode 100644
index 00000000000..491862a5e95
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/iso8859-1.html
@@ -0,0 +1,239 @@
+<!-- X-URL: http://www.uni-passau.de/~ramsch/iso8859-1.html -->
+<BASE HREF="http://www.uni-passau.de/~ramsch/iso8859-1.html">
+
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
+<TITLE>Martin Ramsch - iso8859-1 table</TITLE>
+<BASE HREF="http://www.uni-passau.de/~ramsch/iso8859-1.html">
+</HEAD>
+
+<BODY>
+
+<H1 ALIGN=center>iso8859-1 table</H1>
+
+<PRE>
+Description Code Entity name
+=================================== ============ ==============
+quotation mark &amp;#34; --> &#34; &amp;quot; --> &quot;
+ampersand &amp;#38; --> &#38; &amp;amp; --> &amp;
+less-than sign &amp;#60; --> &#60; &amp;lt; --> &lt;
+greater-than sign &amp;#62; --> &#62; &amp;gt; --> &gt;
+
+Description Char Code Entity name
+=================================== ==== ============ ==============
+non-breaking space   &amp;#160; --> &#160; &amp;nbsp; --> &nbsp;
+inverted exclamation ¡ &amp;#161; --> &#161; &amp;iexcl; --> &iexcl;
+cent sign ¢ &amp;#162; --> &#162; &amp;cent; --> &cent;
+pound sterling £ &amp;#163; --> &#163; &amp;pound; --> &pound;
+general currency sign ¤ &amp;#164; --> &#164; &amp;curren; --> &curren;
+yen sign ¥ &amp;#165; --> &#165; &amp;yen; --> &yen;
+broken vertical bar ¦ &amp;#166; --> &#166; &amp;brvbar; --> &brvbar;
+ &amp;brkbar; --> &brkbar;
+section sign § &amp;#167; --> &#167; &amp;sect; --> &sect;
+umlaut (dieresis) ¨ &amp;#168; --> &#168; &amp;uml; --> &uml;
+ &amp;die; --> &die;
+copyright © &amp;#169; --> &#169; &amp;copy; --> &copy;
+feminine ordinal ª &amp;#170; --> &#170; &amp;ordf; --> &ordf;
+left angle quote, guillemotleft « &amp;#171; --> &#171; &amp;laquo; --> &laquo;
+not sign ¬ &amp;#172; --> &#172; &amp;not; --> &not;
+soft hyphen ­ &amp;#173; --> &#173; &amp;shy; --> &shy;
+registered trademark ® &amp;#174; --> &#174; &amp;reg; --> &reg;
+macron accent ¯ &amp;#175; --> &#175; &amp;macr; --> &macr;
+ &amp;hibar; --> &hibar;
+degree sign ° &amp;#176; --> &#176; &amp;deg; --> &deg;
+plus or minus ± &amp;#177; --> &#177; &amp;plusmn; --> &plusmn;
+superscript two ² &amp;#178; --> &#178; &amp;sup2; --> &sup2;
+superscript three ³ &amp;#179; --> &#179; &amp;sup3; --> &sup3;
+acute accent ´ &amp;#180; --> &#180; &amp;acute; --> &acute;
+micro sign µ &amp;#181; --> &#181; &amp;micro; --> &micro;
+paragraph sign ¶ &amp;#182; --> &#182; &amp;para; --> &para;
+middle dot · &amp;#183; --> &#183; &amp;middot; --> &middot;
+cedilla ¸ &amp;#184; --> &#184; &amp;cedil; --> &cedil;
+superscript one ¹ &amp;#185; --> &#185; &amp;sup1; --> &sup1;
+masculine ordinal º &amp;#186; --> &#186; &amp;ordm; --> &ordm;
+right angle quote, guillemotright » &amp;#187; --> &#187; &amp;raquo; --> &raquo;
+fraction one-fourth ¼ &amp;#188; --> &#188; &amp;frac14; --> &frac14;
+fraction one-half ½ &amp;#189; --> &#189; &amp;frac12; --> &frac12;
+fraction three-fourths ¾ &amp;#190; --> &#190; &amp;frac34; --> &frac34;
+inverted question mark ¿ &amp;#191; --> &#191; &amp;iquest; --> &iquest;
+capital A, grave accent À &amp;#192; --> &#192; &amp;Agrave; --> &Agrave;
+capital A, acute accent Á &amp;#193; --> &#193; &amp;Aacute; --> &Aacute;
+capital A, circumflex accent  &amp;#194; --> &#194; &amp;Acirc; --> &Acirc;
+capital A, tilde à &amp;#195; --> &#195; &amp;Atilde; --> &Atilde;
+capital A, dieresis or umlaut mark Ä &amp;#196; --> &#196; &amp;Auml; --> &Auml;
+capital A, ring Å &amp;#197; --> &#197; &amp;Aring; --> &Aring;
+capital AE diphthong (ligature) Æ &amp;#198; --> &#198; &amp;AElig; --> &AElig;
+capital C, cedilla Ç &amp;#199; --> &#199; &amp;Ccedil; --> &Ccedil;
+capital E, grave accent È &amp;#200; --> &#200; &amp;Egrave; --> &Egrave;
+capital E, acute accent É &amp;#201; --> &#201; &amp;Eacute; --> &Eacute;
+capital E, circumflex accent Ê &amp;#202; --> &#202; &amp;Ecirc; --> &Ecirc;
+capital E, dieresis or umlaut mark Ë &amp;#203; --> &#203; &amp;Euml; --> &Euml;
+capital I, grave accent Ì &amp;#204; --> &#204; &amp;Igrave; --> &Igrave;
+capital I, acute accent Í &amp;#205; --> &#205; &amp;Iacute; --> &Iacute;
+capital I, circumflex accent Î &amp;#206; --> &#206; &amp;Icirc; --> &Icirc;
+capital I, dieresis or umlaut mark Ï &amp;#207; --> &#207; &amp;Iuml; --> &Iuml;
+capital Eth, Icelandic Ð &amp;#208; --> &#208; &amp;ETH; --> &ETH;
+ &amp;Dstrok; --> &Dstrok;
+capital N, tilde Ñ &amp;#209; --> &#209; &amp;Ntilde; --> &Ntilde;
+capital O, grave accent Ò &amp;#210; --> &#210; &amp;Ograve; --> &Ograve;
+capital O, acute accent Ó &amp;#211; --> &#211; &amp;Oacute; --> &Oacute;
+capital O, circumflex accent Ô &amp;#212; --> &#212; &amp;Ocirc; --> &Ocirc;
+capital O, tilde Õ &amp;#213; --> &#213; &amp;Otilde; --> &Otilde;
+capital O, dieresis or umlaut mark Ö &amp;#214; --> &#214; &amp;Ouml; --> &Ouml;
+multiply sign × &amp;#215; --> &#215; &amp;times; --> &times;
+capital O, slash Ø &amp;#216; --> &#216; &amp;Oslash; --> &Oslash;
+capital U, grave accent Ù &amp;#217; --> &#217; &amp;Ugrave; --> &Ugrave;
+capital U, acute accent Ú &amp;#218; --> &#218; &amp;Uacute; --> &Uacute;
+capital U, circumflex accent Û &amp;#219; --> &#219; &amp;Ucirc; --> &Ucirc;
+capital U, dieresis or umlaut mark Ü &amp;#220; --> &#220; &amp;Uuml; --> &Uuml;
+capital Y, acute accent Ý &amp;#221; --> &#221; &amp;Yacute; --> &Yacute;
+capital THORN, Icelandic Þ &amp;#222; --> &#222; &amp;THORN; --> &THORN;
+small sharp s, German (sz ligature) ß &amp;#223; --> &#223; &amp;szlig; --> &szlig;
+small a, grave accent à &amp;#224; --> &#224; &amp;agrave; --> &agrave;
+small a, acute accent á &amp;#225; --> &#225; &amp;aacute; --> &aacute;
+small a, circumflex accent â &amp;#226; --> &#226; &amp;acirc; --> &acirc;
+small a, tilde ã &amp;#227; --> &#227; &amp;atilde; --> &atilde;
+small a, dieresis or umlaut mark ä &amp;#228; --> &#228; &amp;auml; --> &auml;
+small a, ring å &amp;#229; --> &#229; &amp;aring; --> &aring;
+small ae diphthong (ligature) æ &amp;#230; --> &#230; &amp;aelig; --> &aelig;
+small c, cedilla ç &amp;#231; --> &#231; &amp;ccedil; --> &ccedil;
+small e, grave accent è &amp;#232; --> &#232; &amp;egrave; --> &egrave;
+small e, acute accent é &amp;#233; --> &#233; &amp;eacute; --> &eacute;
+small e, circumflex accent ê &amp;#234; --> &#234; &amp;ecirc; --> &ecirc;
+small e, dieresis or umlaut mark ë &amp;#235; --> &#235; &amp;euml; --> &euml;
+small i, grave accent ì &amp;#236; --> &#236; &amp;igrave; --> &igrave;
+small i, acute accent í &amp;#237; --> &#237; &amp;iacute; --> &iacute;
+small i, circumflex accent î &amp;#238; --> &#238; &amp;icirc; --> &icirc;
+small i, dieresis or umlaut mark ï &amp;#239; --> &#239; &amp;iuml; --> &iuml;
+small eth, Icelandic ð &amp;#240; --> &#240; &amp;eth; --> &eth;
+small n, tilde ñ &amp;#241; --> &#241; &amp;ntilde; --> &ntilde;
+small o, grave accent ò &amp;#242; --> &#242; &amp;ograve; --> &ograve;
+small o, acute accent ó &amp;#243; --> &#243; &amp;oacute; --> &oacute;
+small o, circumflex accent ô &amp;#244; --> &#244; &amp;ocirc; --> &ocirc;
+small o, tilde õ &amp;#245; --> &#245; &amp;otilde; --> &otilde;
+small o, dieresis or umlaut mark ö &amp;#246; --> &#246; &amp;ouml; --> &ouml;
+division sign ÷ &amp;#247; --> &#247; &amp;divide; --> &divide;
+small o, slash ø &amp;#248; --> &#248; &amp;oslash; --> &oslash;
+small u, grave accent ù &amp;#249; --> &#249; &amp;ugrave; --> &ugrave;
+small u, acute accent ú &amp;#250; --> &#250; &amp;uacute; --> &uacute;
+small u, circumflex accent û &amp;#251; --> &#251; &amp;ucirc; --> &ucirc;
+small u, dieresis or umlaut mark ü &amp;#252; --> &#252; &amp;uuml; --> &uuml;
+small y, acute accent ý &amp;#253; --> &#253; &amp;yacute; --> &yacute;
+small thorn, Icelandic þ &amp;#254; --> &#254; &amp;thorn; --> &thorn;
+small y, dieresis or umlaut mark ÿ &amp;#255; --> &#255; &amp;yuml; --> &yuml;
+</PRE></PRE>
+<!-- second /PRE is a hack for HotJava 1.0 preBeta 1 -->
+<HR>
+
+<STRONG>How to read</STRONG> this table. The columns are
+<DL COMPACT>
+<DT>1st:<DD>textual <EM>description</EM> of the character
+<DT>2nd:<DD>character inserted directly into the HTML page as <EM>one
+ byte</EM>
+<DT>3rd:<DD>character written as <EM>numeric HTML entity</EM>, in the
+ format:<BR>"how it looks literally" <CODE>--&gt;</CODE>
+ "what your browser does with it"
+<DT>4th:<DD>character written as <EM>symbolic HTML entity</EM>, in the
+ format:<BR>"how it looks literally" <CODE>--&gt;</CODE>
+ "what your browser does with it"
+</DL>
+
+So for example, if you see something like "<CODE>&amp;divide; -->
+&amp;divide;</CODE>" in the 4th column, this means your browser
+doesn't know about the entity name "divide" and just puts it
+literally.
+
+<P>
+<STRONG>This table</STRONG> grew out of an overview of the "ISO
+Latin-1 Character Set" overview related to the Hyper-G Text Format
+(<A HREF="http://www.hyperwave.de/HTFdoc">HTF</A>).
+
+The entity names <CODE>&amp;brkbar;</CODE> and <CODE>&amp;Dstrok;</CODE>
+seem to be unique to HTF.
+
+The entity name <CODE>&amp;hibar;</CODE> has been supported by X Mosaic
+but seems to be replaced with <CODE>&amp;macr;</CODE>.
+
+The entity names <CODE>&amp;uml;</CODE> and <CODE>&amp;die;</CODE> should
+be equivalent.
+
+<P><STRONG>The standards stuff:</STRONG>
+The
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/html-spec/">HTML 2.0 Standard</A>
+includes a section on
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_9.html#SEC99">Character Entity Sets</A>
+and an overview on the
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/html-spec/html-spec_13.html#SEC106">HTML Coded Character Set</A>
+(The entity names are derived from <A HREF="http://www.ucc.ie/info/net/isolat1.html">ISO 8879</A>).
+<BR>
+
+Or have a look at the
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/html3/latin1.html">Latin-1 Character Entities</A>
+as listed in an draft for the
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/html3/CoverPage.html">HTML 3.0 specification</A>.
+<BR>
+
+The
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/HTMLPlus/htmlplus_59.html">Appendix II</A>
+of CERN's
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/HTMLPlus/htmlplus_1.html">HTML+ Discussion Document</A>
+contains a
+<A HREF="http://www.w3.org/hypertext/WWW/MarkUp/HTMLPlus/htmlplus_table.ps">table</A>
+(in PostScript format) of the proposed character entities for HTML+ and their
+corresponding character codes for Unicode and the Adobe Latin-1 &amp; Symbol
+character sets.
+<P>
+
+<STRONG>Please note</STRONG> that there is nothing wrong with using
+characters of ISO Latin-1 above 127: the normal transmission protocol
+for the WWW,
+<A HREF="http://www.w3.org/pub/WWW/Protocols/rfc1945/rfc1945">HTTP/1.0</A>,
+uses the 8bit ISO latin-1 as default encoding.
+(Thanks to Roman Czyborra for pointing this out!)
+<P>
+
+<STRONG>Other information:</STRONG>
+<UL>
+
+<LI><STRONG>Kevin J. Brewer</STRONG> has done two very good pages on the subject:
+ <UL>
+ <LI><A HREF="http://www.bbsinc.com/iso8859.html">ASCII - ISO 8859-1 (Latin-1) with HTML 3.0 Entities Table</A> and
+ <LI><A HREF="http://www.bbsinc.com/iso8879.html">ISO 8879 Entities Gopher Menu</A>
+ </UL>
+
+<LI>The excellent overview on the series of
+ <A HREF="http://www.cs.tu-berlin.de/~czyborra/charsets/">ISO 8859
+ character sets</A> compiled by Roman Czyborra.
+
+<LI>Also have a look on Alan Flavell's page of
+ <A HREF="http://ppewww.ph.gla.ac.uk/%7Eflavell/iso8859/iso8859-pointers.html">pointers
+ to information about ISO8859</A>. It's written very well!
+
+<LI>Maybe also of interest to you is the
+ <A HREF="ftp://ftp.vlsivie.tuwien.ac.at/pub/8bit/FAQ-ISO-8859-1">ISO
+ 8859-1 FAQ</A> by Michael Gschwind
+ (<A HREF="mailto:mike@vlsivie.tuwien.ac.at">mike@vlsivie.tuwien.ac.at</A>),
+ part of his page on
+ <A HREF="http://www.vlsivie.tuwien.ac.at/mike/i18n.html">Internationalization</A>.
+
+<LI>For users of X11R5 on SunOS systems: the
+ <A HREF="Compose.txt">table over the compose combinations</A>
+ (also coded <A HREF="Compose.html">with entities</A> where possible).
+ It's taken from the MIT X sources in
+ <CODE>server/ddx/sun/Compose.list</CODE>.
+
+<LI>Finally you could have a look at
+ <A HREF="ftp://ds.internic.net/rfc/rfc1345.txt">RFC 1345:
+ Character Mnemonics & Character Sets</A>
+ by K. Simonsen (06/11/92, 103 pages, approx. 240 kbyte).
+
+</UL>
+
+
+<HR>
+
+<ADDRESS><A HREF="http://www.forwiss.uni-passau.de/personen/ramsch/">Martin Ramsch</A>, 16.02.1994, 07.01.1996, 01.07.1996</ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/test/iso88592.html b/gnu/usr.bin/lynx/test/iso88592.html
new file mode 100644
index 00000000000..7b7f3fe9577
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/iso88592.html
@@ -0,0 +1,173 @@
+<!-- X-URL: http://www.uni-passau.de/~ramsch/iso8859-1.html -->
+<HTML>
+<HEAD>
+<TITLE>Martin Ramsch's character table modified and enhanced for iso8859-2</TITLE>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-2">
+<LINK REV="made" HREF="mailto:kweide@tezcat.com">
+<LINK REV="owner" HREF="http://www.flora.org/lynx-dev/">
+<LINK REL="sibling" HREF="iso8859-1.html" TITLE="iso-8859-1 test">
+<LINK REL="sibling" HREF="ALT88592.html" TITLE="iso-8859-2 ALT test">
+</HEAD>
+
+<BODY>
+
+<H1 ALIGN=center>iso8859-2 plus table</H1>
+
+<PRE>
+Description Code Entity name
+=================================== ============ ==============
+quotation mark &amp;#34; --> &#34; &amp;quot; --> &quot;
+ampersand &amp;#38; --> &#38; &amp;amp; --> &amp;
+less-than sign &amp;#60; --> &#60; &amp;lt; --> &lt;
+greater-than sign &amp;#62; --> &#62; &amp;gt; --> &gt;
+
+Description Char Code Entity name
+=================================== ==== ============ ==============
+non-breaking space   &amp;#160; --> &#160; &amp;nbsp; --> &nbsp;
+capital A, ogonek ¡ &amp;#260; --> &#260; &amp;Aogon; --> &Aogon;
+breve {¢} {&amp;#728;}-->{&#728;} {&amp;breve;} -->{&breve;}
+capital L, stroke £ &amp;#321; --> &#321; &amp;Lstrok; --> &Lstrok;
+general currency sign ¤ &amp;#164; --> &#164; &amp;curren; --> &curren;
+capital L, caron ¥ &amp;#317; --> &#317; &amp;Lcaron; --> &Lcaron;
+capital S, acute accent ¦ &amp;#346; --> &#346; &amp;Sacute; --> &Sacute;
+section sign § &amp;#167; --> &#167; &amp;sect; --> &sect;
+umlaut (dieresis) ¨ &amp;#168; --> &#168; &amp;uml; --> &uml;
+ &amp;die; --> &die;
+capital S, caron © &amp;#352; --> &#352; &amp;Scaron; --> &Scaron;
+capital S, cedilla ª &amp;#350; --> &#350; &amp;Scedil; --> &Scedil;
+capital T, caron « &amp;#356; --> &#356; &amp;Tcaron; --> &Tcaron;
+capital Z, acute accent ¬ &amp;#377; --> &#377; &amp;Zacute; --> &Zacute;
+soft hyphen [­] [&amp;#173;]-->[&#173;] [&amp;shy;] -->[&shy;]
+capital Z, caron ® &amp;#381; --> &#381; &amp;Zcaron; --> &Zcaron;
+capital Z, dot above ¯ &amp;#379; --> &#379; &amp;Zdot; --> &Zdot;
+degree sign ° &amp;#176; --> &#176; &amp;deg; --> &deg;
+small a, ogonek ± &amp;#261; --> &#261; &amp;aogon; --> &aogon;
+ogonek {²} {&amp;#731;}-->{&#731;} {&amp;ogon;} -->{&ogon;}
+small l, stroke ³ &amp;#322; --> &#322; &amp;lstrok; --> &lstrok;
+acute accent ´ &amp;#180; --> &#180; &amp;acute; --> &acute;
+small l, caron µ &amp;#318; --> &#318; &amp;lcaron; --> &lcaron;
+small s, acute accent ¶ &amp;#347; --> &#347; &amp;sacute; --> &sacute;
+caron {·} {&amp;#711;}-->{&#711;} {&amp;caron;} -->{&caron;}
+cedilla ¸ &amp;#184; --> &#184; &amp;cedil; --> &cedil;
+small s, caron ¹ &amp;#353; --> &#353; &amp;scaron; --> &scaron;
+small s, cedilla º &amp;#351; --> &#351; &amp;scedil; --> &scedil;
+small t, caron » &amp;#357; --> &#357; &amp;tcaron; --> &tcaron;
+small z, acute accent ¼ &amp;#378; --> &#378; &amp;zacute; --> &zacute;
+double acute accent {½} {&amp;#733;}-->{&#733;} {&amp;dblac;} -->{&dblac;}
+small z, caron ¾ &amp;#382; --> &#382; &amp;zcaron; --> &zcaron;
+small z, dot above ¿ &amp;#380; --> &#380; &amp;zdot; --> &zdot;
+capital R, acute accent À &amp;#340; --> &#340; &amp;Racute; --> &Racute;
+capital A, acute accent Á &amp;#193; --> &#193; &amp;Aacute; --> &Aacute;
+capital A, circumflex accent  &amp;#194; --> &#194; &amp;Acirc; --> &Acirc;
+capital A, breve à &amp;#258; --> &#258; &amp;Abreve; --> &Abreve;
+capital A, dieresis or umlaut mark Ä &amp;#196; --> &#196; &amp;Auml; --> &Auml;
+capital L, acute accent Å &amp;#313; --> &#313; &amp;Lacute; --> &Lacute;
+capital C, acute accent Æ &amp;#262; --> &#262; &amp;Cacute; --> &Cacute;
+capital C, cedilla Ç &amp;#199; --> &#199; &amp;Ccedil; --> &Ccedil;
+capital C, caron È &amp;#268; --> &#268; &amp;Ccaron; --> &Ccaron;
+capital E, acute accent É &amp;#201; --> &#201; &amp;Eacute; --> &Eacute;
+capital E, ogonek Ê &amp;#280; --> &#280; &amp;Eogon; --> &Eogon;
+capital E, dieresis or umlaut mark Ë &amp;#203; --> &#203; &amp;Euml; --> &Euml;
+capital E, caron Ì &amp;#282; --> &#282; &amp;Ecaron; --> &Ecaron;
+capital I, acute accent Í &amp;#205; --> &#205; &amp;Iacute; --> &Iacute;
+capital I, circumflex accent Î &amp;#206; --> &#206; &amp;Icirc; --> &Icirc;
+capital D, caron Ï &amp;#270; --> &#270; &amp;Dcaron; --> &Dcaron;
+capital D, stroke Ð &amp;#272; --> &#272; &amp;Dstrok; --> &Dstrok;
+capital Eth, Icelandic N/A &amp;#208; --> &#208; &amp;ETH; --> &ETH;
+capital N, acute accent Ñ &amp;#323; --> &#323; &amp;Nacute; --> &Nacute;
+capital N, caron Ò &amp;#327; --> &#327; &amp;Ncaron; --> &Ncaron;
+capital O, acute accent Ó &amp;#211; --> &#211; &amp;Oacute; --> &Oacute;
+capital O, circumflex accent Ô &amp;#212; --> &#212; &amp;Ocirc; --> &Ocirc;
+capital O, double acute accent Õ &amp;#368; --> &#368; &amp;Odblac; --> &Odblac;
+capital O, dieresis or umlaut mark Ö &amp;#214; --> &#214; &amp;Ouml; --> &Ouml;
+multiply sign × &amp;#215; --> &#215; &amp;times; --> &times;
+capital R, caron Ø &amp;#344; --> &#344; &amp;Rcaron; --> &Rcaron;
+capital U, ring Ù &amp;#366; --> &#366; &amp;Uring; --> &Uring;
+capital U, acute accent Ú &amp;#218; --> &#218; &amp;Uacute; --> &Uacute;
+capital U, double acute accent Û &amp;#368; --> &#368; &amp;Udblac; --> &Udblac;
+capital U, dieresis or umlaut mark Ü &amp;#220; --> &#220; &amp;Uuml; --> &Uuml;
+capital Y, acute accent Ý &amp;#221; --> &#221; &amp;Yacute; --> &Yacute;
+capital T, cedilla Þ &amp;#354; --> &#354; &amp;Tcedil; --> &Tcedil;
+small sharp s, German (sz ligature) ß &amp;#223; --> &#223; &amp;szlig; --> &szlig;
+small r, acute accent à &amp;#341; --> &#341; &amp;racute; --> &racute;
+small a, acute accent á &amp;#225; --> &#225; &amp;aacute; --> &aacute;
+small a, circumflex accent â &amp;#226; --> &#226; &amp;acirc; --> &acirc;
+small a, breve ã &amp;#259; --> &#259; &amp;abreve; --> &abreve;
+small a, dieresis or umlaut mark ä &amp;#228; --> &#228; &amp;auml; --> &auml;
+small l, acute accent å &amp;#314; --> &#314; &amp;lacute; --> &lacute;
+small c, acute accent æ &amp;#263; --> &#263; &amp;cacute; --> &cacute;
+small c, cedilla ç &amp;#231; --> &#231; &amp;ccedil; --> &ccedil;
+small c, caron è &amp;#269; --> &#269; &amp;ccaron; --> &ccaron;
+small e, acute accent é &amp;#233; --> &#233; &amp;eacute; --> &eacute;
+small e, ogonek ê &amp;#281; --> &#281; &amp;eogon; --> &eogon;
+small e, dieresis or umlaut mark ë &amp;#235; --> &#235; &amp;euml; --> &euml;
+small e, caron ì &amp;#283; --> &#283; &amp;ecaron; --> &ecaron;
+small i, acute accent í &amp;#237; --> &#237; &amp;iacute; --> &iacute;
+small i, circumflex accent î &amp;#238; --> &#238; &amp;icirc; --> &icirc;
+small d, caron ï &amp;#271; --> &#271; &amp;dcaron; --> &dcaron;
+small d, stroke ð &amp;#273; --> &#273; &amp;dstrok; --> &dstrok;
+small eth, Icelandic N/A &amp;#240; --> &#240; &amp;eth; --> &eth;
+small n, acute accent ñ &amp;#324; --> &#324; &amp;nacute; --> &nacute;
+small n, caron ò &amp;#328; --> &#328; &amp;ncaron; --> &ncaron;
+small o, acute accent ó &amp;#243; --> &#243; &amp;oacute; --> &oacute;
+small o, circumflex accent ô &amp;#244; --> &#244; &amp;ocirc; --> &ocirc;
+small o, double acute accent õ &amp;#369; --> &#369; &amp;odblac; --> &odblac;
+small o, dieresis or umlaut mark ö &amp;#246; --> &#246; &amp;ouml; --> &ouml;
+division sign ÷ &amp;#247; --> &#247; &amp;divide; --> &divide;
+small r, caron ø &amp;#345; --> &#345; &amp;rcaron; --> &rcaron;
+small u, ring ù &amp;#367; --> &#367; &amp;uring; --> &uring;
+small u, acute accent ú &amp;#250; --> &#250; &amp;uacute; --> &uacute;
+small u, double acute accent û &amp;#369; --> &#369; &amp;udblac; --> &udblac;
+small u, dieresis or umlaut mark ü &amp;#252; --> &#252; &amp;uuml; --> &uuml;
+small y, acute accent ý &amp;#253; --> &#253; &amp;yacute; --> &yacute;
+small t, cedilla þ &amp;#355; --> &#355; &amp;tcedil; --> &tcedil;
+dot above {ÿ} {&amp;#729;}-->{&#729;} {&amp;dot;} -->{&dot;}
+
+Some other characters of interest Char Code Entity name
+=================================== ==== ============ ==============
+capital AE diphthong (ligature) N/A &amp;#198; --> &#198; &amp;AElig; --> &AElig;
+small ae diphthong (ligature) N/A &amp;#230; --> &#230; &amp;aelig; --> &aelig;
+capital OE ligature N/A {&amp;#338;}-->{&#338;} {&amp;OElig;} -->{&OElig;}
+small oe ligature N/A {&amp;#339;}-->{&#339;} {&amp;oelig;} -->{&oelig;}
+copyright N/A &amp;#169; --> &#169; &amp;copy; --> &copy;
+registered trademark N/A &amp;#174; --> &#174; &amp;reg; --> &reg;
+trademark sign N/A &amp;#8482;--> &#8482; &amp;trade; --> &trade;
+em space N/A [&amp;#8195;]->[&#8195;] [&amp;emsp;] -->[&emsp;]
+en space N/A [&amp;#8194;]->[&#8194;] [&amp;ensp;] -->[&ensp;]
+1/3-em space N/A [&amp;#8196;]->[&#8196;] [&amp;emsp13;] -->[&emsp13;]
+1/4-em space N/A [&amp;#8197;]->[&#8197;] [&amp;emsp14;] -->[&emsp14;]
+thin space N/A [&amp;#8201;]->[&#8201;] [&amp;thinsp;]-->[&thinsp;]
+hair space N/A [&amp;#8202;]->[&#8202;] [&amp;hairsp;]-->[&hairsp;]
+em dash N/A [&amp;#8212;]->[&#8212;] [&amp;mdash;] -->[&mdash;]
+en dash N/A [&amp;#8211;]->[&#8211;] [&amp;ndash;] -->[&ndash;]
+
+</PRE><!-- </PRE> no HotJava preBeta hackx - kw -->
+<!-- second /PRE is a hack for HotJava 1.0 preBeta 1 -->
+<HR>
+<P>
+Characters not found in ISO-8859-2 have "N/A" in the <TT>Char</TT> column.
+Some characters for which I could not find entity names in either
+<A HREF="http://www.internic.net/rfc/rfc2070.txt">RFC 2070</A>
+or the
+<A HREF="ftp://www.ucc.ie/pub/sgml/">ISOlat1, ISOlat2, ISOnum, ISOpub and ISOtech</A>
+sets (the ones included by Peter Flynn's
+<A HREF="http://www.ucc.ie/doc/www/html/dtds/htmlpro.html">HTML Pro DTD</A>)
+are shown enclosed in <TT>{</TT>braces<TT>}</TT>.
+</P>
+<P>
+There also is a variation of this table which tests
+<A HREF="ALT88592.html">ISO-8859-2 characters and entities in ALT attributes</A>.
+</P>
+<P>
+See Martin Ramsch's original
+<A CHARSET="iso-8859-1" HREF="http://www.uni-passau.de/~ramsch/iso8859-1.html">ISO-8859-1 Table</A>
+for related info and links, and for some notes on entity names.
+This file is mostly just an adaptation of his table
+to the ISO-8859-2 character set.
+</P>
+<HR>
+
+<ADDRESS>kweide@tezcat.com 1997-03-09</ADDRESS>
+
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/test/sgml.html b/gnu/usr.bin/lynx/test/sgml.html
new file mode 100644
index 00000000000..e5c2105d716
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/sgml.html
@@ -0,0 +1,1070 @@
+<HTML>
+<HEAD>
+<TITLE> Test of some Unicode symbols enclosed as SGML entity names </TITLE>
+</HEAD>
+<BODY>
+<PRE>
+
+ This table prepared from SGML.TXT available at ftp.unicode.org
+
+ ftp://ftp.unicode.org/MAPPINGS/VENDORS/MISC/SGML.TXT
+ (if doing ftp, try cd Public/MAPPINGS/VENDORS/MISC)
+
+
+original comment:
+
+# Author: John Cowan <cowan@ccil.org>
+# Date: 25 July 1997
+#
+# The following table maps SGML character entities from various
+# public sets (namely, ISOamsa, ISOamsb, ISOamsc, ISOamsn, ISOamso,
+# ISOamsr, ISObox, ISOcyr1, ISOcyr2, ISOdia, ISOgrk1, ISOgrk2,
+# ISOgrk3, ISOgrk4, ISOlat1, ISOlat2, ISOnum, ISOpub, ISOtech,
+# HTMLspecial, HTMLsymbol) to corresponding Unicode characters.
+#
+# The table has four tab-separated columns:
+# Column 1: SGML character entity name
+# Column 2: SGML public entity set
+# Column 3: Unicode 2.0 character code
+# Column 4: Unicode 2.0 character name (UPPER CASE)
+# Entries which don't have Unicode equivalents have "0x????"
+# in Column 3 and a lower case description (from the public entity
+# set DTD) in Column 4. The mapping is not reversible, because many
+# distinctions are unified away in Unicode, particularly between
+# mathematical symbols.
+#
+# The table is sorted case-blind by SGML character entity name.
+#
+# The contents of this table are drawn from various sources, and
+# are in the public domain.
+#
+
+
+This test illuminating SGML character entities implementation in your browser.
+We sort the entities according unicode numbers.
+You should see visible character if your display character set support it
+or some substitution string picked up from src/chrtrans/def7_uni.tbl.
+If you see &amp;somename; - this name is not implemented yet,
+you may search for &amp;. (Sorry, ISOgrk4 seems to be a nonsense.
+Keep in mind that this table is much wider than in HTML 4.0 draft).
+ Leonid Pauzner.
+
+
+0x0021 &excl; ISOnum # EXCLAMATION MARK
+0x0022 &quot; ISOnum # QUOTATION MARK
+0x0023 &num; ISOnum # NUMBER SIGN
+0x0024 &dollar; ISOnum # DOLLAR SIGN
+0x0025 &percnt; ISOnum # PERCENT SIGN
+0x0026 &amp; ISOnum # AMPERSAND
+0x0028 &lpar; ISOnum # LEFT PARENTHESIS
+0x0029 &rpar; ISOnum # RIGHT PARENTHESIS
+0x002A &ast; ISOnum # ASTERISK
+0x002B &plus; ISOnum # PLUS SIGN
+0x002C &comma; ISOnum # COMMA
+0x002D &hyphen; ISOnum # HYPHEN-MINUS
+0x002E &period; ISOnum # FULL STOP
+0x002F &sol; ISOnum # SOLIDUS
+0x003A &colon; ISOnum # COLON
+0x003B &semi; ISOnum # SEMICOLON
+0x003C &lt; ISOnum # LESS-THAN SIGN
+0x003D &equals; ISOnum # EQUALS SIGN
+0x003E &gt; ISOnum # GREATER-THAN SIGN
+0x003F &quest; ISOnum # QUESTION MARK
+0x0040 &commat; ISOnum # COMMERCIAL AT
+0x005B &lsqb; ISOnum # LEFT SQUARE BRACKET
+0x005C &bsol; ISOnum # REVERSE SOLIDUS
+0x005C &sbsol; ISOamso # REVERSE SOLIDUS
+0x005D &rsqb; ISOnum # RIGHT SQUARE BRACKET
+0x005F &lowbar; ISOnum # LOW LINE
+0x0060 &grave; ISOdia # GRAVE ACCENT
+0x007B &lcub; ISOnum # LEFT CURLY BRACKET
+0x007C &verbar; ISOnum # VERTICAL LINE
+0x007D &rcub; ISOnum # RIGHT CURLY BRACKET
+0x00A0 &nbsp; ISOnum # NO-BREAK SPACE
+0x00A1 &iexcl; ISOnum # INVERTED EXCLAMATION MARK
+0x00A2 &cent; ISOnum # CENT SIGN
+0x00A3 &pound; ISOnum # POUND SIGN
+0x00A4 &curren; ISOnum # CURRENCY SIGN
+0x00A5 &yen; ISOnum # YEN SIGN
+0x00A6 &brvbar; ISOnum # BROKEN BAR
+0x00A7 &sect; ISOnum # SECTION SIGN
+0x00A8 &Dot; ISOtech # DIAERESIS
+0x00A8 &die; ISOdia # DIAERESIS
+0x00A8 &uml; ISOdia # DIAERESIS
+0x00A9 &copy; ISOnum # COPYRIGHT SIGN
+0x00AA &ordf; ISOnum # FEMININE ORDINAL INDICATOR
+0x00AB &laquo; ISOnum # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0x00AC &not; ISOnum # NOT SIGN
+0x00AD &shy; ISOnum # SOFT HYPHEN
+0x00AE &reg; ISOnum # REGISTERED SIGN
+0x00AF &macr; ISOdia # MACRON
+0x00B0 &deg; ISOnum # DEGREE SIGN
+0x00B1 &plusmn; ISOnum # PLUS-MINUS SIGN
+0x00B2 &sup2; ISOnum # SUPERSCRIPT TWO
+0x00B3 &sup3; ISOnum # SUPERSCRIPT THREE
+0x00B4 &acute; ISOdia # ACUTE ACCENT
+0x00B5 &micro; ISOnum # MICRO SIGN
+0x00B6 &para; ISOnum # PILCROW SIGN
+0x00B7 &middot; ISOnum # MIDDLE DOT
+0x00B8 &cedil; ISOdia # CEDILLA
+0x00B9 &sup1; ISOnum # SUPERSCRIPT ONE
+0x00BA &ordm; ISOnum # MASCULINE ORDINAL INDICATOR
+0x00BB &raquo; ISOnum # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0x00BC &frac14; ISOnum # VULGAR FRACTION ONE QUARTER
+0x00BD &frac12; ISOnum # VULGAR FRACTION ONE HALF
+0x00BD &half; ISOnum # VULGAR FRACTION ONE HALF
+0x00BE &frac34; ISOnum # VULGAR FRACTION THREE QUARTERS
+0x00BF &iquest; ISOnum # INVERTED QUESTION MARK
+0x00C0 &Agrave; ISOlat1 # LATIN CAPITAL LETTER A WITH GRAVE
+0x00C1 &Aacute; ISOlat1 # LATIN CAPITAL LETTER A WITH ACUTE
+0x00C2 &Acirc; ISOlat1 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0x00C3 &Atilde; ISOlat1 # LATIN CAPITAL LETTER A WITH TILDE
+0x00C4 &Auml; ISOlat1 # LATIN CAPITAL LETTER A WITH DIAERESIS
+0x00C5 &Aring; ISOlat1 # LATIN CAPITAL LETTER A WITH RING ABOVE
+0x00C6 &AElig; ISOlat1 # LATIN CAPITAL LETTER AE
+0x00C7 &Ccedil; ISOlat1 # LATIN CAPITAL LETTER C WITH CEDILLA
+0x00C8 &Egrave; ISOlat1 # LATIN CAPITAL LETTER E WITH GRAVE
+0x00C9 &Eacute; ISOlat1 # LATIN CAPITAL LETTER E WITH ACUTE
+0x00CA &Ecirc; ISOlat1 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0x00CB &Euml; ISOlat1 # LATIN CAPITAL LETTER E WITH DIAERESIS
+0x00CC &Igrave; ISOlat1 # LATIN CAPITAL LETTER I WITH GRAVE
+0x00CD &Iacute; ISOlat1 # LATIN CAPITAL LETTER I WITH ACUTE
+0x00CE &Icirc; ISOlat1 # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0x00CF &Iuml; ISOlat1 # LATIN CAPITAL LETTER I WITH DIAERESIS
+0x00D0 &ETH; ISOlat1 # LATIN CAPITAL LETTER ETH
+0x00D1 &Ntilde; ISOlat1 # LATIN CAPITAL LETTER N WITH TILDE
+0x00D2 &Ograve; ISOlat1 # LATIN CAPITAL LETTER O WITH GRAVE
+0x00D3 &Oacute; ISOlat1 # LATIN CAPITAL LETTER O WITH ACUTE
+0x00D4 &Ocirc; ISOlat1 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0x00D5 &Otilde; ISOlat1 # LATIN CAPITAL LETTER O WITH TILDE
+0x00D6 &Ouml; ISOlat1 # LATIN CAPITAL LETTER O WITH DIAERESIS
+0x00D7 &times; ISOnum # MULTIPLICATION SIGN
+0x00D8 &Oslash; ISOlat1 # LATIN CAPITAL LETTER O WITH STROKE
+0x00D9 &Ugrave; ISOlat1 # LATIN CAPITAL LETTER U WITH GRAVE
+0x00DA &Uacute; ISOlat1 # LATIN CAPITAL LETTER U WITH ACUTE
+0x00DB &Ucirc; ISOlat1 # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0x00DC &Uuml; ISOlat1 # LATIN CAPITAL LETTER U WITH DIAERESIS
+0x00DD &Yacute; ISOlat1 # LATIN CAPITAL LETTER Y WITH ACUTE
+0x00DE &THORN; ISOlat1 # LATIN CAPITAL LETTER THORN
+0x00DF &szlig; ISOlat1 # LATIN SMALL LETTER SHARP S
+0x00E0 &agrave; ISOlat1 # LATIN SMALL LETTER A WITH GRAVE
+0x00E1 &aacute; ISOlat1 # LATIN SMALL LETTER A WITH ACUTE
+0x00E2 &acirc; ISOlat1 # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x00E3 &atilde; ISOlat1 # LATIN SMALL LETTER A WITH TILDE
+0x00E4 &auml; ISOlat1 # LATIN SMALL LETTER A WITH DIAERESIS
+0x00E5 &aring; ISOlat1 # LATIN SMALL LETTER A WITH RING ABOVE
+0x00E6 &aelig; ISOlat1 # LATIN SMALL LETTER AE
+0x00E7 &ccedil; ISOlat1 # LATIN SMALL LETTER C WITH CEDILLA
+0x00E8 &egrave; ISOlat1 # LATIN SMALL LETTER E WITH GRAVE
+0x00E9 &eacute; ISOlat1 # LATIN SMALL LETTER E WITH ACUTE
+0x00EA &ecirc; ISOlat1 # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x00EB &euml; ISOlat1 # LATIN SMALL LETTER E WITH DIAERESIS
+0x00EC &igrave; ISOlat1 # LATIN SMALL LETTER I WITH GRAVE
+0x00ED &iacute; ISOlat1 # LATIN SMALL LETTER I WITH ACUTE
+0x00EE &icirc; ISOlat1 # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x00EF &iuml; ISOlat1 # LATIN SMALL LETTER I WITH DIAERESIS
+0x00F0 &eth; ISOlat1 # LATIN SMALL LETTER ETH
+0x00F1 &ntilde; ISOlat1 # LATIN SMALL LETTER N WITH TILDE
+0x00F2 &ograve; ISOlat1 # LATIN SMALL LETTER O WITH GRAVE
+0x00F3 &oacute; ISOlat1 # LATIN SMALL LETTER O WITH ACUTE
+0x00F4 &ocirc; ISOlat1 # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x00F5 &otilde; ISOlat1 # LATIN SMALL LETTER O WITH TILDE
+0x00F6 &ouml; ISOlat1 # LATIN SMALL LETTER O WITH DIAERESIS
+0x00F7 &divide; ISOnum # DIVISION SIGN
+0x00F8 &oslash; ISOlat1 # LATIN SMALL LETTER O WITH STROKE
+0x00F9 &ugrave; ISOlat1 # LATIN SMALL LETTER U WITH GRAVE
+0x00FA &uacute; ISOlat1 # LATIN SMALL LETTER U WITH ACUTE
+0x00FB &ucirc; ISOlat1 # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x00FC &uuml; ISOlat1 # LATIN SMALL LETTER U WITH DIAERESIS
+0x00FD &yacute; ISOlat1 # LATIN SMALL LETTER Y WITH ACUTE
+0x00FE &thorn; ISOlat1 # LATIN SMALL LETTER THORN
+0x00FF &yuml; ISOlat1 # LATIN SMALL LETTER Y WITH DIAERESIS
+0x0100 &Amacr; ISOlat2 # LATIN CAPITAL LETTER A WITH MACRON
+0x0101 &amacr; ISOlat2 # LATIN SMALL LETTER A WITH MACRON
+0x0102 &Abreve; ISOlat2 # LATIN CAPITAL LETTER A WITH BREVE
+0x0103 &abreve; ISOlat2 # LATIN SMALL LETTER A WITH BREVE
+0x0104 &Aogon; ISOlat2 # LATIN CAPITAL LETTER A WITH OGONEK
+0x0105 &aogon; ISOlat2 # LATIN SMALL LETTER A WITH OGONEK
+0x0106 &Cacute; ISOlat2 # LATIN CAPITAL LETTER C WITH ACUTE
+0x0107 &cacute; ISOlat2 # LATIN SMALL LETTER C WITH ACUTE
+0x0108 &Ccirc; ISOlat2 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0x0109 &ccirc; ISOlat2 # LATIN SMALL LETTER C WITH CIRCUMFLEX
+0x010A &Cdot; ISOlat2 # LATIN CAPITAL LETTER C WITH DOT ABOVE
+0x010B &cdot; ISOlat2 # LATIN SMALL LETTER C WITH DOT ABOVE
+0x010C &Ccaron; ISOlat2 # LATIN CAPITAL LETTER C WITH CARON
+0x010D &ccaron; ISOlat2 # LATIN SMALL LETTER C WITH CARON
+0x010E &Dcaron; ISOlat2 # LATIN CAPITAL LETTER D WITH CARON
+0x010F &dcaron; ISOlat2 # LATIN SMALL LETTER D WITH CARON
+0x0110 &Dstrok; ISOlat2 # LATIN CAPITAL LETTER D WITH STROKE
+0x0111 &dstrok; ISOlat2 # LATIN SMALL LETTER D WITH STROKE
+0x0112 &Emacr; ISOlat2 # LATIN CAPITAL LETTER E WITH MACRON
+0x0113 &emacr; ISOlat2 # LATIN SMALL LETTER E WITH MACRON
+0x0116 &Edot; ISOlat2 # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0x0117 &edot; ISOlat2 # LATIN SMALL LETTER E WITH DOT ABOVE
+0x0118 &Eogon; ISOlat2 # LATIN CAPITAL LETTER E WITH OGONEK
+0x0119 &eogon; ISOlat2 # LATIN SMALL LETTER E WITH OGONEK
+0x011A &Ecaron; ISOlat2 # LATIN CAPITAL LETTER E WITH CARON
+0x011B &ecaron; ISOlat2 # LATIN SMALL LETTER E WITH CARON
+0x011C &Gcirc; ISOlat2 # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0x011D &gcirc; ISOlat2 # LATIN SMALL LETTER G WITH CIRCUMFLEX
+0x011E &Gbreve; ISOlat2 # LATIN CAPITAL LETTER G WITH BREVE
+0x011F &gbreve; ISOlat2 # LATIN SMALL LETTER G WITH BREVE
+0x0120 &Gdot; ISOlat2 # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0x0121 &gdot; ISOlat2 # LATIN SMALL LETTER G WITH DOT ABOVE
+0x0122 &Gcedil; ISOlat2 # LATIN CAPITAL LETTER G WITH CEDILLA
+0x0123 &gcedil; ISOlat2 # LATIN SMALL LETTER G WITH CEDILLA
+0x0124 &Hcirc; ISOlat2 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0x0125 &hcirc; ISOlat2 # LATIN SMALL LETTER H WITH CIRCUMFLEX
+0x0126 &Hstrok; ISOlat2 # LATIN CAPITAL LETTER H WITH STROKE
+0x0127 &hstrok; ISOlat2 # LATIN SMALL LETTER H WITH STROKE
+0x0128 &Itilde; ISOlat2 # LATIN CAPITAL LETTER I WITH TILDE
+0x0129 &itilde; ISOlat2 # LATIN SMALL LETTER I WITH TILDE
+0x012A &Imacr; ISOlat2 # LATIN CAPITAL LETTER I WITH MACRON
+0x012B &imacr; ISOlat2 # LATIN SMALL LETTER I WITH MACRON
+0x012E &Iogon; ISOlat2 # LATIN CAPITAL LETTER I WITH OGONEK
+0x012F &iogon; ISOlat2 # LATIN SMALL LETTER I WITH OGONEK
+0x0130 &Idot; ISOlat2 # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0x0131 &inodot; ISOamso # LATIN SMALL LETTER DOTLESS I
+0x0131 &inodot; ISOlat2 # LATIN SMALL LETTER DOTLESS I
+0x0132 &IJlig; ISOlat2 # LATIN CAPITAL LIGATURE IJ
+0x0133 &ijlig; ISOlat2 # LATIN SMALL LIGATURE IJ
+0x0134 &Jcirc; ISOlat2 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0x0135 &jcirc; ISOlat2 # LATIN SMALL LETTER J WITH CIRCUMFLEX
+0x0136 &Kcedil; ISOlat2 # LATIN CAPITAL LETTER K WITH CEDILLA
+0x0137 &kcedil; ISOlat2 # LATIN SMALL LETTER K WITH CEDILLA
+0x0138 &kgreen; ISOlat2 # LATIN SMALL LETTER KRA
+0x0139 &Lacute; ISOlat2 # LATIN CAPITAL LETTER L WITH ACUTE
+0x013A &lacute; ISOlat2 # LATIN SMALL LETTER L WITH ACUTE
+0x013B &Lcedil; ISOlat2 # LATIN CAPITAL LETTER L WITH CEDILLA
+0x013C &lcedil; ISOlat2 # LATIN SMALL LETTER L WITH CEDILLA
+0x013D &Lcaron; ISOlat2 # LATIN CAPITAL LETTER L WITH CARON
+0x013E &lcaron; ISOlat2 # LATIN SMALL LETTER L WITH CARON
+0x013F &Lmidot; ISOlat2 # LATIN CAPITAL LETTER L WITH MIDDLE DOT
+0x0140 &lmidot; ISOlat2 # LATIN SMALL LETTER L WITH MIDDLE DOT
+0x0141 &Lstrok; ISOlat2 # LATIN CAPITAL LETTER L WITH STROKE
+0x0142 &lstrok; ISOlat2 # LATIN SMALL LETTER L WITH STROKE
+0x0143 &Nacute; ISOlat2 # LATIN CAPITAL LETTER N WITH ACUTE
+0x0144 &nacute; ISOlat2 # LATIN SMALL LETTER N WITH ACUTE
+0x0145 &Ncedil; ISOlat2 # LATIN CAPITAL LETTER N WITH CEDILLA
+0x0146 &ncedil; ISOlat2 # LATIN SMALL LETTER N WITH CEDILLA
+0x0147 &Ncaron; ISOlat2 # LATIN CAPITAL LETTER N WITH CARON
+0x0148 &ncaron; ISOlat2 # LATIN SMALL LETTER N WITH CARON
+0x0149 &napos; ISOlat2 # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+0x014A &ENG; ISOlat2 # LATIN CAPITAL LETTER ENG
+0x014B &eng; ISOlat2 # LATIN SMALL LETTER ENG
+0x014C &Omacr; ISOlat2 # LATIN CAPITAL LETTER O WITH MACRON
+0x014D &omacr; ISOlat2 # LATIN SMALL LETTER O WITH MACRON
+0x0150 &Odblac; ISOlat2 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0x0151 &odblac; ISOlat2 # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0x0152 &OElig; ISOlat2 # LATIN CAPITAL LIGATURE OE
+0x0153 &oelig; ISOlat2 # LATIN SMALL LIGATURE OE
+0x0154 &Racute; ISOlat2 # LATIN CAPITAL LETTER R WITH ACUTE
+0x0155 &racute; ISOlat2 # LATIN SMALL LETTER R WITH ACUTE
+0x0156 &Rcedil; ISOlat2 # LATIN CAPITAL LETTER R WITH CEDILLA
+0x0157 &rcedil; ISOlat2 # LATIN SMALL LETTER R WITH CEDILLA
+0x0158 &Rcaron; ISOlat2 # LATIN CAPITAL LETTER R WITH CARON
+0x0159 &rcaron; ISOlat2 # LATIN SMALL LETTER R WITH CARON
+0x015A &Sacute; ISOlat2 # LATIN CAPITAL LETTER S WITH ACUTE
+0x015B &sacute; ISOlat2 # LATIN SMALL LETTER S WITH ACUTE
+0x015C &Scirc; ISOlat2 # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0x015D &scirc; ISOlat2 # LATIN SMALL LETTER S WITH CIRCUMFLEX
+0x015E &Scedil; ISOlat2 # LATIN CAPITAL LETTER S WITH CEDILLA
+0x015F &scedil; ISOlat2 # LATIN SMALL LETTER S WITH CEDILLA
+0x0160 &Scaron; ISOlat2 # LATIN CAPITAL LETTER S WITH CARON
+0x0161 &scaron; ISOlat2 # LATIN SMALL LETTER S WITH CARON
+0x0162 &Tcedil; ISOlat2 # LATIN CAPITAL LETTER T WITH CEDILLA
+0x0163 &tcedil; ISOlat2 # LATIN SMALL LETTER T WITH CEDILLA
+0x0164 &Tcaron; ISOlat2 # LATIN CAPITAL LETTER T WITH CARON
+0x0165 &tcaron; ISOlat2 # LATIN SMALL LETTER T WITH CARON
+0x0166 &Tstrok; ISOlat2 # LATIN CAPITAL LETTER T WITH STROKE
+0x0167 &tstrok; ISOlat2 # LATIN SMALL LETTER T WITH STROKE
+0x0168 &Utilde; ISOlat2 # LATIN CAPITAL LETTER U WITH TILDE
+0x0169 &utilde; ISOlat2 # LATIN SMALL LETTER U WITH TILDE
+0x016A &Umacr; ISOlat2 # LATIN CAPITAL LETTER U WITH MACRON
+0x016B &umacr; ISOlat2 # LATIN SMALL LETTER U WITH MACRON
+0x016C &Ubreve; ISOlat2 # LATIN CAPITAL LETTER U WITH BREVE
+0x016D &ubreve; ISOlat2 # LATIN SMALL LETTER U WITH BREVE
+0x016E &Uring; ISOlat2 # LATIN CAPITAL LETTER U WITH RING ABOVE
+0x016F &uring; ISOlat2 # LATIN SMALL LETTER U WITH RING ABOVE
+0x0170 &Udblac; ISOlat2 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0x0171 &udblac; ISOlat2 # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0x0172 &Uogon; ISOlat2 # LATIN CAPITAL LETTER U WITH OGONEK
+0x0173 &uogon; ISOlat2 # LATIN SMALL LETTER U WITH OGONEK
+0x0174 &Wcirc; ISOlat2 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0x0175 &wcirc; ISOlat2 # LATIN SMALL LETTER W WITH CIRCUMFLEX
+0x0176 &Ycirc; ISOlat2 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0x0177 &ycirc; ISOlat2 # LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0x0178 &Yuml; ISOlat2 # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0x0179 &Zacute; ISOlat2 # LATIN CAPITAL LETTER Z WITH ACUTE
+0x017A &zacute; ISOlat2 # LATIN SMALL LETTER Z WITH ACUTE
+0x017B &Zdot; ISOlat2 # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0x017C &zdot; ISOlat2 # LATIN SMALL LETTER Z WITH DOT ABOVE
+0x017D &Zcaron; ISOlat2 # LATIN CAPITAL LETTER Z WITH CARON
+0x017E &zcaron; ISOlat2 # LATIN SMALL LETTER Z WITH CARON
+0x0192 &fnof; ISOtech # LATIN SMALL LETTER F WITH HOOK
+0x01F5 &gacute; ISOlat2 # LATIN SMALL LETTER G WITH ACUTE
+0x02BC &apos; ISOnum # MODIFIER LETTER APOSTROPHE
+0x02C6 &circ; ISOdia # MODIFIER LETTER CIRCUMFLEX ACCENT
+0x02C7 &caron; ISOdia # CARON
+0x02D8 &breve; ISOdia # BREVE
+0x02D9 &dot; ISOdia # DOT ABOVE
+0x02DA &ring; ISOdia # RING ABOVE
+0x02DB &ogon; ISOdia # OGONEK
+0x02DC &tilde; ISOdia # SMALL TILDE
+0x02DD &dblac; ISOdia # DOUBLE ACUTE ACCENT
+0x0386 &Aacgr; ISOgrk2 # GREEK CAPITAL LETTER ALPHA WITH TONOS
+0x0388 &Eacgr; ISOgrk2 # GREEK CAPITAL LETTER EPSILON WITH TONOS
+0x0389 &EEacgr; ISOgrk2 # GREEK CAPITAL LETTER ETA WITH TONOS
+0x038A &Iacgr; ISOgrk2 # GREEK CAPITAL LETTER IOTA WITH TONOS
+0x038C &Oacgr; ISOgrk2 # GREEK CAPITAL LETTER OMICRON WITH TONOS
+0x038E &Uacgr; ISOgrk2 # GREEK CAPITAL LETTER UPSILON WITH TONOS
+0x038F &OHacgr; ISOgrk2 # GREEK CAPITAL LETTER OMEGA WITH TONOS
+0x0390 &idiagr; ISOgrk2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0x0391 &Agr; ISOgrk1 # GREEK CAPITAL LETTER ALPHA
+0x0391 &Alpha; HTMLsymbol # GREEK CAPITAL LETTER ALPHA
+0x0392 &Beta; HTMLsymbol # GREEK CAPITAL LETTER BETA
+0x0392 &Bgr; ISOgrk1 # GREEK CAPITAL LETTER BETA
+0x0393 &Gamma; ISOgrk3 # GREEK CAPITAL LETTER GAMMA
+0x0393 &Ggr; ISOgrk1 # GREEK CAPITAL LETTER GAMMA
+0x0393 &b.Gamma; ISOgrk4 # GREEK CAPITAL LETTER GAMMA
+0x0394 &Delta; ISOgrk3 # GREEK CAPITAL LETTER DELTA
+0x0394 &Dgr; ISOgrk1 # GREEK CAPITAL LETTER DELTA
+0x0394 &b.Delta; ISOgrk4 # GREEK CAPITAL LETTER DELTA
+0x0395 &Egr; ISOgrk1 # GREEK CAPITAL LETTER EPSILON
+0x0395 &Epsilon; HTMLsymbol # GREEK CAPITAL LETTER EPSILON
+0x0396 &Zeta; HTMLsymbol # GREEK CAPITAL LETTER ZETA
+0x0396 &Zgr; ISOgrk1 # GREEK CAPITAL LETTER ZETA
+0x0397 &EEgr; ISOgrk1 # GREEK CAPITAL LETTER ETA
+0x0397 &Eta; HTMLsymbol # GREEK CAPITAL LETTER ETA
+0x0398 &THgr; ISOgrk1 # GREEK CAPITAL LETTER THETA
+0x0398 &Theta; ISOgrk3 # GREEK CAPITAL LETTER THETA
+0x0398 &b.Theta; ISOgrk4 # GREEK CAPITAL LETTER THETA
+0x0399 &Igr; ISOgrk1 # GREEK CAPITAL LETTER IOTA
+0x0399 &Iota; HTMLsymbol # GREEK CAPITAL LETTER IOTA
+0x039A &Kappa; HTMLsymbol # GREEK CAPITAL LETTER KAPPA
+0x039A &Kgr; ISOgrk1 # GREEK CAPITAL LETTER KAPPA
+0x039B &Lambda; ISOgrk3 # GREEK CAPITAL LETTER LAMDA
+0x039B &Lgr; ISOgrk1 # GREEK CAPITAL LETTER LAMDA
+0x039B &b.Lambda; ISOgrk4 # GREEK CAPITAL LETTER LAMDA
+0x039C &Mgr; ISOgrk1 # GREEK CAPITAL LETTER MU
+0x039C &Mu; HTMLsymbol # GREEK CAPITAL LETTER MU
+0x039D &Ngr; ISOgrk1 # GREEK CAPITAL LETTER NU
+0x039D &Nu; HTMLsymbol # GREEK CAPITAL LETTER NU
+0x039E &Xgr; ISOgrk1 # GREEK CAPITAL LETTER XI
+0x039E &Xi; ISOgrk3 # GREEK CAPITAL LETTER XI
+0x039E &b.Xi; ISOgrk4 # GREEK CAPITAL LETTER XI
+0x039F &Ogr; ISOgrk1 # GREEK CAPITAL LETTER OMICRON
+0x039F &Omicron; HTMLsymbol # GREEK CAPITAL LETTER OMICRON
+0x03A0 &Pgr; ISOgrk1 # GREEK CAPITAL LETTER PI
+0x03A0 &Pi; ISOgrk3 # GREEK CAPITAL LETTER PI
+0x03A0 &b.Pi; ISOgrk4 # GREEK CAPITAL LETTER PI
+0x03A1 &Rgr; ISOgrk1 # GREEK CAPITAL LETTER RHO
+0x03A1 &Rho; HTMLsymbol # GREEK CAPITAL LETTER RHO
+0x03A3 &Sgr; ISOgrk1 # GREEK CAPITAL LETTER SIGMA
+0x03A3 &Sigma; ISOgrk3 # GREEK CAPITAL LETTER SIGMA
+0x03A3 &b.Sigma; ISOgrk4 # GREEK CAPITAL LETTER SIGMA
+0x03A4 &Tau; HTMLsymbol # GREEK CAPITAL LETTER TAU
+0x03A4 &Tgr; ISOgrk1 # GREEK CAPITAL LETTER TAU
+0x03A5 &Ugr; ISOgrk1 # GREEK CAPITAL LETTER UPSILON
+0x03A5 &Upsi; ISOgrk3 # GREEK CAPITAL LETTER UPSILON
+0x03A5 &Upsilon; HTMLsymbol # GREEK CAPITAL LETTER UPSILON
+0x03A5 &b.Upsi; ISOgrk4 # GREEK CAPITAL LETTER UPSILON
+0x03A6 &PHgr; ISOgrk1 # GREEK CAPITAL LETTER PHI
+0x03A6 &Phi; ISOgrk3 # GREEK CAPITAL LETTER PHI
+0x03A6 &b.Phi; ISOgrk4 # GREEK CAPITAL LETTER PHI
+0x03A7 &Chi; HTMLsymbol # GREEK CAPITAL LETTER CHI
+0x03A7 &KHgr; ISOgrk1 # GREEK CAPITAL LETTER CHI
+0x03A8 &PSgr; ISOgrk1 # GREEK CAPITAL LETTER PSI
+0x03A8 &Psi; ISOgrk3 # GREEK CAPITAL LETTER PSI
+0x03A8 &b.Psi; ISOgrk4 # GREEK CAPITAL LETTER PSI
+0x03A9 &OHgr; ISOgrk1 # GREEK CAPITAL LETTER OMEGA
+0x03A9 &Omega; ISOgrk3 # GREEK CAPITAL LETTER OMEGA
+0x03A9 &b.Omega; ISOgrk4 # GREEK CAPITAL LETTER OMEGA
+0x03AA &Idigr; ISOgrk2 # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0x03AB &Udigr; ISOgrk2 # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0x03AC &aacgr; ISOgrk2 # GREEK SMALL LETTER ALPHA WITH TONOS
+0x03AD &eacgr; ISOgrk2 # GREEK SMALL LETTER EPSILON WITH TONOS
+0x03AE &eeacgr; ISOgrk2 # GREEK SMALL LETTER ETA WITH TONOS
+0x03AF &iacgr; ISOgrk2 # GREEK SMALL LETTER IOTA WITH TONOS
+0x03B0 &udiagr; ISOgrk2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND
+0x03B1 &agr; ISOgrk1 # GREEK SMALL LETTER ALPHA
+0x03B1 &alpha; ISOgrk3 # GREEK SMALL LETTER ALPHA
+0x03B1 &b.alpha; ISOgrk4 # GREEK SMALL LETTER ALPHA
+0x03B2 &b.beta; ISOgrk4 # GREEK SMALL LETTER BETA
+0x03B2 &beta; ISOgrk3 # GREEK SMALL LETTER BETA
+0x03B2 &bgr; ISOgrk1 # GREEK SMALL LETTER BETA
+0x03B3 &b.delta; ISOgrk4 # GREEK SMALL LETTER GAMMA
+0x03B3 &b.gamma; ISOgrk4 # GREEK SMALL LETTER GAMMA
+0x03B3 &gamma; ISOgrk3 # GREEK SMALL LETTER GAMMA
+0x03B3 &ggr; ISOgrk1 # GREEK SMALL LETTER GAMMA
+0x03B4 &delta; ISOgrk3 # GREEK SMALL LETTER DELTA
+0x03B4 &dgr; ISOgrk1 # GREEK SMALL LETTER DELTA
+0x03B5 &b.epsi; ISOgrk4 # GREEK SMALL LETTER EPSILON
+0x03B5 &b.epsis; ISOgrk4 # GREEK SMALL LETTER EPSILON
+0x03B5 &b.epsiv; ISOgrk4 # GREEK SMALL LETTER EPSILON
+0x03B5 &egr; ISOgrk1 # GREEK SMALL LETTER EPSILON
+0x03B5 &epsi; ISOgrk3 # GREEK SMALL LETTER EPSILON
+0x03B5 &epsilon; HTMLsymbol # GREEK SMALL LETTER EPSILON
+0x03B6 &b.zeta; ISOgrk4 # GREEK SMALL LETTER ZETA
+0x03B6 &zeta; ISOgrk3 # GREEK SMALL LETTER ZETA
+0x03B6 &zgr; ISOgrk1 # GREEK SMALL LETTER ZETA
+0x03B7 &b.eta; ISOgrk4 # GREEK SMALL LETTER ETA
+0x03B7 &eegr; ISOgrk1 # GREEK SMALL LETTER ETA
+0x03B7 &eta; ISOgrk3 # GREEK SMALL LETTER ETA
+0x03B8 &b.thetas; ISOgrk4 # GREEK SMALL LETTER THETA
+0x03B8 &theta; HTMLsymbol # GREEK SMALL LETTER THETA
+0x03B8 &thetas; ISOgrk3 # GREEK SMALL LETTER THETA
+0x03B8 &thgr; ISOgrk1 # GREEK SMALL LETTER THETA
+0x03B9 &b.iota; ISOgrk4 # GREEK SMALL LETTER IOTA
+0x03B9 &igr; ISOgrk1 # GREEK SMALL LETTER IOTA
+0x03B9 &iota; ISOgrk3 # GREEK SMALL LETTER IOTA
+0x03BA &b.kappa; ISOgrk4 # GREEK SMALL LETTER KAPPA
+0x03BA &kappa; ISOgrk3 # GREEK SMALL LETTER KAPPA
+0x03BA &kgr; ISOgrk1 # GREEK SMALL LETTER KAPPA
+0x03BB &b.lambda; ISOgrk4 # GREEK SMALL LETTER LAMDA
+0x03BB &lambda; ISOgrk3 # GREEK SMALL LETTER LAMDA
+0x03BB &lgr; ISOgrk1 # GREEK SMALL LETTER LAMDA
+0x03BC &b.mu; ISOgrk4 # GREEK SMALL LETTER MU
+0x03BC &mgr; ISOgrk1 # GREEK SMALL LETTER MU
+0x03BC &mu; ISOgrk3 # GREEK SMALL LETTER MU
+0x03BD &b.nu; ISOgrk4 # GREEK SMALL LETTER NU
+0x03BD &ngr; ISOgrk1 # GREEK SMALL LETTER NU
+0x03BD &nu; ISOgrk3 # GREEK SMALL LETTER NU
+0x03BE &b.xi; ISOgrk4 # GREEK SMALL LETTER XI
+0x03BE &xgr; ISOgrk1 # GREEK SMALL LETTER XI
+0x03BE &xi; ISOgrk3 # GREEK SMALL LETTER XI
+0x03BF &ogr; ISOgrk1 # GREEK SMALL LETTER OMICRON
+0x03BF &omicron; HTMLsymbol # GREEK SMALL LETTER OMICRON
+0x03C0 &b.pi; ISOgrk4 # GREEK SMALL LETTER PI
+0x03C0 &pgr; ISOgrk1 # GREEK SMALL LETTER PI
+0x03C0 &pi; ISOgrk3 # GREEK SMALL LETTER PI
+0x03C1 &b.rho; ISOgrk4 # GREEK SMALL LETTER RHO
+0x03C1 &rgr; ISOgrk1 # GREEK SMALL LETTER RHO
+0x03C1 &rho; ISOgrk3 # GREEK SMALL LETTER RHO
+0x03C2 &b.sigmav; ISOgrk4 # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &sfgr; ISOgrk1 # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &sigmaf; HTMLsymbol # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &sigmav; ISOgrk3 # GREEK SMALL LETTER FINAL SIGMA
+0x03C3 &b.sigma; ISOgrk4 # GREEK SMALL LETTER SIGMA
+0x03C3 &sgr; ISOgrk1 # GREEK SMALL LETTER SIGMA
+0x03C3 &sigma; ISOgrk3 # GREEK SMALL LETTER SIGMA
+0x03C4 &b.tau; ISOgrk4 # GREEK SMALL LETTER TAU
+0x03C4 &tau; ISOgrk3 # GREEK SMALL LETTER TAU
+0x03C4 &tgr; ISOgrk1 # GREEK SMALL LETTER TAU
+0x03C5 &b.upsi; ISOgrk4 # GREEK SMALL LETTER UPSILON
+0x03C5 &ugr; ISOgrk1 # GREEK SMALL LETTER UPSILON
+0x03C5 &upsi; ISOgrk3 # GREEK SMALL LETTER UPSILON
+0x03C5 &upsilon; HTMLsymbol # GREEK SMALL LETTER UPSILON
+0x03C6 &b.phis; ISOgrk4 # GREEK SMALL LETTER PHI
+0x03C6 &phgr; ISOgrk1 # GREEK SMALL LETTER PHI
+0x03C6 &phi; HTMLsymbol # GREEK SMALL LETTER PHI
+0x03C6 &phis; ISOgrk3 # GREEK SMALL LETTER PHI
+0x03C7 &b.chi; ISOgrk4 # GREEK SMALL LETTER CHI
+0x03C7 &chi; ISOgrk3 # GREEK SMALL LETTER CHI
+0x03C7 &khgr; ISOgrk1 # GREEK SMALL LETTER CHI
+0x03C8 &b.psi; ISOgrk4 # GREEK SMALL LETTER PSI
+0x03C8 &psgr; ISOgrk1 # GREEK SMALL LETTER PSI
+0x03C8 &psi; ISOgrk3 # GREEK SMALL LETTER PSI
+0x03C9 &ohgr; ISOgrk1 # GREEK SMALL LETTER OMEGA
+0x03C9 &omega; ISOgrk3 # GREEK SMALL LETTER OMEGA
+0x03CA &idigr; ISOgrk2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0x03CB &udigr; ISOgrk2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0x03CC &oacgr; ISOgrk2 # GREEK SMALL LETTER OMICRON WITH TONOS
+0x03CD &uacgr; ISOgrk2 # GREEK SMALL LETTER UPSILON WITH TONOS
+0x03CE &b.omega; ISOgrk4 # GREEK SMALL LETTER OMEGA WITH TONOS
+0x03CE &ohacgr; ISOgrk2 # GREEK SMALL LETTER OMEGA WITH TONOS
+0x03D1 &b.thetav; ISOgrk4 # GREEK THETA SYMBOL
+0x03D1 &thetasym; HTMLsymbol # GREEK THETA SYMBOL
+0x03D1 &thetav; ISOgrk3 # GREEK THETA SYMBOL
+0x03D2 &upsih; HTMLsymbol # GREEK UPSILON WITH HOOK SYMBOL
+0x03D5 &b.phiv; ISOgrk4 # GREEK PHI SYMBOL
+0x03D5 &phiv; ISOgrk3 # GREEK PHI SYMBOL
+0x03D6 &b.piv; ISOgrk4 # GREEK PI SYMBOL
+0x03D6 &piv; ISOgrk3 # GREEK PI SYMBOL
+0x03DC &b.gammad; ISOgrk4 # GREEK LETTER DIGAMMA
+0x03DC &gammad; ISOgrk3 # GREEK LETTER DIGAMMA
+0x03F0 &b.kappav; ISOgrk4 # GREEK KAPPA SYMBOL
+0x03F0 &kappav; ISOgrk3 # GREEK KAPPA SYMBOL
+0x03F1 &b.rhov; ISOgrk4 # GREEK RHO SYMBOL
+0x03F1 &rhov; ISOgrk3 # GREEK RHO SYMBOL
+0x0401 &IOcy; ISOcyr1 # CYRILLIC CAPITAL LETTER IO
+0x0402 &DJcy; ISOcyr2 # CYRILLIC CAPITAL LETTER DJE
+0x0403 &GJcy; ISOcyr2 # CYRILLIC CAPITAL LETTER GJE
+0x0404 &Jukcy; ISOcyr2 # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0x0405 &DScy; ISOcyr2 # CYRILLIC CAPITAL LETTER DZE
+0x0406 &Iukcy; ISOcyr2 # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0x0407 &YIcy; ISOcyr2 # CYRILLIC CAPITAL LETTER YI
+0x0408 &Jsercy; ISOcyr2 # CYRILLIC CAPITAL LETTER JE
+0x0409 &LJcy; ISOcyr2 # CYRILLIC CAPITAL LETTER LJE
+0x040A &NJcy; ISOcyr2 # CYRILLIC CAPITAL LETTER NJE
+0x040B &TSHcy; ISOcyr2 # CYRILLIC CAPITAL LETTER TSHE
+0x040C &KJcy; ISOcyr2 # CYRILLIC CAPITAL LETTER KJE
+0x040E &Ubrcy; ISOcyr2 # CYRILLIC CAPITAL LETTER SHORT U
+0x040F &DZcy; ISOcyr2 # CYRILLIC CAPITAL LETTER DZHE
+0x0410 &Acy; ISOcyr1 # CYRILLIC CAPITAL LETTER A
+0x0411 &Bcy; ISOcyr1 # CYRILLIC CAPITAL LETTER BE
+0x0412 &Vcy; ISOcyr1 # CYRILLIC CAPITAL LETTER VE
+0x0413 &Gcy; ISOcyr1 # CYRILLIC CAPITAL LETTER GHE
+0x0414 &Dcy; ISOcyr1 # CYRILLIC CAPITAL LETTER DE
+0x0415 &IEcy; ISOcyr1 # CYRILLIC CAPITAL LETTER IE
+0x0416 &ZHcy; ISOcyr1 # CYRILLIC CAPITAL LETTER ZHE
+0x0417 &Zcy; ISOcyr1 # CYRILLIC CAPITAL LETTER ZE
+0x0418 &Icy; ISOcyr1 # CYRILLIC CAPITAL LETTER I
+0x0419 &Jcy; ISOcyr1 # CYRILLIC CAPITAL LETTER SHORT I
+0x041A &Kcy; ISOcyr1 # CYRILLIC CAPITAL LETTER KA
+0x041B &Lcy; ISOcyr1 # CYRILLIC CAPITAL LETTER EL
+0x041C &Mcy; ISOcyr1 # CYRILLIC CAPITAL LETTER EM
+0x041D &Ncy; ISOcyr1 # CYRILLIC CAPITAL LETTER EN
+0x041E &Ocy; ISOcyr1 # CYRILLIC CAPITAL LETTER O
+0x041F &Pcy; ISOcyr1 # CYRILLIC CAPITAL LETTER PE
+0x0420 &Rcy; ISOcyr1 # CYRILLIC CAPITAL LETTER ER
+0x0421 &Scy; ISOcyr1 # CYRILLIC CAPITAL LETTER ES
+0x0422 &Tcy; ISOcyr1 # CYRILLIC CAPITAL LETTER TE
+0x0423 &Ucy; ISOcyr1 # CYRILLIC CAPITAL LETTER U
+0x0424 &Fcy; ISOcyr1 # CYRILLIC CAPITAL LETTER EF
+0x0425 &KHcy; ISOcyr1 # CYRILLIC CAPITAL LETTER HA
+0x0426 &TScy; ISOcyr1 # CYRILLIC CAPITAL LETTER TSE
+0x0427 &CHcy; ISOcyr1 # CYRILLIC CAPITAL LETTER CHE
+0x0428 &SHcy; ISOcyr1 # CYRILLIC CAPITAL LETTER SHA
+0x0429 &SHCHcy; ISOcyr1 # CYRILLIC CAPITAL LETTER SHCHA
+0x042A &HARDcy; ISOcyr1 # CYRILLIC CAPITAL LETTER HARD SIGN
+0x042B &Ycy; ISOcyr1 # CYRILLIC CAPITAL LETTER YERU
+0x042C &SOFTcy; ISOcyr1 # CYRILLIC CAPITAL LETTER SOFT SIGN
+0x042D &Ecy; ISOcyr1 # CYRILLIC CAPITAL LETTER E
+0x042E &YUcy; ISOcyr1 # CYRILLIC CAPITAL LETTER YU
+0x042F &YAcy; ISOcyr1 # CYRILLIC CAPITAL LETTER YA
+0x0430 &acy; ISOcyr1 # CYRILLIC SMALL LETTER A
+0x0431 &bcy; ISOcyr1 # CYRILLIC SMALL LETTER BE
+0x0432 &vcy; ISOcyr1 # CYRILLIC SMALL LETTER VE
+0x0433 &gcy; ISOcyr1 # CYRILLIC SMALL LETTER GHE
+0x0434 &dcy; ISOcyr1 # CYRILLIC SMALL LETTER DE
+0x0435 &iecy; ISOcyr1 # CYRILLIC SMALL LETTER IE
+0x0436 &zhcy; ISOcyr1 # CYRILLIC SMALL LETTER ZHE
+0x0437 &zcy; ISOcyr1 # CYRILLIC SMALL LETTER ZE
+0x0438 &icy; ISOcyr1 # CYRILLIC SMALL LETTER I
+0x0439 &jcy; ISOcyr1 # CYRILLIC SMALL LETTER SHORT I
+0x043A &kcy; ISOcyr1 # CYRILLIC SMALL LETTER KA
+0x043B &lcy; ISOcyr1 # CYRILLIC SMALL LETTER EL
+0x043C &mcy; ISOcyr1 # CYRILLIC SMALL LETTER EM
+0x043D &ncy; ISOcyr1 # CYRILLIC SMALL LETTER EN
+0x043E &ocy; ISOcyr1 # CYRILLIC SMALL LETTER O
+0x043F &pcy; ISOcyr1 # CYRILLIC SMALL LETTER PE
+0x0440 &rcy; ISOcyr1 # CYRILLIC SMALL LETTER ER
+0x0441 &scy; ISOcyr1 # CYRILLIC SMALL LETTER ES
+0x0442 &tcy; ISOcyr1 # CYRILLIC SMALL LETTER TE
+0x0443 &ucy; ISOcyr1 # CYRILLIC SMALL LETTER U
+0x0444 &fcy; ISOcyr1 # CYRILLIC SMALL LETTER EF
+0x0445 &khcy; ISOcyr1 # CYRILLIC SMALL LETTER HA
+0x0446 &tscy; ISOcyr1 # CYRILLIC SMALL LETTER TSE
+0x0447 &chcy; ISOcyr1 # CYRILLIC SMALL LETTER CHE
+0x0448 &shcy; ISOcyr1 # CYRILLIC SMALL LETTER SHA
+0x0449 &shchcy; ISOcyr1 # CYRILLIC SMALL LETTER SHCHA
+0x044A &hardcy; ISOcyr1 # CYRILLIC SMALL LETTER HARD SIGN
+0x044B &ycy; ISOcyr1 # CYRILLIC SMALL LETTER YERU
+0x044C &softcy; ISOcyr1 # CYRILLIC SMALL LETTER SOFT SIGN
+0x044D &ecy; ISOcyr1 # CYRILLIC SMALL LETTER E
+0x044E &yucy; ISOcyr1 # CYRILLIC SMALL LETTER YU
+0x044F &yacy; ISOcyr1 # CYRILLIC SMALL LETTER YA
+0x0451 &iocy; ISOcyr1 # CYRILLIC SMALL LETTER IO
+0x0452 &djcy; ISOcyr2 # CYRILLIC SMALL LETTER DJE
+0x0453 &gjcy; ISOcyr2 # CYRILLIC SMALL LETTER GJE
+0x0454 &jukcy; ISOcyr2 # CYRILLIC SMALL LETTER UKRAINIAN IE
+0x0455 &dscy; ISOcyr2 # CYRILLIC SMALL LETTER DZE
+0x0456 &iukcy; ISOcyr2 # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0x0457 &yicy; ISOcyr2 # CYRILLIC SMALL LETTER YI
+0x0458 &jsercy; ISOcyr2 # CYRILLIC SMALL LETTER JE
+0x0459 &ljcy; ISOcyr2 # CYRILLIC SMALL LETTER LJE
+0x045A &njcy; ISOcyr2 # CYRILLIC SMALL LETTER NJE
+0x045B &tshcy; ISOcyr2 # CYRILLIC SMALL LETTER TSHE
+0x045C &kjcy; ISOcyr2 # CYRILLIC SMALL LETTER KJE
+0x045E &ubrcy; ISOcyr2 # CYRILLIC SMALL LETTER SHORT U
+0x045F &dzcy; ISOcyr2 # CYRILLIC SMALL LETTER DZHE
+0x2002 &ensp; ISOpub # EN SPACE
+0x2003 &emsp; ISOpub # EM SPACE
+0x2004 &emsp13; ISOpub # THREE-PER-EM SPACE
+0x2005 &emsp14; ISOpub # FOUR-PER-EM SPACE
+0x2007 &numsp; ISOpub # FIGURE SPACE
+0x2008 &puncsp; ISOpub # PUNCTUATION SPACE
+0x2009 &thinsp; ISOpub # THIN SPACE
+0x200A &hairsp; ISOpub # HAIR SPACE
+0x200C &zwnj; HTMLspecial # ZERO WIDTH NON-JOINER
+0x200D &zwj; HTMLspecial # ZERO WIDTH JOINER
+0x200E &lrm; HTMLspecial # LEFT-TO-RIGHT MARK
+0x200F &rlm; HTMLspecial # RIGHT-TO-LEFT MARK
+0x2010 &dash; ISOpub # HYPHEN
+0x2013 &ndash; ISOpub # EN DASH
+0x2014 &mdash; ISOpub # EM DASH
+0x2015 &horbar; ISOnum # HORIZONTAL BAR
+0x2016 &Verbar; ISOtech # DOUBLE VERTICAL LINE
+0x2018 &lsquo; ISOnum # LEFT SINGLE QUOTATION MARK
+0x2018 &rsquor; ISOpub # LEFT SINGLE QUOTATION MARK
+0x2019 &rsquo; ISOnum # RIGHT SINGLE QUOTATION MARK
+0x201A &lsquor; ISOpub # SINGLE LOW-9 QUOTATION MARK
+0x201A &sbquo; HTMLspecial # SINGLE LOW-9 QUOTATION MARK
+0x201C &ldquo; ISOnum # LEFT DOUBLE QUOTATION MARK
+0x201C &rdquor; ISOpub # LEFT DOUBLE QUOTATION MARK
+0x201D &rdquo; ISOnum # RIGHT DOUBLE QUOTATION MARK
+0x201E &bdquo; HTMLspecial # DOUBLE LOW-9 QUOTATION MARK
+0x201E &ldquor; ISOpub # DOUBLE LOW-9 QUOTATION MARK
+0x2020 &dagger; ISOpub # DAGGER
+0x2021 &Dagger; ISOpub # DOUBLE DAGGER
+0x2022 &bull; ISOpub # BULLET
+0x2025 &nldr; ISOpub # TWO DOT LEADER
+0x2026 &hellip; ISOpub # HORIZONTAL ELLIPSIS
+0x2026 &mldr; ISOpub # HORIZONTAL ELLIPSIS
+0x2030 &permil; ISOtech # PER MILLE SIGN
+0x2032 &prime; ISOtech # PRIME
+0x2032 &vprime; ISOamso # PRIME
+0x2033 &Prime; ISOtech # DOUBLE PRIME
+0x2034 &tprime; ISOtech # TRIPLE PRIME
+0x2035 &bprime; ISOamso # REVERSED PRIME
+0x2039 &lsaquo; HTMLspecial # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x203A &rsaquo; HTMLspecial # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x203E &oline; HTMLsymbol # OVERLINE
+0x2041 &caret; ISOpub # CARET INSERTION POINT
+0x2043 &hybull; ISOpub # HYPHEN BULLET
+0x2044 &frasl; HTMLsymbol # FRACTION SLASH
+0x20DB &tdot; ISOtech # COMBINING THREE DOTS ABOVE
+0x20DC &DotDot; ISOtech # COMBINING FOUR DOTS ABOVE
+0x2105 &incare; ISOpub # CARE OF
+0x210B &hamilt; ISOtech # SCRIPT CAPITAL H
+0x210F &planck; ISOamso # PLANCK CONSTANT OVER TWO PI
+0x2111 &image; ISOamso # BLACK-LETTER CAPITAL I
+0x2112 &lagran; ISOtech # SCRIPT CAPITAL L
+0x2113 &ell; ISOamso # SCRIPT SMALL L
+0x2116 &numero; ISOcyr1 # NUMERO SIGN
+0x2117 &copysr; ISOpub # SOUND RECORDING COPYRIGHT
+0x2118 &weierp; ISOamso # SCRIPT CAPITAL P
+0x211C &real; ISOamso # BLACK-LETTER CAPITAL R
+0x211E &rx; ISOpub # PRESCRIPTION TAKE
+0x2122 &trade; ISOnum # TRADE MARK SIGN
+0x2126 &ohm; ISOnum # OHM SIGN
+0x212B &angst; ISOtech # ANGSTROM SIGN
+0x212C &bernou; ISOtech # SCRIPT CAPITAL B
+0x2133 &phmmat; ISOtech # SCRIPT CAPITAL M
+0x2134 &order; ISOtech # SCRIPT SMALL O
+0x2135 &alefsym; HTMLsymbol # ALEF SYMBOL
+0x2135 &aleph; ISOtech # ALEF SYMBOL
+0x2136 &beth; ISOamso # BET SYMBOL
+0x2137 &gimel; ISOamso # GIMEL SYMBOL
+0x2138 &daleth; ISOamso # DALET SYMBOL
+0x2153 &frac13; ISOpub # VULGAR FRACTION ONE THIRD
+0x2154 &frac23; ISOpub # VULGAR FRACTION TWO THIRDS
+0x2155 &frac15; ISOpub # VULGAR FRACTION ONE FIFTH
+0x2156 &frac25; ISOpub # VULGAR FRACTION TWO FIFTHS
+0x2157 &frac35; ISOpub # VULGAR FRACTION THREE FIFTHS
+0x2158 &frac45; ISOpub # VULGAR FRACTION FOUR FIFTHS
+0x2159 &frac16; ISOpub # VULGAR FRACTION ONE SIXTH
+0x215A &frac56; ISOpub # VULGAR FRACTION FIVE SIXTHS
+0x215B &frac18; ISOnum # VULGAR FRACTION ONE EIGHTH
+0x215C &frac38; ISOnum # VULGAR FRACTION THREE EIGHTHS
+0x215D &frac58; ISOnum # VULGAR FRACTION FIVE EIGHTHS
+0x215E &frac78; ISOnum # VULGAR FRACTION SEVEN EIGHTHS
+0x2190 &larr; ISOnum # LEFTWARDS ARROW
+0x2191 &uarr; ISOnum # UPWARDS ARROW
+0x2192 &rarr; ISOnum # RIGHTWARDS ARROW
+0x2193 &darr; ISOnum # DOWNWARDS ARROW
+0x2194 &harr; ISOamsa # LEFT RIGHT ARROW
+0x2194 &xhArr; ISOamsa # LEFT RIGHT ARROW
+0x2194 &xharr; ISOamsa # LEFT RIGHT ARROW
+0x2195 &varr; ISOamsa # UP DOWN ARROW
+0x2196 &nwarr; ISOamsa # NORTH WEST ARROW
+0x2197 &nearr; ISOamsa # NORTH EAST ARROW
+0x2198 &drarr; ISOamsa # SOUTH EAST ARROW
+0x2199 &dlarr; ISOamsa # SOUTH WEST ARROW
+0x219A &nlarr; ISOamsa # LEFTWARDS ARROW WITH STROKE
+0x219B &nrarr; ISOamsa # RIGHTWARDS ARROW WITH STROKE
+0x219D &rarrw; ISOamsa # RIGHTWARDS WAVE ARROW
+0x219E &Larr; ISOamsa # LEFTWARDS TWO HEADED ARROW
+0x21A0 &Rarr; ISOamsa # RIGHTWARDS TWO HEADED ARROW
+0x21A2 &larrtl; ISOamsa # LEFTWARDS ARROW WITH TAIL
+0x21A3 &rarrtl; ISOamsa # RIGHTWARDS ARROW WITH TAIL
+0x21A6 &map; ISOamsa # RIGHTWARDS ARROW FROM BAR
+0x21A9 &larrhk; ISOamsa # LEFTWARDS ARROW WITH HOOK
+0x21AA &rarrhk; ISOamsa # RIGHTWARDS ARROW WITH HOOK
+0x21AB &larrlp; ISOamsa # LEFTWARDS ARROW WITH LOOP
+0x21AC &rarrlp; ISOamsa # RIGHTWARDS ARROW WITH LOOP
+0x21AD &harrw; ISOamsa # LEFT RIGHT WAVE ARROW
+0x21AE &nharr; ISOamsa # LEFT RIGHT ARROW WITH STROKE
+0x21B0 &lsh; ISOamsa # UPWARDS ARROW WITH TIP LEFTWARDS
+0x21B1 &rsh; ISOamsa # UPWARDS ARROW WITH TIP RIGHTWARDS
+0x21B5 &crarr; HTMLsymbol # DOWNWARDS ARROW WITH CORNER LEFTWARDS
+0x21B6 &cularr; ISOamsa # ANTICLOCKWISE TOP SEMICIRCLE ARROW
+0x21B7 &curarr; ISOamsa # CLOCKWISE TOP SEMICIRCLE ARROW
+0x21BA &olarr; ISOamsa # ANTICLOCKWISE OPEN CIRCLE ARROW
+0x21BB &orarr; ISOamsa # CLOCKWISE OPEN CIRCLE ARROW
+0x21BC &lharu; ISOamsa # LEFTWARDS HARPOON WITH BARB UPWARDS
+0x21BD &lhard; ISOamsa # LEFTWARDS HARPOON WITH BARB DOWNWARDS
+0x21BE &uharr; ISOamsa # UPWARDS HARPOON WITH BARB RIGHTWARDS
+0x21BF &uharl; ISOamsa # UPWARDS HARPOON WITH BARB LEFTWARDS
+0x21C0 &rharu; ISOamsa # RIGHTWARDS HARPOON WITH BARB UPWARDS
+0x21C1 &rhard; ISOamsa # RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+0x21C2 &dharr; ISOamsa # DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+0x21C3 &dharl; ISOamsa # DOWNWARDS HARPOON WITH BARB LEFTWARDS
+0x21C4 &rlarr2; ISOamsa # RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+0x21C6 &lrarr2; ISOamsa # LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+0x21C7 &larr2; ISOamsa # LEFTWARDS PAIRED ARROWS
+0x21C8 &uarr2; ISOamsa # UPWARDS PAIRED ARROWS
+0x21C9 &rarr2; ISOamsa # RIGHTWARDS PAIRED ARROWS
+0x21CA &darr2; ISOamsa # DOWNWARDS PAIRED ARROWS
+0x21CB &lrhar2; ISOamsa # LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+0x21CC &rlhar2; ISOamsa # RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+0x21CD &nlArr; ISOamsa # LEFTWARDS DOUBLE ARROW WITH STROKE
+0x21CE &nhArr; ISOamsa # LEFT RIGHT DOUBLE ARROW WITH STROKE
+0x21CF &nrArr; ISOamsa # RIGHTWARDS DOUBLE ARROW WITH STROKE
+0x21D0 &lArr; ISOtech # LEFTWARDS DOUBLE ARROW
+0x21D0 &xlArr; ISOamsa # LEFTWARDS DOUBLE ARROW
+0x21D1 &uArr; ISOamsa # UPWARDS DOUBLE ARROW
+0x21D2 &rArr; ISOtech # RIGHTWARDS DOUBLE ARROW
+0x21D2 &xrArr; ISOamsa # RIGHTWARDS DOUBLE ARROW
+0x21D3 &dArr; ISOamsa # DOWNWARDS DOUBLE ARROW
+0x21D4 &hArr; ISOamsa # LEFT RIGHT DOUBLE ARROW
+0x21D4 &iff; ISOtech # LEFT RIGHT DOUBLE ARROW
+0x21D5 &vArr; ISOamsa # UP DOWN DOUBLE ARROW
+0x21DA &lAarr; ISOamsa # LEFTWARDS TRIPLE ARROW
+0x21DB &rAarr; ISOamsa # RIGHTWARDS TRIPLE ARROW
+0x2200 &forall; ISOtech # FOR ALL
+0x2201 &comp; ISOamso # COMPLEMENT
+0x2202 &part; ISOtech # PARTIAL DIFFERENTIAL
+0x2203 &exist; ISOtech # THERE EXISTS
+0x2204 &nexist; ISOamso # THERE DOES NOT EXIST
+0x2205 &empty; ISOamso # EMPTY SET
+0x2207 &nabla; ISOtech # NABLA
+0x2208 &isin; ISOtech # ELEMENT OF
+0x2209 &notin; ISOtech # NOT AN ELEMENT OF
+0x220A &epsis; ISOgrk3 # SMALL ELEMENT OF
+0x220B &ni; ISOtech # CONTAINS AS MEMBER
+0x220D &bepsi; ISOamsr # SMALL CONTAINS AS MEMBER
+0x220F &prod; ISOamsb # N-ARY PRODUCT
+0x2210 &amalg; ISOamsb # N-ARY COPRODUCT
+0x2210 &coprod; ISOamsb # N-ARY COPRODUCT
+0x2210 &samalg; ISOamsr # N-ARY COPRODUCT
+0x2211 &sum; ISOamsb # N-ARY SUMMATION
+0x2212 &minus; ISOtech # MINUS SIGN
+0x2213 &mnplus; ISOtech # MINUS-OR-PLUS SIGN
+0x2214 &plusdo; ISOamsb # DOT PLUS
+0x2216 &setmn; ISOamsb # SET MINUS
+0x2216 &ssetmn; ISOamsb # SET MINUS
+0x2217 &lowast; ISOtech # ASTERISK OPERATOR
+0x2218 &compfn; ISOtech # RING OPERATOR
+0x221A &radic; ISOtech # SQUARE ROOT
+0x221D &prop; ISOtech # PROPORTIONAL TO
+0x221D &vprop; ISOamsr # PROPORTIONAL TO
+0x221E &infin; ISOtech # INFINITY
+0x221F &ang90; ISOtech # RIGHT ANGLE
+0x2220 &ang; ISOamso # ANGLE
+0x2221 &angmsd; ISOamso # MEASURED ANGLE
+0x2222 &angsph; ISOtech # SPHERICAL ANGLE
+0x2223 &mid; ISOamsr # DIVIDES
+0x2224 &nmid; ISOamsn # DOES NOT DIVIDE
+0x2225 &par; ISOtech # PARALLEL TO
+0x2225 &spar; ISOamsr # PARALLEL TO
+0x2226 &npar; ISOamsn # NOT PARALLEL TO
+0x2226 &nspar; ISOamsn # NOT PARALLEL TO
+0x2227 &and; ISOtech # LOGICAL AND
+0x2228 &or; ISOtech # LOGICAL OR
+0x2229 &cap; ISOtech # INTERSECTION
+0x222A &cup; ISOtech # UNION
+0x222B &int; ISOtech # INTEGRAL
+0x222E &conint; ISOtech # CONTOUR INTEGRAL
+0x2234 &there4; ISOtech # THEREFORE
+0x2235 &becaus; ISOtech # BECAUSE
+0x223C &sim; ISOtech # TILDE OPERATOR
+0x223C &thksim; ISOamsr # TILDE OPERATOR
+0x223D &bsim; ISOamsr # REVERSED TILDE
+0x2240 &wreath; ISOamsb # WREATH PRODUCT
+0x2241 &nsim; ISOamsn # NOT TILDE
+0x2243 &sime; ISOtech # ASYMPTOTICALLY EQUAL TO
+0x2244 &nsime; ISOamsn # NOT ASYMPTOTICALLY EQUAL TO
+0x2245 &cong; ISOtech # APPROXIMATELY EQUAL TO
+0x2247 &ncong; ISOamsn # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+0x2248 &ap; ISOtech # ALMOST EQUAL TO
+0x2248 &asymp; ISOamsr # ALMOST EQUAL TO
+0x2248 &thkap; ISOamsr # ALMOST EQUAL TO
+0x2249 &nap; ISOamsn # NOT ALMOST EQUAL TO
+0x224A &ape; ISOamsr # ALMOST EQUAL OR EQUAL TO
+0x224C &bcong; ISOamsr # ALL EQUAL TO
+0x224E &bump; ISOamsr # GEOMETRICALLY EQUIVALENT TO
+0x224F &bumpe; ISOamsr # DIFFERENCE BETWEEN
+0x2250 &esdot; ISOamsr # APPROACHES THE LIMIT
+0x2251 &eDot; ISOamsr # GEOMETRICALLY EQUAL TO
+0x2252 &efDot; ISOamsr # APPROXIMATELY EQUAL TO OR THE IMAGE OF
+0x2253 &erDot; ISOamsr # IMAGE OF OR APPROXIMATELY EQUAL TO
+0x2254 &colone; ISOamsr # COLON EQUALS
+0x2255 &ecolon; ISOamsr # EQUALS COLON
+0x2256 &ecir; ISOamsr # RING IN EQUAL TO
+0x2257 &cire; ISOamsr # RING EQUAL TO
+0x2259 &wedgeq; ISOtech # ESTIMATES
+0x225C &trie; ISOamsr # DELTA EQUAL TO
+0x2260 &ne; ISOtech # NOT EQUAL TO
+0x2261 &equiv; ISOtech # IDENTICAL TO
+0x2262 &nequiv; ISOamsn # NOT IDENTICAL TO
+0x2264 &le; ISOtech # LESS-THAN OR EQUAL TO
+0x2264 &les; ISOamsr # LESS-THAN OR EQUAL TO
+0x2265 &ge; ISOtech # GREATER-THAN OR EQUAL TO
+0x2265 &ges; ISOamsr # GREATER-THAN OR EQUAL TO
+0x2266 &lE; ISOamsr # LESS-THAN OVER EQUAL TO
+0x2267 &gE; ISOamsr # GREATER-THAN OVER EQUAL TO
+0x2268 &lnE; ISOamsn # LESS-THAN BUT NOT EQUAL TO
+0x2268 &lne; ISOamsn # LESS-THAN BUT NOT EQUAL TO
+0x2268 &lvnE; ISOamsn # LESS-THAN BUT NOT EQUAL TO
+0x2269 &gnE; ISOamsn # GREATER-THAN BUT NOT EQUAL TO
+0x2269 &gne; ISOamsn # GREATER-THAN BUT NOT EQUAL TO
+0x2269 &gvnE; ISOamsn # GREATER-THAN BUT NOT EQUAL TO
+0x226A &Lt; ISOamsr # MUCH LESS-THAN
+0x226B &Gt; ISOamsr # MUCH GREATER-THAN
+0x226C &twixt; ISOamsr # BETWEEN
+0x226E &nlt; ISOamsn # NOT LESS-THAN
+0x226F &ngt; ISOamsn # NOT GREATER-THAN
+0x2270 &nle; ISOamsn # NEITHER LESS-THAN NOR EQUAL TO
+0x2270 &nles; ISOamsn # NEITHER LESS-THAN NOR EQUAL TO
+0x2271 &nge; ISOamsn # NEITHER GREATER-THAN NOR EQUAL TO
+0x2271 &nges; ISOamsn # NEITHER GREATER-THAN NOR EQUAL TO
+0x2272 &lsim; ISOamsr # LESS-THAN OR EQUIVALENT TO
+0x2273 &gsim; ISOamsr # GREATER-THAN OR EQUIVALENT TO
+0x2276 &lg; ISOamsr # LESS-THAN OR GREATER-THAN
+0x2277 &gl; ISOamsr # GREATER-THAN OR LESS-THAN
+0x227A &pr; ISOamsr # PRECEDES
+0x227B &sc; ISOamsr # SUCCEEDS
+0x227C &cupre; ISOamsr # PRECEDES OR EQUAL TO
+0x227C &pre; ISOamsr # PRECEDES OR EQUAL TO
+0x227D &sccue; ISOamsr # SUCCEEDS OR EQUAL TO
+0x227D &sce; ISOamsr # SUCCEEDS OR EQUAL TO
+0x227E &prsim; ISOamsr # PRECEDES OR EQUIVALENT TO
+0x227F &scsim; ISOamsr # SUCCEEDS OR EQUIVALENT TO
+0x2280 &npr; ISOamsn # DOES NOT PRECEDE
+0x2281 &nsc; ISOamsn # DOES NOT SUCCEED
+0x2282 &sub; ISOtech # SUBSET OF
+0x2283 &sup; ISOtech # SUPERSET OF
+0x2284 &nsub; ISOamsn # NOT A SUBSET OF
+0x2285 &nsup; ISOamsn # NOT A SUPERSET OF
+0x2286 &subE; ISOamsr # SUBSET OF OR EQUAL TO
+0x2286 &sube; ISOtech # SUBSET OF OR EQUAL TO
+0x2287 &supE; ISOamsr # SUPERSET OF OR EQUAL TO
+0x2287 &supe; ISOtech # SUPERSET OF OR EQUAL TO
+0x2288 &nsubE; ISOamsn # NEITHER A SUBSET OF NOR EQUAL TO
+0x2288 &nsube; ISOamsn # NEITHER A SUBSET OF NOR EQUAL TO
+0x2289 &nsupE; ISOamsn # NEITHER A SUPERSET OF NOR EQUAL TO
+0x2289 &nsupe; ISOamsn # NEITHER A SUPERSET OF NOR EQUAL TO
+0x228A &subnE; ISOamsn # SUBSET OF WITH NOT EQUAL TO
+0x228A &subne; ISOamsn # SUBSET OF WITH NOT EQUAL TO
+0x228A &vsubnE; ISOamsn # SUBSET OF WITH NOT EQUAL TO
+0x228A &vsubne; ISOamsn # SUBSET OF WITH NOT EQUAL TO
+0x228B &supnE; ISOamsn # SUPERSET OF WITH NOT EQUAL TO
+0x228B &supne; ISOamsn # SUPERSET OF WITH NOT EQUAL TO
+0x228B &vsupnE; ISOamsn # SUPERSET OF WITH NOT EQUAL TO
+0x228B &vsupne; ISOamsn # SUPERSET OF WITH NOT EQUAL TO
+0x228E &uplus; ISOamsb # MULTISET UNION
+0x228F &sqsub; ISOamsr # SQUARE IMAGE OF
+0x2290 &sqsup; ISOamsr # SQUARE ORIGINAL OF
+0x2291 &sqsube; ISOamsr # SQUARE IMAGE OF OR EQUAL TO
+0x2292 &sqsupe; ISOamsr # SQUARE ORIGINAL OF OR EQUAL TO
+0x2293 &sqcap; ISOamsb # SQUARE CAP
+0x2294 &sqcup; ISOamsb # SQUARE CUP
+0x2295 &oplus; ISOamsb # CIRCLED PLUS
+0x2296 &ominus; ISOamsb # CIRCLED MINUS
+0x2297 &otimes; ISOamsb # CIRCLED TIMES
+0x2298 &osol; ISOamsb # CIRCLED DIVISION SLASH
+0x2299 &odot; ISOamsb # CIRCLED DOT OPERATOR
+0x229A &ocir; ISOamsb # CIRCLED RING OPERATOR
+0x229B &oast; ISOamsb # CIRCLED ASTERISK OPERATOR
+0x229D &odash; ISOamsb # CIRCLED DASH
+0x229E &plusb; ISOamsb # SQUARED PLUS
+0x229F &minusb; ISOamsb # SQUARED MINUS
+0x22A0 &timesb; ISOamsb # SQUARED TIMES
+0x22A1 &sdotb; ISOamsb # SQUARED DOT OPERATOR
+0x22A2 &vdash; ISOamsr # RIGHT TACK
+0x22A3 &dashv; ISOamsr # LEFT TACK
+0x22A4 &top; ISOamsb # DOWN TACK
+0x22A5 &bottom; ISOtech # UP TACK
+0x22A5 &perp; ISOtech # UP TACK
+0x22A7 &models; ISOamsr # MODELS
+0x22A8 &vDash; ISOamsr # TRUE
+0x22A9 &Vdash; ISOamsr # FORCES
+0x22AA &Vvdash; ISOamsr # TRIPLE VERTICAL BAR RIGHT TURNSTILE
+0x22AC &nvdash; ISOamsn # DOES NOT PROVE
+0x22AD &nvDash; ISOamsn # NOT TRUE
+0x22AE &nVdash; ISOamsn # DOES NOT FORCE
+0x22AF &nVDash; ISOamsn # NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT
+0x22B2 &vltri; ISOamsr # NORMAL SUBGROUP OF
+0x22B3 &vrtri; ISOamsr # CONTAINS AS NORMAL SUBGROUP
+0x22B4 &ltrie; ISOamsr # NORMAL SUBGROUP OF OR EQUAL TO
+0x22B5 &rtrie; ISOamsr # CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+0x22B8 &mumap; ISOamsa # MULTIMAP
+0x22BA &intcal; ISOamsb # INTERCALATE
+0x22BB &veebar; ISOamsr # XOR
+0x22BC &barwed; ISOamsb # NAND
+0x22C4 &diam; ISOamsb # DIAMOND OPERATOR
+0x22C5 &sdot; ISOamsb # DOT OPERATOR
+0x22C6 &sstarf; ISOamsb # STAR OPERATOR
+0x22C7 &divonx; ISOamsb # DIVISION TIMES
+0x22C8 &bowtie; ISOamsr # BOWTIE
+0x22C9 &ltimes; ISOamsb # LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+0x22CA &rtimes; ISOamsb # RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+0x22CB &lthree; ISOamsb # LEFT SEMIDIRECT PRODUCT
+0x22CC &rthree; ISOamsb # RIGHT SEMIDIRECT PRODUCT
+0x22CD &bsime; ISOamsr # REVERSED TILDE EQUALS
+0x22CE &cuvee; ISOamsb # CURLY LOGICAL OR
+0x22CF &cuwed; ISOamsb # CURLY LOGICAL AND
+0x22D0 &Sub; ISOamsr # DOUBLE SUBSET
+0x22D1 &Sup; ISOamsr # DOUBLE SUPERSET
+0x22D2 &Cap; ISOamsb # DOUBLE INTERSECTION
+0x22D3 &Cup; ISOamsb # DOUBLE UNION
+0x22D4 &fork; ISOamsr # PITCHFORK
+0x22D6 &ldot; ISOamsr # LESS-THAN WITH DOT
+0x22D7 &gsdot; ISOamsr # GREATER-THAN WITH DOT
+0x22D8 &Ll; ISOamsr # VERY MUCH LESS-THAN
+0x22D9 &Gg; ISOamsr # VERY MUCH GREATER-THAN
+0x22DA &leg; ISOamsr # LESS-THAN EQUAL TO OR GREATER-THAN
+0x22DB &gel; ISOamsr # GREATER-THAN EQUAL TO OR LESS-THAN
+0x22DC &els; ISOamsr # EQUAL TO OR LESS-THAN
+0x22DD &egs; ISOamsr # EQUAL TO OR GREATER-THAN
+0x22DE &cuepr; ISOamsr # EQUAL TO OR PRECEDES
+0x22DF &cuesc; ISOamsr # EQUAL TO OR SUCCEEDS
+0x22E0 &npre; ISOamsn # DOES NOT PRECEDE OR EQUAL
+0x22E1 &nsce; ISOamsn # DOES NOT SUCCEED OR EQUAL
+0x22E6 &lnsim; ISOamsn # LESS-THAN BUT NOT EQUIVALENT TO
+0x22E7 &gnsim; ISOamsn # GREATER-THAN BUT NOT EQUIVALENT TO
+0x22E8 &prnsim; ISOamsn # PRECEDES BUT NOT EQUIVALENT TO
+0x22E9 &scnsim; ISOamsn # SUCCEEDS BUT NOT EQUIVALENT TO
+0x22EA &nltri; ISOamsn # NOT NORMAL SUBGROUP OF
+0x22EB &nrtri; ISOamsn # DOES NOT CONTAIN AS NORMAL SUBGROUP
+0x22EC &nltrie; ISOamsn # NOT NORMAL SUBGROUP OF OR EQUAL TO
+0x22ED &nrtrie; ISOamsn # DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+0x22EE &vellip; ISOpub # VERTICAL ELLIPSIS
+0x2306 &Barwed; ISOamsb # PERSPECTIVE
+0x2308 &lceil; ISOamsc # LEFT CEILING
+0x2309 &rceil; ISOamsc # RIGHT CEILING
+0x230A &lfloor; ISOamsc # LEFT FLOOR
+0x230B &rfloor; ISOamsc # RIGHT FLOOR
+0x230C &drcrop; ISOpub # BOTTOM RIGHT CROP
+0x230D &dlcrop; ISOpub # BOTTOM LEFT CROP
+0x230E &urcrop; ISOpub # TOP RIGHT CROP
+0x230F &ulcrop; ISOpub # TOP LEFT CROP
+0x2315 &telrec; ISOpub # TELEPHONE RECORDER
+0x2316 &target; ISOpub # POSITION INDICATOR
+0x231C &ulcorn; ISOamsc # TOP LEFT CORNER
+0x231D &urcorn; ISOamsc # TOP RIGHT CORNER
+0x231E &dlcorn; ISOamsc # BOTTOM LEFT CORNER
+0x231F &drcorn; ISOamsc # BOTTOM RIGHT CORNER
+0x2322 &frown; ISOamsr # FROWN
+0x2322 &sfrown; ISOamsr # FROWN
+0x2323 &smile; ISOamsr # SMILE
+0x2323 &ssmile; ISOamsr # SMILE
+0x2329 &lang; ISOtech # LEFT-POINTING ANGLE BRACKET
+0x232A &rang; ISOtech # RIGHT-POINTING ANGLE BRACKET
+0x2423 &blank; ISOpub # OPEN BOX
+0x24C8 &oS; ISOamso # CIRCLED LATIN CAPITAL LETTER S
+0x2500 &boxh; ISObox # BOX DRAWINGS LIGHT HORIZONTAL
+0x2502 &boxv; ISObox # BOX DRAWINGS LIGHT VERTICAL
+0x250C &boxdr; ISObox # BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x2510 &boxdl; ISObox # BOX DRAWINGS LIGHT DOWN AND LEFT
+0x2514 &boxur; ISObox # BOX DRAWINGS LIGHT UP AND RIGHT
+0x2518 &boxul; ISObox # BOX DRAWINGS LIGHT UP AND LEFT
+0x251C &boxvr; ISObox # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x2524 &boxvl; ISObox # BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x252C &boxhd; ISObox # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x2534 &boxhu; ISObox # BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x253C &boxvh; ISObox # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x2550 &boxH; ISObox # BOX DRAWINGS DOUBLE HORIZONTAL
+0x2551 &boxV; ISObox # BOX DRAWINGS DOUBLE VERTICAL
+0x2552 &boxdR; ISObox # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0x2553 &boxDr; ISObox # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0x2554 &boxDR; ISObox # BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0x2555 &boxdL; ISObox # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0x2556 &boxDl; ISObox # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0x2557 &boxDL; ISObox # BOX DRAWINGS DOUBLE DOWN AND LEFT
+0x2558 &boxuR; ISObox # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0x2559 &boxUr; ISObox # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0x255A &boxUR; ISObox # BOX DRAWINGS DOUBLE UP AND RIGHT
+0x255B &boxuL; ISObox # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0x255C &boxUl; ISObox # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0x255D &boxUL; ISObox # BOX DRAWINGS DOUBLE UP AND LEFT
+0x255E &boxvR; ISObox # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0x255F &boxVr; ISObox # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0x2560 &boxVR; ISObox # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0x2561 &boxvL; ISObox # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0x2562 &boxVl; ISObox # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0x2563 &boxVL; ISObox # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0x2564 &boxHd; ISObox # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0x2565 &boxhD; ISObox # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0x2566 &boxHD; ISObox # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0x2567 &boxHu; ISObox # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0x2568 &boxhU; ISObox # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0x2569 &boxHU; ISObox # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0x256A &boxvH; ISObox # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0x256B &boxVh; ISObox # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0x256C &boxVH; ISObox # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0x2580 &uhblk; ISOpub # UPPER HALF BLOCK
+0x2584 &lhblk; ISOpub # LOWER HALF BLOCK
+0x2588 &block; ISOpub # FULL BLOCK
+0x2591 &blk14; ISOpub # LIGHT SHADE
+0x2592 &blk12; ISOpub # MEDIUM SHADE
+0x2593 &blk34; ISOpub # DARK SHADE
+0x25A1 &squ; ISOpub # WHITE SQUARE
+0x25A1 &square; ISOtech # WHITE SQUARE
+0x25AA &squf; ISOpub # BLACK SMALL SQUARE
+0x25AD &rect; ISOpub # WHITE RECTANGLE
+0x25AE &marker; ISOpub # BLACK VERTICAL RECTANGLE
+0x25B3 &xutri; ISOamsb # WHITE UP-POINTING TRIANGLE
+0x25B4 &utrif; ISOpub # BLACK UP-POINTING SMALL TRIANGLE
+0x25B5 &utri; ISOpub # WHITE UP-POINTING SMALL TRIANGLE
+0x25B8 &rtrif; ISOpub # BLACK RIGHT-POINTING SMALL TRIANGLE
+0x25B9 &rtri; ISOpub # WHITE RIGHT-POINTING SMALL TRIANGLE
+0x25BD &xdtri; ISOamsb # WHITE DOWN-POINTING TRIANGLE
+0x25BE &dtrif; ISOpub # BLACK DOWN-POINTING SMALL TRIANGLE
+0x25BF &dtri; ISOpub # WHITE DOWN-POINTING SMALL TRIANGLE
+0x25C2 &ltrif; ISOpub # BLACK LEFT-POINTING SMALL TRIANGLE
+0x25C3 &ltri; ISOpub # WHITE LEFT-POINTING SMALL TRIANGLE
+0x25CA &loz; ISOpub # LOZENGE
+0x25CB &cir; ISOpub # WHITE CIRCLE
+0x25CB &xcirc; ISOamsb # WHITE CIRCLE
+0x2605 &starf; ISOpub # BLACK STAR
+0x2606 &star; ISOpub # WHITE STAR
+0x260E &phone; ISOpub # BLACK TELEPHONE
+0x2640 &female; ISOpub # FEMALE SIGN
+0x2642 &male; ISOpub # MALE SIGN
+0x2660 &spades; ISOpub # BLACK SPADE SUIT
+0x2663 &clubs; ISOpub # BLACK CLUB SUIT
+0x2665 &hearts; ISOpub # BLACK HEART SUIT
+0x2666 &diams; ISOpub # BLACK DIAMOND SUIT
+0x266A &sung; ISOnum # EIGHTH NOTE
+0x266D &flat; ISOpub # MUSIC FLAT SIGN
+0x266E &natur; ISOpub # MUSIC NATURAL SIGN
+0x266F &sharp; ISOpub # MUSIC SHARP SIGN
+0x2713 &check; ISOpub # CHECK MARK
+0x2717 &cross; ISOpub # BALLOT X
+0x2720 &malt; ISOpub # MALTESE CROSS
+0x2726 &lozf; ISOpub # BLACK FOUR POINTED STAR
+0x2727 &loz; ISOpub # WHITE FOUR POINTED STAR
+0x2736 &sext; ISOpub # SIX POINTED BLACK STAR
+0x???? &epsiv; ISOgrk3 # variant epsilon
+0x???? &fjlig; ISOpub # fj ligature
+0x???? &gEl; ISOamsr # greater-than, double equals, less-than
+0x???? &gap; ISOamsr # greater-than, approximately equal to
+0x???? &gnap; ISOamsn # greater-than, not approximately equal to
+0x???? &jnodot; ISOamso # latin small letter dotless j
+0x???? &lEg; ISOamsr # less-than, double equals, greater-than
+0x???? &lap; ISOamsr # less-than, approximately equal to
+0x???? &lnap; ISOamsn # less-than, not approximately equal to
+0x???? &lpargt; ISOamsc # left parenthesis, greater-than
+0x???? &ngE; ISOamsn # not greater-than, double equals
+0x???? &nlE; ISOamsn # not less-than, double equals
+0x???? &nsmid; ISOamsn # nshortmid
+0x???? &prap; ISOamsr # precedes, approximately equal to
+0x???? &prnE; ISOamsn # precedes, not double equal
+0x???? &prnap; ISOamsn # precedes, not approximately equal to
+0x???? &rpargt; ISOamsc # right parenthesis, greater-than
+0x???? &scap; ISOamsr # succeeds, approximately equal to
+0x???? &scnE; ISOamsn # succeeds, not double equals
+0x???? &scnap; ISOamsn # succeeds, not approximately equal to
+0x???? &smid; ISOamsr # shortmid
+0xFB00 &fflig; ISOpub # LATIN SMALL LIGATURE FF
+0xFB01 &filig; ISOpub # LATIN SMALL LIGATURE FI
+0xFB02 &fllig; ISOpub # LATIN SMALL LIGATURE FL
+0xFB03 &ffilig; ISOpub # LATIN SMALL LIGATURE FFI
+0xFB04 &ffllig; ISOpub # LATIN SMALL LIGATURE FFL
+
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/test/tabtest.html b/gnu/usr.bin/lynx/test/tabtest.html
new file mode 100644
index 00000000000..b253bae77b5
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/tabtest.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 3.0//EN">
+<html>
+<head>
+<title>Tests of TAB element.</title>
+<link rev="made" href="mailto:lynx-dev@sig.net">
+</head>
+
+<body>
+<h1>Tests of TAB element.</h1>
+
+<TAB INDENT="16" ID="t0"><em>Normal Style:</em><br>
+One<TAB INDENT="26" ID="t1">Two<TAB INDENT="44" ID="t2">Three
+<TAB INDENT="62" ID="t3">Four<TAB INDENT="80" ID="t4">Five
+<TAB INDENT="98" ID="t5">Six<TAB INDENT="116" ID="t6">Seven
+<TAB INDENT="132" ID="t7">Eight<br>
+1.<TAB TO="t1">2.<TAB TO="t2">3.<TAB TO="t3">4.<TAB TO="t4">5.
+<TAB TO="t5">6.<TAB TO="t6">7.<TAB TO="t7">8.<br>
+i.<TAB TO="t1">ii.<TAB TO="t2">iii.<TAB TO="t3">iv.<TAB TO="t4">v.
+<TAB TO="t5">vi.<TAB TO="t6">vii.<TAB TO="t7">viii.
+
+<p><pre><TAB TO="t0"><em>In PRE block:</em>
+One<TAB TO="t1">Two<TAB TO="t3">Three<TAB TO="t5">Four<TAB TO="t7">Five
+1.<TAB TO="t1">2.<TAB TO="t3">3.<TAB TO="t5">4.<TAB TO="t7">5.
+i.<TAB TO="t1">ii.<TAB TO="t3">iii.<TAB TO="t5">iv.<TAB TO="t7">v.
+</pre>
+
+<bq>
+<TAB TO="t0"><em>In BQ block:</em><br>
+One<TAB TO="t2">Two<TAB TO="t4">Three<TAB TO="t6">Four<br>
+1.<TAB TO="t2">2.<TAB TO="t4">3.<TAB TO="t6">4.<br>
+i.<TAB TO="t2">ii.<TAB TO="t4">iii.<TAB TO="t6">iv.
+</bq>
+
+<p><b>noct<TAB ID="tn">ambulant</b> - walking at night<br>
+<TAB TO="tn">(from Latin: <i>nox noctis</i> night + <i>ambulare</i> walk)
+<pre>|<TAB INDENT="78">|<TAB INDENT="156">|
+0<TAB INDENT="76">80<TAB INDENT="152">158</pre>
+</body>
+</html>
diff --git a/gnu/usr.bin/lynx/test/unicode.html b/gnu/usr.bin/lynx/test/unicode.html
new file mode 100644
index 00000000000..f5c2f495d3d
--- /dev/null
+++ b/gnu/usr.bin/lynx/test/unicode.html
@@ -0,0 +1,1053 @@
+<HTML>
+<HEAD>
+<TITLE> Test of some Unicode symbols in numeric character reference form </TITLE>
+</HEAD>
+<BODY>
+<PRE>
+
+ This table prepared from SGML.TXT available at ftp.unicode.org
+
+ ftp://ftp.unicode.org/MAPPINGS/VENDORS/MISC/SGML.TXT
+ (if doing ftp, try cd Public/MAPPINGS/VENDORS/MISC)
+
+
+original comment:
+
+# Author: John Cowan <cowan@ccil.org>
+# Date: 25 July 1997
+#
+# The following table maps SGML character entities from various
+# public sets (namely, ISOamsa, ISOamsb, ISOamsc, ISOamsn, ISOamso,
+# ISOamsr, ISObox, ISOcyr1, ISOcyr2, ISOdia, ISOgrk1, ISOgrk2,
+# ISOgrk3, ISOgrk4, ISOlat1, ISOlat2, ISOnum, ISOpub, ISOtech,
+# HTMLspecial, HTMLsymbol) to corresponding Unicode characters.
+#
+# The table has four tab-separated columns:
+# Column 1: SGML character entity name
+# Column 2: SGML public entity set
+# Column 3: Unicode 2.0 character code
+# Column 4: Unicode 2.0 character name (UPPER CASE)
+# Entries which don't have Unicode equivalents have "0x????"
+# in Column 3 and a lower case description (from the public entity
+# set DTD) in Column 4. The mapping is not reversible, because many
+# distinctions are unified away in Unicode, particularly between
+# mathematical symbols.
+#
+# The table is sorted case-blind by SGML character entity name.
+#
+# The contents of this table are drawn from various sources, and
+# are in the public domain.
+#
+
+
+This test is illuminated Unicode numeric entities like &amp;#x22AB;
+We sort the entities according to unicode numbers.
+(Sorry, many lines duplicated).
+You should see visible characters if your display character set support them
+or some substitution string picked up from src/chrtrans/def7_uni.tbl
+
+If you see something like &amp;#x34D2; - this number unknown to def7_uni.tbl
+or the internal browser's implementation is broken.
+ Leonid Pauzner.
+
+
+
+
+0x0021 &#x0021; # EXCLAMATION MARK
+0x0022 &#x0022; # QUOTATION MARK
+0x0023 &#x0023; # NUMBER SIGN
+0x0024 &#x0024; # DOLLAR SIGN
+0x0025 &#x0025; # PERCENT SIGN
+0x0026 &#x0026; # AMPERSAND
+0x0028 &#x0028; # LEFT PARENTHESIS
+0x0029 &#x0029; # RIGHT PARENTHESIS
+0x002A &#x002A; # ASTERISK
+0x002B &#x002B; # PLUS SIGN
+0x002C &#x002C; # COMMA
+0x002D &#x002D; # HYPHEN-MINUS
+0x002E &#x002E; # FULL STOP
+0x002F &#x002F; # SOLIDUS
+0x003A &#x003A; # COLON
+0x003B &#x003B; # SEMICOLON
+0x003C &#x003C; # LESS-THAN SIGN
+0x003D &#x003D; # EQUALS SIGN
+0x003E &#x003E; # GREATER-THAN SIGN
+0x003F &#x003F; # QUESTION MARK
+0x0040 &#x0040; # COMMERCIAL AT
+0x005B &#x005B; # LEFT SQUARE BRACKET
+0x005C &#x005C; # REVERSE SOLIDUS
+0x005C &#x005C; # REVERSE SOLIDUS
+0x005D &#x005D; # RIGHT SQUARE BRACKET
+0x005F &#x005F; # LOW LINE
+0x0060 &#x0060; # GRAVE ACCENT
+0x007B &#x007B; # LEFT CURLY BRACKET
+0x007C &#x007C; # VERTICAL LINE
+0x007D &#x007D; # RIGHT CURLY BRACKET
+0x00A0 &#x00A0; # NO-BREAK SPACE
+0x00A1 &#x00A1; # INVERTED EXCLAMATION MARK
+0x00A2 &#x00A2; # CENT SIGN
+0x00A3 &#x00A3; # POUND SIGN
+0x00A4 &#x00A4; # CURRENCY SIGN
+0x00A5 &#x00A5; # YEN SIGN
+0x00A6 &#x00A6; # BROKEN BAR
+0x00A7 &#x00A7; # SECTION SIGN
+0x00A8 &#x00A8; # DIAERESIS
+0x00A8 &#x00A8; # DIAERESIS
+0x00A8 &#x00A8; # DIAERESIS
+0x00A9 &#x00A9; # COPYRIGHT SIGN
+0x00AA &#x00AA; # FEMININE ORDINAL INDICATOR
+0x00AB &#x00AB; # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+0x00AC &#x00AC; # NOT SIGN
+0x00AD &#x00AD; # SOFT HYPHEN
+0x00AE &#x00AE; # REGISTERED SIGN
+0x00AF &#x00AF; # MACRON
+0x00B0 &#x00B0; # DEGREE SIGN
+0x00B1 &#x00B1; # PLUS-MINUS SIGN
+0x00B2 &#x00B2; # SUPERSCRIPT TWO
+0x00B3 &#x00B3; # SUPERSCRIPT THREE
+0x00B4 &#x00B4; # ACUTE ACCENT
+0x00B5 &#x00B5; # MICRO SIGN
+0x00B6 &#x00B6; # PILCROW SIGN
+0x00B7 &#x00B7; # MIDDLE DOT
+0x00B8 &#x00B8; # CEDILLA
+0x00B9 &#x00B9; # SUPERSCRIPT ONE
+0x00BA &#x00BA; # MASCULINE ORDINAL INDICATOR
+0x00BB &#x00BB; # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+0x00BC &#x00BC; # VULGAR FRACTION ONE QUARTER
+0x00BD &#x00BD; # VULGAR FRACTION ONE HALF
+0x00BD &#x00BD; # VULGAR FRACTION ONE HALF
+0x00BE &#x00BE; # VULGAR FRACTION THREE QUARTERS
+0x00BF &#x00BF; # INVERTED QUESTION MARK
+0x00C0 &#x00C0; # LATIN CAPITAL LETTER A WITH GRAVE
+0x00C1 &#x00C1; # LATIN CAPITAL LETTER A WITH ACUTE
+0x00C2 &#x00C2; # LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+0x00C3 &#x00C3; # LATIN CAPITAL LETTER A WITH TILDE
+0x00C4 &#x00C4; # LATIN CAPITAL LETTER A WITH DIAERESIS
+0x00C5 &#x00C5; # LATIN CAPITAL LETTER A WITH RING ABOVE
+0x00C6 &#x00C6; # LATIN CAPITAL LETTER AE
+0x00C7 &#x00C7; # LATIN CAPITAL LETTER C WITH CEDILLA
+0x00C8 &#x00C8; # LATIN CAPITAL LETTER E WITH GRAVE
+0x00C9 &#x00C9; # LATIN CAPITAL LETTER E WITH ACUTE
+0x00CA &#x00CA; # LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+0x00CB &#x00CB; # LATIN CAPITAL LETTER E WITH DIAERESIS
+0x00CC &#x00CC; # LATIN CAPITAL LETTER I WITH GRAVE
+0x00CD &#x00CD; # LATIN CAPITAL LETTER I WITH ACUTE
+0x00CE &#x00CE; # LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+0x00CF &#x00CF; # LATIN CAPITAL LETTER I WITH DIAERESIS
+0x00D0 &#x00D0; # LATIN CAPITAL LETTER ETH
+0x00D1 &#x00D1; # LATIN CAPITAL LETTER N WITH TILDE
+0x00D2 &#x00D2; # LATIN CAPITAL LETTER O WITH GRAVE
+0x00D3 &#x00D3; # LATIN CAPITAL LETTER O WITH ACUTE
+0x00D4 &#x00D4; # LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+0x00D5 &#x00D5; # LATIN CAPITAL LETTER O WITH TILDE
+0x00D6 &#x00D6; # LATIN CAPITAL LETTER O WITH DIAERESIS
+0x00D7 &#x00D7; # MULTIPLICATION SIGN
+0x00D8 &#x00D8; # LATIN CAPITAL LETTER O WITH STROKE
+0x00D9 &#x00D9; # LATIN CAPITAL LETTER U WITH GRAVE
+0x00DA &#x00DA; # LATIN CAPITAL LETTER U WITH ACUTE
+0x00DB &#x00DB; # LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+0x00DC &#x00DC; # LATIN CAPITAL LETTER U WITH DIAERESIS
+0x00DD &#x00DD; # LATIN CAPITAL LETTER Y WITH ACUTE
+0x00DE &#x00DE; # LATIN CAPITAL LETTER THORN
+0x00DF &#x00DF; # LATIN SMALL LETTER SHARP S
+0x00E0 &#x00E0; # LATIN SMALL LETTER A WITH GRAVE
+0x00E1 &#x00E1; # LATIN SMALL LETTER A WITH ACUTE
+0x00E2 &#x00E2; # LATIN SMALL LETTER A WITH CIRCUMFLEX
+0x00E3 &#x00E3; # LATIN SMALL LETTER A WITH TILDE
+0x00E4 &#x00E4; # LATIN SMALL LETTER A WITH DIAERESIS
+0x00E5 &#x00E5; # LATIN SMALL LETTER A WITH RING ABOVE
+0x00E6 &#x00E6; # LATIN SMALL LETTER AE
+0x00E7 &#x00E7; # LATIN SMALL LETTER C WITH CEDILLA
+0x00E8 &#x00E8; # LATIN SMALL LETTER E WITH GRAVE
+0x00E9 &#x00E9; # LATIN SMALL LETTER E WITH ACUTE
+0x00EA &#x00EA; # LATIN SMALL LETTER E WITH CIRCUMFLEX
+0x00EB &#x00EB; # LATIN SMALL LETTER E WITH DIAERESIS
+0x00EC &#x00EC; # LATIN SMALL LETTER I WITH GRAVE
+0x00ED &#x00ED; # LATIN SMALL LETTER I WITH ACUTE
+0x00EE &#x00EE; # LATIN SMALL LETTER I WITH CIRCUMFLEX
+0x00EF &#x00EF; # LATIN SMALL LETTER I WITH DIAERESIS
+0x00F0 &#x00F0; # LATIN SMALL LETTER ETH
+0x00F1 &#x00F1; # LATIN SMALL LETTER N WITH TILDE
+0x00F2 &#x00F2; # LATIN SMALL LETTER O WITH GRAVE
+0x00F3 &#x00F3; # LATIN SMALL LETTER O WITH ACUTE
+0x00F4 &#x00F4; # LATIN SMALL LETTER O WITH CIRCUMFLEX
+0x00F5 &#x00F5; # LATIN SMALL LETTER O WITH TILDE
+0x00F6 &#x00F6; # LATIN SMALL LETTER O WITH DIAERESIS
+0x00F7 &#x00F7; # DIVISION SIGN
+0x00F8 &#x00F8; # LATIN SMALL LETTER O WITH STROKE
+0x00F9 &#x00F9; # LATIN SMALL LETTER U WITH GRAVE
+0x00FA &#x00FA; # LATIN SMALL LETTER U WITH ACUTE
+0x00FB &#x00FB; # LATIN SMALL LETTER U WITH CIRCUMFLEX
+0x00FC &#x00FC; # LATIN SMALL LETTER U WITH DIAERESIS
+0x00FD &#x00FD; # LATIN SMALL LETTER Y WITH ACUTE
+0x00FE &#x00FE; # LATIN SMALL LETTER THORN
+0x00FF &#x00FF; # LATIN SMALL LETTER Y WITH DIAERESIS
+0x0100 &#x0100; # LATIN CAPITAL LETTER A WITH MACRON
+0x0101 &#x0101; # LATIN SMALL LETTER A WITH MACRON
+0x0102 &#x0102; # LATIN CAPITAL LETTER A WITH BREVE
+0x0103 &#x0103; # LATIN SMALL LETTER A WITH BREVE
+0x0104 &#x0104; # LATIN CAPITAL LETTER A WITH OGONEK
+0x0105 &#x0105; # LATIN SMALL LETTER A WITH OGONEK
+0x0106 &#x0106; # LATIN CAPITAL LETTER C WITH ACUTE
+0x0107 &#x0107; # LATIN SMALL LETTER C WITH ACUTE
+0x0108 &#x0108; # LATIN CAPITAL LETTER C WITH CIRCUMFLEX
+0x0109 &#x0109; # LATIN SMALL LETTER C WITH CIRCUMFLEX
+0x010A &#x010A; # LATIN CAPITAL LETTER C WITH DOT ABOVE
+0x010B &#x010B; # LATIN SMALL LETTER C WITH DOT ABOVE
+0x010C &#x010C; # LATIN CAPITAL LETTER C WITH CARON
+0x010D &#x010D; # LATIN SMALL LETTER C WITH CARON
+0x010E &#x010E; # LATIN CAPITAL LETTER D WITH CARON
+0x010F &#x010F; # LATIN SMALL LETTER D WITH CARON
+0x0110 &#x0110; # LATIN CAPITAL LETTER D WITH STROKE
+0x0111 &#x0111; # LATIN SMALL LETTER D WITH STROKE
+0x0112 &#x0112; # LATIN CAPITAL LETTER E WITH MACRON
+0x0113 &#x0113; # LATIN SMALL LETTER E WITH MACRON
+0x0116 &#x0116; # LATIN CAPITAL LETTER E WITH DOT ABOVE
+0x0117 &#x0117; # LATIN SMALL LETTER E WITH DOT ABOVE
+0x0118 &#x0118; # LATIN CAPITAL LETTER E WITH OGONEK
+0x0119 &#x0119; # LATIN SMALL LETTER E WITH OGONEK
+0x011A &#x011A; # LATIN CAPITAL LETTER E WITH CARON
+0x011B &#x011B; # LATIN SMALL LETTER E WITH CARON
+0x011C &#x011C; # LATIN CAPITAL LETTER G WITH CIRCUMFLEX
+0x011D &#x011D; # LATIN SMALL LETTER G WITH CIRCUMFLEX
+0x011E &#x011E; # LATIN CAPITAL LETTER G WITH BREVE
+0x011F &#x011F; # LATIN SMALL LETTER G WITH BREVE
+0x0120 &#x0120; # LATIN CAPITAL LETTER G WITH DOT ABOVE
+0x0121 &#x0121; # LATIN SMALL LETTER G WITH DOT ABOVE
+0x0122 &#x0122; # LATIN CAPITAL LETTER G WITH CEDILLA
+0x0123 &#x0123; # LATIN SMALL LETTER G WITH CEDILLA
+0x0124 &#x0124; # LATIN CAPITAL LETTER H WITH CIRCUMFLEX
+0x0125 &#x0125; # LATIN SMALL LETTER H WITH CIRCUMFLEX
+0x0126 &#x0126; # LATIN CAPITAL LETTER H WITH STROKE
+0x0127 &#x0127; # LATIN SMALL LETTER H WITH STROKE
+0x0128 &#x0128; # LATIN CAPITAL LETTER I WITH TILDE
+0x0129 &#x0129; # LATIN SMALL LETTER I WITH TILDE
+0x012A &#x012A; # LATIN CAPITAL LETTER I WITH MACRON
+0x012B &#x012B; # LATIN SMALL LETTER I WITH MACRON
+0x012E &#x012E; # LATIN CAPITAL LETTER I WITH OGONEK
+0x012F &#x012F; # LATIN SMALL LETTER I WITH OGONEK
+0x0130 &#x0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE
+0x0131 &#x0131; # LATIN SMALL LETTER DOTLESS I
+0x0131 &#x0131; # LATIN SMALL LETTER DOTLESS I
+0x0132 &#x0132; # LATIN CAPITAL LIGATURE IJ
+0x0133 &#x0133; # LATIN SMALL LIGATURE IJ
+0x0134 &#x0134; # LATIN CAPITAL LETTER J WITH CIRCUMFLEX
+0x0135 &#x0135; # LATIN SMALL LETTER J WITH CIRCUMFLEX
+0x0136 &#x0136; # LATIN CAPITAL LETTER K WITH CEDILLA
+0x0137 &#x0137; # LATIN SMALL LETTER K WITH CEDILLA
+0x0138 &#x0138; # LATIN SMALL LETTER KRA
+0x0139 &#x0139; # LATIN CAPITAL LETTER L WITH ACUTE
+0x013A &#x013A; # LATIN SMALL LETTER L WITH ACUTE
+0x013B &#x013B; # LATIN CAPITAL LETTER L WITH CEDILLA
+0x013C &#x013C; # LATIN SMALL LETTER L WITH CEDILLA
+0x013D &#x013D; # LATIN CAPITAL LETTER L WITH CARON
+0x013E &#x013E; # LATIN SMALL LETTER L WITH CARON
+0x013F &#x013F; # LATIN CAPITAL LETTER L WITH MIDDLE DOT
+0x0140 &#x0140; # LATIN SMALL LETTER L WITH MIDDLE DOT
+0x0141 &#x0141; # LATIN CAPITAL LETTER L WITH STROKE
+0x0142 &#x0142; # LATIN SMALL LETTER L WITH STROKE
+0x0143 &#x0143; # LATIN CAPITAL LETTER N WITH ACUTE
+0x0144 &#x0144; # LATIN SMALL LETTER N WITH ACUTE
+0x0145 &#x0145; # LATIN CAPITAL LETTER N WITH CEDILLA
+0x0146 &#x0146; # LATIN SMALL LETTER N WITH CEDILLA
+0x0147 &#x0147; # LATIN CAPITAL LETTER N WITH CARON
+0x0148 &#x0148; # LATIN SMALL LETTER N WITH CARON
+0x0149 &#x0149; # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
+0x014A &#x014A; # LATIN CAPITAL LETTER ENG
+0x014B &#x014B; # LATIN SMALL LETTER ENG
+0x014C &#x014C; # LATIN CAPITAL LETTER O WITH MACRON
+0x014D &#x014D; # LATIN SMALL LETTER O WITH MACRON
+0x0150 &#x0150; # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
+0x0151 &#x0151; # LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0x0152 &#x0152; # LATIN CAPITAL LIGATURE OE
+0x0153 &#x0153; # LATIN SMALL LIGATURE OE
+0x0154 &#x0154; # LATIN CAPITAL LETTER R WITH ACUTE
+0x0155 &#x0155; # LATIN SMALL LETTER R WITH ACUTE
+0x0156 &#x0156; # LATIN CAPITAL LETTER R WITH CEDILLA
+0x0157 &#x0157; # LATIN SMALL LETTER R WITH CEDILLA
+0x0158 &#x0158; # LATIN CAPITAL LETTER R WITH CARON
+0x0159 &#x0159; # LATIN SMALL LETTER R WITH CARON
+0x015A &#x015A; # LATIN CAPITAL LETTER S WITH ACUTE
+0x015B &#x015B; # LATIN SMALL LETTER S WITH ACUTE
+0x015C &#x015C; # LATIN CAPITAL LETTER S WITH CIRCUMFLEX
+0x015D &#x015D; # LATIN SMALL LETTER S WITH CIRCUMFLEX
+0x015E &#x015E; # LATIN CAPITAL LETTER S WITH CEDILLA
+0x015F &#x015F; # LATIN SMALL LETTER S WITH CEDILLA
+0x0160 &#x0160; # LATIN CAPITAL LETTER S WITH CARON
+0x0161 &#x0161; # LATIN SMALL LETTER S WITH CARON
+0x0162 &#x0162; # LATIN CAPITAL LETTER T WITH CEDILLA
+0x0163 &#x0163; # LATIN SMALL LETTER T WITH CEDILLA
+0x0164 &#x0164; # LATIN CAPITAL LETTER T WITH CARON
+0x0165 &#x0165; # LATIN SMALL LETTER T WITH CARON
+0x0166 &#x0166; # LATIN CAPITAL LETTER T WITH STROKE
+0x0167 &#x0167; # LATIN SMALL LETTER T WITH STROKE
+0x0168 &#x0168; # LATIN CAPITAL LETTER U WITH TILDE
+0x0169 &#x0169; # LATIN SMALL LETTER U WITH TILDE
+0x016A &#x016A; # LATIN CAPITAL LETTER U WITH MACRON
+0x016B &#x016B; # LATIN SMALL LETTER U WITH MACRON
+0x016C &#x016C; # LATIN CAPITAL LETTER U WITH BREVE
+0x016D &#x016D; # LATIN SMALL LETTER U WITH BREVE
+0x016E &#x016E; # LATIN CAPITAL LETTER U WITH RING ABOVE
+0x016F &#x016F; # LATIN SMALL LETTER U WITH RING ABOVE
+0x0170 &#x0170; # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
+0x0171 &#x0171; # LATIN SMALL LETTER U WITH DOUBLE ACUTE
+0x0172 &#x0172; # LATIN CAPITAL LETTER U WITH OGONEK
+0x0173 &#x0173; # LATIN SMALL LETTER U WITH OGONEK
+0x0174 &#x0174; # LATIN CAPITAL LETTER W WITH CIRCUMFLEX
+0x0175 &#x0175; # LATIN SMALL LETTER W WITH CIRCUMFLEX
+0x0176 &#x0176; # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
+0x0177 &#x0177; # LATIN SMALL LETTER Y WITH CIRCUMFLEX
+0x0178 &#x0178; # LATIN CAPITAL LETTER Y WITH DIAERESIS
+0x0179 &#x0179; # LATIN CAPITAL LETTER Z WITH ACUTE
+0x017A &#x017A; # LATIN SMALL LETTER Z WITH ACUTE
+0x017B &#x017B; # LATIN CAPITAL LETTER Z WITH DOT ABOVE
+0x017C &#x017C; # LATIN SMALL LETTER Z WITH DOT ABOVE
+0x017D &#x017D; # LATIN CAPITAL LETTER Z WITH CARON
+0x017E &#x017E; # LATIN SMALL LETTER Z WITH CARON
+0x0192 &#x0192; # LATIN SMALL LETTER F WITH HOOK
+0x01F5 &#x01F5; # LATIN SMALL LETTER G WITH ACUTE
+0x02BC &#x02BC; # MODIFIER LETTER APOSTROPHE
+0x02C6 &#x02C6; # MODIFIER LETTER CIRCUMFLEX ACCENT
+0x02C7 &#x02C7; # CARON
+0x02D8 &#x02D8; # BREVE
+0x02D9 &#x02D9; # DOT ABOVE
+0x02DA &#x02DA; # RING ABOVE
+0x02DB &#x02DB; # OGONEK
+0x02DC &#x02DC; # SMALL TILDE
+0x02DD &#x02DD; # DOUBLE ACUTE ACCENT
+0x0386 &#x0386; # GREEK CAPITAL LETTER ALPHA WITH TONOS
+0x0388 &#x0388; # GREEK CAPITAL LETTER EPSILON WITH TONOS
+0x0389 &#x0389; # GREEK CAPITAL LETTER ETA WITH TONOS
+0x038A &#x038A; # GREEK CAPITAL LETTER IOTA WITH TONOS
+0x038C &#x038C; # GREEK CAPITAL LETTER OMICRON WITH TONOS
+0x038E &#x038E; # GREEK CAPITAL LETTER UPSILON WITH TONOS
+0x038F &#x038F; # GREEK CAPITAL LETTER OMEGA WITH TONOS
+0x0390 &#x0390; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0x0391 &#x0391; # GREEK CAPITAL LETTER ALPHA
+0x0391 &#x0391; # GREEK CAPITAL LETTER ALPHA
+0x0392 &#x0392; # GREEK CAPITAL LETTER BETA
+0x0392 &#x0392; # GREEK CAPITAL LETTER BETA
+0x0393 &#x0393; # GREEK CAPITAL LETTER GAMMA
+0x0393 &#x0393; # GREEK CAPITAL LETTER GAMMA
+0x0393 &#x0393; # GREEK CAPITAL LETTER GAMMA
+0x0394 &#x0394; # GREEK CAPITAL LETTER DELTA
+0x0394 &#x0394; # GREEK CAPITAL LETTER DELTA
+0x0394 &#x0394; # GREEK CAPITAL LETTER DELTA
+0x0395 &#x0395; # GREEK CAPITAL LETTER EPSILON
+0x0395 &#x0395; # GREEK CAPITAL LETTER EPSILON
+0x0396 &#x0396; # GREEK CAPITAL LETTER ZETA
+0x0396 &#x0396; # GREEK CAPITAL LETTER ZETA
+0x0397 &#x0397; # GREEK CAPITAL LETTER ETA
+0x0397 &#x0397; # GREEK CAPITAL LETTER ETA
+0x0398 &#x0398; # GREEK CAPITAL LETTER THETA
+0x0398 &#x0398; # GREEK CAPITAL LETTER THETA
+0x0398 &#x0398; # GREEK CAPITAL LETTER THETA
+0x0399 &#x0399; # GREEK CAPITAL LETTER IOTA
+0x0399 &#x0399; # GREEK CAPITAL LETTER IOTA
+0x039A &#x039A; # GREEK CAPITAL LETTER KAPPA
+0x039A &#x039A; # GREEK CAPITAL LETTER KAPPA
+0x039B &#x039B; # GREEK CAPITAL LETTER LAMDA
+0x039B &#x039B; # GREEK CAPITAL LETTER LAMDA
+0x039B &#x039B; # GREEK CAPITAL LETTER LAMDA
+0x039C &#x039C; # GREEK CAPITAL LETTER MU
+0x039C &#x039C; # GREEK CAPITAL LETTER MU
+0x039D &#x039D; # GREEK CAPITAL LETTER NU
+0x039D &#x039D; # GREEK CAPITAL LETTER NU
+0x039E &#x039E; # GREEK CAPITAL LETTER XI
+0x039E &#x039E; # GREEK CAPITAL LETTER XI
+0x039E &#x039E; # GREEK CAPITAL LETTER XI
+0x039F &#x039F; # GREEK CAPITAL LETTER OMICRON
+0x039F &#x039F; # GREEK CAPITAL LETTER OMICRON
+0x03A0 &#x03A0; # GREEK CAPITAL LETTER PI
+0x03A0 &#x03A0; # GREEK CAPITAL LETTER PI
+0x03A0 &#x03A0; # GREEK CAPITAL LETTER PI
+0x03A1 &#x03A1; # GREEK CAPITAL LETTER RHO
+0x03A1 &#x03A1; # GREEK CAPITAL LETTER RHO
+0x03A3 &#x03A3; # GREEK CAPITAL LETTER SIGMA
+0x03A3 &#x03A3; # GREEK CAPITAL LETTER SIGMA
+0x03A3 &#x03A3; # GREEK CAPITAL LETTER SIGMA
+0x03A4 &#x03A4; # GREEK CAPITAL LETTER TAU
+0x03A4 &#x03A4; # GREEK CAPITAL LETTER TAU
+0x03A5 &#x03A5; # GREEK CAPITAL LETTER UPSILON
+0x03A5 &#x03A5; # GREEK CAPITAL LETTER UPSILON
+0x03A5 &#x03A5; # GREEK CAPITAL LETTER UPSILON
+0x03A5 &#x03A5; # GREEK CAPITAL LETTER UPSILON
+0x03A6 &#x03A6; # GREEK CAPITAL LETTER PHI
+0x03A6 &#x03A6; # GREEK CAPITAL LETTER PHI
+0x03A6 &#x03A6; # GREEK CAPITAL LETTER PHI
+0x03A7 &#x03A7; # GREEK CAPITAL LETTER CHI
+0x03A7 &#x03A7; # GREEK CAPITAL LETTER CHI
+0x03A8 &#x03A8; # GREEK CAPITAL LETTER PSI
+0x03A8 &#x03A8; # GREEK CAPITAL LETTER PSI
+0x03A8 &#x03A8; # GREEK CAPITAL LETTER PSI
+0x03A9 &#x03A9; # GREEK CAPITAL LETTER OMEGA
+0x03A9 &#x03A9; # GREEK CAPITAL LETTER OMEGA
+0x03A9 &#x03A9; # GREEK CAPITAL LETTER OMEGA
+0x03AA &#x03AA; # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA
+0x03AB &#x03AB; # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA
+0x03AC &#x03AC; # GREEK SMALL LETTER ALPHA WITH TONOS
+0x03AD &#x03AD; # GREEK SMALL LETTER EPSILON WITH TONOS
+0x03AE &#x03AE; # GREEK SMALL LETTER ETA WITH TONOS
+0x03AF &#x03AF; # GREEK SMALL LETTER IOTA WITH TONOS
+0x03B0 &#x03B0; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+0x03B1 &#x03B1; # GREEK SMALL LETTER ALPHA
+0x03B1 &#x03B1; # GREEK SMALL LETTER ALPHA
+0x03B1 &#x03B1; # GREEK SMALL LETTER ALPHA
+0x03B2 &#x03B2; # GREEK SMALL LETTER BETA
+0x03B2 &#x03B2; # GREEK SMALL LETTER BETA
+0x03B2 &#x03B2; # GREEK SMALL LETTER BETA
+0x03B3 &#x03B3; # GREEK SMALL LETTER GAMMA
+0x03B3 &#x03B3; # GREEK SMALL LETTER GAMMA
+0x03B3 &#x03B3; # GREEK SMALL LETTER GAMMA
+0x03B3 &#x03B3; # GREEK SMALL LETTER GAMMA
+0x03B4 &#x03B4; # GREEK SMALL LETTER DELTA
+0x03B4 &#x03B4; # GREEK SMALL LETTER DELTA
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B5 &#x03B5; # GREEK SMALL LETTER EPSILON
+0x03B6 &#x03B6; # GREEK SMALL LETTER ZETA
+0x03B6 &#x03B6; # GREEK SMALL LETTER ZETA
+0x03B6 &#x03B6; # GREEK SMALL LETTER ZETA
+0x03B7 &#x03B7; # GREEK SMALL LETTER ETA
+0x03B7 &#x03B7; # GREEK SMALL LETTER ETA
+0x03B7 &#x03B7; # GREEK SMALL LETTER ETA
+0x03B8 &#x03B8; # GREEK SMALL LETTER THETA
+0x03B8 &#x03B8; # GREEK SMALL LETTER THETA
+0x03B8 &#x03B8; # GREEK SMALL LETTER THETA
+0x03B8 &#x03B8; # GREEK SMALL LETTER THETA
+0x03B9 &#x03B9; # GREEK SMALL LETTER IOTA
+0x03B9 &#x03B9; # GREEK SMALL LETTER IOTA
+0x03B9 &#x03B9; # GREEK SMALL LETTER IOTA
+0x03BA &#x03BA; # GREEK SMALL LETTER KAPPA
+0x03BA &#x03BA; # GREEK SMALL LETTER KAPPA
+0x03BA &#x03BA; # GREEK SMALL LETTER KAPPA
+0x03BB &#x03BB; # GREEK SMALL LETTER LAMDA
+0x03BB &#x03BB; # GREEK SMALL LETTER LAMDA
+0x03BB &#x03BB; # GREEK SMALL LETTER LAMDA
+0x03BC &#x03BC; # GREEK SMALL LETTER MU
+0x03BC &#x03BC; # GREEK SMALL LETTER MU
+0x03BC &#x03BC; # GREEK SMALL LETTER MU
+0x03BD &#x03BD; # GREEK SMALL LETTER NU
+0x03BD &#x03BD; # GREEK SMALL LETTER NU
+0x03BD &#x03BD; # GREEK SMALL LETTER NU
+0x03BE &#x03BE; # GREEK SMALL LETTER XI
+0x03BE &#x03BE; # GREEK SMALL LETTER XI
+0x03BE &#x03BE; # GREEK SMALL LETTER XI
+0x03BF &#x03BF; # GREEK SMALL LETTER OMICRON
+0x03BF &#x03BF; # GREEK SMALL LETTER OMICRON
+0x03C0 &#x03C0; # GREEK SMALL LETTER PI
+0x03C0 &#x03C0; # GREEK SMALL LETTER PI
+0x03C0 &#x03C0; # GREEK SMALL LETTER PI
+0x03C1 &#x03C1; # GREEK SMALL LETTER RHO
+0x03C1 &#x03C1; # GREEK SMALL LETTER RHO
+0x03C1 &#x03C1; # GREEK SMALL LETTER RHO
+0x03C2 &#x03C2; # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &#x03C2; # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &#x03C2; # GREEK SMALL LETTER FINAL SIGMA
+0x03C2 &#x03C2; # GREEK SMALL LETTER FINAL SIGMA
+0x03C3 &#x03C3; # GREEK SMALL LETTER SIGMA
+0x03C3 &#x03C3; # GREEK SMALL LETTER SIGMA
+0x03C3 &#x03C3; # GREEK SMALL LETTER SIGMA
+0x03C4 &#x03C4; # GREEK SMALL LETTER TAU
+0x03C4 &#x03C4; # GREEK SMALL LETTER TAU
+0x03C4 &#x03C4; # GREEK SMALL LETTER TAU
+0x03C5 &#x03C5; # GREEK SMALL LETTER UPSILON
+0x03C5 &#x03C5; # GREEK SMALL LETTER UPSILON
+0x03C5 &#x03C5; # GREEK SMALL LETTER UPSILON
+0x03C5 &#x03C5; # GREEK SMALL LETTER UPSILON
+0x03C6 &#x03C6; # GREEK SMALL LETTER PHI
+0x03C6 &#x03C6; # GREEK SMALL LETTER PHI
+0x03C6 &#x03C6; # GREEK SMALL LETTER PHI
+0x03C6 &#x03C6; # GREEK SMALL LETTER PHI
+0x03C7 &#x03C7; # GREEK SMALL LETTER CHI
+0x03C7 &#x03C7; # GREEK SMALL LETTER CHI
+0x03C7 &#x03C7; # GREEK SMALL LETTER CHI
+0x03C8 &#x03C8; # GREEK SMALL LETTER PSI
+0x03C8 &#x03C8; # GREEK SMALL LETTER PSI
+0x03C8 &#x03C8; # GREEK SMALL LETTER PSI
+0x03C9 &#x03C9; # GREEK SMALL LETTER OMEGA
+0x03C9 &#x03C9; # GREEK SMALL LETTER OMEGA
+0x03CA &#x03CA; # GREEK SMALL LETTER IOTA WITH DIALYTIKA
+0x03CB &#x03CB; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA
+0x03CC &#x03CC; # GREEK SMALL LETTER OMICRON WITH TONOS
+0x03CD &#x03CD; # GREEK SMALL LETTER UPSILON WITH TONOS
+0x03CE &#x03CE; # GREEK SMALL LETTER OMEGA WITH TONOS
+0x03CE &#x03CE; # GREEK SMALL LETTER OMEGA WITH TONOS
+0x03D1 &#x03D1; # GREEK THETA SYMBOL
+0x03D1 &#x03D1; # GREEK THETA SYMBOL
+0x03D1 &#x03D1; # GREEK THETA SYMBOL
+0x03D2 &#x03D2; # GREEK UPSILON WITH HOOK SYMBOL
+0x03D5 &#x03D5; # GREEK PHI SYMBOL
+0x03D5 &#x03D5; # GREEK PHI SYMBOL
+0x03D6 &#x03D6; # GREEK PI SYMBOL
+0x03D6 &#x03D6; # GREEK PI SYMBOL
+0x03DC &#x03DC; # GREEK LETTER DIGAMMA
+0x03DC &#x03DC; # GREEK LETTER DIGAMMA
+0x03F0 &#x03F0; # GREEK KAPPA SYMBOL
+0x03F0 &#x03F0; # GREEK KAPPA SYMBOL
+0x03F1 &#x03F1; # GREEK RHO SYMBOL
+0x03F1 &#x03F1; # GREEK RHO SYMBOL
+0x0401 &#x0401; # CYRILLIC CAPITAL LETTER IO
+0x0402 &#x0402; # CYRILLIC CAPITAL LETTER DJE
+0x0403 &#x0403; # CYRILLIC CAPITAL LETTER GJE
+0x0404 &#x0404; # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0x0405 &#x0405; # CYRILLIC CAPITAL LETTER DZE
+0x0406 &#x0406; # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0x0407 &#x0407; # CYRILLIC CAPITAL LETTER YI
+0x0408 &#x0408; # CYRILLIC CAPITAL LETTER JE
+0x0409 &#x0409; # CYRILLIC CAPITAL LETTER LJE
+0x040A &#x040A; # CYRILLIC CAPITAL LETTER NJE
+0x040B &#x040B; # CYRILLIC CAPITAL LETTER TSHE
+0x040C &#x040C; # CYRILLIC CAPITAL LETTER KJE
+0x040E &#x040E; # CYRILLIC CAPITAL LETTER SHORT U
+0x040F &#x040F; # CYRILLIC CAPITAL LETTER DZHE
+0x0410 &#x0410; # CYRILLIC CAPITAL LETTER A
+0x0411 &#x0411; # CYRILLIC CAPITAL LETTER BE
+0x0412 &#x0412; # CYRILLIC CAPITAL LETTER VE
+0x0413 &#x0413; # CYRILLIC CAPITAL LETTER GHE
+0x0414 &#x0414; # CYRILLIC CAPITAL LETTER DE
+0x0415 &#x0415; # CYRILLIC CAPITAL LETTER IE
+0x0416 &#x0416; # CYRILLIC CAPITAL LETTER ZHE
+0x0417 &#x0417; # CYRILLIC CAPITAL LETTER ZE
+0x0418 &#x0418; # CYRILLIC CAPITAL LETTER I
+0x0419 &#x0419; # CYRILLIC CAPITAL LETTER SHORT I
+0x041A &#x041A; # CYRILLIC CAPITAL LETTER KA
+0x041B &#x041B; # CYRILLIC CAPITAL LETTER EL
+0x041C &#x041C; # CYRILLIC CAPITAL LETTER EM
+0x041D &#x041D; # CYRILLIC CAPITAL LETTER EN
+0x041E &#x041E; # CYRILLIC CAPITAL LETTER O
+0x041F &#x041F; # CYRILLIC CAPITAL LETTER PE
+0x0420 &#x0420; # CYRILLIC CAPITAL LETTER ER
+0x0421 &#x0421; # CYRILLIC CAPITAL LETTER ES
+0x0422 &#x0422; # CYRILLIC CAPITAL LETTER TE
+0x0423 &#x0423; # CYRILLIC CAPITAL LETTER U
+0x0424 &#x0424; # CYRILLIC CAPITAL LETTER EF
+0x0425 &#x0425; # CYRILLIC CAPITAL LETTER HA
+0x0426 &#x0426; # CYRILLIC CAPITAL LETTER TSE
+0x0427 &#x0427; # CYRILLIC CAPITAL LETTER CHE
+0x0428 &#x0428; # CYRILLIC CAPITAL LETTER SHA
+0x0429 &#x0429; # CYRILLIC CAPITAL LETTER SHCHA
+0x042A &#x042A; # CYRILLIC CAPITAL LETTER HARD SIGN
+0x042B &#x042B; # CYRILLIC CAPITAL LETTER YERU
+0x042C &#x042C; # CYRILLIC CAPITAL LETTER SOFT SIGN
+0x042D &#x042D; # CYRILLIC CAPITAL LETTER E
+0x042E &#x042E; # CYRILLIC CAPITAL LETTER YU
+0x042F &#x042F; # CYRILLIC CAPITAL LETTER YA
+0x0430 &#x0430; # CYRILLIC SMALL LETTER A
+0x0431 &#x0431; # CYRILLIC SMALL LETTER BE
+0x0432 &#x0432; # CYRILLIC SMALL LETTER VE
+0x0433 &#x0433; # CYRILLIC SMALL LETTER GHE
+0x0434 &#x0434; # CYRILLIC SMALL LETTER DE
+0x0435 &#x0435; # CYRILLIC SMALL LETTER IE
+0x0436 &#x0436; # CYRILLIC SMALL LETTER ZHE
+0x0437 &#x0437; # CYRILLIC SMALL LETTER ZE
+0x0438 &#x0438; # CYRILLIC SMALL LETTER I
+0x0439 &#x0439; # CYRILLIC SMALL LETTER SHORT I
+0x043A &#x043A; # CYRILLIC SMALL LETTER KA
+0x043B &#x043B; # CYRILLIC SMALL LETTER EL
+0x043C &#x043C; # CYRILLIC SMALL LETTER EM
+0x043D &#x043D; # CYRILLIC SMALL LETTER EN
+0x043E &#x043E; # CYRILLIC SMALL LETTER O
+0x043F &#x043F; # CYRILLIC SMALL LETTER PE
+0x0440 &#x0440; # CYRILLIC SMALL LETTER ER
+0x0441 &#x0441; # CYRILLIC SMALL LETTER ES
+0x0442 &#x0442; # CYRILLIC SMALL LETTER TE
+0x0443 &#x0443; # CYRILLIC SMALL LETTER U
+0x0444 &#x0444; # CYRILLIC SMALL LETTER EF
+0x0445 &#x0445; # CYRILLIC SMALL LETTER HA
+0x0446 &#x0446; # CYRILLIC SMALL LETTER TSE
+0x0447 &#x0447; # CYRILLIC SMALL LETTER CHE
+0x0448 &#x0448; # CYRILLIC SMALL LETTER SHA
+0x0449 &#x0449; # CYRILLIC SMALL LETTER SHCHA
+0x044A &#x044A; # CYRILLIC SMALL LETTER HARD SIGN
+0x044B &#x044B; # CYRILLIC SMALL LETTER YERU
+0x044C &#x044C; # CYRILLIC SMALL LETTER SOFT SIGN
+0x044D &#x044D; # CYRILLIC SMALL LETTER E
+0x044E &#x044E; # CYRILLIC SMALL LETTER YU
+0x044F &#x044F; # CYRILLIC SMALL LETTER YA
+0x0451 &#x0451; # CYRILLIC SMALL LETTER IO
+0x0452 &#x0452; # CYRILLIC SMALL LETTER DJE
+0x0453 &#x0453; # CYRILLIC SMALL LETTER GJE
+0x0454 &#x0454; # CYRILLIC SMALL LETTER UKRAINIAN IE
+0x0455 &#x0455; # CYRILLIC SMALL LETTER DZE
+0x0456 &#x0456; # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0x0457 &#x0457; # CYRILLIC SMALL LETTER YI
+0x0458 &#x0458; # CYRILLIC SMALL LETTER JE
+0x0459 &#x0459; # CYRILLIC SMALL LETTER LJE
+0x045A &#x045A; # CYRILLIC SMALL LETTER NJE
+0x045B &#x045B; # CYRILLIC SMALL LETTER TSHE
+0x045C &#x045C; # CYRILLIC SMALL LETTER KJE
+0x045E &#x045E; # CYRILLIC SMALL LETTER SHORT U
+0x045F &#x045F; # CYRILLIC SMALL LETTER DZHE
+0x2002 &#x2002; # EN SPACE
+0x2003 &#x2003; # EM SPACE
+0x2004 &#x2004; # THREE-PER-EM SPACE
+0x2005 &#x2005; # FOUR-PER-EM SPACE
+0x2007 &#x2007; # FIGURE SPACE
+0x2008 &#x2008; # PUNCTUATION SPACE
+0x2009 &#x2009; # THIN SPACE
+0x200A &#x200A; # HAIR SPACE
+0x200C &#x200C; # ZERO WIDTH NON-JOINER
+0x200D &#x200D; # ZERO WIDTH JOINER
+0x200E &#x200E; # LEFT-TO-RIGHT MARK
+0x200F &#x200F; # RIGHT-TO-LEFT MARK
+0x2010 &#x2010; # HYPHEN
+0x2013 &#x2013; # EN DASH
+0x2014 &#x2014; # EM DASH
+0x2015 &#x2015; # HORIZONTAL BAR
+0x2016 &#x2016; # DOUBLE VERTICAL LINE
+0x2018 &#x2018; # LEFT SINGLE QUOTATION MARK
+0x2018 &#x2018; # LEFT SINGLE QUOTATION MARK
+0x2019 &#x2019; # RIGHT SINGLE QUOTATION MARK
+0x201A &#x201A; # SINGLE LOW-9 QUOTATION MARK
+0x201A &#x201A; # SINGLE LOW-9 QUOTATION MARK
+0x201C &#x201C; # LEFT DOUBLE QUOTATION MARK
+0x201C &#x201C; # LEFT DOUBLE QUOTATION MARK
+0x201D &#x201D; # RIGHT DOUBLE QUOTATION MARK
+0x201E &#x201E; # DOUBLE LOW-9 QUOTATION MARK
+0x201E &#x201E; # DOUBLE LOW-9 QUOTATION MARK
+0x2020 &#x2020; # DAGGER
+0x2021 &#x2021; # DOUBLE DAGGER
+0x2022 &#x2022; # BULLET
+0x2025 &#x2025; # TWO DOT LEADER
+0x2026 &#x2026; # HORIZONTAL ELLIPSIS
+0x2026 &#x2026; # HORIZONTAL ELLIPSIS
+0x2030 &#x2030; # PER MILLE SIGN
+0x2032 &#x2032; # PRIME
+0x2032 &#x2032; # PRIME
+0x2033 &#x2033; # DOUBLE PRIME
+0x2034 &#x2034; # TRIPLE PRIME
+0x2035 &#x2035; # REVERSED PRIME
+0x2039 &#x2039; # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+0x203A &#x203A; # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+0x203E &#x203E; # OVERLINE
+0x2041 &#x2041; # CARET INSERTION POINT
+0x2043 &#x2043; # HYPHEN BULLET
+0x2044 &#x2044; # FRACTION SLASH
+0x20DB &#x20DB; # COMBINING THREE DOTS ABOVE
+0x20DC &#x20DC; # COMBINING FOUR DOTS ABOVE
+0x2105 &#x2105; # CARE OF
+0x210B &#x210B; # SCRIPT CAPITAL H
+0x210F &#x210F; # PLANCK CONSTANT OVER TWO PI
+0x2111 &#x2111; # BLACK-LETTER CAPITAL I
+0x2112 &#x2112; # SCRIPT CAPITAL L
+0x2113 &#x2113; # SCRIPT SMALL L
+0x2116 &#x2116; # NUMERO SIGN
+0x2117 &#x2117; # SOUND RECORDING COPYRIGHT
+0x2118 &#x2118; # SCRIPT CAPITAL P
+0x211C &#x211C; # BLACK-LETTER CAPITAL R
+0x211E &#x211E; # PRESCRIPTION TAKE
+0x2122 &#x2122; # TRADE MARK SIGN
+0x2126 &#x2126; # OHM SIGN
+0x212B &#x212B; # ANGSTROM SIGN
+0x212C &#x212C; # SCRIPT CAPITAL B
+0x2133 &#x2133; # SCRIPT CAPITAL M
+0x2134 &#x2134; # SCRIPT SMALL O
+0x2135 &#x2135; # ALEF SYMBOL
+0x2135 &#x2135; # ALEF SYMBOL
+0x2136 &#x2136; # BET SYMBOL
+0x2137 &#x2137; # GIMEL SYMBOL
+0x2138 &#x2138; # DALET SYMBOL
+0x2153 &#x2153; # VULGAR FRACTION ONE THIRD
+0x2154 &#x2154; # VULGAR FRACTION TWO THIRDS
+0x2155 &#x2155; # VULGAR FRACTION ONE FIFTH
+0x2156 &#x2156; # VULGAR FRACTION TWO FIFTHS
+0x2157 &#x2157; # VULGAR FRACTION THREE FIFTHS
+0x2158 &#x2158; # VULGAR FRACTION FOUR FIFTHS
+0x2159 &#x2159; # VULGAR FRACTION ONE SIXTH
+0x215A &#x215A; # VULGAR FRACTION FIVE SIXTHS
+0x215B &#x215B; # VULGAR FRACTION ONE EIGHTH
+0x215C &#x215C; # VULGAR FRACTION THREE EIGHTHS
+0x215D &#x215D; # VULGAR FRACTION FIVE EIGHTHS
+0x215E &#x215E; # VULGAR FRACTION SEVEN EIGHTHS
+0x2190 &#x2190; # LEFTWARDS ARROW
+0x2191 &#x2191; # UPWARDS ARROW
+0x2192 &#x2192; # RIGHTWARDS ARROW
+0x2193 &#x2193; # DOWNWARDS ARROW
+0x2194 &#x2194; # LEFT RIGHT ARROW
+0x2194 &#x2194; # LEFT RIGHT ARROW
+0x2194 &#x2194; # LEFT RIGHT ARROW
+0x2195 &#x2195; # UP DOWN ARROW
+0x2196 &#x2196; # NORTH WEST ARROW
+0x2197 &#x2197; # NORTH EAST ARROW
+0x2198 &#x2198; # SOUTH EAST ARROW
+0x2199 &#x2199; # SOUTH WEST ARROW
+0x219A &#x219A; # LEFTWARDS ARROW WITH STROKE
+0x219B &#x219B; # RIGHTWARDS ARROW WITH STROKE
+0x219D &#x219D; # RIGHTWARDS WAVE ARROW
+0x219E &#x219E; # LEFTWARDS TWO HEADED ARROW
+0x21A0 &#x21A0; # RIGHTWARDS TWO HEADED ARROW
+0x21A2 &#x21A2; # LEFTWARDS ARROW WITH TAIL
+0x21A3 &#x21A3; # RIGHTWARDS ARROW WITH TAIL
+0x21A6 &#x21A6; # RIGHTWARDS ARROW FROM BAR
+0x21A9 &#x21A9; # LEFTWARDS ARROW WITH HOOK
+0x21AA &#x21AA; # RIGHTWARDS ARROW WITH HOOK
+0x21AB &#x21AB; # LEFTWARDS ARROW WITH LOOP
+0x21AC &#x21AC; # RIGHTWARDS ARROW WITH LOOP
+0x21AD &#x21AD; # LEFT RIGHT WAVE ARROW
+0x21AE &#x21AE; # LEFT RIGHT ARROW WITH STROKE
+0x21B0 &#x21B0; # UPWARDS ARROW WITH TIP LEFTWARDS
+0x21B1 &#x21B1; # UPWARDS ARROW WITH TIP RIGHTWARDS
+0x21B5 &#x21B5; # DOWNWARDS ARROW WITH CORNER LEFTWARDS
+0x21B6 &#x21B6; # ANTICLOCKWISE TOP SEMICIRCLE ARROW
+0x21B7 &#x21B7; # CLOCKWISE TOP SEMICIRCLE ARROW
+0x21BA &#x21BA; # ANTICLOCKWISE OPEN CIRCLE ARROW
+0x21BB &#x21BB; # CLOCKWISE OPEN CIRCLE ARROW
+0x21BC &#x21BC; # LEFTWARDS HARPOON WITH BARB UPWARDS
+0x21BD &#x21BD; # LEFTWARDS HARPOON WITH BARB DOWNWARDS
+0x21BE &#x21BE; # UPWARDS HARPOON WITH BARB RIGHTWARDS
+0x21BF &#x21BF; # UPWARDS HARPOON WITH BARB LEFTWARDS
+0x21C0 &#x21C0; # RIGHTWARDS HARPOON WITH BARB UPWARDS
+0x21C1 &#x21C1; # RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+0x21C2 &#x21C2; # DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+0x21C3 &#x21C3; # DOWNWARDS HARPOON WITH BARB LEFTWARDS
+0x21C4 &#x21C4; # RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+0x21C6 &#x21C6; # LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+0x21C7 &#x21C7; # LEFTWARDS PAIRED ARROWS
+0x21C8 &#x21C8; # UPWARDS PAIRED ARROWS
+0x21C9 &#x21C9; # RIGHTWARDS PAIRED ARROWS
+0x21CA &#x21CA; # DOWNWARDS PAIRED ARROWS
+0x21CB &#x21CB; # LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+0x21CC &#x21CC; # RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+0x21CD &#x21CD; # LEFTWARDS DOUBLE ARROW WITH STROKE
+0x21CE &#x21CE; # LEFT RIGHT DOUBLE ARROW WITH STROKE
+0x21CF &#x21CF; # RIGHTWARDS DOUBLE ARROW WITH STROKE
+0x21D0 &#x21D0; # LEFTWARDS DOUBLE ARROW
+0x21D0 &#x21D0; # LEFTWARDS DOUBLE ARROW
+0x21D1 &#x21D1; # UPWARDS DOUBLE ARROW
+0x21D2 &#x21D2; # RIGHTWARDS DOUBLE ARROW
+0x21D2 &#x21D2; # RIGHTWARDS DOUBLE ARROW
+0x21D3 &#x21D3; # DOWNWARDS DOUBLE ARROW
+0x21D4 &#x21D4; # LEFT RIGHT DOUBLE ARROW
+0x21D4 &#x21D4; # LEFT RIGHT DOUBLE ARROW
+0x21D5 &#x21D5; # UP DOWN DOUBLE ARROW
+0x21DA &#x21DA; # LEFTWARDS TRIPLE ARROW
+0x21DB &#x21DB; # RIGHTWARDS TRIPLE ARROW
+0x2200 &#x2200; # FOR ALL
+0x2201 &#x2201; # COMPLEMENT
+0x2202 &#x2202; # PARTIAL DIFFERENTIAL
+0x2203 &#x2203; # THERE EXISTS
+0x2204 &#x2204; # THERE DOES NOT EXIST
+0x2205 &#x2205; # EMPTY SET
+0x2207 &#x2207; # NABLA
+0x2208 &#x2208; # ELEMENT OF
+0x2209 &#x2209; # NOT AN ELEMENT OF
+0x220A &#x220A; # SMALL ELEMENT OF
+0x220B &#x220B; # CONTAINS AS MEMBER
+0x220D &#x220D; # SMALL CONTAINS AS MEMBER
+0x220F &#x220F; # N-ARY PRODUCT
+0x2210 &#x2210; # N-ARY COPRODUCT
+0x2210 &#x2210; # N-ARY COPRODUCT
+0x2210 &#x2210; # N-ARY COPRODUCT
+0x2211 &#x2211; # N-ARY SUMMATION
+0x2212 &#x2212; # MINUS SIGN
+0x2213 &#x2213; # MINUS-OR-PLUS SIGN
+0x2214 &#x2214; # DOT PLUS
+0x2216 &#x2216; # SET MINUS
+0x2216 &#x2216; # SET MINUS
+0x2217 &#x2217; # ASTERISK OPERATOR
+0x2218 &#x2218; # RING OPERATOR
+0x221A &#x221A; # SQUARE ROOT
+0x221D &#x221D; # PROPORTIONAL TO
+0x221D &#x221D; # PROPORTIONAL TO
+0x221E &#x221E; # INFINITY
+0x221F &#x221F; # RIGHT ANGLE
+0x2220 &#x2220; # ANGLE
+0x2221 &#x2221; # MEASURED ANGLE
+0x2222 &#x2222; # SPHERICAL ANGLE
+0x2223 &#x2223; # DIVIDES
+0x2224 &#x2224; # DOES NOT DIVIDE
+0x2225 &#x2225; # PARALLEL TO
+0x2225 &#x2225; # PARALLEL TO
+0x2226 &#x2226; # NOT PARALLEL TO
+0x2226 &#x2226; # NOT PARALLEL TO
+0x2227 &#x2227; # LOGICAL AND
+0x2228 &#x2228; # LOGICAL OR
+0x2229 &#x2229; # INTERSECTION
+0x222A &#x222A; # UNION
+0x222B &#x222B; # INTEGRAL
+0x222E &#x222E; # CONTOUR INTEGRAL
+0x2234 &#x2234; # THEREFORE
+0x2235 &#x2235; # BECAUSE
+0x223C &#x223C; # TILDE OPERATOR
+0x223C &#x223C; # TILDE OPERATOR
+0x223D &#x223D; # REVERSED TILDE
+0x2240 &#x2240; # WREATH PRODUCT
+0x2241 &#x2241; # NOT TILDE
+0x2243 &#x2243; # ASYMPTOTICALLY EQUAL TO
+0x2244 &#x2244; # NOT ASYMPTOTICALLY EQUAL TO
+0x2245 &#x2245; # APPROXIMATELY EQUAL TO
+0x2247 &#x2247; # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+0x2248 &#x2248; # ALMOST EQUAL TO
+0x2248 &#x2248; # ALMOST EQUAL TO
+0x2248 &#x2248; # ALMOST EQUAL TO
+0x2249 &#x2249; # NOT ALMOST EQUAL TO
+0x224A &#x224A; # ALMOST EQUAL OR EQUAL TO
+0x224C &#x224C; # ALL EQUAL TO
+0x224E &#x224E; # GEOMETRICALLY EQUIVALENT TO
+0x224F &#x224F; # DIFFERENCE BETWEEN
+0x2250 &#x2250; # APPROACHES THE LIMIT
+0x2251 &#x2251; # GEOMETRICALLY EQUAL TO
+0x2252 &#x2252; # APPROXIMATELY EQUAL TO OR THE IMAGE OF
+0x2253 &#x2253; # IMAGE OF OR APPROXIMATELY EQUAL TO
+0x2254 &#x2254; # COLON EQUALS
+0x2255 &#x2255; # EQUALS COLON
+0x2256 &#x2256; # RING IN EQUAL TO
+0x2257 &#x2257; # RING EQUAL TO
+0x2259 &#x2259; # ESTIMATES
+0x225C &#x225C; # DELTA EQUAL TO
+0x2260 &#x2260; # NOT EQUAL TO
+0x2261 &#x2261; # IDENTICAL TO
+0x2262 &#x2262; # NOT IDENTICAL TO
+0x2264 &#x2264; # LESS-THAN OR EQUAL TO
+0x2264 &#x2264; # LESS-THAN OR EQUAL TO
+0x2265 &#x2265; # GREATER-THAN OR EQUAL TO
+0x2265 &#x2265; # GREATER-THAN OR EQUAL TO
+0x2266 &#x2266; # LESS-THAN OVER EQUAL TO
+0x2267 &#x2267; # GREATER-THAN OVER EQUAL TO
+0x2268 &#x2268; # LESS-THAN BUT NOT EQUAL TO
+0x2268 &#x2268; # LESS-THAN BUT NOT EQUAL TO
+0x2268 &#x2268; # LESS-THAN BUT NOT EQUAL TO
+0x2269 &#x2269; # GREATER-THAN BUT NOT EQUAL TO
+0x2269 &#x2269; # GREATER-THAN BUT NOT EQUAL TO
+0x2269 &#x2269; # GREATER-THAN BUT NOT EQUAL TO
+0x226A &#x226A; # MUCH LESS-THAN
+0x226B &#x226B; # MUCH GREATER-THAN
+0x226C &#x226C; # BETWEEN
+0x226E &#x226E; # NOT LESS-THAN
+0x226F &#x226F; # NOT GREATER-THAN
+0x2270 &#x2270; # NEITHER LESS-THAN NOR EQUAL TO
+0x2270 &#x2270; # NEITHER LESS-THAN NOR EQUAL TO
+0x2271 &#x2271; # NEITHER GREATER-THAN NOR EQUAL TO
+0x2271 &#x2271; # NEITHER GREATER-THAN NOR EQUAL TO
+0x2272 &#x2272; # LESS-THAN OR EQUIVALENT TO
+0x2273 &#x2273; # GREATER-THAN OR EQUIVALENT TO
+0x2276 &#x2276; # LESS-THAN OR GREATER-THAN
+0x2277 &#x2277; # GREATER-THAN OR LESS-THAN
+0x227A &#x227A; # PRECEDES
+0x227B &#x227B; # SUCCEEDS
+0x227C &#x227C; # PRECEDES OR EQUAL TO
+0x227C &#x227C; # PRECEDES OR EQUAL TO
+0x227D &#x227D; # SUCCEEDS OR EQUAL TO
+0x227D &#x227D; # SUCCEEDS OR EQUAL TO
+0x227E &#x227E; # PRECEDES OR EQUIVALENT TO
+0x227F &#x227F; # SUCCEEDS OR EQUIVALENT TO
+0x2280 &#x2280; # DOES NOT PRECEDE
+0x2281 &#x2281; # DOES NOT SUCCEED
+0x2282 &#x2282; # SUBSET OF
+0x2283 &#x2283; # SUPERSET OF
+0x2284 &#x2284; # NOT A SUBSET OF
+0x2285 &#x2285; # NOT A SUPERSET OF
+0x2286 &#x2286; # SUBSET OF OR EQUAL TO
+0x2286 &#x2286; # SUBSET OF OR EQUAL TO
+0x2287 &#x2287; # SUPERSET OF OR EQUAL TO
+0x2287 &#x2287; # SUPERSET OF OR EQUAL TO
+0x2288 &#x2288; # NEITHER A SUBSET OF NOR EQUAL TO
+0x2288 &#x2288; # NEITHER A SUBSET OF NOR EQUAL TO
+0x2289 &#x2289; # NEITHER A SUPERSET OF NOR EQUAL TO
+0x2289 &#x2289; # NEITHER A SUPERSET OF NOR EQUAL TO
+0x228A &#x228A; # SUBSET OF WITH NOT EQUAL TO
+0x228A &#x228A; # SUBSET OF WITH NOT EQUAL TO
+0x228A &#x228A; # SUBSET OF WITH NOT EQUAL TO
+0x228A &#x228A; # SUBSET OF WITH NOT EQUAL TO
+0x228B &#x228B; # SUPERSET OF WITH NOT EQUAL TO
+0x228B &#x228B; # SUPERSET OF WITH NOT EQUAL TO
+0x228B &#x228B; # SUPERSET OF WITH NOT EQUAL TO
+0x228B &#x228B; # SUPERSET OF WITH NOT EQUAL TO
+0x228E &#x228E; # MULTISET UNION
+0x228F &#x228F; # SQUARE IMAGE OF
+0x2290 &#x2290; # SQUARE ORIGINAL OF
+0x2291 &#x2291; # SQUARE IMAGE OF OR EQUAL TO
+0x2292 &#x2292; # SQUARE ORIGINAL OF OR EQUAL TO
+0x2293 &#x2293; # SQUARE CAP
+0x2294 &#x2294; # SQUARE CUP
+0x2295 &#x2295; # CIRCLED PLUS
+0x2296 &#x2296; # CIRCLED MINUS
+0x2297 &#x2297; # CIRCLED TIMES
+0x2298 &#x2298; # CIRCLED DIVISION SLASH
+0x2299 &#x2299; # CIRCLED DOT OPERATOR
+0x229A &#x229A; # CIRCLED RING OPERATOR
+0x229B &#x229B; # CIRCLED ASTERISK OPERATOR
+0x229D &#x229D; # CIRCLED DASH
+0x229E &#x229E; # SQUARED PLUS
+0x229F &#x229F; # SQUARED MINUS
+0x22A0 &#x22A0; # SQUARED TIMES
+0x22A1 &#x22A1; # SQUARED DOT OPERATOR
+0x22A2 &#x22A2; # RIGHT TACK
+0x22A3 &#x22A3; # LEFT TACK
+0x22A4 &#x22A4; # DOWN TACK
+0x22A5 &#x22A5; # UP TACK
+0x22A5 &#x22A5; # UP TACK
+0x22A7 &#x22A7; # MODELS
+0x22A8 &#x22A8; # TRUE
+0x22A9 &#x22A9; # FORCES
+0x22AA &#x22AA; # TRIPLE VERTICAL BAR RIGHT TURNSTILE
+0x22AC &#x22AC; # DOES NOT PROVE
+0x22AD &#x22AD; # NOT TRUE
+0x22AE &#x22AE; # DOES NOT FORCE
+0x22AF &#x22AF; # NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+0x22B2 &#x22B2; # NORMAL SUBGROUP OF
+0x22B3 &#x22B3; # CONTAINS AS NORMAL SUBGROUP
+0x22B4 &#x22B4; # NORMAL SUBGROUP OF OR EQUAL TO
+0x22B5 &#x22B5; # CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+0x22B8 &#x22B8; # MULTIMAP
+0x22BA &#x22BA; # INTERCALATE
+0x22BB &#x22BB; # XOR
+0x22BC &#x22BC; # NAND
+0x22C4 &#x22C4; # DIAMOND OPERATOR
+0x22C5 &#x22C5; # DOT OPERATOR
+0x22C6 &#x22C6; # STAR OPERATOR
+0x22C7 &#x22C7; # DIVISION TIMES
+0x22C8 &#x22C8; # BOWTIE
+0x22C9 &#x22C9; # LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+0x22CA &#x22CA; # RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+0x22CB &#x22CB; # LEFT SEMIDIRECT PRODUCT
+0x22CC &#x22CC; # RIGHT SEMIDIRECT PRODUCT
+0x22CD &#x22CD; # REVERSED TILDE EQUALS
+0x22CE &#x22CE; # CURLY LOGICAL OR
+0x22CF &#x22CF; # CURLY LOGICAL AND
+0x22D0 &#x22D0; # DOUBLE SUBSET
+0x22D1 &#x22D1; # DOUBLE SUPERSET
+0x22D2 &#x22D2; # DOUBLE INTERSECTION
+0x22D3 &#x22D3; # DOUBLE UNION
+0x22D4 &#x22D4; # PITCHFORK
+0x22D6 &#x22D6; # LESS-THAN WITH DOT
+0x22D7 &#x22D7; # GREATER-THAN WITH DOT
+0x22D8 &#x22D8; # VERY MUCH LESS-THAN
+0x22D9 &#x22D9; # VERY MUCH GREATER-THAN
+0x22DA &#x22DA; # LESS-THAN EQUAL TO OR GREATER-THAN
+0x22DB &#x22DB; # GREATER-THAN EQUAL TO OR LESS-THAN
+0x22DC &#x22DC; # EQUAL TO OR LESS-THAN
+0x22DD &#x22DD; # EQUAL TO OR GREATER-THAN
+0x22DE &#x22DE; # EQUAL TO OR PRECEDES
+0x22DF &#x22DF; # EQUAL TO OR SUCCEEDS
+0x22E0 &#x22E0; # DOES NOT PRECEDE OR EQUAL
+0x22E1 &#x22E1; # DOES NOT SUCCEED OR EQUAL
+0x22E6 &#x22E6; # LESS-THAN BUT NOT EQUIVALENT TO
+0x22E7 &#x22E7; # GREATER-THAN BUT NOT EQUIVALENT TO
+0x22E8 &#x22E8; # PRECEDES BUT NOT EQUIVALENT TO
+0x22E9 &#x22E9; # SUCCEEDS BUT NOT EQUIVALENT TO
+0x22EA &#x22EA; # NOT NORMAL SUBGROUP OF
+0x22EB &#x22EB; # DOES NOT CONTAIN AS NORMAL SUBGROUP
+0x22EC &#x22EC; # NOT NORMAL SUBGROUP OF OR EQUAL TO
+0x22ED &#x22ED; # DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
+0x22EE &#x22EE; # VERTICAL ELLIPSIS
+0x2306 &#x2306; # PERSPECTIVE
+0x2308 &#x2308; # LEFT CEILING
+0x2309 &#x2309; # RIGHT CEILING
+0x230A &#x230A; # LEFT FLOOR
+0x230B &#x230B; # RIGHT FLOOR
+0x230C &#x230C; # BOTTOM RIGHT CROP
+0x230D &#x230D; # BOTTOM LEFT CROP
+0x230E &#x230E; # TOP RIGHT CROP
+0x230F &#x230F; # TOP LEFT CROP
+0x2315 &#x2315; # TELEPHONE RECORDER
+0x2316 &#x2316; # POSITION INDICATOR
+0x231C &#x231C; # TOP LEFT CORNER
+0x231D &#x231D; # TOP RIGHT CORNER
+0x231E &#x231E; # BOTTOM LEFT CORNER
+0x231F &#x231F; # BOTTOM RIGHT CORNER
+0x2322 &#x2322; # FROWN
+0x2322 &#x2322; # FROWN
+0x2323 &#x2323; # SMILE
+0x2323 &#x2323; # SMILE
+0x2329 &#x2329; # LEFT-POINTING ANGLE BRACKET
+0x232A &#x232A; # RIGHT-POINTING ANGLE BRACKET
+0x2423 &#x2423; # OPEN BOX
+0x24C8 &#x24C8; # CIRCLED LATIN CAPITAL LETTER S
+0x2500 &#x2500; # BOX DRAWINGS LIGHT HORIZONTAL
+0x2502 &#x2502; # BOX DRAWINGS LIGHT VERTICAL
+0x250C &#x250C; # BOX DRAWINGS LIGHT DOWN AND RIGHT
+0x2510 &#x2510; # BOX DRAWINGS LIGHT DOWN AND LEFT
+0x2514 &#x2514; # BOX DRAWINGS LIGHT UP AND RIGHT
+0x2518 &#x2518; # BOX DRAWINGS LIGHT UP AND LEFT
+0x251C &#x251C; # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+0x2524 &#x2524; # BOX DRAWINGS LIGHT VERTICAL AND LEFT
+0x252C &#x252C; # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+0x2534 &#x2534; # BOX DRAWINGS LIGHT UP AND HORIZONTAL
+0x253C &#x253C; # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+0x2550 &#x2550; # BOX DRAWINGS DOUBLE HORIZONTAL
+0x2551 &#x2551; # BOX DRAWINGS DOUBLE VERTICAL
+0x2552 &#x2552; # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+0x2553 &#x2553; # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+0x2554 &#x2554; # BOX DRAWINGS DOUBLE DOWN AND RIGHT
+0x2555 &#x2555; # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+0x2556 &#x2556; # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+0x2557 &#x2557; # BOX DRAWINGS DOUBLE DOWN AND LEFT
+0x2558 &#x2558; # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+0x2559 &#x2559; # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+0x255A &#x255A; # BOX DRAWINGS DOUBLE UP AND RIGHT
+0x255B &#x255B; # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+0x255C &#x255C; # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+0x255D &#x255D; # BOX DRAWINGS DOUBLE UP AND LEFT
+0x255E &#x255E; # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+0x255F &#x255F; # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+0x2560 &#x2560; # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+0x2561 &#x2561; # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+0x2562 &#x2562; # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+0x2563 &#x2563; # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+0x2564 &#x2564; # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+0x2565 &#x2565; # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+0x2566 &#x2566; # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+0x2567 &#x2567; # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+0x2568 &#x2568; # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+0x2569 &#x2569; # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+0x256A &#x256A; # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+0x256B &#x256B; # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+0x256C &#x256C; # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+0x2580 &#x2580; # UPPER HALF BLOCK
+0x2584 &#x2584; # LOWER HALF BLOCK
+0x2588 &#x2588; # FULL BLOCK
+0x2591 &#x2591; # LIGHT SHADE
+0x2592 &#x2592; # MEDIUM SHADE
+0x2593 &#x2593; # DARK SHADE
+0x25A1 &#x25A1; # WHITE SQUARE
+0x25A1 &#x25A1; # WHITE SQUARE
+0x25AA &#x25AA; # BLACK SMALL SQUARE
+0x25AD &#x25AD; # WHITE RECTANGLE
+0x25AE &#x25AE; # BLACK VERTICAL RECTANGLE
+0x25B3 &#x25B3; # WHITE UP-POINTING TRIANGLE
+0x25B4 &#x25B4; # BLACK UP-POINTING SMALL TRIANGLE
+0x25B5 &#x25B5; # WHITE UP-POINTING SMALL TRIANGLE
+0x25B8 &#x25B8; # BLACK RIGHT-POINTING SMALL TRIANGLE
+0x25B9 &#x25B9; # WHITE RIGHT-POINTING SMALL TRIANGLE
+0x25BD &#x25BD; # WHITE DOWN-POINTING TRIANGLE
+0x25BE &#x25BE; # BLACK DOWN-POINTING SMALL TRIANGLE
+0x25BF &#x25BF; # WHITE DOWN-POINTING SMALL TRIANGLE
+0x25C2 &#x25C2; # BLACK LEFT-POINTING SMALL TRIANGLE
+0x25C3 &#x25C3; # WHITE LEFT-POINTING SMALL TRIANGLE
+0x25CA &#x25CA; # LOZENGE
+0x25CB &#x25CB; # WHITE CIRCLE
+0x25CB &#x25CB; # WHITE CIRCLE
+0x2605 &#x2605; # BLACK STAR
+0x2606 &#x2606; # WHITE STAR
+0x260E &#x260E; # BLACK TELEPHONE
+0x2640 &#x2640; # FEMALE SIGN
+0x2642 &#x2642; # MALE SIGN
+0x2660 &#x2660; # BLACK SPADE SUIT
+0x2663 &#x2663; # BLACK CLUB SUIT
+0x2665 &#x2665; # BLACK HEART SUIT
+0x2666 &#x2666; # BLACK DIAMOND SUIT
+0x266A &#x266A; # EIGHTH NOTE
+0x266D &#x266D; # MUSIC FLAT SIGN
+0x266E &#x266E; # MUSIC NATURAL SIGN
+0x266F &#x266F; # MUSIC SHARP SIGN
+0x2713 &#x2713; # CHECK MARK
+0x2717 &#x2717; # BALLOT X
+0x2720 &#x2720; # MALTESE CROSS
+0x2726 &#x2726; # BLACK FOUR POINTED STAR
+0x2727 &#x2727; # WHITE FOUR POINTED STAR
+0x2736 &#x2736; # SIX POINTED BLACK STAR
+0xFB00 &#xFB00; # LATIN SMALL LIGATURE FF
+0xFB01 &#xFB01; # LATIN SMALL LIGATURE FI
+0xFB02 &#xFB02; # LATIN SMALL LIGATURE FL
+0xFB03 &#xFB03; # LATIN SMALL LIGATURE FFI
+0xFB04 &#xFB04; # LATIN SMALL LIGATURE FFL
+
+
+</PRE>
+</BODY>
+</HTML>
diff --git a/gnu/usr.bin/lynx/userdefs.h b/gnu/usr.bin/lynx/userdefs.h
new file mode 100644
index 00000000000..a4c6d24696a
--- /dev/null
+++ b/gnu/usr.bin/lynx/userdefs.h
@@ -0,0 +1,1464 @@
+/*
+ * Lynx - Hypertext navigation system
+ *
+ * (c) Copyright 1992, 1993, 1994 University of Kansas
+ * 1995, 1996: GNU General Public License
+ */
+
+/*******************************************************************
+ * There are four sections to this document:
+ * Section 1. Things you MUST change or verify
+ * Section 1a) VMS specific things
+ * Section 1b) UNIX specific things
+ * Section 1c) ALL Platforms
+ *
+ * Section 2. Things you should probably check!
+ *
+ * Section 3. Things you should only change after you have a good
+ * understanding of the program!
+ *
+ * Section 4. Things you MUST check only if you plan to use Lynx in
+ * an anonymous account (allow public access to Lynx)!
+ *
+ */
+
+#ifndef USERDEFS_H
+#define USERDEFS_H
+
+#ifdef HAVE_CONFIG_H
+#include <lynx_cfg.h>
+#endif
+
+/*******************************************************************
+ * Things you must change
+ * Section 1.
+ */
+
+/*******************************************************************
+ * Things you must change VMS specific
+ * Section 1a).
+ */
+#ifdef VMS
+/**************************
+ * TEMP_SPACE is where Lynx temporary cache files will be placed.
+ * Temporary files are removed automatically as long as nothing
+ * goes terribly wrong :) If you include "$USER" in the definition
+ * (e.g., "device:[dir.$USER]"), Lynx will replace the "$USER" with
+ * the username of the account which invoked the Lynx image. Such
+ * directories should already exist, and have protections/ACLs set
+ * so that only the appropriate user(s) will have read/write access.
+ * On VMS, "sys$scratch:" defaults to "sys$login:" if it has not been
+ * defined externally, or you can use "sys$login:" explicitly here.
+ * If the path has SHELL syntax and includes a tilde (e.g, "~/lynxtmp"),
+ * Lynx will replace the tilde with the full path for the user's home
+ * and convert the result to VMS syntax.
+ * The definition here can be overridden at run time by defining a
+ * "LYNX_TEMP_SPACE" VMS logical.
+ */
+#define TEMP_SPACE "sys$scratch:"
+
+/**************************
+ * LYNX_CFG_FILE is the location and name of the default lynx
+ * global configuration file. It is sought and processed at
+ * startup of Lynx, followed by a seek and processing of a
+ * personal RC file (.lynxrc in the user's HOME directory,
+ * created if the user saves values in the 'o'ptions menu).
+ * You also can define the location and name of the global
+ * configuration file via a VMS logical, "LYNX_CFG", which
+ * will override the "LYNX_CFG_FILE" definition here. SYS$LOGIN:
+ * can be used as the device in either or both definitions if
+ * you want lynx.cfg treated as a personal configuration file.
+ * You also can use Unix syntax with a '~' for a subdirectory
+ * of the login directory, (e.g., ~/lynx/lynx.cfg).
+ * The -cfg command line switch will override these definitions.
+ * You can pass the compilation default via build.com or descrip.mms.
+ *
+ * Note that some implementations of telnet allow passing of
+ * environment variables, which might be used by unscrupulous
+ * people to modify the environment in anonymous accounts. When
+ * making Lynx and Web access publically available via anonymous
+ * accounts intended to run Lynx captively, be sure the wrapper
+ * uses the -cfg switch and specifies the startfile, rather than
+ * relying on the LYNX_CFG, LYNX_CFG_FILE, or WWW_HOME variables.
+ *
+ * Note that any SUFFIX or VIEWER mappings in the configuration
+ * file will be overidden by any suffix or viewer mappings
+ * that are established as defaults in src/HTInit.c. You can
+ * override the src/HTInit.c defaults via the mime.types and
+ * mailcap files (see the examples in the samples directory).
+ */
+#ifndef LYNX_CFG_FILE
+#define LYNX_CFG_FILE "Lynx_Dir:lynx.cfg"
+#endif /* LYNX_CFG_FILE */
+
+/**************************
+ * The EXTENSION_MAP file allows you to map file suffix's to
+ * mime types.
+ * These global and personal files override anything in
+ * lynx.cfg or src/HTInit.c
+ */
+#define GLOBAL_EXTENSION_MAP "Lynx_Dir:mime.types"
+#define PERSONAL_EXTENSION_MAP "mime.types"
+
+/**************************
+ * The MAILCAP file allows you to map file MIME types to
+ * external viewers.
+ * These global and personal files override anything in
+ * lynx.cfg or src/HTInit.c
+ */
+#define GLOBAL_MAILCAP "Lynx_Dir:mailcap"
+#define PERSONAL_MAILCAP ".mailcap"
+
+/**************************
+ * XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c
+ * for viewing image content types when the DECW$DISPLAY logical
+ * is set. Make it the foreign command for your system's X image
+ * viewer (commonly, "xv"). Make it "exit" or something like that
+ * if you don't have one. It can be anything that will handle GIF,
+ * TIFF and other popular image formats. Freeware ports of xv for
+ * VMS are available in the ftp://ftp.wku.edu/vms/unsupported and
+ * http://www.openvms.digital.com/cd/XV310A/ subdirectories. You
+ * must also have a "%s" for the filename. The default defined
+ * here can be overridden in lynx.cfg, or via the global or personal
+ * mailcap files.
+ */
+#define XLOADIMAGE_COMMAND "xv %s"
+
+/**************************
+ * SYSTEM_MAIL must be defined here to your mail sending command,
+ * and SYSTEM_MAIL_FLAGS to approrpriate qualifiers. They can be
+ * changed in lynx.cfg.
+ *
+ * The mail command will be spawned as a subprocess of lynx
+ * and used to send the email, with headers specified in a
+ * temporary file for PMDF. If you define SYSTEM_MAIL to the
+ * "generic" MAIL utility for VMS, headers cannot be specified
+ * via a header file (and thus may not be included), and the
+ * subject line will be specified by use of the /subject="SUBJECT"
+ * qualifier.
+ *
+ * If your mailer uses another syntax, some hacking of the
+ * mailform(), mailmsg() and reply_by_mail() functions in
+ * LYMail.c, and printfile() function in LYPrint.c, may be
+ * required.
+ */
+#define SYSTEM_MAIL "PMDF SEND"
+#define SYSTEM_MAIL_FLAGS "/headers"
+/* #define SYSTEM_MAIL "MAIL" */
+/* #define SYSTEM_MAIL_FLAGS "" */
+
+/*************************
+ * Below is the argument for an sprintf command that will add
+ * "IN%""ADDRESS""" to the Internet mail address given by the user.
+ * It is structured for PMDF's IN%"INTERNET_ADDRESS" scheme. The %s
+ * is replaced with the address given by the user. If you are using
+ * a different Internet mail transport, change the IN appropriately
+ * (e.g., to SMTP, MX, or WINS), here or in lynx.cfg.
+ */
+#define MAIL_ADRS "\"IN%%\"\"%s\"\"\""
+
+/*********************************
+ * On VMS, CSwing (an XTree emulation for VTxxx terminals) is intended for
+ * use as the Directory/File Manager (sources, objects, or executables are
+ * available from ftp://narnia.memst.edu/). CSWING_PATH should be defined
+ * here or in lynx.cfg to your foreign command for CSwing, with any
+ * regulatory switches you want included. If not defined, or defined as
+ * a zero-length string ("") or "none" (case-insensitive), the support
+ * will be disabled. It will also be disabled if the -nobrowse or
+ * -selective switches are used, or if the file_url restriction is set.
+ *
+ * When enabled, the DIRED_MENU command (normally 'f' or 'F') will invoke
+ * CSwing, normally with the current default directory as an argument to
+ * position the user on that node of the directory tree. However, if the
+ * current document is a local directory listing, or a local file and not
+ * one of the temporary menu or list files, the associated directory will
+ * be passed as an argument, to position the user on that node of the tree.
+ */
+/* #define CSWING_PATH "swing" */
+
+/*********************************
+ * If USE_FIXED_RECORDS is set to TRUE here and/or in lynx.cfg, Lynx will
+ * convert 'd'ownloaded binary files to FIXED 512 record format before saving
+ * them to disk or acting on a DOWNLOADER option. If set to FALSE, the
+ * headers of such files will indicate that they are Stream_LF with Implied
+ * Carriage Control, which is incorrect, and can cause downloading software
+ * to get confused and unhappy. If you do set it FALSE, you can use the
+ * FIXED512.COM command file, which is included in this distribution, to do
+ * the conversion externally.
+ */
+#define USE_FIXED_RECORDS TRUE /* convert binaries to FIXED 512 */
+
+/********************************
+ * If NO_ANONYMOUS_EMAIL is defined, Lynx will not offer to insert X-From
+ * and X_Personal_Name lines in the body of email messages. On VMS, the
+ * actual From and Personal Name (if defined for the account) headers always
+ * are those of the account running the Lynx image. If the account is not
+ * the one to which the recipient should reply, you can indicate the alternate
+ * address and personal name via the X-From and X_Personal_Name entries, but
+ * the recipient must explicitly send the reply to the X_From address, rather
+ * than using the VMS REPLY command (which will use the actual From address).
+ *
+ * This symbol constant might be defined on Unix for security reasons that
+ * don't apply on VMS. There is no security reason for defining this on VMS,
+ * but if you have no anonymous accounts (i.e., the From always will point to
+ * the actual user's email address, you can define it to avoid the bother of
+ * X-From and X_Personal_Name offers.
+ */
+/*#define NO_ANONYMOUS_EMAIL TRUE */
+
+/**************************
+ * LYNX_LSS_FILE is the location and name of the default lynx
+ * character style sheet file. It is sought and processed at
+ * startup of Lynx only if experimental character style code has
+ * been compiled in, otherwise it will be ignored. Note that use
+ * of the character style option is _experimental_ AND _unsupported_.
+ * There is no documentation other than a sample lynx.lss file in
+ * the samples subdirectory. This code probably won't even work on
+ * VMS. You can define the location and name of this file via an
+ * environment variable, "lynx_lss", which will override the definition
+ * here. You can use '~' to refer to the user's home directory. The
+ * -lss command line switch will override these definitions.
+ */
+#ifndef LYNX_LSS_FILE
+#define LYNX_LSS_FILE "Lynx_Dir:lynx.lss"
+#endif /* LYNX_LSS_FILE */
+
+/*******************************************************************
+ * Things you must change UNIX specific
+ * Section 1b).
+ */
+#else /* UNIX */
+
+/**************************
+ * NOTE: This variable is set by the configure scrip; editing changes will
+ * be ignored.
+ *
+ * LYNX_CFG_FILE is the location and name of the default lynx
+ * global configuration file. It is sought and processed at
+ * startup of Lynx, followed by a seek and processing of a
+ * personal RC file (.lynxrc in the user's HOME directory,
+ * created if the user saves values in the 'o'ptions menu).
+ * You also can define the location and name of the global
+ * configuration file via an environment variable, "LYNX_CFG",
+ * which will override the "LYNX_CFG_FILE" definition here.
+ * You can use '~' in either or both definitions if you want
+ * lynx.cfg treated as a personal configuration file. The
+ * -cfg command line switch will override these definitions.
+ * You can pass the compilation default via the Makefile.
+ *
+ * If you are building Lynx using the configure script, you should specify
+ * the default location of the configuration file via that script, since it
+ * also generates the makefile and install-cfg rules.
+ *
+ * Note that many implementations of telnetd allow passing of
+ * environment variables, which might be used by unscrupulous
+ * people to modify the environment in anonymous accounts. When
+ * making Lynx and Web access publically available via anonymous
+ * accounts intended to run Lynx captively, be sure the wrapper
+ * uses the -cfg switch and specifies the startfile, rather than
+ * relying on the LYNX_CFG, LYNX_CFG_FILE, or WWW_HOME variables.
+ *
+ * Note that any SUFFIX or VIEWER mappings in the configuration
+ * file will be overidden by any suffix or viewer mappings
+ * that are established as defaults in src/HTInit.c. You can
+ * override the src/HTInit.c defaults via the mime.types and
+ * mailcap files (see the examples in the samples directory).
+ */
+#ifndef HAVE_CONFIG_H
+#ifndef LYNX_CFG_FILE
+#ifdef DOSPATH
+#define LYNX_CFG_FILE "./lynx.cfg"
+#else
+#define LYNX_CFG_FILE "/usr/local/lib/lynx.cfg"
+#endif /* DOSPATH */
+#endif /* LYNX_CFG_FILE */
+#endif /* HAVE_CONFIG_H */
+
+/**************************
+ * The EXTENSION_MAP file allows you to map file suffix's to
+ * mime types.
+ * These global and personal files override anything in
+ * lynx.cfg or src/HTInit.c
+ */
+#define GLOBAL_EXTENSION_MAP "/usr/local/lib/mosaic/mime.types"
+#define PERSONAL_EXTENSION_MAP ".mime.types"
+
+/**************************
+ * The MAILCAP file allows you to map file MIME types to
+ * external viewers.
+ * These global and personal files override anything in
+ * lynx.cfg or src/HTInit.c
+ */
+#define GLOBAL_MAILCAP "/usr/local/lib/mosaic/mailcap"
+#define PERSONAL_MAILCAP ".mailcap"
+
+/**************************
+ * the full path and name of the telnet command
+ */
+#define TELNET_COMMAND "telnet"
+
+/**************************
+ * the full path and name of the tn3270 command
+ */
+#define TN3270_COMMAND "tn3270"
+
+/**************************
+ * the full path and name of the rlogin command
+ */
+#define RLOGIN_COMMAND "rlogin"
+
+/**************************
+ * XLOADIMAGE_COMMAND will be used as a default in src/HTInit.c for
+ * viewing image content types when the DISPLAY environment variable
+ * is set. Make it the full path and name of the xli (also known as
+ * xloadimage or xview) command, or other image viewer. Put 'echo' or
+ * something like it here if you don't have a suitable viewer. It can
+ * be anything that will handle GIF, TIFF and other popular image formats
+ * (xli does). The freeware distribution of xli is available in the
+ * ftp://ftp.x.org/contrib/ subdirectory. The shareware, xv, also is
+ * suitable. You must also have a "%s" for the filename; "&" for
+ * background is optional. The default defined here can be overridden
+ * in lynx.cfg, or via the global or personal mailcap files. Note that
+ * open is used as the default for NeXT, instead of the XLOADIMAGE_COMMAND
+ * definition.
+ */
+#define XLOADIMAGE_COMMAND "xli %s &"
+
+/**************************
+ * For UNIX systems this should be sendmail
+ * sendmail should be in /usr/lib
+ *
+ * You definitely want sendmail, not mail or elm or something else,
+ * except in the case where MMDF is your mail agent.
+ * For MMDF you should use submit (SCO)
+ *
+ * SYSTEM_MAIL must be defined here. You can change it in lynx.cfg.
+ *
+ * SYSTEM_MAIL_FLAGS must be defined here appropriately for your
+ * SYSTEM_MAIL definition. You can change it in lynx.cfg.
+ */
+#ifndef HAVE_CONFIG_H
+#ifdef MMDF
+#define SYSTEM_MAIL "/usr/mmdf/bin/submit"
+#define SYSTEM_MAIL_FLAGS "-mlruxto,cc\\*"
+#else
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__bsdi__)
+#define SYSTEM_MAIL "/usr/sbin/sendmail"
+#define SYSTEM_MAIL_FLAGS "-t -oi"
+#else /* everything else: */
+#define SYSTEM_MAIL "/usr/lib/sendmail"
+#define SYSTEM_MAIL_FLAGS "-t -oi"
+#endif /* __FreeBSD || __NetBSD__ || __bsdi__ */
+#endif /* MMDF */
+#endif /* !HAVE_CONFIG_H */
+
+/**************************
+ * A place to put temporary files, it's almost always in "/tmp/"
+ * for UNIX systems. If you include "$USER" in the definition
+ * (e.g., "/tmp/$USER"), Lynx will replace the "$USER" with the
+ * username of the account which invoked the Lynx image. Such
+ * directories should already exist, and have protections/ACLs set
+ * so that only the appropriate user(s) will have read/write access.
+ * If the path includes a tilde (e.g, "~" or "~/lynxtmp"), Lynx will
+ * replace the tilde with the full path for the user's home.
+ * The definition here can be overridden at run time by setting a
+ * "LYNX_TEMP_SPACE" environment symbol.
+ */
+#define TEMP_SPACE "/tmp/"
+
+/********************************
+ * Don't let the user enter his/her email address when sending a message.
+ * Anonymous mail makes it far too easy for a user to spoof someone else's
+ * email address.
+ * This requires that your mailer agent put in the From: field for you.
+ *
+ * The default should be to uncomment this line but there probably are too
+ * many mail agents out there that won't do the right thing if there is no
+ * From: line.
+ */
+/* #define NO_ANONYMOUS_EMAIL TRUE */
+
+/********************************
+ * LIST_FORMAT defines the display for local files when LONG_LIST
+ * is defined in the Makefile. The default set here can be changed
+ * in lynx.cfg.
+ *
+ * The percent items in the list are interpreted as follows:
+ *
+ * %p Unix-style permission bits
+ * %l link count
+ * %o owner of file
+ * %g group of file
+ * %d date of last modification
+ * %a anchor pointing to file or directory
+ * %A as above but don't show symbolic links
+ * %k size of file in Kilobytes
+ * %K as above but omit size for directories
+ * %s size of file in bytes
+ *
+ * Anything between the percent and the letter is passed on to sprintf.
+ * A double percent yields a literal percent on output. Other characters
+ * are passed through literally.
+ *
+ * If you want only the filename: " %a"
+ *
+ * If you want a brief output: " %4K %-12.12d %a"
+ *
+ * For the Unix "ls -l" format: " %p %4l %-8.8o %-8.8g %7s %-12.12d %a"
+ */
+#define LIST_FORMAT " %p %4l %-8.8o %-8.8g %7s %-12.12d %a"
+
+/*
+ * If NO_FORCED_CORE_DUMP is set to TRUE, Lynx will not force
+ * core dumps via abort() calls on fatal errors or assert()
+ * calls to check potentially fatal errors. The default defined
+ * here can be changed in lynx.cfg, and the compilation or
+ * configuration default can be toggled via the -core command
+ * line switch.
+ */
+#define NO_FORCED_CORE_DUMP FALSE
+
+/**************************
+ * LYNX_LSS_FILE is the location and name of the default lynx
+ * character style sheet file. It is sought and processed at
+ * startup of Lynx only if experimental character style code
+ * has been compiled in, otherwise it will be ignored. Note
+ * that use of the character style option is _experimental_ AND
+ * _unsupported_. There is no documentation other than a sample
+ * lynx.lss file in the samples subdirectory. You also can
+ * define the location and name of this file via environment
+ * variables "LYNX_LSS" or "lynx_lss" which will override the
+ * "LYNX_LSS_FILE" definition here. You can use '~' in either or
+ * both definitions to refer to the user's home directory. The
+ * -lss command line switch will override these definitions.
+ */
+#ifndef LYNX_LSS_FILE
+#define LYNX_LSS_FILE "/usr/local/lib/lynx.lss"
+#endif /* LYNX_LSS_FILE */
+
+#endif /* VMS OR UNIX */
+
+/*************************************************************
+ * Section 1c) Every platform must change or verify these
+ *
+ */
+
+/*****************************
+ * STARTFILE is the default file if none is specified in lynx.cfg,
+ * on the command line, or via a WWW_HOME environment variable.
+ *
+ * note: STARTFILE must be a URL. See the Lynx online help for more
+ * information on URLs
+ */
+#define STARTFILE "http://lynx.browser.org/"
+
+/*****************************
+ * HELPFILE must be defined as a URL and must have a
+ * complete path if local:
+ * file://localhost/PATH_TO/lynx_help/lynx_help_main.html
+ * Replace PATH_TO with the path to the lynx_help subdirectory
+ * for this distribution (use SHELL syntax including the device
+ * on VMS systems).
+ * The default HELPFILE is:
+ * http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html
+ * This should be changed here or in lynx.cfg to the local path.
+ */
+#define HELPFILE "http://www.crl.com/~subir/lynx/lynx_help/lynx_help_main.html"
+/* #define HELPFILE "file://localhost/PATH_TO/lynx_help/lynx_help_main.html" */
+
+/*****************************
+ * DEFAULT_INDEX_FILE is the default file retrieved when the
+ * user presses the 'I' key when viewing any document.
+ * An index to your CWIS can be placed here or a document containing
+ * pointers to lots of interesting places on the web.
+ */
+#define DEFAULT_INDEX_FILE "http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/MetaIndex.html"
+
+/*****************************
+ * If USE_TRACE_LOG is set FALSE, then when TRACE mode is invoked the
+ * syserr messages will not be directed to a log file named lynx.trace
+ * in the account's HOME directory. The default defined here can be
+ * toggled via the -tlog command line switch. Also, it is set FALSE
+ * automatically when Lynx is executed in an anonymous or validation
+ * account (if indicated via the -anonymous or -validate command line
+ * switches, or via the check for the ANONYMOUS_USER, defined below).
+ * When FALSE, the TRACE_LOG command (normally ';') cannot be used to
+ * examine the Lynx Trace Log during the current session. If left
+ * TRUE, but you wish to use command line piping of stderr to a file
+ * you specify, include the -tlog toggle on the command line. Note
+ * that once TRACE mode is turned on during a session and stderr is
+ * directed to the log, all stderr messages will continue going to
+ * the log, even if TRACE mode is turned off via the TOGGLE_TRACE
+ * (Control-T) command.
+ */
+#define USE_TRACE_LOG FALSE
+
+/*******************************
+ * If GOTOBUFFER is set to TRUE here or in lynx.cfg the last entered
+ * goto URL, if any, will be offered as a default for reuse or editing
+ * when the 'g'oto command is entered. All previously used goto URLs
+ * can be accessed for reuse or editing via a circular buffer invoked
+ * with the Up-Arrow or Down-Arrow keys after entering the 'g'oto
+ * command, whether or not a default is offered.
+ */
+#define GOTOBUFFER FALSE
+
+/*****************************
+ * JUMPFILE is the default local file checked for shortcut URLs when
+ * the user presses the 'J' (JUMP) key. The user will be prompted for
+ * a shortcut entry (analogously to 'g'oto), and can enter one
+ * or use '?' for a list of the shortcuts with associated links to
+ * their actual URLs. See the sample jumps files in the samples
+ * subdirectory. Make sure your jumps file includes a '?' shortcut
+ * for a file://localhost URL to itself:
+ *
+ * <dt>?<dd><a href="file://localhost/path/jumps.html">This Shortcut List</a>
+ *
+ * If not defined here or in lynx.cfg, the JUMP command will invoke
+ * the NO_JUMPFILE statusline message (see LYMessages_en.h). The prompt
+ * associated with the default jumps file is defined as JUMP_PROMPT in
+ * LYMessages_en.h and can be modified in lynx.cfg. Additional, alternate
+ * jumps files can be defined and mapped to keystrokes, and alternate
+ * prompts can be set for them, in lynx.cfg, but at least one default
+ * jumps file and associated prompt should be established before adding
+ * others.
+ *
+ * On VMS, use Unix SHELL syntax (including a lead slash) to define it.
+ *
+ * Do not include "file://localhost" in the definition.
+ */
+/* #define JUMPFILE "/Lynx_Dir/jumps.html" */
+
+/*******************************
+ * If JUMPBUFFER is set to TRUE here or in lynx.cfg the last entered
+ * jump shortcut, if any, will be offered as a default for reuse or
+ * editing when the JUMP command is entered. All previously used
+ * shortcuts can be accessed for reuse or editing via a circular buffer
+ * invoked with the Up-Arrow or Down-Arrow keys after entering the JUMP
+ * command, whether or not a default is offered. If you have multiple
+ * jumps files and corresponding key mappings, each will have its own
+ * circular buffer.
+ */
+#define JUMPBUFFER FALSE
+
+/********************************
+ * If PERMIT_GOTO_FROM_JUMP is defined, then a : or / in a jump target
+ * will be treated as a full or partial URL (to be resolved versus the
+ * startfile), and will be handled analogously to a 'g'oto command.
+ * Such "random URLs" will be entered in the circular buffer for goto
+ * URLs, not the buffer for jump targets (shortcuts). If the target
+ * is the single character ':', it will be treated equivalently to an
+ * Up-Arrow or Down-Arrow following a 'g'oto command, for accessing the
+ * circular buffer of goto URLs.
+ */
+/* #define PERMIT_GOTO_FROM_JUMP */
+
+/*****************************
+ * If LYNX_HOST_NAME is defined here and/or in lynx.cfg, it will be
+ * treated as an alias for the local host name in checks for URLs on
+ * the local host (e.g., when the -localhost switch is set), and this
+ * host name, "localhost", and HTHostName (the fully qualified domain
+ * name of the system on which Lynx is running) will all be passed as
+ * local. A different definition in lynx.cfg will override this one.
+ */
+/* #define LYNX_HOST_NAME "www.cc.ukans.edu" */
+
+/*********************
+ * LOCAL_DOMAIN is used for a tail match with the ut_host element of
+ * the utmp or utmpx structure on systems with utmp capabilites, to
+ * determine if a user is local to your campus or organization when
+ * handling -restrictions=inside_foo or outside_foo settings for ftp,
+ * news, telnet/tn3270 and rlogin URLs. An "inside" user is assumed
+ * if your system does not have utmp capabilities. CHANGE THIS here
+ * or in lynx.cfg.
+ */
+#define LOCAL_DOMAIN "ukans.edu"
+
+/********************************
+* The DEFAULT_CACHE_SIZE specifies the number of WWW documents to be
+* cached in memory at one time.
+*
+* This so-called cache size (actually, number) may be modified in lynx.cfg
+* and or with the command line argument -cache=NUMBER The minimum allowed
+* value is 2, for the current document and at least one to fetch, and there
+* is no absolute maximum number of cached documents. On Unix, and VMS not
+* compiled with VAXC, whenever the number is exceeded the least recently
+* displayed document will be removed from memory.
+*
+* On VMS compiled with VAXC, the DEFAULT_VIRTUAL_MEMORY_SIZE specifies the
+* amount (bytes) of virtual memory that can be allocated and not yet be freed
+* before previous documents are removed from memory. If the values for both
+* the DEFAULT_CACHE_SIZE and DEFAULT_VIRTUAL_MEMORY_SIZE are exceeded, then
+* least recently displayed documents will be freed until one or the other
+* value is no longer exceeded. The value can be modified in lynx.cfg.
+*
+* The Unix and VMS but not VAXC implementations use the C library malloc's
+* and calloc's for memory allocation, and procedures for taking the actual
+* amount of cache into account still need to be developed. They use only
+* the DEFAULT_CACHE_SIZE value, and that specifies the absolute maximum
+* number of documents to cache (rather than the maximum number only if
+* DEFAULT_VIRTUAL_MEMORY_SIZE has been exceeded, as with VAXC/VAX).
+*/
+#define DEFAULT_CACHE_SIZE 10
+
+#if defined(VMS) && defined(VAXC) && !defined(__DECC)
+#define DEFAULT_VIRTUAL_MEMORY_SIZE 512000
+#endif /* VMS && VAXC && !__DECC */
+
+/********************************
+ * If ALWAYS_RESUBMIT_POSTS is set TRUE, Lynx always will resubmit forms
+ * with method POST, dumping any cache from a previous submission of the
+ * form, including when the document returned by that form is sought with
+ * the PREV_DOC command or via the history list. Lynx always resubmits
+ * forms with method POST when a submit button or a submitting text input
+ * is activated, but normally retrieves the previously returned document
+ * if it had links which you activated, and then go back with the PREV_DOC
+ * command or via the history list.
+ *
+ * The default defined here can be changed in lynx.cfg, and can be toggled
+ * via the -resubmit_posts command line switch.
+ */
+#define ALWAYS_RESUBMIT_POSTS FALSE
+
+/********************************
+ * CHARACTER_SET defines the default character set, i.e., that assumed
+ * to be installed on the user's termimal. It determines which characters
+ * or strings will be used to represent 8-bit character entities within
+ * HTML. New character sets may be defined as explained in the README
+ * files of the src/chrtrans directory in the Lynx source code distribution.
+ * For Asian (CJK) character sets, it also determines how Kanji code will
+ * be handled. The default defined here can be changed in lynx.cfg, and
+ * via the 'o'ptions menu. The 'o'ptions menu setting will be stored in
+ * the user's RC file whenever those settings are saved, and thereafter
+ * will be used as the default. Also see lynx.cfg for information about
+ * the -raw switch and LYE_RAW_TOGGLE command.
+ *
+ * The default character sets include:
+ *
+ * Display Character Set name MIME name
+ * ========================== =========
+ * 7 bit approximations us-ascii
+ * Chinese euc-cn
+ * DEC Multinational dec-mcs
+ * DosArabic (cp864) cp864
+ * DosBaltRim (cp775) cp775
+ * DosCyrillic (cp866) cp866
+ * DosGreek (cp737) cp737
+ * DosGreek2 (cp869) cp869
+ * DosHebrew (cp862) cp862
+ * DosLatin1 (cp850) cp850
+ * DosLatin2 (cp852) cp852
+ * DosLatinUS (cp437) cp437
+ * ISO 8859-10 iso-8859-10
+ * ISO 8859-5 Cyrillic iso-8859-5
+ * ISO 8859-6 Arabic iso-8859-6
+ * ISO 8859-7 Greek iso-8859-7
+ * ISO 8859-8 Hebrew iso-8859-8
+ * ISO 8859-9 (Latin 5) iso-8859-9
+ * ISO Latin 1 iso-8859-1
+ * ISO Latin 2 iso-8859-2
+ * ISO Latin 3 iso-8859-3
+ * ISO Latin 4 iso-8859-4
+ * Japanese (EUC) euc-jp
+ * Japanese (SJIS) shift_jis
+ * KOI8-R Cyrillic koi8-r
+ * Korean euc-kr
+ * Macintosh (8 bit) macintosh
+ * NeXT character set next
+ * RFC 1345 Mnemonic mnemonic
+ * RFC 1345 w/o Intro mnemonic+ascii+0
+ * Taipei (Big5) big5
+ * Transparent x-transparent
+ * UNICODE UTF-8 utf-8
+ * Vietnamese (VISCII) viscii
+ * WinArabic (cp1256) windows-1256
+ * WinBaltRim (cp1257) windows-1257
+ * WinCyrillic (cp1251) windows-1251
+ * WinGreek (cp1253) windows-1253
+ * WinHebrew (cp1255) windows-1255
+ * WinLatin1 (cp1252) windows-1252
+ * WinLatin2 (cp1250) windows-1250
+ */
+#define CHARACTER_SET "ISO Latin 1"
+
+/*****************************
+ * PREFERRED_LANGUAGE is the language in MIME notation (e.g., "en",
+ * "fr") which will be indicated by Lynx in its Accept-Language headers
+ * as the preferred language. If available, the document will be
+ * transmitted in that language. This definition can be overriden via
+ * lynx.cfg. Users also can change it via the 'o'ptions menu and save
+ * that preference in their RC file. This may be a comma-separated list
+ * of languages in decreasing preference.
+ */
+#define PREFERRED_LANGUAGE "en"
+
+/*****************************
+ * PREFERRED_CHARSET specifies the character set in MIME notation (e.g.,
+ * "ISO-8859-2", "ISO-8859-5") which Lynx will indicate you prefer in
+ * requests to http servers using an Accept-Charsets header.
+ * This definition can be overriden via lynx.cfg. Users also can change it
+ * via the 'o'ptions menu and save that preference in their RC file.
+ * The value should NOT include "ISO-8859-1" or "US-ASCII", since those
+ * values are always assumed by default.
+ * If a file in that character set is available, the server will send it.
+ * If no Accept-Charset header is present, the default is that any
+ * character set is acceptable. If an Accept-Charset header is present,
+ * and if the server cannot send a response which is acceptable
+ * according to the Accept-Charset header, then the server SHOULD send
+ * an error response with the 406 (not acceptable) status code, though
+ * the sending of an unacceptable response is also allowed. (RFC2068)
+ */
+#define PREFERRED_CHARSET ""
+
+/*****************************
+* If MULTI_BOOKMARK_SUPPORT is set TRUE, and BLOCK_MULTI_BOOKMARKS (see
+* below) is FALSE, and sub-bookmarks exist, all bookmark operations will
+* first prompt the user to select an active sub-bookmark file or the
+* default bookmark file. FALSE is the default so that one (the default)
+* bookmark file will be available initially. The default set here can
+* be overridden in lynx.cfg. The user can turn on multiple bookmark
+* support via the 'o'ptions menu, and can save that choice as the startup
+* default via the .lynxrc file. When on, the setting can be STANDARD or
+* ADVANCED. If support is set to the latter, and the user mode also is
+* ADVANCED, the VIEW_BOOKMARK command will invoke a statusline prompt at
+* which the user can enter the letter token (A - Z) of the desired bookmark,
+* or '=' to get a menu of available bookmark files. The menu always is
+* presented in NOVICE or INTERMEDIATE mode, or if the support is set to
+* STANDARD. No prompting or menu display occurs if only one (the startup
+* default) bookmark file has been defined (define additional ones via the
+* 'o'ptions menu). The startup default, however set, can be overridden on
+* the command line via the -restrictions=multibook or the -anonymous or
+* -validate switches.
+*/
+#ifndef MULTI_BOOKMARK_SUPPORT
+#define MULTI_BOOKMARK_SUPPORT FALSE
+#endif /* MULTI_BOOKMARK_SUPPORT */
+
+/*****************************
+* If BLOCK_MULTI_BOOKMARKS is set TRUE, multiple bookmark support will
+* be forced off, and cannot be toggled on via the 'o'ptions menu. This
+* compilation setting can be overridden via lynx.cfg.
+*/
+#ifndef BLOCK_MULTI_BOOKMARKS
+#define BLOCK_MULTI_BOOKMARKS FALSE
+#endif /* BLOCK_MULTI_BOOKMARKS */
+
+/********************************
+ * URL_DOMAIN_PREFIXES and URL_DOMAIN_SUFFIXES are strings which will be
+ * prepended (together with a scheme://) and appended to the first element
+ * of command line or 'g'oto arguments which are not complete URLs and
+ * cannot be opened as a local file (file://localhost/string). Both
+ * can be comma-separated lists. Each prefix must end with a dot, each
+ * suffix must begin with a dot, and either may contain other dots (e.g.,
+ * .com.jp). The default lists are defined here, and can be changed
+ * in lynx.cfg. Each prefix will be used with each suffix, in order,
+ * until a valid Internet host is created, based on a successful DNS
+ * lookup (e.g., foo will be tested as www.foo.com and then www.foo.edu
+ * etc.). The first element can include a :port and/or /path which will
+ * be restored with the expanded host (e.g., wfbr:8002/dir/lynx will
+ * become http://www.wfbr.edu:8002/dir/lynx). The prefixes will not be
+ * used if the first element ends in a dot (or has a dot before the
+ * :port or /path), and similarly the suffixes will not be used if the
+ * the first element begins with a dot (e.g., .nyu.edu will become
+ * http://www.nyu.edu without testing www.nyu.com). Lynx will try to
+ * guess the scheme based on the first field of the expanded host name,
+ * and use "http://" as the default (e.g., gopher.wfbr.edu or gopher.wfbr.
+ * will be made gopher://gopher.wfbr.edu).
+ */
+#define URL_DOMAIN_PREFIXES "www."
+#define URL_DOMAIN_SUFFIXES ".com,.edu,.net,.org"
+
+/********************************
+ * If LIST_NEWS_NUMBERS is set TRUE, Lynx will use an ordered list
+ * and include the numbers of articles in news listings, instead of
+ * using an unordered list.
+ *
+ * The default defined here can be changed in lynx.cfg.
+ */
+#define LIST_NEWS_NUMBERS FALSE
+
+/********************************
+ * If LIST_NEWS_DATES is set TRUE, Lynx will include the dates of
+ * articles in news listings. The dates always are included in the
+ * articles, themselves.
+ *
+ * The default defined here can be changed in lynx.cfg.
+ */
+#define LIST_NEWS_DATES FALSE
+
+/*************************
+ * Set NEWS_POSTING to FALSE if you do not want to support posting to
+ * news groups via Lynx. If left TRUE, Lynx will use its news gateway to
+ * post new messages or followups to news groups, using the URL schemes
+ * described in the "Supported URL" section of the online 'h'elp. The
+ * posts will be attempted via the nntp server specified in the URL, or
+ * if none was specified, via the NNTPSERVER configuration or environment
+ * variable. Links with these URLs for posting or sending followups are
+ * created by the news gateway when reading group listings or articles
+ * from nntp servers if the server indicates that it permits posting.
+ * The setting here can be changed in lynx.cfg.
+ */
+#define NEWS_POSTING TRUE
+
+/*************************
+ * Define LYNX_SIG_FILE to the name of a file containing a signature which
+ * can be appended to email messages and news postings or followups. The
+ * user will be prompted whether to append it. It is sought in the home
+ * directory. If it is in a subdirectory, begin it with a dot-slash
+ * (e.g., ./lynx/.lynxsig). The definition here can be changed in lynx.cfg.
+ */
+#define LYNX_SIG_FILE ".lynxsig"
+
+/********************************
+ * If USE_SELECT_POPUPS is set FALSE, Lynx will present a vertical list
+ * of radio buttons for the OPTIONs in SELECT blocks which lack the
+ * MULTIPLE attribute, instead of using a popup menu. Note that if
+ * the MULTIPLE attribute is present in the SELECT start tag, Lynx
+ * always will create a vertical list of checkboxes for the OPTIONs.
+ *
+ * The default defined here can be changed in lynx.cfg. It can be
+ * set and saved via the 'o'ptions menu to override the compilation
+ * and configuration defaults, and the default always can be toggled
+ * via the -popup command line switch.
+ */
+#define USE_SELECT_POPUPS TRUE
+
+/********************************
+ * If COLLAPSE_BR_TAGS is set FALSE, Lynx will not collapse serial
+ * BR tags. Note that the valid way to insert extra blank lines in
+ * HTML is via a PRE block with only newlines in the block.
+ *
+ * The default defined here can be changed in lynx.cfg.
+ */
+#define COLLAPSE_BR_TAGS TRUE
+
+/********************************
+ * If SET_COOKIES is set FALSE, Lynx will ignore Set-Cookie headers
+ * in http server replies.
+ *
+ * The default defined here can be changed in lynx.cfg, and can be toggled
+ * via the -cookies command line switch.
+ */
+#define SET_COOKIES TRUE
+
+
+/****************************************************************
+ * Section 2. Things that you probably want to change or review
+ *
+ */
+
+/*****************************
+ * The following three definitions set the number of seconds for
+ * pauses following statusline messages that would otherwise be
+ * replaced immediately, and are more important than the unpaused
+ * progress messages. Those set by INFOSECS are also basically
+ * progress messages (e.g., that a prompted input has been cancelled)
+ * and should have the shortest pause. Those set by MESSAGESECS are
+ * informational (e.g., that a function is disabled) and should have
+ * a pause of intermediate duration. Those set by ALERTSECS typically
+ * report a serious problem and should be paused long enough to read
+ * whenever they appear (typically unexpectedly). The default values
+ * defined here can be modified via lynx.cfg, should longer pauses be
+ * desired for braille-based access to Lynx.
+ */
+#define INFOSECS 1
+#define MESSAGESECS 2
+#define ALERTSECS 3
+
+/******************************
+ * SHOW_COLOR controls whether the program displays in color by default.
+ */
+#ifdef COLOR_CURSES
+#define SHOW_COLOR TRUE
+#else
+#define SHOW_COLOR FALSE
+#endif
+
+/******************************
+ * SHOW_CURSOR controls whether or not the cursor is hidden or appears
+ * over the current link, or current option in select popup windows.
+ * Showing the cursor is handy if you are a sighted user with a poor
+ * terminal that can't do bold and reverse video at the same time or
+ * at all. It also can be useful to blind users, as an alternative
+ * or supplement to setting LINKS_AND_FORM_FIELDS_ARE_NUMBERED or
+ * LINKS_ARE_NUMBERED.
+ *
+ * The default defined here can be changed in lynx.cfg. It can be
+ * set and saved via the 'o'ptions menu to override the compilation
+ * and configuration defaults, and the default always can be toggled
+ * via the -show_cursor command line switch.
+ */
+#define SHOW_CURSOR FALSE
+
+/******************************
+ * BOXVERT and BOXHORI control the layout of popup menus. Set to 0 if your
+ * curses supports line-drawing characters, set to '*' or any other character
+ * to not use line-drawing (e.g., '|' for vertical and '-' for horizontal).
+ */
+#ifndef HAVE_CONFIG_H
+#ifdef DOSPATH
+#define BOXVERT 0
+#define BOXHORI 0
+#else
+#define BOXVERT '|'
+/* #define BOXVERT 0 */
+#define BOXHORI '-'
+/* #define BOXHORI 0 */
+#endif /* DOSPATH */
+#endif /* !HAVE_CONFIG_H */
+
+/******************************
+ * LY_UMLAUT controls the 7-bit expansion of characters with dieresis or
+ * umlaut. If defined, a digraph is displayed, e.g., auml --> ae
+ * Otherwise, a single character is displayed, e.g., auml --> a
+ * Note that this is currently not supported with the chartrans code,
+ * or rather it doesn't have an effect if translations for a display
+ * character set are taken from one of the *.tbl files in src/chrtrans.
+ * One would have to modify the corresponding *.tbl file for this.
+ */
+#define LY_UMLAUT
+
+/*******************************
+ * Execution links/scripts configuration.
+ *
+ * Execution links and scripts allow you to run
+ * local programs by activating links within Lynx.
+ *
+ * An execution link is of the form:
+ *
+ * lynxexec:<COMMAND>
+ * or:
+ * lynxexec://<COMMAND>
+ * or:
+ * lynxprog:<COMMAND>
+ * or:
+ * lynxprog://<COMMAND>
+ *
+ * where <COMMAND> is a command that Lynx will run when the link is
+ * activated. The double-slash should be included if the command begins
+ * with an '@', as for executing VMS command files. Otherwise, the double-
+ * slash can be omitted.
+ * Use lynxexec for commands or scripts that generate a screen output which
+ * should be held via a prompt to press <return> before returning to Lynx
+ * for display of the current document.
+ * Use lynxprog for programs such as mail which do require a pause before
+ * Lynx restores the display of the current document.
+ *
+ * Execution scripts take the form of a standard
+ * URL. Extension mapping or MIME typing is used
+ * to decide if the file is a script and should be
+ * executed. The current extensions are:
+ * .csh, .ksh, and .sh on UNIX systems and .com on
+ * VMS systems. Any time a file of this type is
+ * accessed Lynx will look at the user's options
+ * settings to decide if the script can be executed.
+ * Current options include: Only exec files that
+ * reside on the local machine and are referenced
+ * with a "file://localhost" URL, All execution
+ * off, and all execution on.
+ *
+ * The following definitions will add execution
+ * capabilities to Lynx. You may define none, one
+ * or both.
+ *
+ * I strongly recommend that you define neither one
+ * of these since execution links/scripts can represent
+ * very serious security risk to your system and its
+ * users. If you do define these I suggest that
+ * you only allow users to execute files/scripts
+ * that reside on your local machine.
+ *
+ * YOU HAVE BEEN WARNED!
+ *
+ * Note: if you are enabling execution scripts you should
+ * also see src/HTInit.c to verify/change the execution
+ * script extensions and/or commands.
+ */
+/* #define EXEC_LINKS */
+/* #define EXEC_SCRIPTS */
+
+/**********
+ * UNIX:
+ * =====
+ * CGI script support. Defining LYNXCGI_LINKS allows you to use the
+ *
+ * lynxcgi:path
+ *
+ * URL which allows lynx to access a cgi script directly without the need for
+ * a http daemon. Redirection or mime support is not supported but just about
+ * everything else is. If the path is not an executable file then the URL is
+ * rewritten as file://localhost and passed to the file loader. This means that
+ * if your http:html files are currently set up to use relative addressing, you
+ * should be able to fire up your main page with lynxcgi:path and everything
+ * should work as if you were talking to the http daemon.
+ *
+ * Note that TRUSTED_LYNXCGI directives must be defined in your lynx.cfg file
+ * if you wish to place restrictions on source documents and/or paths for
+ * lynxcgi links.
+ *
+ * The cgi scripts are called with a fork()/execve() sequence so you don't
+ * have to worry about people trying to abuse the code. :-)
+ *
+ * George Lindholm (George.Lindholm@ubc.ca)
+ *
+ * VMS:
+ * ====
+ * The lynxcgi scheme, if enabled, yields an informational message regardless
+ * of the path, and use of the freeware OSU DECthreads server as a local
+ * script server is recommended instead of lynxcgi URLs. Uncomment the
+ * following line to define LYNXCGI_LINKS, and when running Lynx, enter
+ * lynxcgi:advice as a G)oto URL for more information and links to the
+ * OSU server distribution.
+ */
+/* #define LYNXCGI_LINKS */
+
+#if defined(EXEC_LINKS) || defined(EXEC_SCRIPTS)
+
+/**********
+ * if ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS
+ * is defined then the user will be able to change
+ * the execution status within the options screen.
+ */
+/* #define ALLOW_USERS_TO_CHANGE_EXEC_WITHIN_OPTIONS */
+
+/**********
+ * if NEVER_ALLOW_REMOTE_EXEC is defined then local execution of
+ * scripts or lynxexec and lynxprog URLs will only be implemented
+ * from HTML files that were accessed via a "file://localhost/" URL,
+ * and the options menu for "L)ocal executions links" will only
+ * allow toggling between "ALWAYS OFF" and "FOR LOCAL FILES ONLY".
+ */
+/* #define NEVER_ALLOW_REMOTE_EXEC */
+
+/*****************************
+ * These are for executable shell scripts and links.
+ * Set to FALSE unless you really know what you're
+ * doing.
+ *
+ * This only applies if you are compiling with EXEC_LINKS or
+ * EXEC_SCRIPTS defined.
+ *
+ * The first two settings:
+ * LOCAL_EXECUTION_LINKS_ALWAYS_ON
+ * LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE
+ * specify the DEFAULT setting of the users execution link
+ * options, but the user may still change those options.
+ * If you do not wish the user to be able to change the
+ * execution link settings you may wish to use the commandline option:
+ * -restrictions=exec_frozen
+ *
+ * LOCAL_EXECUTION_LINKS_ALWAYS_ON will be FALSE
+ * if NEVER_ALLOW_REMOTE_EXEC has been defined.
+ *
+ * if LOCAL_EXECUTION_LINKS_ALWAYS_OFF_FOR_ANONYMOUS is
+ * true all execution links will be disabled when the
+ * -anonymous command line option is used. Anonymous
+ * users are not allowed to change the execution options
+ * from within the Lynx options menu so you might be able
+ * to use this option to enable execution links and set
+ * LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE to TRUE to
+ * give anonymous execution link capability without compromising
+ * your system (see comments about TRUSTED_EXEC rules in
+ * lynx.cfg for more information).
+ *
+ */
+#define LOCAL_EXECUTION_LINKS_ALWAYS_ON FALSE
+#define LOCAL_EXECUTION_LINKS_ON_BUT_NOT_REMOTE FALSE
+#define LOCAL_EXECUTION_LINKS_ALWAYS_OFF_FOR_ANONYMOUS FALSE
+
+#endif /* defined(EXEC_LINKS) || defined(EXEC_SCRIPTS) */
+
+/*********************************
+ * MAIL_SYSTEM_ERROR_LOGGING will send a message to the owner of
+ * the information if there is one, every time
+ * that a document cannot be accessed!
+ *
+ * NOTE: This can generate A LOT of mail, be warned.
+ */
+#define MAIL_SYSTEM_ERROR_LOGGING FALSE /*mail a message for every error?*/
+
+/*********************************
+ * If CHECKMAIL is set to TRUE, the user will be informed (via a statusline
+ * message) about the existence of any unread mail at startup of Lynx, and
+ * will get statusline messages if subsequent new mail arrives. If a jumps
+ * file with a lynxprog URL for invoking mail is available, or your html
+ * pages include an mail launch file URL, the user thereby can access mail
+ * and read the messages. The checks and statusline reports will not be
+ * performed if Lynx has been invoked with the -restrictions=mail switch.
+ *
+ * VMS USERS !!!
+ * New mail is normally broadcast as it arrives, via "unsolicitied screen
+ * broadcasts", which can be "wiped" from the Lynx display via the Ctrl-W
+ * command. You may prefer to disable the broadcasts and use CHECKMAIL
+ * instead (e.g., in a public account which will be used by people who
+ * are ignorant about VMS).
+ */
+#define CHECKMAIL FALSE /* report unread and new mail messages */
+
+/*********************************
+ * VI_KEYS can be turned on by the user in the options
+ * screen or the .lynxrc file. This is just the default.
+ */
+#define VI_KEYS_ALWAYS_ON FALSE /* familiar h,j,k, & l */
+
+/*********************************
+ * EMACS_KEYS can be turned on by the user in the options
+ * screen or the .lynxrc file. This is just the default.
+ */
+#define EMACS_KEYS_ALWAYS_ON FALSE /* familiar ^N, ^P, ^F, ^B */
+
+/*********************************
+ * DEFAULT_KEYPAD_MODE specifies whether by default the user
+ * has numbers that work like arrows or else numbered links
+ * DEFAULT KEYPAD MODE may be set to
+ * NUMBERS_AS_ARROWS or
+ * LINKS_ARE_NUMBERED or
+ * LINKS_AND_FORM_FIELDS_ARE_NUMBERED
+ */
+#define DEFAULT_KEYPAD_MODE NUMBERS_AS_ARROWS
+
+/********************************
+ * The default search.
+ * This is a default that can be overridden by the user!
+ */
+#define CASE_SENSITIVE_ALWAYS_ON FALSE /* case sensitive user search */
+
+/********************************
+ * If NO_DOT_FILES is set TRUE here or in lynx.cfg, the user will not be
+ * allowed to specify files beginning with a dot in reply to output filename
+ * prompts, and files beginning with a dot (e.g., file://localhost/foo/.lynxrc)
+ * will not be included in the directory browser's listings. The setting here
+ * will be overridden by the setting in lynx.cfg. If FALSE, you can force it
+ * to be treated as TRUE via -restrictions=dotfiles (or -anonymous, which sets
+ * this and most other restrictions).
+ *
+ * If it's FALSE at startup of Lynx, the user can regulate it via the
+ * 'o'ptions menu, and may save the preference in the RC file.
+ */
+#define NO_DOT_FILES TRUE /* disallow access to dot files */
+
+/********************************
+ * If MAKE_LINKS_FOR_ALL_IMAGES is TRUE, all images will be given links
+ * which can be ACTIVATEd. For inlines, the ALT or pseudo-ALT ("[INLINE]")
+ * strings will be links for the resolved SRC rather than just text. For
+ * ISMAP or other graphic links, the ALT or pseudo-ALT ("[ISMAP]" or "[LINK]")
+ * strings will have '-' and a link labeled "[IMAGE]" for the resolved SRC
+ * appended.
+ *
+ * The default defined here can be changed in lynx.cfg, and the user can
+ * use LYK_IMAGE_TOGGLE to toggle the feature on or off at run time.
+ *
+ * The default also can be toggled via an "-image_links" command line switch.
+ */
+#define MAKE_LINKS_FOR_ALL_IMAGES FALSE /* inlines cast to links */
+
+/********************************
+ * If MAKE_PSEUDO_ALTS_FOR_INLINES is FALSE, inline images which do not
+ * specify an ALT string will not have "[INLINE]" inserted as a pseudo-ALT,
+ * i.e., they'll be treated as having ALT="". If MAKE_LINKS_FOR_ALL_IMAGES
+ * is defined or toggled to TRUE, however, the pseudo-ALTs will be created
+ * for inlines, so that they can be used as links to the SRCs.
+ *
+ * The default defined here can be changed in lynx.cfg, and the user can
+ * use LYK_INLINE_TOGGLE to toggle the feature on or off at run time.
+ *
+ * The default also can be toggled via a "-pseudo_inlines" command line
+ * switch.
+ */
+#define MAKE_PSEUDO_ALTS_FOR_INLINES TRUE /* Use "[INLINE]" pseudo-ALTs */
+
+/********************************
+ * If SUBSTITUTE_UNDERSCORES is TRUE, the _underline_ format will be used
+ * for emphasis tags in dumps.
+ *
+ * The default defined here can be changed in lynx.cfg, and the user can
+ * toggle the default via a "-underscore" command line switch.
+ */
+#define SUBSTITUTE_UNDERSCORES FALSE /* Use _underline_ format in dumps */
+
+/********************************
+ * If QUIT_DEFAULT_YES is defined as TRUE then when the QUIT command
+ * is entered, any response other than n or N will confirm. Define it
+ * as FALSE if you prefer the more conservative action of requiring an
+ * explicit Y or y to confirm. The default defined here can be changed
+ * in lynx.cfg.
+ */
+#define QUIT_DEFAULT_YES TRUE
+
+/********************************
+ * These definitions specify files created or used in conjunction
+ * with traversals. See CRAWL.ANNOUNCE for more infomation.
+ */
+#define TRAVERSE_FILE "traverse.dat"
+#define TRAVERSE_FOUND_FILE "traverse2.dat"
+#define TRAVERSE_REJECT_FILE "reject.dat"
+#define TRAVERSE_ERRORS "traverse.errors"
+
+/****************************************************************
+ * The LYMessages_en.h header defines default, English strings
+ * used in statusline prompts, messages, and warnings during
+ * program execution. See the comments in LYMessages_en.h for
+ * information on translating or customizing them for your site.
+ */
+#ifndef HTTELNET_H
+#include "LYMessages_en.h"
+#endif /* !HTTELNET_H */
+
+
+/****************************************************************
+ * Section 3. Things that you should not change until you
+ * have a good knowledge of the program
+ */
+
+#define LYNX_NAME "Lynx"
+/* The strange-looking comments on the next line tell PRCS to replace
+ * the version definition with the Project Version on checkout. Just
+ * ignore it. - kw */
+/* $Format: "#define LYNX_VERSION \"$ProjectVersion$\""$ */
+#define LYNX_VERSION "2.8rel.2"
+
+#ifndef MAXINT
+#define MAXINT 2147483647 /* max integer */
+#endif /* !MAXINT */
+#define MAXBASE 100 /* max length of base directory */
+#define MAXHIGHLIGHT 160 /* max length of highlighted text */
+#define MAXTARGET 130 /* max length of target string */
+#define LINESIZE 1024 /* max length of line to read from file */
+#define MAXFNAME 1280 /* max filename length DDD/FILENAME.EXT */
+#define MAXCOMMAND MAXFNAME /* max length of command should be the same */
+#define MAXHIST 1024 /* max links we remember in history */
+#define MAXLINKS 1024 /* max links on one screen */
+
+#ifndef SEARCH_GOAL_LINE
+#define SEARCH_GOAL_LINE 4 /* try to position search target there */
+#endif
+
+#define MAXCHARSETS 60 /* max character sets supported */
+#define MAXCHARSETSP 61 /* always one more than MAXCHARSETS */
+
+#ifdef __DJGPP__
+#define FNAMES_8_3
+#endif
+
+#ifdef FNAMES_8_3
+#define HTML_SUFFIX ".htm"
+#else
+#define HTML_SUFFIX ".html"
+#endif
+
+#ifdef VMS
+/*
+** Use the VMS port of gzip for uncompressing both .Z and .gz files.
+*/
+#define UNCOMPRESS_PATH "gzip -d"
+#define GZIP_PATH "gzip"
+
+#else
+
+#ifdef DOSPATH
+/*
+** Following executables may be sought from your PATH at run-time.
+** To get those programs look for GNU-port stuff elsewhere.
+** Currently, if compiled with -DUSE_ZLIB (default), you need only "cp"
+**
+** WINDOWS
+** ===========
+*/
+#define COMPRESS_PATH "compress"
+#define UNCOMPRESS_PATH "uncompress"
+#define UUDECODE_PATH "uudecode"
+#define ZCAT_PATH "zcat"
+#define GZIP_PATH "gzip"
+#define INSTALL_PATH "install"
+#define TAR_PATH "tar"
+#define TOUCH_PATH "touch"
+
+/*
+** WINDOWS/DOS
+** ===========
+*/
+#define ZIP_PATH "zip"
+#define UNZIP_PATH "unzip"
+#define MKDIR_PATH "mkdir"
+#define MV_PATH "mv"
+#define RM_PATH "rm"
+#define COPY_PATH "cp"
+#define CHMOD_PATH "chmod"
+
+#else /* Unix */
+
+/*
+** Check these paths on Unix!
+** ==========================
+*/
+#ifndef HAVE_CONFIG_H
+#if defined(__FreeBSD__)||defined(__NetBSD__)||defined(__bsdi__)||defined(LINUX)
+/*
+** FreeBSD, NetBSD, BSDI, or Linux:
+** ================================
+*/
+#define COMPRESS_PATH "/usr/bin/compress"
+#define UNCOMPRESS_PATH "/usr/bin/gunzip"
+#define UUDECODE_PATH "/usr/bin/uudecode"
+#define ZCAT_PATH "/usr/bin/zcat"
+#define GZIP_PATH "/usr/bin/gzip"
+#define INSTALL_PATH "/usr/bin/install"
+#define INSTALL_ARGS "-c"
+#define TAR_PATH "/usr/bin/tar"
+#define TOUCH_PATH "/usr/bin/touch"
+#else
+/*
+** Other Unix:
+** ===========
+*/
+#define COMPRESS_PATH "/usr/ucb/compress"
+#define UNCOMPRESS_PATH "/usr/ucb/uncompress"
+#define UUDECODE_PATH "/bin/uudecode"
+#define ZCAT_PATH "/usr/local/bin/zcat"
+#define GZIP_PATH "/usr/local/bin/gzip"
+#define INSTALL_PATH "/bin/install"
+#define INSTALL_ARGS "-c"
+#define TAR_PATH "/bin/tar"
+#define TOUCH_PATH "/bin/touch"
+
+#endif /* __FreeBSD__ || __NetBSD__ || __bsdi__ || LINUX */
+
+/*
+** All Unix:
+** =========
+*/
+#define ZIP_PATH "/usr/local/bin/zip"
+#define UNZIP_PATH "/usr/local/bin/unzip"
+#define MKDIR_PATH "/bin/mkdir"
+#define MV_PATH "/bin/mv"
+#define RM_PATH "/bin/rm"
+#define COPY_PATH "/bin/cp"
+#define CHMOD_PATH "/bin/chmod"
+
+#endif /* HAVE_CONFIG_H */
+#endif /* DOSPATH */
+#endif /* VMS */
+
+
+/****************************************************************
+ * Section 4. Things you MUST check only if you plan to use Lynx
+ * in an anonymous account (allow public access to Lynx).
+ * This section may be skipped by those people building
+ * Lynx for private use only.
+ *
+ */
+
+/*****************************
+ * Enter the name of your anonymous account if you have one
+ * as ANONYMOUS_USER. UNIX systems will use a cuserid
+ * or get_login call to determine if the current user is
+ * the ANONYMOUS_USER. VMS systems will use getenv("USER").
+ *
+ * You may use the "-anonymous" option for multiple accounts,
+ * or for precautionary reasons in the anonymous account, as well.
+ *
+ * Specify privileges for the anonymous account below.
+ *
+ * It is very important to have this correctly defined or include
+ * the "-anonymous" command line option for invocation of Lynx
+ * in an anonymous account! If you do not you will be putting
+ * yourself at GREAT security risk!
+ */
+#define ANONYMOUS_USER ""
+
+/*******************************
+ * In the following four pairs of defines,
+ * INSIDE_DOMAIN means users connecting from inside your local domain,
+ * OUTSIDE_DOMAIN means users connecting from outside your local domain.
+ *
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to telnet back out
+ */
+#define CAN_ANONYMOUS_INSIDE_DOMAIN_TELNET TRUE
+#define CAN_ANONYMOUS_OUTSIDE_DOMAIN_TELNET FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to use ftp
+ */
+#define CAN_ANONYMOUS_INSIDE_DOMAIN_FTP TRUE
+#define CAN_ANONYMOUS_OUTSIDE_DOMAIN_FTP FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to use rlogin
+ */
+#define CAN_ANONYMOUS_INSIDE_DOMAIN_RLOGIN TRUE
+#define CAN_ANONYMOUS_OUTSIDE_DOMAIN_RLOGIN FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to read news
+ */
+#define CAN_ANONYMOUS_INSIDE_DOMAIN_READ_NEWS TRUE
+#define CAN_ANONYMOUS_OUTSIDE_DOMAIN_READ_NEWS FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to goto random URLs. (The 'g' command)
+ */
+#define CAN_ANONYMOUS_GOTO TRUE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to goto particular URLs.
+ */
+#define CAN_ANONYMOUS_GOTO_CSO FALSE
+#define CAN_ANONYMOUS_GOTO_FILE FALSE
+#define CAN_ANONYMOUS_GOTO_FINGER TRUE
+#define CAN_ANONYMOUS_GOTO_FTP FALSE
+#define CAN_ANONYMOUS_GOTO_GOPHER FALSE
+#define CAN_ANONYMOUS_GOTO_HTTP TRUE
+#define CAN_ANONYMOUS_GOTO_HTTPS FALSE
+#define CAN_ANONYMOUS_GOTO_LYNXCGI FALSE
+#define CAN_ANONYMOUS_GOTO_LYNXEXEC FALSE
+#define CAN_ANONYMOUS_GOTO_LYNXPROG FALSE
+#define CAN_ANONYMOUS_GOTO_MAILTO TRUE
+#define CAN_ANONYMOUS_GOTO_NEWS FALSE
+#define CAN_ANONYMOUS_GOTO_NNTP FALSE
+#define CAN_ANONYMOUS_GOTO_RLOGIN FALSE
+#define CAN_ANONYMOUS_GOTO_SNEWS FALSE
+#define CAN_ANONYMOUS_GOTO_TELNET FALSE
+#define CAN_ANONYMOUS_GOTO_TN3270 FALSE
+#define CAN_ANONYMOUS_GOTO_WAIS TRUE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to specify a port in 'g'oto commands
+ * for telnet URLs.
+ */
+#define CAN_ANONYMOUS_GOTO_TELNET_PORT FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to jump to URLs (The 'J' command)
+ * via the shortcut entries in your JUMPFILE.
+ */
+#define CAN_ANONYMOUS_JUMP FALSE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to mail
+ */
+#define CAN_ANONYMOUS_MAIL TRUE
+
+/*******************************
+ * set to FALSE if you don't want users of your anonymous
+ * account to be able to print
+ */
+#define CAN_ANONYMOUS_PRINT FALSE
+
+/*****************************
+ * Be sure you have read about and set defines above in Sections
+ * 1, 2 and 3 that could affect Lynx in an anonymous account,
+ * especially LOCAL_EXECUTION_LINKS_ALWAYS_OFF_FOR_ANONYMOUS.
+ *
+ * This ends the section specific to anonymous accounts.
+ */
+
+#endif /* USERDEFS_H */
diff --git a/gnu/usr.bin/lynx/utils/lpansi/Makefile b/gnu/usr.bin/lynx/utils/lpansi/Makefile
new file mode 100644
index 00000000000..a88c6dca333
--- /dev/null
+++ b/gnu/usr.bin/lynx/utils/lpansi/Makefile
@@ -0,0 +1,24 @@
+# Makefile for lpansi
+#
+VERSION=2.1
+# For hp-ux
+# CFLAGS=-Aa -O
+# For others:
+CFLAGS=-O
+BINDIR=/usr/local/bin
+MANDIR=/usr/local/man/man1
+
+lpansi: lpansi.o Makefile
+ $(CC) -o lpansi lpansi.o
+
+clean:
+ rm -f lpansi.o
+
+shar:
+ shar -v README lpansi.c lpansi.1 Makefile > lpansi-$(VERSION).shar
+
+install: lpansi
+ chmod o+rx,g+rx,u+rx lpansi; cp -p lpansi $(BINDIR)/lpansi
+
+install_man:
+ chmod o+rx,g+rx,u+rx lpansi.1; cp -p lpansi.1 $(MANDIR)/lpansi.1
diff --git a/gnu/usr.bin/lynx/utils/lpansi/README b/gnu/usr.bin/lynx/utils/lpansi/README
new file mode 100644
index 00000000000..252614a8e13
--- /dev/null
+++ b/gnu/usr.bin/lynx/utils/lpansi/README
@@ -0,0 +1,82 @@
+README for lpansi.c v2.1 10/20/1994
+
+ Print to ANSI printer on local terminal
+
+ SYNOPSIS
+ lpansi [options] [file-list]
+
+ DESCRIPTION
+ The Problem
+ UNIX supplies a printing program called lp <filename> which allows the
+ user to print a text (or any really) file to a printer.
+ Unfortunately, that printer is attached to the UNIX server which is
+ not where the user usually is. In my case, it is about 230 miles
+ away. I needed a similar program that would allow me to print to my
+ home printer.
+
+ The solution:
+ The VT100 standard defines a printer on and off escape sequence.
+ [FYI: esc[5i is printer on, esc[4i is printer off.] Lpansi is a VERY
+ simple program that issues a printer on sequence, opens the files sent
+ as an argument, reads it character by character, echos it to stdout
+ (now your local printer) and ends by sending a form feed and printer
+ off command.
+
+ Usage:
+ I had several purposes in mind when I wrote this. The first was to
+ find a way to replace lp in a gopher client I had with something that
+ would print at home. I also wanted to be able to print text files to
+ my home printer directly from the UNIX prompt. A natural extension of
+ this is to add it to LYNX, and other printing clients as your printer
+ command.
+
+ Syntax:
+ This program accepts miltiple filenames as an argument. If no
+ filename is present, lpansi will use standard input.
+
+ Thanks:
+ Thanks go to Michael Seibel on the PINE development team for helping
+ me find the correct ANSI codes to turn off the printer. I found out
+ later that PINE distributes a similar program called ansiprt which is
+ supposed to do the same thing. Here, the source code is provided so
+ you may incorporate the concept directly in your program.
+
+
+ Options:
+ -f Form feed off, no form feed at end of each file
+ -v Verbose, prints helpful information for debugging purposes.
+
+ Disclaimer:
+ [Everyone has one so...] I make no promises whatsoever about how this
+ will work for you. If you have VT100 and/or ANSI, it should work just
+ fine. If it doesn't, quit using it. :) This program is free to use
+ and modify, but try to keep my name with it. I don't do that much
+ cool stuff, so I need all the credit I can get. Thanks.
+
+ AUTHOR
+ Written by Gary Day (gday@comp.uark.edu)
+
+ MODIFICATIONS
+ Version 1.1 Modified by Noel Hunter (noel@wfu.edu)
+ Version 2.0 Modified by Noel Hunter (noel@wfu.edu)
+ Version 2.1 Modified by Noel Hunter (noel@wfu.edu)
+
+ FILES
+ /usr/local/bin/lpansi
+
+ SEE ALSO
+ lp, lynx, pine
+
+ EXAMPLES
+ lpansi .profile
+
+ Will print the file named .profile to a printer attached to your
+ terminal. NCSA Telnet, WRC Reflections for PC, and Kermit are known
+ to work.
+
+ In pine, use lpansi by typing "m" for "Main Menu", then selecting "s"
+ for setup. Next, enter "p" for "Printer", and select "1. Printer
+ attached to IBM PC or compatible, Macintosh". From then on, when you
+ choose print in pine, it will be sent to your terminal program and
+ attached printer.
+
diff --git a/gnu/usr.bin/lynx/utils/lpansi/lpansi.1 b/gnu/usr.bin/lynx/utils/lpansi/lpansi.1
new file mode 100644
index 00000000000..d0b854f7920
--- /dev/null
+++ b/gnu/usr.bin/lynx/utils/lpansi/lpansi.1
@@ -0,0 +1,77 @@
+.TH lpansi 1 "Print to ANSI printer on local terminal"
+.ds)H LPANSI
+.ds]W Release 2.1: October, 1994
+.SH lpansi
+.SH
+.SH SYNOPSIS
+lpansi [options] [file-list]
+.SH DESCRIPTION
+.SH The Problem
+UNIX supplies a printing program called lp <filename> which
+allows the user to print a text (or any really) file to a
+printer. Unfortunately, that printer is attached to the UNIX
+server which is not where the user usually is. In my case, it is
+about 230 miles away. I needed a similar program that would
+allow me to print to my home printer.
+
+.SH The solution:
+The VT100 standard defines a printer on and off escape
+sequence. [FYI: esc[5i is printer on, esc[4i is printer off.]
+Lpansi is a VERY simple program that issues a printer on
+sequence, opens the files sent as an argument, reads it character
+by character, echos it to stdout (now your local printer) and
+ends by sending a form feed and printer off command.
+
+.SH Usage:
+I had several purposes in mind when I wrote this. The first was to
+find a way to replace lp in a gopher client I had with something that
+would print at home. I also wanted to be able to print text
+files to my home printer directly from the UNIX prompt. A
+natural extension of this is to add it to LYNX, and other printing
+clients as your printer command.
+
+.SH Syntax:
+This program accepts miltiple filenames as an argument.
+If no filename is present, lpansi will use standard input.
+.SH Thanks:
+Thanks go to Michael Seibel on the PINE development team for
+helping me find the correct ANSI codes to turn off the printer.
+I found out later that PINE distributes a similar program called
+ansiprt which is supposed to do the same thing. Here, the source
+code is provided so you may incorporate the concept directly in your
+program.
+
+.SH Options:
+.nfill
+ -f Form feed off, no form feed at end of each file
+ -v Verbose, prints helpful information for debugging purposes.
+.fill
+.SH Disclaimer:
+[Everyone has one so...] I make no promises whatsoever about
+how this will work for you. If you have VT100 and/or ANSI, it
+should work just fine. If it doesn't, quit using it. :) This
+program is free to use and modify, but try to keep my name with
+it. I don't do that much cool stuff, so I need all the credit
+I can get. Thanks.
+.SH AUTHOR
+Written by Gary Day (gday@comp.uark.edu)
+.SH MODIFICATIONS
+.nfill
+Version 1.1 Modified by Noel Hunter (noel@wfu.edu)
+Version 2.0 Modified by Noel Hunter (noel@wfu.edu)
+Version 2.1 Modified by Noel Hunter (noel@wfu.edu)
+.fill
+.SH FILES
+/usr/local/bin/lpansi
+.SH SEE ALSO
+lp, lynx, pine
+.SH EXAMPLES
+lpansi .profile
+
+Will print the file named .profile to a printer attached to your terminal.
+NCSA Telnet, WRC Reflections for PC, and Kermit are known to work.
+
+In pine, use lpansi by typing "m" for "Main Menu", then selecting "s" for
+setup. Next, enter "p" for "Printer", and select "1. Printer attached to
+IBM PC or compatible, Macintosh". From then on, when you choose print
+in pine, it will be sent to your terminal program and attached printer.
diff --git a/gnu/usr.bin/lynx/utils/lpansi/lpansi.c b/gnu/usr.bin/lynx/utils/lpansi/lpansi.c
new file mode 100644
index 00000000000..4ea10e4f9b9
--- /dev/null
+++ b/gnu/usr.bin/lynx/utils/lpansi/lpansi.c
@@ -0,0 +1,160 @@
+/********************************************************
+ * lpansi.c *
+ * Original author: Gary Day, 11/30/93 *
+ * Current version: 2.1 by Noel Hunter, 10/20/94 *
+ * *
+ * Basic structure based on print -- format files for *
+ * printing from _Pratical_C_Programming by Steve *
+ * Oualline, O'Reilly & Associates *
+ ********************************************************/
+#include <stdio.h>
+#include <stdlib.h> /* ANSI Standard only */
+#include <string.h>
+#ifdef VMS
+#include <unixio.h>
+#include <unixlib.h>
+#endif /* VMS */
+
+int verbose = 0; /* verbose mode (default = false) */
+int formfeed = 1; /* form feed mode (default = true) */
+char *program_name; /* name of the program (for errors) */
+
+/* Ansi C function prototypes */
+void ansi_printer_on(void);
+void ansi_printer_off(void);
+int main(int argc, char *argv[]);
+
+main(int argc, char *argv[])
+{
+ void do_file(char *); /* print a file */
+ void usage(void); /* tell user how to use the program */
+
+ /* save the program name for future use */
+ program_name = argv[0];
+
+ /*
+ * loop for each option.
+ * Stop if we run out of arguments
+ * or we get an argument without a dash.
+ */
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ /*
+ * argv[1][1] is the actual option character.
+ */
+ switch (argv[1][1]) {
+ /*
+ * -v verbose
+ */
+ case 'v':
+ verbose = 1;
+ (void)printf("VERBOSE mode ON\n");
+ break;
+ case 'f':
+ formfeed = 0;
+ break;
+ default:
+ (void)fprintf(stderr,"Bad option %s\n", argv[1]);
+ usage();
+ }
+ /*
+ * move the argument list up one
+ * move the count down one
+ */
+ argv++;
+ argc--;
+ }
+
+ /*
+ * At this point all the options have been processed.
+ * Check to see if we have no files in the list
+ * and if so, we need to process just standard in.
+ */
+ if (argc == 1) {
+ do_file("stdin");
+ } else {
+ while (argc > 1) {
+ do_file(argv[1]);
+ argv++;
+ argc--;
+ }
+ }
+ return (0);
+}
+/********************************************************
+ * do_file -- send a file to the printer *
+ * *
+ * Parameter *
+ * name -- name of the file to print *
+ ********************************************************/
+void do_file(char *name)
+{
+ int ch; /* Where we store our characters */
+ FILE *fp; /* File pointer */
+
+ if ( verbose == 1 ) (void)printf("Processing: %s\n", name);
+
+ ansi_printer_on();
+
+ if ( strcmp(name,"stdin") == 0 )
+ {
+ while ((ch=getc(stdin))!=EOF)
+ {
+ putc(ch,stdout);
+ }
+ }
+ else /* Reading from a file */
+ {
+ if ((fp=fopen(name, "r"))==NULL)
+ {
+ printf("Can't open %s\n",name);
+ exit(1);
+ }
+ while ((ch=getc(fp))!=EOF)
+ {
+ putc(ch,stdout);
+ }
+ fclose(fp);
+ }
+
+ if ( formfeed == 1 )
+ {
+ printf("\n\x0C"); /* Do a form feed at the end of the document */
+ }
+
+ ansi_printer_off();
+
+ if ( verbose == 1 ) (void)printf("Finished processing: %s\n", name);
+
+}
+
+/********************************************************
+ * usage -- tell the user how to use this program and *
+ * exit *
+ ********************************************************/
+void usage(void)
+{
+ (void)fprintf(stderr,"Usage is %s [options] [file-list]\n",
+ program_name);
+ (void)fprintf(stderr,"Options\n");
+ (void)fprintf(stderr," -f form feed OFF\n");
+ (void)fprintf(stderr," -v verbose\n");
+ exit (1);
+}
+
+/********************************************************
+ * Send a printer on escape sequence *
+ *******************************************************/
+void ansi_printer_on(void)
+{
+ if ( verbose == 1 ) (void)printf("ANSI printer ON\n");
+ printf("\x1B[5i");
+}
+
+/********************************************************
+ * Send a printer off escape sequence *
+ *******************************************************/
+void ansi_printer_off(void)
+{
+ printf("\x1B[4i");
+ if ( verbose == 1 ) (void)printf("ANSI printer OFF\n");
+}
diff --git a/gnu/usr.bin/lynx/utils/lpansi/vmsbuild.com b/gnu/usr.bin/lynx/utils/lpansi/vmsbuild.com
new file mode 100644
index 00000000000..12e44b461dd
--- /dev/null
+++ b/gnu/usr.bin/lynx/utils/lpansi/vmsbuild.com
@@ -0,0 +1,73 @@
+$ v = 'f$verify(0)'
+$! VMSBUILD.COM for lpansi.c
+$!
+$! Command file to build LPANSI.EXE on VMS systems.
+$!
+$! 19-Dec-1996 F.Macrides macrides@sci.wfeb.edu
+$! Initial version, for Lynx.
+$!
+$ ON CONTROL_Y THEN GOTO CLEANUP
+$ ON ERROR THEN GOTO CLEANUP
+$ proc = f$environment("PROCEDURE")
+$ where = f$parse(proc,,,"DEVICE") + f$parse(proc,,,"DIRECTORY")
+$ set default 'where'
+$ write sys$output "Default directory:"
+$ show default
+$ write sys$output ""
+$!
+$!
+$ if p1 .nes. ""
+$ then
+$ cc_opts = "/DEBUG/NOOPT"
+$ link_opts = "/DEBUG"
+$ else
+$ cc_opts = ""
+$ link_opts = ""
+$ endif
+$!
+$ v1 = f$verify(1)
+$!
+$! Build LPANSI.EXE
+$!
+$ v1 = 'f$verify(0)'
+$ IF f$trnlnm("VAXCMSG") .eqs. "DECC$MSG" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/DECC" .or. -
+ f$trnlnm("DECC$CC_DEFAULT") .eqs. "/VAXC"
+$ THEN
+$ compiler := "DECC"
+$ v1 = f$verify(1)
+$! Compile with DECC:
+$ cc := cc/decc/prefix=all 'cc_opts'
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ IF f$search("gnu_cc:[000000]gcclib.olb") .nes. ""
+$ THEN
+$ compiler := "GNUC"
+$ v1 = f$verify(1)
+$! Compile with GNUC:
+$ cc := gcc 'cc_opts'
+$ v1 = 'f$verify(0)'
+$ ELSE
+$ compiler := "VAXC"
+$ v1 = f$verify(1)
+$! Compile with VAXC:
+$ cc := cc 'cc_opts'
+$ v1 = 'f$verify(0)'
+$ ENDIF
+$ ENDIF
+$ v1 = f$verify(1)
+$!
+$ cc lpansi
+$!
+$! Link the objects and libaries.
+$!
+$ link/exe=lpansi.exe 'link_opts' -
+lpansi.obj, -
+sys$disk:[--.src]'compiler'.opt/opt
+$ v1 = 'f$verify(0)'
+$ CLEANUP:
+$ v1 = 'f$verify(0)'
+$ write sys$output "Default directory:"
+$ show default
+$ v1 = f$verify(v)
+$ exit